Annotation of libaitrpc/src/lists.c, revision 1.2.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.2.2.1 ! misho 6: * $Id: lists.c,v 1.2 2011/05/02 23:12:08 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.2.2.1 ! misho 262: if (!f) /* not found element for unregister */
1.2 misho 263: return 0;
264:
265: pthread_mutex_lock(&srv->srv_mtx);
1.2.2.1 ! 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.2.2.1 ! 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.2.2.1 ! 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>