File:  [ELWIX - Embedded LightWeight unIX -] / libaitrpc / src / blob.c
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Wed Sep 7 07:24:21 2011 UTC (12 years, 10 months ago) by misho
Branches: MAIN
CVS tags: rpc2_1, rpc2_0, RPC2_0, RPC1_3, HEAD
ver 1.3

    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: blob.c,v 1.4 2011/09/07 07:24:21 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: */
   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: 
   73: 	memset(szFName, 0, sizeof szFName);
   74: 	snprintf(szFName, sizeof szFName, BLOB_FILE, srv->srv_blob.dir, rnd);
   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: 	if (blob->blob_data) {
  131: 		rpc_SetErr(EPERM, "Error:: already mmapped object found!\n");
  132: 		return -1;
  133: 	}
  134: 
  135: 	memset(szFName, 0, sizeof szFName);
  136: 	snprintf(szFName, sizeof szFName, BLOB_FILE, srv->srv_blob.dir, blob->blob_var);
  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: 
  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) {
  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: 
  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) {
  225: 			LOGERR;
  226: 			return -1;
  227: 		}
  228: 	}
  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: 
  261: 		len = recv(cli->cli_sock, pos, ret, 0);
  262: 		if (len == -1) {
  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
  281: rpc_cli_sendBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var, void * __restrict data)
  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;
  298: 	hdr.hdr_len = AIT_LEN(var);
  299: 	if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
  300: 		LOGERR;
  301: 		return -1;
  302: 	}
  303: 
  304: 	/* send BLOB to server */
  305: 	for (ret = AIT_LEN(var), pos = data; ret > 0; ret -= len, pos += len)
  306: 		if ((len = send(cli->cli_sock, pos, ret, 0)) == -1) {
  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) {
  326: 		if (hdr.hdr_len != AIT_LEN(var)) {
  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
  345: rpc_cli_recvBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var, void ** __restrict data)
  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: 
  358: 	*data = malloc(AIT_LEN(var));
  359: 	if (!*data) {
  360: 		LOGERR;
  361: 		return -1;
  362: 	} else
  363: 		memset(*data, 0, AIT_LEN(var));
  364: 
  365: 	memcpy(&hdr.hdr_session, cli->cli_parent, sizeof(rpc_sess_t));
  366: 	hdr.hdr_cmd = get;
  367: 	hdr.hdr_var = (uint32_t) AIT_GET_BLOB(var);
  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: 
  377: 	/* receive BLOB from server */
  378: 	for (ret = AIT_LEN(var), pos = *data; ret > 0; ret -= len, pos += len) {
  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: 
  389: 		if ((len = recv(cli->cli_sock, pos, ret, 0)) == -1) {
  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) {
  418: 		if (hdr.hdr_len != AIT_LEN(var)) {
  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
  436: rpc_cli_delBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var)
  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;
  449: 	hdr.hdr_var = (uint32_t) AIT_GET_BLOB(var);
  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
  483: rpc_cli_getBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var, void ** __restrict data)
  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>