Annotation of libaitrpc/src/blob.c, revision 1.17
1.2 misho 1: /*************************************************************************
2: * (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
3: * by Michael Pounov <misho@openbsd-bg.org>
4: *
5: * $Author: misho $
1.17 ! misho 6: * $Id: blob.c,v 1.16.4.1 2015/07/02 17:52:53 misho Exp $
1.2 misho 7: *
8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
1.16 misho 15: Copyright 2004 - 2015
1.2 misho 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
46: #include "global.h"
47:
48:
1.14 misho 49: static void *
50: toutBLOB(sched_task_t *task)
51: {
52: rpc_srv_unregisterBLOB(TASK_DATA(task), ((rpc_blob_t*) TASK_ARG(task))->blob_var);
53:
54: return NULL;
55: }
56:
57:
1.2 misho 58: /*
1.8 misho 59: * rpc_srv_blobCreate() - Create and map blob to memory region and return object
1.5 misho 60: *
1.2 misho 61: * @srv = RPC Server instance
62: * @len = BLOB length object
1.14 misho 63: * @tout = BLOB live timeout in seconds
1.2 misho 64: * return: NULL error or !=NULL allocated BLOB object
65: */
1.13 misho 66: rpc_blob_t *
1.14 misho 67: rpc_srv_blobCreate(rpc_srv_t * __restrict srv, int len, int tout)
1.2 misho 68: {
69: rpc_blob_t *blob = NULL;
70: char szFName[MAXPATHLEN];
71: int f;
72: u_int rnd;
1.17 ! misho 73: struct timespec ts = { tout ? tout : DEF_RPC_BLOB_TIMEOUT, 0 };
1.2 misho 74:
75: again:
76: rnd = random() % UINT_MAX;
77:
1.3 misho 78: memset(szFName, 0, sizeof szFName);
1.10 misho 79: snprintf(szFName, sizeof szFName, BLOB_FILE, AIT_GET_STRZ(&srv->srv_blob.dir), rnd);
1.2 misho 80: f = open(szFName, O_CREAT | O_EXCL | O_RDWR, 0600);
81: if (f == -1) {
82: if (errno == EEXIST)
83: goto again;
84:
85: LOGERR;
86: return NULL;
87: }
1.8 misho 88: if (ftruncate(f, len) == -1) {
1.2 misho 89: LOGERR;
90: close(f);
91: unlink(szFName);
92: return NULL;
1.8 misho 93: }
1.2 misho 94:
1.11 misho 95: blob = e_malloc(sizeof(rpc_blob_t));
1.2 misho 96: if (!blob) {
97: LOGERR;
98: close(f);
99: unlink(szFName);
100: return NULL;
101: }
102:
103: blob->blob_data = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);
104: if (blob->blob_data == MAP_FAILED) {
105: LOGERR;
1.11 misho 106: e_free(blob);
1.2 misho 107: close(f);
108: unlink(szFName);
109: return NULL;
1.17 ! misho 110: } else {
1.2 misho 111: close(f);
112:
1.17 ! misho 113: madvise(blob->blob_data, len, MADV_SEQUENTIAL);
! 114: }
! 115:
1.2 misho 116: blob->blob_len = len;
117: blob->blob_var = rnd;
1.14 misho 118:
119: schedTimer(srv->srv_blob.root, toutBLOB, blob, ts, srv, 0);
1.2 misho 120: return blob;
121: }
122:
123: /*
1.5 misho 124: * rpc_srv_blobMap() - Map blob to memory region
125: *
1.2 misho 126: * @srv = RPC Server instance
127: * @blob = Map to this BLOB element
128: * return: -1 error or 0 ok
129: */
1.13 misho 130: int
1.2 misho 131: rpc_srv_blobMap(rpc_srv_t * __restrict srv, rpc_blob_t * __restrict blob)
132: {
133: int f;
134: char szFName[MAXPATHLEN];
135:
136: if (!blob) {
1.5 misho 137: rpc_SetErr(EINVAL, "Invalid argument BLOB");
1.2 misho 138: return -1;
139: }
1.4 misho 140: if (blob->blob_data) {
1.5 misho 141: rpc_SetErr(EPERM, "Already mmapped object found!");
1.4 misho 142: return -1;
143: }
1.2 misho 144:
1.3 misho 145: memset(szFName, 0, sizeof szFName);
1.10 misho 146: snprintf(szFName, sizeof szFName, BLOB_FILE, AIT_GET_STRZ(&srv->srv_blob.dir), blob->blob_var);
1.2 misho 147: f = open(szFName, O_RDWR);
148: if (f == -1) {
149: LOGERR;
150: return -1;
151: }
152:
153: blob->blob_data = mmap(NULL, blob->blob_len, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);
154: if (blob->blob_data == MAP_FAILED) {
155: LOGERR;
156: close(f);
157: blob->blob_data = NULL;
158: return -1;
159: } else {
160: close(f);
161:
162: madvise(blob->blob_data, blob->blob_len, MADV_SEQUENTIAL);
163: }
164:
165: return 0;
166: }
167:
168: /*
1.5 misho 169: * rpc_srv_blobUnmap() - Unmap blob memory region
170: *
1.2 misho 171: * @blob = Mapped BLOB element
172: * return: none
173: */
1.13 misho 174: void
1.2 misho 175: rpc_srv_blobUnmap(rpc_blob_t * __restrict blob)
176: {
1.8 misho 177: if (blob && blob->blob_data) {
1.2 misho 178: munmap(blob->blob_data, blob->blob_len);
179: blob->blob_data = NULL;
180: }
181: }
182:
183: /*
1.5 misho 184: * rpc_srv_blobFree() - Free blob from disk & memory
185: *
1.2 misho 186: * @srv = RPC Server instance
187: * @blob = Mapped BLOB element
188: * return: -1 error or 0 ok
189: */
1.13 misho 190: int
1.2 misho 191: rpc_srv_blobFree(rpc_srv_t * __restrict srv, rpc_blob_t * __restrict blob)
192: {
193: char szFName[MAXPATHLEN];
194:
195: if (!blob) {
1.5 misho 196: rpc_SetErr(EINVAL, "Invalid argument BLOB");
1.2 misho 197: return -1;
1.8 misho 198: } else
1.2 misho 199: rpc_srv_blobUnmap(blob);
200:
1.14 misho 201: schedCancelby(srv->srv_blob.root, taskTIMER, CRITERIA_ARG, blob, NULL);
202:
1.3 misho 203: memset(szFName, 0, sizeof szFName);
1.10 misho 204: snprintf(szFName, sizeof szFName, BLOB_FILE, AIT_GET_STRZ(&srv->srv_blob.dir), blob->blob_var);
1.3 misho 205: if (unlink(szFName) == -1) {
1.2 misho 206: LOGERR;
207: return -1;
208: }
209:
210: return 0;
211: }
212:
1.8 misho 213: /* ------------------------------------------------------------ */
1.2 misho 214:
215: /*
1.5 misho 216: * rpc_srv_sendBLOB() - Send mapped BLOB to client
217: *
1.2 misho 218: * @cli = Client instance
219: * @blob = Mapped BLOB element
220: * return: -1 error, 0 ok
221: */
222: int
223: rpc_srv_sendBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob)
224: {
225: int ret, len;
226: uint8_t *pos;
227:
228: if (!cli || !blob || !blob->blob_data) {
1.5 misho 229: rpc_SetErr(EINVAL, "Invalid arguments");
1.2 misho 230: return -1;
231: }
232:
1.3 misho 233: for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len) {
1.8 misho 234: len = send(cli->cli_sock, pos, ret, MSG_NOSIGNAL);
1.3 misho 235: if (len == -1) {
1.2 misho 236: LOGERR;
237: return -1;
238: }
1.3 misho 239: }
1.2 misho 240:
241: return ret;
242: }
243:
244: /*
1.5 misho 245: * rpc_srv_recvBLOB() - Receive BLOB from client
246: *
1.2 misho 247: * @cli = Client instance
248: * @blob = Mapped BLOB element
249: * return: -1 error, 0 ok, >0 unreceived data from client, may be error?
250: */
251: int
252: rpc_srv_recvBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob)
253: {
254: int ret, len;
255: uint8_t *pos;
1.7 misho 256: struct pollfd pfd;
1.2 misho 257:
258: if (!cli || !blob || !blob->blob_data) {
1.5 misho 259: rpc_SetErr(EINVAL, "Invalid arguments");
1.2 misho 260: return -1;
1.7 misho 261: }
1.2 misho 262:
1.7 misho 263: pfd.fd = cli->cli_sock;
264: pfd.events = POLLIN | POLLPRI;
1.2 misho 265: for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len) {
1.8 misho 266: if ((len = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 ||
1.7 misho 267: pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
1.8 misho 268: if (len)
269: LOGERR;
270: else
271: rpc_SetErr(ETIMEDOUT, "Timeout reached! Server not respond");
1.2 misho 272: return -1;
273: }
274:
1.3 misho 275: len = recv(cli->cli_sock, pos, ret, 0);
276: if (len == -1) {
1.2 misho 277: LOGERR;
278: return -1;
279: }
280: }
281:
282: return ret;
283: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>