Annotation of libaitrpc/src/blob.c, revision 1.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.3 ! misho 6: * $Id: blob.c,v 1.2.4.5 2011/08/19 14:10: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:
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: }
130:
1.3 ! misho 131: memset(szFName, 0, sizeof szFName);
! 132: snprintf(szFName, sizeof szFName, BLOB_FILE, srv->srv_blob.dir, blob->blob_var);
1.2 misho 133: f = open(szFName, O_RDWR);
134: if (f == -1) {
135: LOGERR;
136: return -1;
137: }
138:
139: blob->blob_data = mmap(NULL, blob->blob_len, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);
140: if (blob->blob_data == MAP_FAILED) {
141: LOGERR;
142: close(f);
143: blob->blob_data = NULL;
144: return -1;
145: } else {
146: close(f);
147:
148: madvise(blob->blob_data, blob->blob_len, MADV_SEQUENTIAL);
149: }
150:
151: return 0;
152: }
153:
154: /*
155: * rpc_srv_blobUnmap() Unmap blob memory region
156: * @blob = Mapped BLOB element
157: * return: none
158: */
159: inline void
160: rpc_srv_blobUnmap(rpc_blob_t * __restrict blob)
161: {
162: if (!blob || !blob->blob_data)
163: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
164: else {
165: munmap(blob->blob_data, blob->blob_len);
166: blob->blob_data = NULL;
167: }
168: }
169:
170: /*
171: * rpc_srv_blobFree() Free blob from disk & memory
172: * @srv = RPC Server instance
173: * @blob = Mapped BLOB element
174: * return: -1 error or 0 ok
175: */
176: inline int
177: rpc_srv_blobFree(rpc_srv_t * __restrict srv, rpc_blob_t * __restrict blob)
178: {
179: char szFName[MAXPATHLEN];
180:
181: if (!blob) {
182: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
183: return -1;
184: }
185:
186: if (blob->blob_data)
187: rpc_srv_blobUnmap(blob);
188:
1.3 ! misho 189: memset(szFName, 0, sizeof szFName);
! 190: snprintf(szFName, sizeof szFName, BLOB_FILE, srv->srv_blob.dir, blob->blob_var);
! 191: if (unlink(szFName) == -1) {
1.2 misho 192: LOGERR;
193: return -1;
194: }
195:
196: return 0;
197: }
198:
199: // ------------------------------------------------------------
200:
201: /*
202: * rpc_srv_sendBLOB() Send mapped BLOB to client
203: * @cli = Client instance
204: * @blob = Mapped BLOB element
205: * return: -1 error, 0 ok
206: */
207: int
208: rpc_srv_sendBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob)
209: {
210: int ret, len;
211: uint8_t *pos;
212:
213: if (!cli || !blob || !blob->blob_data) {
214: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
215: return -1;
216: }
217:
1.3 ! misho 218: for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len) {
! 219: len = send(cli->cli_sock, pos, ret, 0);
! 220: if (len == -1) {
1.2 misho 221: LOGERR;
222: return -1;
223: }
1.3 ! misho 224: }
1.2 misho 225:
226: return ret;
227: }
228:
229: /*
230: * rpc_srv_recvBLOB() Receive BLOB from client
231: * @cli = Client instance
232: * @blob = Mapped BLOB element
233: * return: -1 error, 0 ok, >0 unreceived data from client, may be error?
234: */
235: int
236: rpc_srv_recvBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob)
237: {
238: int ret, len;
239: uint8_t *pos;
240: fd_set fds;
241: struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
242:
243: if (!cli || !blob || !blob->blob_data) {
244: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
245: return -1;
246: }
247:
248: for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len) {
249: FD_ZERO(&fds);
250: FD_SET(cli->cli_sock, &fds);
251: len = select(cli->cli_sock + 1, &fds, NULL, NULL, &tv);
252: if (len < 1) {
253: LOGERR;
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:
267: // ------------------------------------------------------------
268:
269: /*
270: * rpc_cli_sendBLOB() Send BLOB to server
271: * @cli = Client instance
272: * @var = BLOB variable
273: * @data = BLOB data
274: * return: -1 error, 0 ok, 1 remote error
275: */
276: int
277: rpc_cli_sendBLOB(rpc_cli_t * __restrict cli, rpc_val_t * __restrict var, void * __restrict data)
278: {
279: int ret, len;
280: uint8_t *pos;
281: struct tagBLOBHdr hdr;
282: fd_set fds;
283: struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
284:
285: if (!cli || !var || !data) {
286: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
287: return -1;
288: }
289:
290: memcpy(&hdr.hdr_session, cli->cli_parent, sizeof(rpc_sess_t));
291: hdr.hdr_cmd = set;
292: hdr.hdr_var = 0;
293: hdr.hdr_ret = 0;
294: hdr.hdr_len = var->val_len;
295: if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
296: LOGERR;
297: return -1;
298: }
299:
300: for (ret = var->val_len, pos = data; ret > 0; ret -= len, pos += len)
1.3 ! misho 301: if ((len = send(cli->cli_sock, pos, ret, 0)) == -1) {
1.2 misho 302: LOGERR;
303: return -1;
304: }
305:
306: FD_ZERO(&fds);
307: FD_SET(cli->cli_sock, &fds);
308: switch (select(cli->cli_sock + 1, &fds, NULL, NULL, &tv)) {
309: case -1:
310: LOGERR;
311: return -1;
312: case 0:
313: rpc_SetErr(ETIMEDOUT, "Error:: Timeout reached! Server not responde ...\n");
314: return -1;
315: }
316: if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
317: LOGERR;
318: return -1;
319: }
320: if (hdr.hdr_cmd != error) {
321: if (hdr.hdr_len != var->val_len) {
322: rpc_SetErr(ECANCELED, "Error:: Bad return length packet ...\n");
323: return -1;
324: }
325:
326: var->val.blob = hdr.hdr_var;
327: }
328:
329: return hdr.hdr_cmd == error;
330: }
331:
332: /*
333: * rpc_cli_recvBLOB() Receive BLOB from server
334: * @cli = Client instance
335: * @var = BLOB variable
336: * @data = BLOB data, must be free after use!
337: * return: -1 error, 0 ok, 1 remote error
338: */
339: int
340: rpc_cli_recvBLOB(rpc_cli_t * __restrict cli, rpc_val_t * __restrict var, void ** data)
341: {
342: int ret, len;
343: uint8_t *pos;
344: fd_set fds;
345: struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
346: struct tagBLOBHdr hdr;
347:
348: if (!cli || !var || !data) {
349: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
350: return -1;
351: }
352:
353: *data = malloc(var->val_len);
354: if (!*data) {
355: LOGERR;
356: return -1;
357: } else
358: memset(*data, 0, var->val_len);
359:
360: memcpy(&hdr.hdr_session, cli->cli_parent, sizeof(rpc_sess_t));
361: hdr.hdr_cmd = get;
362: hdr.hdr_var = (uint32_t) RPC_GET_BLOB(var);
363: hdr.hdr_ret = 0;
364: hdr.hdr_len = 0;
365: if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
366: LOGERR;
367: free(*data);
368: *data = NULL;
369: return -1;
370: }
371:
372: for (ret = var->val_len, pos = *data; ret > 0; ret -= len, pos += len) {
373: FD_ZERO(&fds);
374: FD_SET(cli->cli_sock, &fds);
375: len = select(cli->cli_sock + 1, &fds, NULL, NULL, &tv);
376: if (len < 1) {
377: LOGERR;
378: free(*data);
379: *data = NULL;
380: return -1;
381: }
382:
1.3 ! misho 383: if ((len = recv(cli->cli_sock, pos, ret, 0)) == -1) {
1.2 misho 384: LOGERR;
385: free(*data);
386: *data = NULL;
387: return -1;
388: }
389: }
390:
391: FD_ZERO(&fds);
392: FD_SET(cli->cli_sock, &fds);
393: switch (select(cli->cli_sock + 1, &fds, NULL, NULL, &tv)) {
394: case -1:
395: LOGERR;
396: free(*data);
397: *data = NULL;
398: return -1;
399: case 0:
400: rpc_SetErr(ETIMEDOUT, "Error:: Timeout reached! Server not responde ...\n");
401: free(*data);
402: *data = NULL;
403: return -1;
404: }
405: if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
406: LOGERR;
407: free(*data);
408: *data = NULL;
409: return -1;
410: }
411: if (hdr.hdr_cmd != error) {
412: if (hdr.hdr_len != var->val_len) {
413: rpc_SetErr(ECANCELED, "Error:: Bad return length packet ...\n");
414: free(*data);
415: *data = NULL;
416: return -1;
417: }
418: }
419:
420: return hdr.hdr_cmd == error;
421: }
422:
423: /*
424: * rpc_cli_delBLOB() Delete BLOB from server
425: * @cli = Client instance
426: * @var = BLOB variable
427: * return: -1 error, 0 ok, 1 remote error
428: */
429: int
430: rpc_cli_delBLOB(rpc_cli_t * __restrict cli, rpc_val_t * __restrict var)
431: {
432: struct tagBLOBHdr hdr;
433: fd_set fds;
434: struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
435:
436: if (!cli || !var) {
437: rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
438: return -1;
439: }
440:
441: memcpy(&hdr.hdr_session, cli->cli_parent, sizeof(rpc_sess_t));
442: hdr.hdr_cmd = unset;
443: hdr.hdr_var = (uint32_t) RPC_GET_BLOB(var);
444: hdr.hdr_ret = 0;
445: hdr.hdr_len = 0;
446: if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
447: LOGERR;
448: return -1;
449: }
450:
451: FD_ZERO(&fds);
452: FD_SET(cli->cli_sock, &fds);
453: switch (select(cli->cli_sock + 1, &fds, NULL, NULL, &tv)) {
454: case -1:
455: LOGERR;
456: return -1;
457: case 0:
458: rpc_SetErr(ETIMEDOUT, "Error:: Timeout reached! Server not responde ...\n");
459: return -1;
460: }
461: if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
462: LOGERR;
463: return -1;
464: }
465:
466: return hdr.hdr_cmd == error;
467: }
468:
469: /*
470: * rpc_cli_getBLOB() Receive BLOB from server and Delete after that
471: * @cli = Client instance
472: * @var = BLOB variable
473: * @data = BLOB data, must be free after use!
474: * return: -1 error, 0 ok, 1 remote error
475: */
476: inline int
477: rpc_cli_getBLOB(rpc_cli_t * __restrict cli, rpc_val_t * __restrict var, void ** data)
478: {
479: int ret;
480:
481: ret = rpc_cli_recvBLOB(cli, var, data);
482: ret |= rpc_cli_delBLOB(cli, var) > 0 ? 2 : 0;
483:
484: return ret;
485: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>