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

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.2.4.4 ! misho       6: * $Id: blob.c,v 1.2.4.3 2011/08/19 13:03:06 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: 
                     73:        memset(szFName, 0, MAXPATHLEN);
                     74:        snprintf(szFName, MAXPATHLEN, 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: 
                    131:        memset(szFName, 0, MAXPATHLEN);
                    132:        snprintf(szFName, MAXPATHLEN, BLOB_FILE, srv->srv_blob.dir, blob->blob_var);
                    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: 
                    189:        memset(szFName, 0, MAXPATHLEN);
                    190:        snprintf(szFName, MAXPATHLEN, BLOB_FILE, srv->srv_blob.dir, blob->blob_var);
1.2.4.3   misho     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.2.4.2   misho     218:        for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len) {
1.2.4.4 ! misho     219:                len = send(cli->cli_sock, pos, ret, 0);
1.2.4.2   misho     220:                if (len == -1) {
1.2       misho     221:                        LOGERR;
                    222:                        return -1;
                    223:                }
1.2.4.2   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.2.4.4 ! misho     257:                len = recv(cli->cli_sock, pos, ret, 0);
1.2.4.2   misho     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;
1.2.4.3   misho     295:        if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
1.2       misho     296:                LOGERR;
                    297:                return -1;
                    298:        }
                    299: 
                    300:        for (ret = var->val_len, pos = data; ret > 0; ret -= len, pos += len)
1.2.4.4 ! 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:        }
1.2.4.3   misho     316:        if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
1.2       misho     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;
1.2.4.3   misho     365:        if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
1.2       misho     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.2.4.4 ! 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:        }
1.2.4.3   misho     405:        if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
1.2       misho     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;
1.2.4.3   misho     446:        if (send(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
1.2       misho     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:        }
1.2.4.3   misho     461:        if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
1.2       misho     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>