core: Changed WS from being a flag on a TCP/TLS connection to a protocol in its own...
[sip-router] / rpc_lookup.c
1 /* 
2  * $Id$
3  * 
4  * Copyright (C) 2009 iptelorg GmbH
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 /*
19  * SER RPC lookup and register functions
20  */
21 /*
22  * History:
23  * --------
24  *  2009-05-11  initial version (andrei)
25 */
26
27 /*!
28  * \file
29  * \brief SIP-router core :: 
30  * \ingroup core
31  * Module: \ref core
32  */
33
34 #include "rpc.h"
35 #include "str_hash.h"
36 #include "ut.h"
37 #include "dprint.h"
38
39 #define RPC_HASH_SIZE   32
40 #define RPC_SARRAY_SIZE 32 /* initial size */
41
42 #define RPC_COPY_EXPORT
43
44 static struct str_hash_table rpc_hash_table;
45
46 /* array of pointer to rpc exports, sorted after their name
47  *  (used by listMethods) */
48 rpc_export_t** rpc_sarray;
49 int rpc_sarray_crt_size; /* used */
50 static int rpc_sarray_max_size; /* number of entries alloc'ed */
51
52 /** init the rpc hash table.
53   * @return 0 on success, -1 on error
54   */
55 int init_rpcs(void)
56 {
57         if (str_hash_alloc(&rpc_hash_table, RPC_HASH_SIZE)<0)
58                 return -1;
59         str_hash_init(&rpc_hash_table);
60         rpc_sarray_max_size=RPC_SARRAY_SIZE;
61         rpc_sarray=pkg_malloc(sizeof(*rpc_sarray)* rpc_sarray_max_size);
62         rpc_sarray_crt_size=0;
63         return 0;
64 }
65
66
67
68 void destroy_rpcs(void)
69 {
70         int r;
71         struct str_hash_entry* e;
72         struct str_hash_entry* bak;
73         for (r=0; r<rpc_hash_table.size; r++){
74                 clist_foreach_safe(&rpc_hash_table.table[r], e, bak, next){
75                         pkg_free(e);
76                 }
77         }
78         if (rpc_hash_table.table) pkg_free(rpc_hash_table.table);
79         if (rpc_sarray) pkg_free(rpc_sarray);
80         rpc_hash_table.table=0;
81         rpc_hash_table.size=0;
82         rpc_sarray=0;
83         rpc_sarray_crt_size=0;
84         rpc_sarray_max_size=0;
85 }
86
87
88
89 /** adds a new rpc to the hash table (no checks).
90  * @return 0 on success, -1 on error, 1 on duplicate
91  */
92 static int rpc_hash_add(struct rpc_export* rpc)
93 {
94         struct str_hash_entry* e;
95         int name_len;
96         int doc0_len, doc1_len;
97         struct rpc_export* n_rpc;
98         struct rpc_export** r;
99         
100         name_len=strlen(rpc->name);
101         doc0_len=rpc->doc_str[0]?strlen(rpc->doc_str[0]):0;
102         doc1_len=rpc->doc_str[1]?strlen(rpc->doc_str[1]):0;
103         /* alloc everything into one block */
104         
105 #ifdef RPC_COPY_EXPORT
106         e=pkg_malloc(ROUND_POINTER(sizeof(struct str_hash_entry))
107                                                                 +ROUND_POINTER(sizeof(*rpc))+2*sizeof(char*)+
108                                                                 +name_len+1+doc0_len+(rpc->doc_str[0]!=0)
109                                                                 +doc1_len+(rpc->doc_str[1]!=0)
110                                                                 );
111 #else /* RPC_COPY_EXPORT */
112         e=pkg_malloc(ROUND_POINTER(sizeof(struct str_hash_entry)));
113 #endif /* RPC_COPY_EXPORT */
114         
115         if (e==0){
116                 ERR("out of memory\n");
117                 goto error;
118         }
119 #ifdef RPC_COPY_EXPORT
120         n_rpc=(rpc_export_t*)((char*)e+
121                         ROUND_POINTER(sizeof(struct str_hash_entry)));
122         /* copy rpc into n_rpc */
123         *n_rpc=*rpc;
124         n_rpc->doc_str=(const char**)((char*)n_rpc+ROUND_POINTER(sizeof(*rpc)));
125         n_rpc->name=(char*)n_rpc->doc_str+2*sizeof(char*);
126         memcpy((char*)n_rpc->name, rpc->name, name_len);
127         *((char*)&n_rpc->name[name_len])=0;
128         if (rpc->doc_str[0]){
129                 n_rpc->doc_str[0]=&n_rpc->name[name_len+1];
130                 memcpy((char*)n_rpc->doc_str[0], rpc->doc_str[0], doc0_len);
131                 *(char*)&(n_rpc->doc_str[0][doc0_len])=0;
132         }else{
133                 n_rpc->doc_str[0]=0;
134         }
135         if (rpc->doc_str[1]){
136                 n_rpc->doc_str[1]=n_rpc->doc_str[0]?&n_rpc->doc_str[0][doc0_len+1]:
137                                                         &n_rpc->name[name_len+1];;
138                 memcpy((char*)n_rpc->doc_str[1], rpc->doc_str[1], doc1_len);
139                 *(char*)&(n_rpc->doc_str[1][doc1_len])=0;
140         }else{
141                 n_rpc->doc_str[1]=0;
142         }
143 #else /* RPC_COPY_EXPORT */
144         n_rpc=rpc;
145 #endif /* RPC_COPY_EXPORT */
146         
147         e->key.s=(char*)n_rpc->name;
148         e->key.len=name_len;
149         e->flags=0;
150         e->u.p=n_rpc;
151         str_hash_add(&rpc_hash_table, e);
152         
153         /* insert it into the sorted array */
154         if (rpc_sarray_max_size<=rpc_sarray_crt_size){
155                 /* array must be increased */
156                 r=pkg_realloc(rpc_sarray, 2*rpc_sarray_max_size*sizeof(*rpc_sarray));
157                 if (r==0){
158                         ERR("out of memory while adding RPC to the sorted list\n");
159                         goto error;
160                 }
161                 rpc_sarray=r;
162                 rpc_sarray_max_size*=2;
163         };
164         /* insert into array, sorted */
165         for (r=rpc_sarray;r<(rpc_sarray+rpc_sarray_crt_size); r++){
166                 if (strcmp(n_rpc->name, (*r)->name)<0)
167                         break;
168         }
169         if (r!=(rpc_sarray+rpc_sarray_crt_size))
170                 memmove(r+1, r, (int)(long)((char*)(rpc_sarray+rpc_sarray_crt_size)-
171                                                                                         (char*)r));
172         rpc_sarray_crt_size++;
173         *r=n_rpc;
174         return 0;
175 error:
176         return -1;
177 }
178
179
180
181 /** lookup an rpc export after its name.
182  * @return pointer to rpc export on success, 0 on error
183  */
184 rpc_export_t* rpc_lookup(const char* name, int len)
185 {
186         struct str_hash_entry* e;
187         
188         e=str_hash_get(&rpc_hash_table, (char*)name, len);
189         return e?(rpc_export_t*)e->u.p:0;
190 }
191
192
193
194 /** register a new rpc.
195  * @return 0 on success, -1 on error, 1 on duplicate
196  */
197 int rpc_register(rpc_export_t* rpc)
198 {
199         
200         /* check if the entry is already registered */
201         if (rpc_lookup(rpc->name, strlen(rpc->name))){
202                 WARN("duplicate rpc \"%s\"\n", rpc->name);
203                 return 1;
204         }
205         if (rpc_hash_add(rpc)!=0) return -1;
206         return 0;
207 }
208
209
210
211 /** register all the rpc in a null-terminated array.
212   * @return 0 on success, >0 if duplicates were found (number of 
213   * duplicates), -1 on error
214   */
215 int rpc_register_array(rpc_export_t* rpc_array)
216 {
217         rpc_export_t* rpc;
218         int ret,i;
219         
220         ret=0;
221         for (rpc=rpc_array; rpc && rpc->name; rpc++){
222                 i=rpc_register(rpc);
223                 if (i!=0){
224                         if (i<0) goto error;
225                         ret++;
226                 }
227         }
228         return ret;
229 error:
230         return -1;
231 }
232
233
234 /* vi: set ts=4 sw=4 tw=79:ai:cindent: */