Annotation of libaitrpc/src/lists.c, revision 1.3

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.3     ! misho       6: * $Id: lists.c,v 1.2.2.1 2011/07/14 01:31:00 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_retValsCall() Declare return variables for RPC call and zeroed values
                     51:                                        (for safe handling return values, use this!)
                     52:  * @call = RPC function call
                     53:  * @return_vals = Number of return variables
                     54:  * return: NULL error, !=NULL array with return values for RPC call with return_vals items
                     55:  */
                     56: inline rpc_val_t *
                     57: rpc_srv_retValsCall(rpc_func_t * __restrict call, int return_vals)
                     58: {
                     59:        rpc_val_t *v = NULL;
                     60: 
                     61:        if (rpc_srv_declValsCall(call, return_vals) == -1)
                     62:                return NULL;
                     63:        else
                     64:                rpc_srv_zeroValsCall(call);
                     65:        if (rpc_srv_getValsCall(call, &v) == -1)
                     66:                return NULL;
                     67: 
                     68:        return v;
                     69: }
                     70: 
                     71: /*
                     72:  * rpc_srv_freeValsCall() Free return variables for RPC call
                     73:  * @call = RPC function call
                     74:  * return: none
                     75:  */
                     76: inline void
                     77: rpc_srv_freeValsCall(rpc_func_t * __restrict call)
                     78: {
                     79:        rpc_srv_declValsCall(call, 0);
                     80: }
                     81: 
                     82: /*
                     83:  * rpc_srv_declValsCall() Declare return variables for RPC call, 
                     84:                                if already allocated memory for RPC call return values 
                     85:                                function reallocate used space with return_vals count elements
                     86:  * @call = RPC function call
                     87:  * @return_vals = Number of return variables
                     88:  * return: -1 error, !=-1 ok
                     89:  */
                     90: inline int
                     91: rpc_srv_declValsCall(rpc_func_t * __restrict call, int return_vals)
                     92: {
                     93:        void *ptr;
                     94: 
                     95:        if (!call || return_vals < 0) {
                     96:                rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t declare return variables for RPC call...\n");
                     97:                return -1;
                     98:        } else
                     99:                call->func_args = return_vals;
                    100: 
                    101:        if (!return_vals) {
                    102:                if (call->func_vals) {
                    103:                        free(call->func_vals);
                    104:                        call->func_vals = NULL;
                    105:                }
                    106:        } else {
                    107:                ptr = realloc(call->func_vals, return_vals * sizeof(rpc_val_t));
                    108:                if (!ptr) {
                    109:                        LOGERR;
                    110:                        call->func_args = 0;
                    111:                        return -1;
                    112:                } else
                    113:                        call->func_vals = ptr;
                    114:        }
                    115: 
                    116:        return return_vals;
                    117: }
                    118: 
                    119: /*
                    120:  * rpc_srv_zeroValsCall() Clean values from return variables of RPC call
                    121:  * @call = RPC function call
                    122:  * return: -1 error, !=-1 Returned number of cleaned RPC variables
                    123:  */
                    124: inline int
                    125: rpc_srv_zeroValsCall(rpc_func_t * __restrict call)
                    126: {
                    127:        if (!call) {
                    128:                rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t delete return variables ...\n");
                    129:                return -1;
                    130:        }
                    131: 
                    132:        memset(call->func_vals, 0, call->func_args * sizeof(rpc_val_t));
                    133:        return call->func_args;
                    134: }
                    135: 
                    136: /*
                    137:  * rpc_srv_copyValsCall() Copy return variables for RPC call to new variable
                    138:  * @call = RPC function call
                    139:  * @newvals = New allocated variables array, must be free after use
                    140:  * return: -1 error, !=-1 Returned number of copied RPC variables
                    141:  */
                    142: inline int
                    143: rpc_srv_copyValsCall(rpc_func_t * __restrict call, rpc_val_t ** __restrict newvals)
                    144: {
                    145:        if (!call || !newvals) {
                    146:                rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t copy return variables to new array\n");
                    147:                return -1;
                    148:        }
                    149: 
                    150:        *newvals = calloc(call->func_args, sizeof(rpc_val_t));
                    151:        if (!*newvals) {
                    152:                LOGERR;
                    153:                return -1;
                    154:        } else
                    155:                memcpy(*newvals, call->func_vals, call->func_args * sizeof(rpc_val_t));
                    156: 
                    157:        return call->func_args;
                    158: }
                    159: 
                    160: /*
                    161:  * rpc_srv_getValsCall() Get return variables for RPC call
                    162:  * @call = RPC function call
                    163:  * @vals = Returned variables, may be NULL
                    164:  * return: -1 error, !=-1 Number of returned variables
                    165:  */
                    166: inline int
                    167: rpc_srv_getValsCall(rpc_func_t * __restrict call, rpc_val_t ** __restrict vals)
                    168: {
                    169:        if (!call) {
                    170:                rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t get return variables ...\n");
                    171:                return -1;
                    172:        }
                    173: 
                    174:        if (vals)
                    175:                *vals = call->func_vals;
                    176:        return call->func_args;
                    177: }
                    178: 
                    179: // ---------------------------------------------------------
                    180: 
                    181: /*
                    182:  * rpc_srv_registerCall() Register call to RPC server
                    183:  * @srv = RPC Server instance
                    184:  * @csModule = Module name, if NULL self binary
                    185:  * @csFunc = Function name
                    186:  * @args = Number of return function arguments, use for restriction case!
                    187:  * return: -1 error or 0 register ok
                    188:  */
                    189: int
                    190: rpc_srv_registerCall(rpc_srv_t * __restrict srv, const char *csModule, const char *csFunc, u_char args)
                    191: {
                    192:        rpc_func_t *func;
                    193:        u_char str[MAXPATHLEN + UCHAR_MAX + 1];
                    194: 
                    195:        memset(str, 0, MAXPATHLEN + UCHAR_MAX + 1);
                    196:        if (!srv || !csFunc) {
                    197:                rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t register function to RPC server ...\n");
                    198:                return -1;
                    199:        }
                    200:        if (!(func = malloc(sizeof(rpc_func_t)))) {
                    201:                LOGERR;
                    202:                return -1;
                    203:        } else {
                    204:                memset(func, 0, sizeof(rpc_func_t));
                    205:                strlcpy((char*) func->func_name, csFunc, UCHAR_MAX + 1);
                    206:        }
                    207:        if (csModule) {
                    208:                strlcpy((char*) func->func_file, csModule, MAXPATHLEN);
                    209:                strlcpy((char*) str, csModule, MAXPATHLEN + UCHAR_MAX + 1);
                    210:        }
                    211:        strlcat((char*) str, "__", MAXPATHLEN + UCHAR_MAX + 1);
                    212:        strlcat((char*) str, csFunc, MAXPATHLEN + UCHAR_MAX + 1);
                    213: 
                    214:        func->func_tag = crcFletcher16((u_short*) str, (MAXPATHLEN + UCHAR_MAX + 1) / 2);
                    215:        func->func_hash = hash_fnv((char*) str, MAXPATHLEN + UCHAR_MAX + 1);
                    216: 
                    217:        func->func_parent = srv;
                    218: 
                    219:        if (args > 0 && rpc_srv_declValsCall(func, args) == -1) {
                    220:                free(func);
                    221:                return -1;
                    222:        }
                    223: 
                    224:        pthread_mutex_lock(&srv->srv_mtx);
                    225:        func->func_next = srv->srv_funcs;
                    226:        srv->srv_funcs = func;
                    227:        pthread_mutex_unlock(&srv->srv_mtx);
                    228:        return 0;
                    229: }
                    230: 
                    231: /*
                    232:  * rpc_srv_unregisterCall() Unregister call from RPC server
                    233:  * @srv = RPC Server instance
                    234:  * @csModule = Module name, if NULL self binary
                    235:  * @csFunc = Function name
                    236:  * return: -1 error, 0 not found call, 1 unregister ok
                    237:  */
                    238: int
                    239: rpc_srv_unregisterCall(rpc_srv_t * __restrict srv, const char *csModule, const char *csFunc)
                    240: {
                    241:        rpc_func_t func, *f, *curr;
                    242:        u_char str[MAXPATHLEN + UCHAR_MAX + 1];
                    243: 
                    244:        memset(&func, 0, sizeof(rpc_func_t));
                    245:        memset(str, 0, MAXPATHLEN + UCHAR_MAX + 1);
                    246:        if (!srv || !csFunc) {
                    247:                rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t unregister function from RPC server ...\n");
                    248:                return -1;
                    249:        } else
                    250:                strlcpy((char*) func.func_name, csFunc, UCHAR_MAX + 1);
                    251:        if (csModule) {
                    252:                strlcpy((char*) func.func_file, csModule, MAXPATHLEN);
                    253:                strlcpy((char*) str, csModule, MAXPATHLEN + UCHAR_MAX + 1);
                    254:        }
                    255:        strlcat((char*) str, "__", MAXPATHLEN + UCHAR_MAX + 1);
                    256:        strlcat((char*) str, csFunc, MAXPATHLEN + UCHAR_MAX + 1);
                    257: 
                    258:        func.func_tag = crcFletcher16((u_short*) str, (MAXPATHLEN + UCHAR_MAX + 1) / 2);
                    259:        func.func_hash = hash_fnv((char*) str, MAXPATHLEN + UCHAR_MAX + 1);
                    260: 
                    261:        f = rpc_srv_getCall(srv, func.func_tag, func.func_hash);
1.3     ! misho     262:        if (!f)                         /* not found element for unregister */
1.2       misho     263:                return 0;
                    264: 
                    265:        pthread_mutex_lock(&srv->srv_mtx);
1.3     ! misho     266:        if (srv->srv_funcs == f) {      /* if is 1st element */
1.2       misho     267:                srv->srv_funcs = srv->srv_funcs->func_next;
                    268: 
                    269:                if (f->func_args && f->func_vals)
                    270:                        free(f->func_vals);
                    271:                free(f);
                    272:        } else {
                    273:                for (curr = srv->srv_funcs; curr->func_next != f; curr = curr->func_next);
                    274:                curr->func_next = curr->func_next->func_next;
                    275: 
                    276:                if (f->func_args && f->func_vals)
                    277:                        free(f->func_vals);
                    278:                free(f);
                    279:        }
                    280:        pthread_mutex_unlock(&srv->srv_mtx);
                    281: 
                    282:        return 1;
                    283: }
                    284: 
                    285: /*
                    286:  * rpc_srv_getCall() Get registered call from RPC server
                    287:  * @srv = RPC Server instance
                    288:  * @tag = tag for function
                    289:  * @hash = hash for function
                    290:  * return: NULL not found call, !=NULL return call
                    291:  */
                    292: inline rpc_func_t *
                    293: rpc_srv_getCall(rpc_srv_t * __restrict srv, uint16_t tag, uint32_t hash)
                    294: {
                    295:        rpc_func_t *f;
                    296: 
                    297:        if (!srv) {
                    298:                rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t get function from RPC server ...\n");
                    299:                return NULL;
                    300:        }
                    301: 
                    302:        for (f = srv->srv_funcs; f; f = f->func_next)
                    303:                if (f->func_tag == tag && f->func_hash == hash)
                    304:                        break;
                    305: 
                    306:        return f;
                    307: }
                    308: 
                    309: /*
                    310:  * rpc_srv_getFunc() Get registered call from RPC server by Name
                    311:  * @srv = RPC Server instance
                    312:  * @csModule = Module name, if NULL self binary
                    313:  * @csFunc = Function name
                    314:  * return: NULL not found call, !=NULL return call
                    315:  */
                    316: rpc_func_t *
                    317: rpc_srv_getFunc(rpc_srv_t * __restrict srv, const char *csModule, const char *csFunc)
                    318: {
                    319:        rpc_func_t func;
                    320:        u_char str[MAXPATHLEN + UCHAR_MAX + 1];
                    321: 
                    322:        memset(&func, 0, sizeof(rpc_func_t));
                    323:        memset(str, 0, MAXPATHLEN + UCHAR_MAX + 1);
                    324:        if (!srv || !csFunc) {
                    325:                rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t get function from RPC server ...\n");
                    326:                return NULL;
                    327:        } else
                    328:                strlcpy((char*) func.func_name, csFunc, UCHAR_MAX + 1);
                    329:        if (csModule) {
                    330:                strlcpy((char*) func.func_file, csModule, MAXPATHLEN);
                    331:                strlcpy((char*) str, csModule, MAXPATHLEN + UCHAR_MAX + 1);
                    332:        }
                    333:        strlcat((char*) str, "__", MAXPATHLEN + UCHAR_MAX + 1);
                    334:        strlcat((char*) str, csFunc, MAXPATHLEN + UCHAR_MAX + 1);
                    335: 
                    336:        func.func_tag = crcFletcher16((u_short*) str, (MAXPATHLEN + UCHAR_MAX + 1) / 2);
                    337:        func.func_hash = hash_fnv((char*) str, MAXPATHLEN + UCHAR_MAX + 1);
                    338: 
                    339:        return rpc_srv_getCall(srv, func.func_tag, func.func_hash);
                    340: }
                    341: 
                    342: // ---------------------------------------------------------
                    343: 
                    344: /*
                    345:  * rpc_srv_getBLOB() Get registered BLOB 
                    346:  * @srv = RPC Server instance
                    347:  * @var = hash for variable
                    348:  * return: NULL not found, !=NULL return blob var
                    349:  */
                    350: inline rpc_blob_t *
                    351: rpc_srv_getBLOB(rpc_srv_t * __restrict srv, uint32_t var)
                    352: {
                    353:        rpc_blob_t *b;
                    354: 
                    355:        if (!srv) {
                    356:                rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t get variable from BLOB server ...\n");
                    357:                return NULL;
                    358:        }
                    359: 
                    360:        pthread_mutex_lock(&srv->srv_blob.mtx);
                    361:        for (b = srv->srv_blob.blobs; b; b = b->blob_next) {
                    362:                if (b->blob_var == var)
                    363:                        break;
                    364:        }
                    365:        pthread_mutex_unlock(&srv->srv_blob.mtx);
                    366: 
                    367:        return b;
                    368: }
                    369: 
                    370: /*
                    371:  * rpc_srv_registerBLOB() Register new BLOB to server
                    372:  * @srv = RPC Server instance
                    373:  * @len = BLOB length
                    374:  * return: NULL error or new registered BLOB
                    375:  */
                    376: rpc_blob_t *
                    377: rpc_srv_registerBLOB(rpc_srv_t * __restrict srv, size_t len)
                    378: {
                    379:        rpc_blob_t *blob = NULL;
                    380: 
                    381:        if (!srv || !len) {
                    382:                rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t register BLOB to server ...\n");
                    383:                return blob;
                    384:        }
                    385: 
                    386:        blob = rpc_srv_blobCreate(srv, len);
                    387:        if (blob) {
                    388:                pthread_mutex_lock(&srv->srv_blob.mtx);
                    389:                blob->blob_next = srv->srv_blob.blobs;
                    390:                srv->srv_blob.blobs = blob;
                    391:                pthread_mutex_unlock(&srv->srv_blob.mtx);
                    392:        }
                    393: 
                    394:        return blob;
                    395: }
                    396: 
                    397: /*
                    398:  * rpc_srv_unregisterBLOB() Unregister BLOB from server
                    399:  * @srv = RPC Server instance
                    400:  * @var = BLOB Variable for unregister
                    401:  * return: -1 error, 0 not found call, 1 unregister ok
                    402:  */
                    403: int
                    404: rpc_srv_unregisterBLOB(rpc_srv_t * __restrict srv, uint32_t var)
                    405: {
                    406:        rpc_blob_t *b, *curr;
                    407: 
                    408:        if (!srv) {
                    409:                rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t unregister BLOB from server ...\n");
                    410:                return -1;
                    411:        }
                    412: 
                    413:        b = rpc_srv_getBLOB(srv, var);
1.3     ! misho     414:        if (!b)                         /* not found element for unregister */
1.2       misho     415:                return 0;
                    416: 
                    417:        pthread_mutex_lock(&srv->srv_blob.mtx);
1.3     ! misho     418:        if (srv->srv_blob.blobs == b) { /* if is 1st element */
1.2       misho     419:                srv->srv_blob.blobs = srv->srv_blob.blobs->blob_next;
                    420:        } else {
                    421:                for (curr = srv->srv_blob.blobs; curr->blob_next != b; curr = curr->blob_next);
                    422:                curr->blob_next = curr->blob_next->blob_next;
                    423:        }
                    424:        rpc_srv_blobFree(srv, b);
                    425:        free(b);
                    426:        pthread_mutex_unlock(&srv->srv_blob.mtx);
                    427: 
                    428:        return 1;
                    429: }

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