rpc_lookup.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. * \file
  28. * \brief SIP-router core ::
  29. * \ingroup core
  30. * Module: \ref core
  31. */
  32. #include "rpc.h"
  33. #include "str_hash.h"
  34. #include "ut.h"
  35. #include "dprint.h"
  36. #define RPC_HASH_SIZE 32
  37. #define RPC_SARRAY_SIZE 32 /* initial size */
  38. #define RPC_COPY_EXPORT
  39. static struct str_hash_table rpc_hash_table;
  40. /* array of pointer to rpc exports, sorted after their name
  41. * (used by listMethods) */
  42. rpc_export_t** rpc_sarray;
  43. int rpc_sarray_crt_size; /* used */
  44. static int rpc_sarray_max_size; /* number of entries alloc'ed */
  45. /** init the rpc hash table.
  46. * @return 0 on success, -1 on error
  47. */
  48. int init_rpcs(void)
  49. {
  50. if (str_hash_alloc(&rpc_hash_table, RPC_HASH_SIZE)<0)
  51. return -1;
  52. str_hash_init(&rpc_hash_table);
  53. rpc_sarray_max_size=RPC_SARRAY_SIZE;
  54. rpc_sarray=pkg_malloc(sizeof(*rpc_sarray)* rpc_sarray_max_size);
  55. rpc_sarray_crt_size=0;
  56. return 0;
  57. }
  58. void destroy_rpcs(void)
  59. {
  60. int r;
  61. struct str_hash_entry* e;
  62. struct str_hash_entry* bak;
  63. for (r=0; r<rpc_hash_table.size; r++){
  64. clist_foreach_safe(&rpc_hash_table.table[r], e, bak, next){
  65. pkg_free(e);
  66. }
  67. }
  68. if (rpc_hash_table.table) pkg_free(rpc_hash_table.table);
  69. if (rpc_sarray) pkg_free(rpc_sarray);
  70. rpc_hash_table.table=0;
  71. rpc_hash_table.size=0;
  72. rpc_sarray=0;
  73. rpc_sarray_crt_size=0;
  74. rpc_sarray_max_size=0;
  75. }
  76. /** adds a new rpc to the hash table (no checks).
  77. * @return 0 on success, -1 on error, 1 on duplicate
  78. */
  79. static int rpc_hash_add(struct rpc_export* rpc)
  80. {
  81. struct str_hash_entry* e;
  82. int name_len;
  83. int doc0_len, doc1_len;
  84. struct rpc_export* n_rpc;
  85. struct rpc_export** r;
  86. name_len=strlen(rpc->name);
  87. doc0_len=rpc->doc_str[0]?strlen(rpc->doc_str[0]):0;
  88. doc1_len=rpc->doc_str[1]?strlen(rpc->doc_str[1]):0;
  89. /* alloc everything into one block */
  90. #ifdef RPC_COPY_EXPORT
  91. e=pkg_malloc(ROUND_POINTER(sizeof(struct str_hash_entry))
  92. +ROUND_POINTER(sizeof(*rpc))+2*sizeof(char*)+
  93. +name_len+1+doc0_len+(rpc->doc_str[0]!=0)
  94. +doc1_len+(rpc->doc_str[1]!=0)
  95. );
  96. #else /* RPC_COPY_EXPORT */
  97. e=pkg_malloc(ROUND_POINTER(sizeof(struct str_hash_entry)));
  98. #endif /* RPC_COPY_EXPORT */
  99. if (e==0){
  100. ERR("out of memory\n");
  101. goto error;
  102. }
  103. #ifdef RPC_COPY_EXPORT
  104. n_rpc=(rpc_export_t*)((char*)e+
  105. ROUND_POINTER(sizeof(struct str_hash_entry)));
  106. /* copy rpc into n_rpc */
  107. *n_rpc=*rpc;
  108. n_rpc->doc_str=(const char**)((char*)n_rpc+ROUND_POINTER(sizeof(*rpc)));
  109. n_rpc->name=(char*)n_rpc->doc_str+2*sizeof(char*);
  110. memcpy((char*)n_rpc->name, rpc->name, name_len);
  111. *((char*)&n_rpc->name[name_len])=0;
  112. if (rpc->doc_str[0]){
  113. n_rpc->doc_str[0]=&n_rpc->name[name_len+1];
  114. memcpy((char*)n_rpc->doc_str[0], rpc->doc_str[0], doc0_len);
  115. *(char*)&(n_rpc->doc_str[0][doc0_len])=0;
  116. }else{
  117. n_rpc->doc_str[0]=0;
  118. }
  119. if (rpc->doc_str[1]){
  120. n_rpc->doc_str[1]=n_rpc->doc_str[0]?&n_rpc->doc_str[0][doc0_len+1]:
  121. &n_rpc->name[name_len+1];;
  122. memcpy((char*)n_rpc->doc_str[1], rpc->doc_str[1], doc1_len);
  123. *(char*)&(n_rpc->doc_str[1][doc1_len])=0;
  124. }else{
  125. n_rpc->doc_str[1]=0;
  126. }
  127. #else /* RPC_COPY_EXPORT */
  128. n_rpc=rpc;
  129. #endif /* RPC_COPY_EXPORT */
  130. e->key.s=(char*)n_rpc->name;
  131. e->key.len=name_len;
  132. e->flags=0;
  133. e->u.p=n_rpc;
  134. str_hash_add(&rpc_hash_table, e);
  135. /* insert it into the sorted array */
  136. if (rpc_sarray_max_size<=rpc_sarray_crt_size){
  137. /* array must be increased */
  138. r=pkg_realloc(rpc_sarray, 2*rpc_sarray_max_size*sizeof(*rpc_sarray));
  139. if (r==0){
  140. ERR("out of memory while adding RPC to the sorted list\n");
  141. goto error;
  142. }
  143. rpc_sarray=r;
  144. rpc_sarray_max_size*=2;
  145. };
  146. /* insert into array, sorted */
  147. for (r=rpc_sarray;r<(rpc_sarray+rpc_sarray_crt_size); r++){
  148. if (strcmp(n_rpc->name, (*r)->name)<0)
  149. break;
  150. }
  151. if (r!=(rpc_sarray+rpc_sarray_crt_size))
  152. memmove(r+1, r, (int)(long)((char*)(rpc_sarray+rpc_sarray_crt_size)-
  153. (char*)r));
  154. rpc_sarray_crt_size++;
  155. *r=n_rpc;
  156. return 0;
  157. error:
  158. return -1;
  159. }
  160. /** lookup an rpc export after its name.
  161. * @return pointer to rpc export on success, 0 on error
  162. */
  163. rpc_export_t* rpc_lookup(const char* name, int len)
  164. {
  165. struct str_hash_entry* e;
  166. e=str_hash_get(&rpc_hash_table, (char*)name, len);
  167. return e?(rpc_export_t*)e->u.p:0;
  168. }
  169. /** register a new rpc.
  170. * @return 0 on success, -1 on error, 1 on duplicate
  171. */
  172. int rpc_register(rpc_export_t* rpc)
  173. {
  174. /* check if the entry is already registered */
  175. if (rpc_lookup(rpc->name, strlen(rpc->name))){
  176. WARN("duplicate rpc \"%s\"\n", rpc->name);
  177. return 1;
  178. }
  179. if (rpc_hash_add(rpc)!=0) return -1;
  180. return 0;
  181. }
  182. /** register all the rpc in a null-terminated array.
  183. * @return 0 on success, >0 if duplicates were found (number of
  184. * duplicates), -1 on error
  185. */
  186. int rpc_register_array(rpc_export_t* rpc_array)
  187. {
  188. rpc_export_t* rpc;
  189. int ret,i;
  190. ret=0;
  191. for (rpc=rpc_array; rpc && rpc->name; rpc++){
  192. i=rpc_register(rpc);
  193. if (i!=0){
  194. if (i<0) goto error;
  195. ret++;
  196. }
  197. }
  198. return ret;
  199. error:
  200. return -1;
  201. }
  202. /* vi: set ts=4 sw=4 tw=79:ai:cindent: */