Annotation of libaitrpc/src/lists.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: lists.c,v 1.1.2.10 2011/05/02 23:07:55 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_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);
        !           262:        if (!f)         // not found element for unregister
        !           263:                return 0;
        !           264: 
        !           265:        pthread_mutex_lock(&srv->srv_mtx);
        !           266:        if (srv->srv_funcs == f) {      // if is 1st element
        !           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);
        !           414:        if (!b)         // not found element for unregister
        !           415:                return 0;
        !           416: 
        !           417:        pthread_mutex_lock(&srv->srv_blob.mtx);
        !           418:        if (srv->srv_blob.blobs == b) { // if is 1st element
        !           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>