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

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.17    ! misho       6: * $Id: blob.c,v 1.16.4.1 2015/07/02 17:52:53 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: 
1.16      misho      15: Copyright 2004 - 2015
1.2       misho      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: 
1.14      misho      49: static void *
                     50: toutBLOB(sched_task_t *task)
                     51: {
                     52:        rpc_srv_unregisterBLOB(TASK_DATA(task), ((rpc_blob_t*) TASK_ARG(task))->blob_var);
                     53: 
                     54:        return NULL;
                     55: }
                     56: 
                     57: 
1.2       misho      58: /*
1.8       misho      59:  * rpc_srv_blobCreate() - Create and map blob to memory region and return object
1.5       misho      60:  *
1.2       misho      61:  * @srv = RPC Server instance
                     62:  * @len = BLOB length object
1.14      misho      63:  * @tout = BLOB live timeout in seconds
1.2       misho      64:  * return: NULL error or !=NULL allocated BLOB object
                     65:  */
1.13      misho      66: rpc_blob_t *
1.14      misho      67: rpc_srv_blobCreate(rpc_srv_t * __restrict srv, int len, int tout)
1.2       misho      68: {
                     69:        rpc_blob_t *blob = NULL;
                     70:        char szFName[MAXPATHLEN];
                     71:        int f;
                     72:        u_int rnd;
1.17    ! misho      73:        struct timespec ts = { tout ? tout : DEF_RPC_BLOB_TIMEOUT, 0 };
1.2       misho      74: 
                     75: again:
                     76:        rnd = random() % UINT_MAX;
                     77: 
1.3       misho      78:        memset(szFName, 0, sizeof szFName);
1.10      misho      79:        snprintf(szFName, sizeof szFName, BLOB_FILE, AIT_GET_STRZ(&srv->srv_blob.dir), rnd);
1.2       misho      80:        f = open(szFName, O_CREAT | O_EXCL | O_RDWR, 0600);
                     81:        if (f == -1) {
                     82:                if (errno == EEXIST)
                     83:                        goto again;
                     84: 
                     85:                LOGERR;
                     86:                return NULL;
                     87:        }
1.8       misho      88:        if (ftruncate(f, len) == -1) {
1.2       misho      89:                LOGERR;
                     90:                close(f);
                     91:                unlink(szFName);
                     92:                return NULL;
1.8       misho      93:        }
1.2       misho      94: 
1.11      misho      95:        blob = e_malloc(sizeof(rpc_blob_t));
1.2       misho      96:        if (!blob) {
                     97:                LOGERR;
                     98:                close(f);
                     99:                unlink(szFName);
                    100:                return NULL;
                    101:        }
                    102: 
                    103:        blob->blob_data = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);
                    104:        if (blob->blob_data == MAP_FAILED) {
                    105:                LOGERR;
1.11      misho     106:                e_free(blob);
1.2       misho     107:                close(f);
                    108:                unlink(szFName);
                    109:                return NULL;
1.17    ! misho     110:        } else {
1.2       misho     111:                close(f);
                    112: 
1.17    ! misho     113:                madvise(blob->blob_data, len, MADV_SEQUENTIAL);
        !           114:        }
        !           115: 
1.2       misho     116:        blob->blob_len = len;
                    117:        blob->blob_var = rnd;
1.14      misho     118: 
                    119:        schedTimer(srv->srv_blob.root, toutBLOB, blob, ts, srv, 0);
1.2       misho     120:        return blob;
                    121: }
                    122: 
                    123: /*
1.5       misho     124:  * rpc_srv_blobMap() - Map blob to memory region 
                    125:  *
1.2       misho     126:  * @srv = RPC Server instance
                    127:  * @blob = Map to this BLOB element
                    128:  * return: -1 error or 0 ok
                    129:  */
1.13      misho     130: int
1.2       misho     131: rpc_srv_blobMap(rpc_srv_t * __restrict srv, rpc_blob_t * __restrict blob)
                    132: {
                    133:        int f;
                    134:        char szFName[MAXPATHLEN];
                    135: 
                    136:        if (!blob) {
1.5       misho     137:                rpc_SetErr(EINVAL, "Invalid argument BLOB");
1.2       misho     138:                return -1;
                    139:        }
1.4       misho     140:        if (blob->blob_data) {
1.5       misho     141:                rpc_SetErr(EPERM, "Already mmapped object found!");
1.4       misho     142:                return -1;
                    143:        }
1.2       misho     144: 
1.3       misho     145:        memset(szFName, 0, sizeof szFName);
1.10      misho     146:        snprintf(szFName, sizeof szFName, BLOB_FILE, AIT_GET_STRZ(&srv->srv_blob.dir), blob->blob_var);
1.2       misho     147:        f = open(szFName, O_RDWR);
                    148:        if (f == -1) {
                    149:                LOGERR;
                    150:                return -1;
                    151:        }
                    152: 
                    153:        blob->blob_data = mmap(NULL, blob->blob_len, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);
                    154:        if (blob->blob_data == MAP_FAILED) {
                    155:                LOGERR;
                    156:                close(f);
                    157:                blob->blob_data = NULL;
                    158:                return -1;
                    159:        } else {
                    160:                close(f);
                    161: 
                    162:                madvise(blob->blob_data, blob->blob_len, MADV_SEQUENTIAL);
                    163:        }
                    164: 
                    165:        return 0;
                    166: }
                    167: 
                    168: /*
1.5       misho     169:  * rpc_srv_blobUnmap() - Unmap blob memory region 
                    170:  *
1.2       misho     171:  * @blob = Mapped BLOB element
                    172:  * return: none
                    173:  */
1.13      misho     174: void
1.2       misho     175: rpc_srv_blobUnmap(rpc_blob_t * __restrict blob)
                    176: {
1.8       misho     177:        if (blob && blob->blob_data) {
1.2       misho     178:                munmap(blob->blob_data, blob->blob_len);
                    179:                blob->blob_data = NULL;
                    180:        }
                    181: }
                    182: 
                    183: /*
1.5       misho     184:  * rpc_srv_blobFree() - Free blob from disk & memory
                    185:  *
1.2       misho     186:  * @srv = RPC Server instance
                    187:  * @blob = Mapped BLOB element
                    188:  * return: -1 error or 0 ok
                    189:  */
1.13      misho     190: int
1.2       misho     191: rpc_srv_blobFree(rpc_srv_t * __restrict srv, rpc_blob_t * __restrict blob)
                    192: {
                    193:        char szFName[MAXPATHLEN];
                    194: 
                    195:        if (!blob) {
1.5       misho     196:                rpc_SetErr(EINVAL, "Invalid argument BLOB");
1.2       misho     197:                return -1;
1.8       misho     198:        } else
1.2       misho     199:                rpc_srv_blobUnmap(blob);
                    200: 
1.14      misho     201:        schedCancelby(srv->srv_blob.root, taskTIMER, CRITERIA_ARG, blob, NULL);
                    202: 
1.3       misho     203:        memset(szFName, 0, sizeof szFName);
1.10      misho     204:        snprintf(szFName, sizeof szFName, BLOB_FILE, AIT_GET_STRZ(&srv->srv_blob.dir), blob->blob_var);
1.3       misho     205:        if (unlink(szFName) == -1) {
1.2       misho     206:                LOGERR;
                    207:                return -1;
                    208:        }
                    209: 
                    210:        return 0;
                    211: }
                    212: 
1.8       misho     213: /* ------------------------------------------------------------ */
1.2       misho     214: 
                    215: /*
1.5       misho     216:  * rpc_srv_sendBLOB() - Send mapped BLOB to client
                    217:  *
1.2       misho     218:  * @cli = Client instance
                    219:  * @blob = Mapped BLOB element
                    220:  * return: -1 error, 0 ok
                    221:  */
                    222: int
                    223: rpc_srv_sendBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob)
                    224: {
                    225:        int ret, len;
                    226:        uint8_t *pos;
                    227: 
                    228:        if (!cli || !blob || !blob->blob_data) {
1.5       misho     229:                rpc_SetErr(EINVAL, "Invalid arguments");
1.2       misho     230:                return -1;
                    231:        }
                    232: 
1.3       misho     233:        for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len) {
1.8       misho     234:                len = send(cli->cli_sock, pos, ret, MSG_NOSIGNAL);
1.3       misho     235:                if (len == -1) {
1.2       misho     236:                        LOGERR;
                    237:                        return -1;
                    238:                }
1.3       misho     239:        }
1.2       misho     240: 
                    241:        return ret;
                    242: }
                    243: 
                    244: /*
1.5       misho     245:  * rpc_srv_recvBLOB() - Receive BLOB from client
                    246:  *
1.2       misho     247:  * @cli = Client instance
                    248:  * @blob = Mapped BLOB element
                    249:  * return: -1 error, 0 ok, >0 unreceived data from client, may be error?
                    250:  */
                    251: int
                    252: rpc_srv_recvBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob)
                    253: {
                    254:        int ret, len;
                    255:        uint8_t *pos;
1.7       misho     256:        struct pollfd pfd;
1.2       misho     257: 
                    258:        if (!cli || !blob || !blob->blob_data) {
1.5       misho     259:                rpc_SetErr(EINVAL, "Invalid arguments");
1.2       misho     260:                return -1;
1.7       misho     261:        }
1.2       misho     262: 
1.7       misho     263:        pfd.fd = cli->cli_sock;
                    264:        pfd.events = POLLIN | POLLPRI;
1.2       misho     265:        for (ret = blob->blob_len, pos = blob->blob_data; ret > 0; ret -= len, pos += len) {
1.8       misho     266:                if ((len = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || 
1.7       misho     267:                                pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
1.8       misho     268:                        if (len)
                    269:                                LOGERR;
                    270:                        else
                    271:                                rpc_SetErr(ETIMEDOUT, "Timeout reached! Server not respond");
1.2       misho     272:                        return -1;
                    273:                }
                    274: 
1.3       misho     275:                len = recv(cli->cli_sock, pos, ret, 0);
                    276:                if (len == -1) {
1.2       misho     277:                        LOGERR;
                    278:                        return -1;
                    279:                }
                    280:        }
                    281: 
                    282:        return ret;
                    283: }

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