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>