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>