Annotation of libaitrpc/src/blob.c, revision 1.1.2.17

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 $
1.1.2.17! misho       6: * $Id: blob.c,v 1.1.2.16 2011/05/02 23:07:55 misho Exp $
1.1.2.16  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: */
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: 
1.1.2.17! misho      63: #ifdef HAVE_SRANDOMDEV
1.1.2.7   misho      64:        srandomdev();
1.1.2.17! misho      65: #else
        !            66:        time_t tim;
        !            67: 
        !            68:        srandom((time(&tim) ^ getpid()));
        !            69: #endif
1.1.2.7   misho      70: again:
                     71:        rnd = random() % UINT_MAX;
1.1.2.4   misho      72: 
                     73:        memset(szFName, 0, MAXPATHLEN);
1.1.2.7   misho      74:        snprintf(szFName, MAXPATHLEN, BLOB_FILE, srv->srv_blob.dir, rnd);
                     75:        f = open(szFName, O_CREAT | O_EXCL | O_RDWR, 0600);
1.1.2.4   misho      76:        if (f == -1) {
1.1.2.7   misho      77:                if (errno == EEXIST)
                     78:                        goto again;
                     79: 
1.1.2.4   misho      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;
1.1.2.7   misho     110:        blob->blob_var = rnd;
1.1.2.4   misho     111:        return blob;
                    112: }
                    113: 
                    114: /*
1.1.2.2   misho     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: 
                    131:        memset(szFName, 0, MAXPATHLEN);
                    132:        snprintf(szFName, MAXPATHLEN, BLOB_FILE, srv->srv_blob.dir, blob->blob_var);
1.1.2.8   misho     133:        f = open(szFName, O_RDWR);
1.1.2.2   misho     134:        if (f == -1) {
                    135:                LOGERR;
                    136:                return -1;
                    137:        }
                    138: 
1.1.2.12  misho     139:        blob->blob_data = mmap(NULL, blob->blob_len, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);
1.1.2.2   misho     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);
1.1.2.4   misho     147: 
1.1.2.12  misho     148:                madvise(blob->blob_data, blob->blob_len, MADV_SEQUENTIAL);
1.1.2.2   misho     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: 
                    189:        memset(szFName, 0, MAXPATHLEN);
                    190:        snprintf(szFName, MAXPATHLEN, BLOB_FILE, srv->srv_blob.dir, blob->blob_var);
                    191:        if (remove(szFName) == -1) {
                    192:                LOGERR;
                    193:                return -1;
                    194:        }
                    195: 
                    196:        return 0;
                    197: }
                    198: 
                    199: // ------------------------------------------------------------
                    200: 
1.1.2.3   misho     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:  */
1.1.2.2   misho     207: int
1.1.2.3   misho     208: rpc_srv_sendBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob)
1.1.2.2   misho     209: {
1.1.2.3   misho     210:        int ret, len;
                    211:        uint8_t *pos;
1.1.2.2   misho     212: 
1.1.2.3   misho     213:        if (!cli || !blob || !blob->blob_data) {
1.1.2.2   misho     214:                rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
                    215:                return -1;
                    216:        }
                    217: 
1.1.2.3   misho     218:        for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len)
                    219:                if ((len = send(cli->cli_sock, pos, ret > BLOBSIZ ? BLOBSIZ : ret, 0)) == -1) {
                    220:                        LOGERR;
                    221:                        return -1;
                    222:                }
1.1.2.2   misho     223: 
1.1.2.3   misho     224:        return ret;
                    225: }
                    226: 
                    227: /*
                    228:  * rpc_srv_recvBLOB() Receive BLOB from client
                    229:  * @cli = Client instance
1.1.2.4   misho     230:  * @blob = Mapped BLOB element
                    231:  * return: -1 error, 0 ok, >0 unreceived data from client, may be error?
1.1.2.3   misho     232:  */
                    233: int
1.1.2.4   misho     234: rpc_srv_recvBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob)
1.1.2.3   misho     235: {
                    236:        int ret, len;
                    237:        uint8_t *pos;
1.1.2.4   misho     238:        fd_set fds;
                    239:        struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
1.1.2.3   misho     240: 
1.1.2.4   misho     241:        if (!cli || !blob || !blob->blob_data) {
1.1.2.3   misho     242:                rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
                    243:                return -1;
1.1.2.4   misho     244:        }
                    245: 
                    246:        for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len) {
                    247:                FD_ZERO(&fds);
                    248:                FD_SET(cli->cli_sock, &fds);
                    249:                len = select(cli->cli_sock + 1, &fds, NULL, NULL, &tv);
                    250:                if (len < 1) {
                    251:                        LOGERR;
                    252:                        return -1;
                    253:                }
1.1.2.3   misho     254: 
1.1.2.4   misho     255:                if ((len = recv(cli->cli_sock, pos, BLOBSIZ, 0)) == -1) {
                    256:                        LOGERR;
                    257:                        return -1;
                    258:                }
                    259:        }
1.1.2.3   misho     260: 
                    261:        return ret;
1.1.2.2   misho     262: }
1.1.2.5   misho     263: 
                    264: // ------------------------------------------------------------
                    265: 
                    266: /*
                    267:  * rpc_cli_sendBLOB() Send BLOB to server
                    268:  * @cli = Client instance
                    269:  * @var = BLOB variable
                    270:  * @data = BLOB data
1.1.2.6   misho     271:  * return: -1 error, 0 ok, 1 remote error
1.1.2.5   misho     272:  */
                    273: int
                    274: rpc_cli_sendBLOB(rpc_cli_t * __restrict cli, rpc_val_t * __restrict var, void * __restrict data)
                    275: {
                    276:        int ret, len;
                    277:        uint8_t *pos;
1.1.2.6   misho     278:        struct tagBLOBHdr hdr;
                    279:        fd_set fds;
                    280:        struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
1.1.2.5   misho     281: 
                    282:        if (!cli || !var || !data) {
                    283:                rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
                    284:                return -1;
                    285:        }
                    286: 
1.1.2.6   misho     287:        memcpy(&hdr.hdr_session, cli->cli_parent, sizeof(rpc_sess_t));
                    288:        hdr.hdr_cmd = set;
1.1.2.10  misho     289:        hdr.hdr_var = 0;
1.1.2.11  misho     290:        hdr.hdr_ret = 0;
1.1.2.6   misho     291:        hdr.hdr_len = var->val_len;
                    292:        if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
                    293:                LOGERR;
                    294:                return -1;
                    295:        }
                    296: 
1.1.2.5   misho     297:        for (ret = var->val_len, pos = data; ret > 0; ret -= len, pos += len)
                    298:                if ((len = send(cli->cli_sock, pos, ret > BLOBSIZ ? BLOBSIZ : ret, 0)) == -1) {
                    299:                        LOGERR;
                    300:                        return -1;
                    301:                }
                    302: 
1.1.2.6   misho     303:        FD_ZERO(&fds);
                    304:        FD_SET(cli->cli_sock, &fds);
                    305:        switch (select(cli->cli_sock + 1, &fds, NULL, NULL, &tv)) {
                    306:                case -1:
                    307:                        LOGERR;
                    308:                        return -1;
                    309:                case 0:
                    310:                        rpc_SetErr(ETIMEDOUT, "Error:: Timeout reached! Server not responde ...\n");
                    311:                        return -1;
                    312:        }
1.1.2.10  misho     313:        if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
1.1.2.6   misho     314:                LOGERR;
                    315:                return -1;
                    316:        }
1.1.2.7   misho     317:        if (hdr.hdr_cmd != error) {
                    318:                if (hdr.hdr_len != var->val_len) {
1.1.2.15  misho     319:                        rpc_SetErr(ECANCELED, "Error:: Bad return length packet ...\n");
1.1.2.7   misho     320:                        return -1;
                    321:                }
                    322: 
1.1.2.10  misho     323:                var->val.blob = hdr.hdr_var;
1.1.2.7   misho     324:        }
1.1.2.6   misho     325: 
                    326:        return hdr.hdr_cmd == error;
1.1.2.5   misho     327: }
                    328: 
                    329: /*
                    330:  * rpc_cli_recvBLOB() Receive BLOB from server
                    331:  * @cli = Client instance
                    332:  * @var = BLOB variable
                    333:  * @data = BLOB data, must be free after use!
1.1.2.10  misho     334:  * return: -1 error, 0 ok, 1 remote error
1.1.2.5   misho     335:  */
                    336: int
                    337: rpc_cli_recvBLOB(rpc_cli_t * __restrict cli, rpc_val_t * __restrict var, void ** data)
                    338: {
                    339:        int ret, len;
                    340:        uint8_t *pos;
                    341:        fd_set fds;
                    342:        struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
1.1.2.10  misho     343:        struct tagBLOBHdr hdr;
1.1.2.5   misho     344: 
                    345:        if (!cli || !var || !data) {
                    346:                rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
                    347:                return -1;
                    348:        }
                    349: 
                    350:        *data = malloc(var->val_len);
                    351:        if (!*data) {
                    352:                LOGERR;
                    353:                return -1;
                    354:        } else
                    355:                memset(*data, 0, var->val_len);
                    356: 
1.1.2.10  misho     357:        memcpy(&hdr.hdr_session, cli->cli_parent, sizeof(rpc_sess_t));
                    358:        hdr.hdr_cmd = get;
                    359:        hdr.hdr_var = (uint32_t) RPC_GET_BLOB(var);
1.1.2.11  misho     360:        hdr.hdr_ret = 0;
1.1.2.10  misho     361:        hdr.hdr_len = 0;
                    362:        if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
                    363:                LOGERR;
                    364:                free(*data);
                    365:                *data = NULL;
                    366:                return -1;
                    367:        }
                    368: 
1.1.2.5   misho     369:        for (ret = var->val_len, pos = *data; ret > 0; ret -= len, pos += len) {
                    370:                FD_ZERO(&fds);
                    371:                FD_SET(cli->cli_sock, &fds);
                    372:                len = select(cli->cli_sock + 1, &fds, NULL, NULL, &tv);
                    373:                if (len < 1) {
                    374:                        LOGERR;
                    375:                        free(*data);
                    376:                        *data = NULL;
                    377:                        return -1;
                    378:                }
                    379: 
                    380:                if ((len = recv(cli->cli_sock, pos, BLOBSIZ, 0)) == -1) {
                    381:                        LOGERR;
                    382:                        free(*data);
                    383:                        *data = NULL;
                    384:                        return -1;
                    385:                }
                    386:        }
                    387: 
1.1.2.10  misho     388:        FD_ZERO(&fds);
                    389:        FD_SET(cli->cli_sock, &fds);
                    390:        switch (select(cli->cli_sock + 1, &fds, NULL, NULL, &tv)) {
                    391:                case -1:
                    392:                        LOGERR;
                    393:                        free(*data);
                    394:                        *data = NULL;
                    395:                        return -1;
                    396:                case 0:
                    397:                        rpc_SetErr(ETIMEDOUT, "Error:: Timeout reached! Server not responde ...\n");
                    398:                        free(*data);
                    399:                        *data = NULL;
                    400:                        return -1;
                    401:        }
                    402:        if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
                    403:                LOGERR;
                    404:                free(*data);
                    405:                *data = NULL;
                    406:                return -1;
                    407:        }
                    408:        if (hdr.hdr_cmd != error) {
                    409:                if (hdr.hdr_len != var->val_len) {
1.1.2.15  misho     410:                        rpc_SetErr(ECANCELED, "Error:: Bad return length packet ...\n");
1.1.2.10  misho     411:                        free(*data);
                    412:                        *data = NULL;
                    413:                        return -1;
                    414:                }
                    415:        }
                    416: 
                    417:        return hdr.hdr_cmd == error;
1.1.2.5   misho     418: }
1.1.2.13  misho     419: 
                    420: /*
                    421:  * rpc_cli_delBLOB() Delete BLOB from server
                    422:  * @cli = Client instance
                    423:  * @var = BLOB variable
                    424:  * return: -1 error, 0 ok, 1 remote error
                    425:  */
                    426: int
                    427: rpc_cli_delBLOB(rpc_cli_t * __restrict cli, rpc_val_t * __restrict var)
                    428: {
                    429:        struct tagBLOBHdr hdr;
                    430:        fd_set fds;
                    431:        struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
                    432: 
                    433:        if (!cli || !var) {
                    434:                rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
                    435:                return -1;
                    436:        }
                    437: 
                    438:        memcpy(&hdr.hdr_session, cli->cli_parent, sizeof(rpc_sess_t));
                    439:        hdr.hdr_cmd = unset;
                    440:        hdr.hdr_var = (uint32_t) RPC_GET_BLOB(var);
                    441:        hdr.hdr_ret = 0;
                    442:        hdr.hdr_len = 0;
                    443:        if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
                    444:                LOGERR;
                    445:                return -1;
                    446:        }
                    447: 
                    448:        FD_ZERO(&fds);
                    449:        FD_SET(cli->cli_sock, &fds);
                    450:        switch (select(cli->cli_sock + 1, &fds, NULL, NULL, &tv)) {
                    451:                case -1:
                    452:                        LOGERR;
                    453:                        return -1;
                    454:                case 0:
                    455:                        rpc_SetErr(ETIMEDOUT, "Error:: Timeout reached! Server not responde ...\n");
                    456:                        return -1;
                    457:        }
                    458:        if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
                    459:                LOGERR;
                    460:                return -1;
                    461:        }
                    462: 
                    463:        return hdr.hdr_cmd == error;
                    464: }
                    465: 
                    466: /*
                    467:  * rpc_cli_getBLOB() Receive BLOB from server and Delete after that
                    468:  * @cli = Client instance
                    469:  * @var = BLOB variable
                    470:  * @data = BLOB data, must be free after use!
                    471:  * return: -1 error, 0 ok, 1 remote error
                    472:  */
                    473: inline int
                    474: rpc_cli_getBLOB(rpc_cli_t * __restrict cli, rpc_val_t * __restrict var, void ** data)
                    475: {
                    476:        int ret;
                    477: 
                    478:        ret = rpc_cli_recvBLOB(cli, var, data);
                    479:        ret |= rpc_cli_delBLOB(cli, var) > 0 ? 2 : 0;
                    480: 
                    481:        return ret;
                    482: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>