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