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