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