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