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

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 $
        !             6: * $Id: blob.c,v 1.1.2.17 2011/05/02 23:11:17 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, 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);
        !           191:        if (remove(szFName) == -1) {
        !           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: 
        !           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:                }
        !           223: 
        !           224:        return ret;
        !           225: }
        !           226: 
        !           227: /*
        !           228:  * rpc_srv_recvBLOB() Receive BLOB from client
        !           229:  * @cli = Client instance
        !           230:  * @blob = Mapped BLOB element
        !           231:  * return: -1 error, 0 ok, >0 unreceived data from client, may be error?
        !           232:  */
        !           233: int
        !           234: rpc_srv_recvBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob)
        !           235: {
        !           236:        int ret, len;
        !           237:        uint8_t *pos;
        !           238:        fd_set fds;
        !           239:        struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
        !           240: 
        !           241:        if (!cli || !blob || !blob->blob_data) {
        !           242:                rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
        !           243:                return -1;
        !           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:                }
        !           254: 
        !           255:                if ((len = recv(cli->cli_sock, pos, BLOBSIZ, 0)) == -1) {
        !           256:                        LOGERR;
        !           257:                        return -1;
        !           258:                }
        !           259:        }
        !           260: 
        !           261:        return ret;
        !           262: }
        !           263: 
        !           264: // ------------------------------------------------------------
        !           265: 
        !           266: /*
        !           267:  * rpc_cli_sendBLOB() Send BLOB to server
        !           268:  * @cli = Client instance
        !           269:  * @var = BLOB variable
        !           270:  * @data = BLOB data
        !           271:  * return: -1 error, 0 ok, 1 remote error
        !           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;
        !           278:        struct tagBLOBHdr hdr;
        !           279:        fd_set fds;
        !           280:        struct timeval tv = { DEF_RPC_TIMEOUT, 0 };
        !           281: 
        !           282:        if (!cli || !var || !data) {
        !           283:                rpc_SetErr(EINVAL, "Error:: invalid arguments ...\n");
        !           284:                return -1;
        !           285:        }
        !           286: 
        !           287:        memcpy(&hdr.hdr_session, cli->cli_parent, sizeof(rpc_sess_t));
        !           288:        hdr.hdr_cmd = set;
        !           289:        hdr.hdr_var = 0;
        !           290:        hdr.hdr_ret = 0;
        !           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: 
        !           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: 
        !           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:        }
        !           313:        if (recv(cli->cli_sock, &hdr, sizeof hdr, 0) == -1) {
        !           314:                LOGERR;
        !           315:                return -1;
        !           316:        }
        !           317:        if (hdr.hdr_cmd != error) {
        !           318:                if (hdr.hdr_len != var->val_len) {
        !           319:                        rpc_SetErr(ECANCELED, "Error:: Bad return length packet ...\n");
        !           320:                        return -1;
        !           321:                }
        !           322: 
        !           323:                var->val.blob = hdr.hdr_var;
        !           324:        }
        !           325: 
        !           326:        return hdr.hdr_cmd == error;
        !           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!
        !           334:  * return: -1 error, 0 ok, 1 remote error
        !           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 };
        !           343:        struct tagBLOBHdr hdr;
        !           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: 
        !           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);
        !           360:        hdr.hdr_ret = 0;
        !           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: 
        !           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: 
        !           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) {
        !           410:                        rpc_SetErr(ECANCELED, "Error:: Bad return length packet ...\n");
        !           411:                        free(*data);
        !           412:                        *data = NULL;
        !           413:                        return -1;
        !           414:                }
        !           415:        }
        !           416: 
        !           417:        return hdr.hdr_cmd == error;
        !           418: }
        !           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>