Annotation of libaitrpc/src/blob.c, revision 1.4
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.4 ! misho 6: * $Id: blob.c,v 1.3.2.2 2011/09/03 12:58:49 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:
15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
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:
49: /*
50: * rpc_srv_blobCreate() Create map blob to memory region and return object
51: * @srv = RPC Server instance
52: * @len = BLOB length object
53: * return: NULL error or !=NULL allocated BLOB object
54: */
55: inline rpc_blob_t *
56: rpc_srv_blobCreate(rpc_srv_t * __restrict srv, int len)
57: {
58: rpc_blob_t *blob = NULL;
59: char szFName[MAXPATHLEN];
60: int f;
61: u_int rnd;
62:
63: #ifdef HAVE_SRANDOMDEV
64: srandomdev();
65: #else
66: time_t tim;
67:
68: srandom((time(&tim) ^ getpid()));
69: #endif
70: again:
71: rnd = random() % UINT_MAX;
72:
1.3 misho 73: memset(szFName, 0, sizeof szFName);
74: snprintf(szFName, sizeof szFName, BLOB_FILE, srv->srv_blob.dir, rnd);
1.2 misho 75: f = open(szFName, O_CREAT | O_EXCL | O_RDWR, 0600);
76: if (f == -1) {
77: if (errno == EEXIST)
78: goto again;
79:
80: LOGERR;
81: return NULL;
82: }
83: if (lseek(f, len - 1, SEEK_SET) == -1) {
84: LOGERR;
85: close(f);
86: unlink(szFName);
87: return NULL;
88: } else
89: write(f, "", 1);
90:
91: blob = malloc(sizeof(rpc_blob_t));
92: if (!blob) {
93: LOGERR;
94: close(f);
95: unlink(szFName);
96: return NULL;
97: }
98:
99: blob->blob_data = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);
100: if (blob->blob_data == MAP_FAILED) {
101: LOGERR;
102: free(blob);
103: close(f);
104: unlink(szFName);
105: return NULL;
106: } else
107: close(f);
108:
109: blob->blob_len = len;
110: blob->blob_var = rnd;
111: return blob;
112: }
113:
114: /*
115: * rpc_srv_blobMap() Map blob to memory region
116: * @srv = RPC Server instance
117: * @blob = Map to this BLOB element
118: * return: -1 error or 0 ok
119: */
120: inline int
121: rpc_srv_blobMap(rpc_srv_t * __restrict srv, rpc_blob_t * __restrict blob)
122: {
123: int f;
124: char szFName[MAXPATHLEN];
125:
126: if (!blob) {
127: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
128: return -1;
129: }
1.4 ! misho 130: if (blob->blob_data) {
! 131: rpc_SetErr(EPERM, "Error:: already mmapped object found!\n");
! 132: return -1;
! 133: }
1.2 misho 134:
1.3 misho 135: memset(szFName, 0, sizeof szFName);
136: snprintf(szFName, sizeof szFName, BLOB_FILE, srv->srv_blob.dir, blob->blob_var);
1.2 misho 137: f = open(szFName, O_RDWR);
138: if (f == -1) {
139: LOGERR;
140: return -1;
141: }
142:
143: blob->blob_data = mmap(NULL, blob->blob_len, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);
144: if (blob->blob_data == MAP_FAILED) {
145: LOGERR;
146: close(f);
147: blob->blob_data = NULL;
148: return -1;
149: } else {
150: close(f);
151:
152: madvise(blob->blob_data, blob->blob_len, MADV_SEQUENTIAL);
153: }
154:
155: return 0;
156: }
157:
158: /*
159: * rpc_srv_blobUnmap() Unmap blob memory region
160: * @blob = Mapped BLOB element
161: * return: none
162: */
163: inline void
164: rpc_srv_blobUnmap(rpc_blob_t * __restrict blob)
165: {
166: if (!blob || !blob->blob_data)
167: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
168: else {
169: munmap(blob->blob_data, blob->blob_len);
170: blob->blob_data = NULL;
171: }
172: }
173:
174: /*
175: * rpc_srv_blobFree() Free blob from disk & memory
176: * @srv = RPC Server instance
177: * @blob = Mapped BLOB element
178: * return: -1 error or 0 ok
179: */
180: inline int
181: rpc_srv_blobFree(rpc_srv_t * __restrict srv, rpc_blob_t * __restrict blob)
182: {
183: char szFName[MAXPATHLEN];
184:
185: if (!blob) {
186: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
187: return -1;
188: }
189:
190: if (blob->blob_data)
191: rpc_srv_blobUnmap(blob);
192:
1.3 misho 193: memset(szFName, 0, sizeof szFName);
194: snprintf(szFName, sizeof szFName, BLOB_FILE, srv->srv_blob.dir, blob->blob_var);
195: if (unlink(szFName) == -1) {
1.2 misho 196: LOGERR;
197: return -1;
198: }
199:
200: return 0;
201: }
202:
203: // ------------------------------------------------------------
204:
205: /*
206: * rpc_srv_sendBLOB() Send mapped BLOB to client
207: * @cli = Client instance
208: * @blob = Mapped BLOB element
209: * return: -1 error, 0 ok
210: */
211: int
212: rpc_srv_sendBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob)
213: {
214: int ret, len;
215: uint8_t *pos;
216:
217: if (!cli || !blob || !blob->blob_data) {
218: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
219: return -1;
220: }
221:
1.3 misho 222: for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len) {
223: len = send(cli->cli_sock, pos, ret, 0);
224: if (len == -1) {
1.2 misho 225: LOGERR;
226: return -1;
227: }
1.3 misho 228: }
1.2 misho 229:
230: return ret;
231: }
232:
233: /*
234: * rpc_srv_recvBLOB() Receive BLOB from client
235: * @cli = Client instance
236: * @blob = Mapped BLOB element
237: * return: -1 error, 0 ok, >0 unreceived data from client, may be error?
238: */
239: int
240: rpc_srv_recvBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob)
241: {
242: int ret, len;
243: uint8_t *pos;
244: fd_set fds;
245: struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
246:
247: if (!cli || !blob || !blob->blob_data) {
248: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
249: return -1;
250: }
251:
252: for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len) {
253: FD_ZERO(&fds);
254: FD_SET(cli->cli_sock, &fds);
255: len = select(cli->cli_sock + 1, &fds, NULL, NULL, &tv);
256: if (len < 1) {
257: LOGERR;
258: return -1;
259: }
260:
1.3 misho 261: len = recv(cli->cli_sock, pos, ret, 0);
262: if (len == -1) {
1.2 misho 263: LOGERR;
264: return -1;
265: }
266: }
267:
268: return ret;
269: }
270:
271: // ------------------------------------------------------------
272:
273: /*
274: * rpc_cli_sendBLOB() Send BLOB to server
275: * @cli = Client instance
276: * @var = BLOB variable
277: * @data = BLOB data
278: * return: -1 error, 0 ok, 1 remote error
279: */
280: int
1.4 ! misho 281: rpc_cli_sendBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var, void * __restrict data)
1.2 misho 282: {
283: int ret, len;
284: uint8_t *pos;
285: struct tagBLOBHdr hdr;
286: fd_set fds;
287: struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
288:
289: if (!cli || !var || !data) {
290: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
291: return -1;
292: }
293:
294: memcpy(&hdr.hdr_session, cli->cli_parent, sizeof(rpc_sess_t));
295: hdr.hdr_cmd = set;
296: hdr.hdr_var = 0;
297: hdr.hdr_ret = 0;
1.4 ! misho 298: hdr.hdr_len = AIT_LEN(var);
1.2 misho 299: if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
300: LOGERR;
301: return -1;
302: }
303:
1.4 ! misho 304: /* send BLOB to server */
! 305: for (ret = AIT_LEN(var), pos = data; ret > 0; ret -= len, pos += len)
1.3 misho 306: if ((len = send(cli->cli_sock, pos, ret, 0)) == -1) {
1.2 misho 307: LOGERR;
308: return -1;
309: }
310:
311: FD_ZERO(&fds);
312: FD_SET(cli->cli_sock, &fds);
313: switch (select(cli->cli_sock + 1, &fds, NULL, NULL, &tv)) {
314: case -1:
315: LOGERR;
316: return -1;
317: case 0:
318: rpc_SetErr(ETIMEDOUT, "Error:: Timeout reached! Server not responde ...\n");
319: return -1;
320: }
321: if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
322: LOGERR;
323: return -1;
324: }
325: if (hdr.hdr_cmd != error) {
1.4 ! misho 326: if (hdr.hdr_len != AIT_LEN(var)) {
1.2 misho 327: rpc_SetErr(ECANCELED, "Error:: Bad return length packet ...\n");
328: return -1;
329: }
330:
331: var->val.blob = hdr.hdr_var;
332: }
333:
334: return hdr.hdr_cmd == error;
335: }
336:
337: /*
338: * rpc_cli_recvBLOB() Receive BLOB from server
339: * @cli = Client instance
340: * @var = BLOB variable
341: * @data = BLOB data, must be free after use!
342: * return: -1 error, 0 ok, 1 remote error
343: */
344: int
1.4 ! misho 345: rpc_cli_recvBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var, void ** __restrict data)
1.2 misho 346: {
347: int ret, len;
348: uint8_t *pos;
349: fd_set fds;
350: struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
351: struct tagBLOBHdr hdr;
352:
353: if (!cli || !var || !data) {
354: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
355: return -1;
356: }
357:
1.4 ! misho 358: *data = malloc(AIT_LEN(var));
1.2 misho 359: if (!*data) {
360: LOGERR;
361: return -1;
362: } else
1.4 ! misho 363: memset(*data, 0, AIT_LEN(var));
1.2 misho 364:
365: memcpy(&hdr.hdr_session, cli->cli_parent, sizeof(rpc_sess_t));
366: hdr.hdr_cmd = get;
1.4 ! misho 367: hdr.hdr_var = (uint32_t) AIT_GET_BLOB(var);
1.2 misho 368: hdr.hdr_ret = 0;
369: hdr.hdr_len = 0;
370: if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
371: LOGERR;
372: free(*data);
373: *data = NULL;
374: return -1;
375: }
376:
1.4 ! misho 377: /* receive BLOB from server */
! 378: for (ret = AIT_LEN(var), pos = *data; ret > 0; ret -= len, pos += len) {
1.2 misho 379: FD_ZERO(&fds);
380: FD_SET(cli->cli_sock, &fds);
381: len = select(cli->cli_sock + 1, &fds, NULL, NULL, &tv);
382: if (len < 1) {
383: LOGERR;
384: free(*data);
385: *data = NULL;
386: return -1;
387: }
388:
1.3 misho 389: if ((len = recv(cli->cli_sock, pos, ret, 0)) == -1) {
1.2 misho 390: LOGERR;
391: free(*data);
392: *data = NULL;
393: return -1;
394: }
395: }
396:
397: FD_ZERO(&fds);
398: FD_SET(cli->cli_sock, &fds);
399: switch (select(cli->cli_sock + 1, &fds, NULL, NULL, &tv)) {
400: case -1:
401: LOGERR;
402: free(*data);
403: *data = NULL;
404: return -1;
405: case 0:
406: rpc_SetErr(ETIMEDOUT, "Error:: Timeout reached! Server not responde ...\n");
407: free(*data);
408: *data = NULL;
409: return -1;
410: }
411: if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
412: LOGERR;
413: free(*data);
414: *data = NULL;
415: return -1;
416: }
417: if (hdr.hdr_cmd != error) {
1.4 ! misho 418: if (hdr.hdr_len != AIT_LEN(var)) {
1.2 misho 419: rpc_SetErr(ECANCELED, "Error:: Bad return length packet ...\n");
420: free(*data);
421: *data = NULL;
422: return -1;
423: }
424: }
425:
426: return hdr.hdr_cmd == error;
427: }
428:
429: /*
430: * rpc_cli_delBLOB() Delete BLOB from server
431: * @cli = Client instance
432: * @var = BLOB variable
433: * return: -1 error, 0 ok, 1 remote error
434: */
435: int
1.4 ! misho 436: rpc_cli_delBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var)
1.2 misho 437: {
438: struct tagBLOBHdr hdr;
439: fd_set fds;
440: struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
441:
442: if (!cli || !var) {
443: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
444: return -1;
445: }
446:
447: memcpy(&hdr.hdr_session, cli->cli_parent, sizeof(rpc_sess_t));
448: hdr.hdr_cmd = unset;
1.4 ! misho 449: hdr.hdr_var = (uint32_t) AIT_GET_BLOB(var);
1.2 misho 450: hdr.hdr_ret = 0;
451: hdr.hdr_len = 0;
452: if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
453: LOGERR;
454: return -1;
455: }
456:
457: FD_ZERO(&fds);
458: FD_SET(cli->cli_sock, &fds);
459: switch (select(cli->cli_sock + 1, &fds, NULL, NULL, &tv)) {
460: case -1:
461: LOGERR;
462: return -1;
463: case 0:
464: rpc_SetErr(ETIMEDOUT, "Error:: Timeout reached! Server not responde ...\n");
465: return -1;
466: }
467: if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
468: LOGERR;
469: return -1;
470: }
471:
472: return hdr.hdr_cmd == error;
473: }
474:
475: /*
476: * rpc_cli_getBLOB() Receive BLOB from server and Delete after that
477: * @cli = Client instance
478: * @var = BLOB variable
479: * @data = BLOB data, must be free after use!
480: * return: -1 error, 0 ok, 1 remote error
481: */
482: inline int
1.4 ! misho 483: rpc_cli_getBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var, void ** __restrict data)
1.2 misho 484: {
485: int ret;
486:
487: ret = rpc_cli_recvBLOB(cli, var, data);
488: ret |= rpc_cli_delBLOB(cli, var) > 0 ? 2 : 0;
489:
490: return ret;
491: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>