Annotation of libaitrpc/src/blob.c, revision 1.7.2.3
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.7.2.3 ! misho 6: * $Id: blob.c,v 1.7.2.2 2012/05/16 08:18:00 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.5 misho 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
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:
49: /*
1.7.2.1 misho 50: * rpc_srv_blobCreate() - Create and map blob to memory region and return object
1.5 misho 51: *
1.2 misho 52: * @srv = RPC Server instance
53: * @len = BLOB length object
54: * return: NULL error or !=NULL allocated BLOB object
55: */
56: inline rpc_blob_t *
57: rpc_srv_blobCreate(rpc_srv_t * __restrict srv, int len)
58: {
59: rpc_blob_t *blob = NULL;
60: char szFName[MAXPATHLEN];
61: int f;
62: u_int rnd;
63:
64: #ifdef HAVE_SRANDOMDEV
65: srandomdev();
66: #else
67: time_t tim;
68:
69: srandom((time(&tim) ^ getpid()));
70: #endif
71: again:
72: rnd = random() % UINT_MAX;
73:
1.3 misho 74: memset(szFName, 0, sizeof szFName);
1.5 misho 75: snprintf(szFName, sizeof szFName, BLOB_FILE, AIT_GET_STR(&srv->srv_blob.dir), rnd);
1.2 misho 76: f = open(szFName, O_CREAT | O_EXCL | O_RDWR, 0600);
77: if (f == -1) {
78: if (errno == EEXIST)
79: goto again;
80:
81: LOGERR;
82: return NULL;
83: }
1.7.2.1 misho 84: if (ftruncate(f, len) == -1) {
1.2 misho 85: LOGERR;
86: close(f);
87: unlink(szFName);
88: return NULL;
1.7.2.1 misho 89: }
1.2 misho 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: /*
1.5 misho 115: * rpc_srv_blobMap() - Map blob to memory region
116: *
1.2 misho 117: * @srv = RPC Server instance
118: * @blob = Map to this BLOB element
119: * return: -1 error or 0 ok
120: */
121: inline int
122: rpc_srv_blobMap(rpc_srv_t * __restrict srv, rpc_blob_t * __restrict blob)
123: {
124: int f;
125: char szFName[MAXPATHLEN];
126:
127: if (!blob) {
1.5 misho 128: rpc_SetErr(EINVAL, "Invalid argument BLOB");
1.2 misho 129: return -1;
130: }
1.4 misho 131: if (blob->blob_data) {
1.5 misho 132: rpc_SetErr(EPERM, "Already mmapped object found!");
1.4 misho 133: return -1;
134: }
1.2 misho 135:
1.3 misho 136: memset(szFName, 0, sizeof szFName);
1.5 misho 137: snprintf(szFName, sizeof szFName, BLOB_FILE, AIT_GET_STR(&srv->srv_blob.dir), blob->blob_var);
1.2 misho 138: f = open(szFName, O_RDWR);
139: if (f == -1) {
140: LOGERR;
141: return -1;
142: }
143:
144: blob->blob_data = mmap(NULL, blob->blob_len, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);
145: if (blob->blob_data == MAP_FAILED) {
146: LOGERR;
147: close(f);
148: blob->blob_data = NULL;
149: return -1;
150: } else {
151: close(f);
152:
153: madvise(blob->blob_data, blob->blob_len, MADV_SEQUENTIAL);
154: }
155:
156: return 0;
157: }
158:
159: /*
1.5 misho 160: * rpc_srv_blobUnmap() - Unmap blob memory region
161: *
1.2 misho 162: * @blob = Mapped BLOB element
163: * return: none
164: */
165: inline void
166: rpc_srv_blobUnmap(rpc_blob_t * __restrict blob)
167: {
1.7.2.3 ! misho 168: if (blob && blob->blob_data) {
1.2 misho 169: munmap(blob->blob_data, blob->blob_len);
170: blob->blob_data = NULL;
171: }
172: }
173:
174: /*
1.5 misho 175: * rpc_srv_blobFree() - Free blob from disk & memory
176: *
1.2 misho 177: * @srv = RPC Server instance
178: * @blob = Mapped BLOB element
179: * return: -1 error or 0 ok
180: */
181: inline int
182: rpc_srv_blobFree(rpc_srv_t * __restrict srv, rpc_blob_t * __restrict blob)
183: {
184: char szFName[MAXPATHLEN];
185:
186: if (!blob) {
1.5 misho 187: rpc_SetErr(EINVAL, "Invalid argument BLOB");
1.2 misho 188: return -1;
1.7.2.1 misho 189: } else
1.2 misho 190: rpc_srv_blobUnmap(blob);
191:
1.3 misho 192: memset(szFName, 0, sizeof szFName);
1.5 misho 193: snprintf(szFName, sizeof szFName, BLOB_FILE, AIT_GET_STR(&srv->srv_blob.dir), blob->blob_var);
1.3 misho 194: if (unlink(szFName) == -1) {
1.2 misho 195: LOGERR;
196: return -1;
197: }
198:
199: return 0;
200: }
201:
1.7.2.1 misho 202: /* ------------------------------------------------------------ */
1.2 misho 203:
204: /*
1.5 misho 205: * rpc_srv_sendBLOB() - Send mapped BLOB to client
206: *
1.2 misho 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) {
1.5 misho 218: rpc_SetErr(EINVAL, "Invalid arguments");
1.2 misho 219: return -1;
220: }
221:
1.3 misho 222: for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len) {
1.7.2.2 misho 223: len = send(cli->cli_sock, pos, ret, MSG_NOSIGNAL);
1.3 misho 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: /*
1.5 misho 234: * rpc_srv_recvBLOB() - Receive BLOB from client
235: *
1.2 misho 236: * @cli = Client instance
237: * @blob = Mapped BLOB element
238: * return: -1 error, 0 ok, >0 unreceived data from client, may be error?
239: */
240: int
241: rpc_srv_recvBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob)
242: {
243: int ret, len;
244: uint8_t *pos;
1.7 misho 245: struct pollfd pfd;
1.2 misho 246:
247: if (!cli || !blob || !blob->blob_data) {
1.5 misho 248: rpc_SetErr(EINVAL, "Invalid arguments");
1.2 misho 249: return -1;
1.7 misho 250: }
1.2 misho 251:
1.7 misho 252: pfd.fd = cli->cli_sock;
253: pfd.events = POLLIN | POLLPRI;
1.2 misho 254: for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len) {
1.7.2.2 misho 255: if ((len = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 ||
1.7 misho 256: pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
1.2 misho 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:
1.7.2.2 misho 271: /* ------------------------------------------------------------ */
1.2 misho 272:
273: /*
1.5 misho 274: * rpc_cli_sendBLOB() - Send BLOB to server
275: *
1.2 misho 276: * @cli = Client instance
277: * @var = BLOB variable
278: * @data = BLOB data
279: * return: -1 error, 0 ok, 1 remote error
280: */
281: int
1.4 misho 282: rpc_cli_sendBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var, void * __restrict data)
1.2 misho 283: {
284: int ret, len;
285: uint8_t *pos;
286: struct tagBLOBHdr hdr;
1.7 misho 287: struct pollfd pfd;
1.2 misho 288:
289: if (!cli || !var || !data) {
1.5 misho 290: rpc_SetErr(EINVAL, "Invalid arguments");
1.2 misho 291: return -1;
1.7 misho 292: }
1.2 misho 293:
1.5 misho 294: rpc_addPktSession(&hdr.hdr_session, cli->cli_parent);
1.2 misho 295: hdr.hdr_cmd = set;
296: hdr.hdr_var = 0;
297: hdr.hdr_ret = 0;
1.5 misho 298: hdr.hdr_len = htonl(AIT_LEN(var));
299: /* calculate CRC */
300: hdr.hdr_crc ^= hdr.hdr_crc;
1.6 misho 301: hdr.hdr_crc = htons(crcFletcher16((u_short*) &hdr, sizeof hdr / 2));
1.5 misho 302:
303: /* send SET request */
1.2 misho 304: if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
305: LOGERR;
306: return -1;
307: }
308:
1.4 misho 309: /* send BLOB to server */
310: for (ret = AIT_LEN(var), pos = data; ret > 0; ret -= len, pos += len)
1.3 misho 311: if ((len = send(cli->cli_sock, pos, ret, 0)) == -1) {
1.2 misho 312: LOGERR;
313: return -1;
314: }
315:
1.5 misho 316: /* wait for reply */
1.7 misho 317: pfd.fd = cli->cli_sock;
318: pfd.events = POLLIN | POLLPRI;
1.7.2.3 ! misho 319: if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 ||
1.7 misho 320: pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
321: if (ret)
1.2 misho 322: LOGERR;
1.7 misho 323: else
324: rpc_SetErr(ETIMEDOUT, "Timeout reached! Server not respond");
325: return -1;
1.2 misho 326: }
327: if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
328: LOGERR;
1.5 misho 329: return 1;
330: }
331: /* check CRC */
332: ret = ntohs(hdr.hdr_crc);
333: hdr.hdr_crc ^= hdr.hdr_crc;
1.6 misho 334: if (ret != crcFletcher16((u_short*) &hdr, sizeof hdr / 2)) {
1.5 misho 335: rpc_SetErr(ERPCMISMATCH, "Bad CRC BLOB packet");
336: return 1;
1.2 misho 337: }
1.5 misho 338:
1.2 misho 339: if (hdr.hdr_cmd != error) {
1.5 misho 340: if (ntohl(hdr.hdr_len) != AIT_LEN(var)) {
341: rpc_SetErr(ECANCELED, "Bad return length packet");
342: return 1;
1.2 misho 343: }
344:
1.5 misho 345: var->val.blob = ntohl(hdr.hdr_var);
1.2 misho 346: }
347:
348: return hdr.hdr_cmd == error;
349: }
350:
351: /*
1.5 misho 352: * rpc_cli_recvBLOB() - Receive BLOB from server
353: *
1.2 misho 354: * @cli = Client instance
355: * @var = BLOB variable
356: * @data = BLOB data, must be free after use!
357: * return: -1 error, 0 ok, 1 remote error
358: */
359: int
1.4 misho 360: rpc_cli_recvBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var, void ** __restrict data)
1.2 misho 361: {
362: int ret, len;
363: uint8_t *pos;
1.7 misho 364: struct pollfd pfd;
1.2 misho 365: struct tagBLOBHdr hdr;
366:
367: if (!cli || !var || !data) {
1.5 misho 368: rpc_SetErr(EINVAL, "Invalid arguments");
1.2 misho 369: return -1;
1.7 misho 370: }
1.2 misho 371:
1.4 misho 372: *data = malloc(AIT_LEN(var));
1.2 misho 373: if (!*data) {
374: LOGERR;
375: return -1;
376: } else
1.4 misho 377: memset(*data, 0, AIT_LEN(var));
1.2 misho 378:
1.5 misho 379: rpc_addPktSession(&hdr.hdr_session, cli->cli_parent);
1.2 misho 380: hdr.hdr_cmd = get;
1.5 misho 381: hdr.hdr_var = htonl((uint32_t) AIT_GET_BLOB(var));
1.2 misho 382: hdr.hdr_ret = 0;
383: hdr.hdr_len = 0;
1.5 misho 384: /* calculate CRC */
385: hdr.hdr_crc ^= hdr.hdr_crc;
1.6 misho 386: hdr.hdr_crc = htons(crcFletcher16((u_short*) &hdr, sizeof hdr / 2));
1.5 misho 387:
388: /* send GET request */
1.2 misho 389: if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
390: LOGERR;
391: free(*data);
392: *data = NULL;
393: return -1;
394: }
395:
1.4 misho 396: /* receive BLOB from server */
1.7 misho 397: pfd.fd = cli->cli_sock;
398: pfd.events = POLLIN | POLLPRI;
1.4 misho 399: for (ret = AIT_LEN(var), pos = *data; ret > 0; ret -= len, pos += len) {
1.7.2.3 ! misho 400: if ((len = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 ||
1.7 misho 401: pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
1.2 misho 402: LOGERR;
403: free(*data);
404: *data = NULL;
405: return -1;
406: }
407:
1.3 misho 408: if ((len = recv(cli->cli_sock, pos, ret, 0)) == -1) {
1.2 misho 409: LOGERR;
410: free(*data);
411: *data = NULL;
412: return -1;
413: }
414: }
415:
1.5 misho 416: /* wait for reply */
1.7.2.3 ! misho 417: if ((len = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 ||
1.7 misho 418: pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
419: if (len)
1.2 misho 420: LOGERR;
1.7 misho 421: else
422: rpc_SetErr(ETIMEDOUT, "Timeout reached! Server not respond");
423: free(*data);
424: *data = NULL;
425: return 1;
1.2 misho 426: }
427: if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
428: LOGERR;
429: free(*data);
430: *data = NULL;
1.5 misho 431: return 1;
432: }
433: /* check CRC */
434: ret = ntohs(hdr.hdr_crc);
435: hdr.hdr_crc ^= hdr.hdr_crc;
1.6 misho 436: if (ret != crcFletcher16((u_short*) &hdr, sizeof hdr / 2)) {
1.5 misho 437: rpc_SetErr(ERPCMISMATCH, "Bad CRC BLOB packet");
438: free(*data);
439: *data = NULL;
440: return 1;
1.2 misho 441: }
442: if (hdr.hdr_cmd != error) {
1.5 misho 443: if (ntohl(hdr.hdr_len) != AIT_LEN(var)) {
444: rpc_SetErr(ECANCELED, "Bad return length packet");
1.2 misho 445: free(*data);
446: *data = NULL;
1.5 misho 447: return 1;
1.2 misho 448: }
449: }
450:
451: return hdr.hdr_cmd == error;
452: }
453:
454: /*
1.5 misho 455: * rpc_cli_delBLOB() - Delete BLOB from server
456: *
1.2 misho 457: * @cli = Client instance
458: * @var = BLOB variable
459: * return: -1 error, 0 ok, 1 remote error
460: */
461: int
1.4 misho 462: rpc_cli_delBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var)
1.2 misho 463: {
464: struct tagBLOBHdr hdr;
1.7 misho 465: struct pollfd pfd;
1.5 misho 466: int ret;
1.2 misho 467:
468: if (!cli || !var) {
1.5 misho 469: rpc_SetErr(EINVAL, "Invalid arguments");
1.2 misho 470: return -1;
1.7 misho 471: }
1.2 misho 472:
1.5 misho 473: rpc_addPktSession(&hdr.hdr_session, cli->cli_parent);
1.2 misho 474: hdr.hdr_cmd = unset;
1.5 misho 475: hdr.hdr_var = htonl((uint32_t) AIT_GET_BLOB(var));
1.2 misho 476: hdr.hdr_ret = 0;
477: hdr.hdr_len = 0;
1.5 misho 478: /* calculate CRC */
479: hdr.hdr_crc ^= hdr.hdr_crc;
1.6 misho 480: hdr.hdr_crc = htons(crcFletcher16((u_short*) &hdr, sizeof hdr / 2));
1.5 misho 481:
482: /* send UNSET request */
1.2 misho 483: if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
484: LOGERR;
485: return -1;
486: }
487:
1.5 misho 488: /* wait for reply */
1.7 misho 489: pfd.fd = cli->cli_sock;
490: pfd.events = POLLIN | POLLPRI;
1.7.2.3 ! misho 491: if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 ||
1.7 misho 492: pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
493: if (ret)
1.2 misho 494: LOGERR;
1.7 misho 495: else
496: rpc_SetErr(ETIMEDOUT, "Timeout reached! Server not respond");
497: return 1;
1.2 misho 498: }
499: if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
500: LOGERR;
1.5 misho 501: return 1;
502: }
503: /* check CRC */
504: ret = ntohs(hdr.hdr_crc);
505: hdr.hdr_crc ^= hdr.hdr_crc;
1.6 misho 506: if (ret != crcFletcher16((u_short*) &hdr, sizeof hdr / 2)) {
1.5 misho 507: rpc_SetErr(ERPCMISMATCH, "Bad CRC BLOB packet");
508: return 1;
1.2 misho 509: }
510:
511: return hdr.hdr_cmd == error;
512: }
513:
514: /*
1.5 misho 515: * rpc_cli_getBLOB() - Receive BLOB from server and Delete after that
516: *
1.2 misho 517: * @cli = Client instance
518: * @var = BLOB variable
519: * @data = BLOB data, must be free after use!
520: * return: -1 error, 0 ok, 1 remote error
521: */
522: inline int
1.4 misho 523: rpc_cli_getBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var, void ** __restrict data)
1.2 misho 524: {
525: int ret;
526:
527: ret = rpc_cli_recvBLOB(cli, var, data);
528: ret |= rpc_cli_delBLOB(cli, var) > 0 ? 2 : 0;
529:
530: return ret;
531: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>