dlist.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * $Id$
  3. *
  4. * List of registered domains
  5. *
  6. * Copyright (C) 2001-2003 FhG Fokus
  7. *
  8. * This file is part of ser, a free SIP server.
  9. *
  10. * ser is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version
  14. *
  15. * For a license to use the ser software under conditions
  16. * other than those described here, or to purchase support for this
  17. * software, please contact iptel.org by e-mail at the following addresses:
  18. * [email protected]
  19. *
  20. * ser is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, write to the Free Software
  27. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  28. */
  29. #include "dlist.h"
  30. #include <stdlib.h> /* abort */
  31. #include <string.h> /* strlen, memcmp */
  32. #include <stdio.h> /* printf */
  33. #include "../../ut.h"
  34. #include "../../mem/shm_mem.h"
  35. #include "../../dprint.h"
  36. #include "../../globals.h"
  37. #include "udomain.h" /* new_udomain, free_udomain */
  38. #include "utime.h"
  39. #include "ul_mod.h"
  40. /*
  41. * List of all registered domains
  42. */
  43. dlist_t* root = 0;
  44. /*
  45. * Find domain with the given name
  46. * Returns 0 if the domain was found
  47. * and 1 of not
  48. */
  49. static inline int find_dlist(str* _n, dlist_t** _d)
  50. {
  51. dlist_t* ptr;
  52. ptr = root;
  53. while(ptr) {
  54. if ((_n->len == ptr->name.len) &&
  55. !memcmp(_n->s, ptr->name.s, _n->len)) {
  56. *_d = ptr;
  57. return 0;
  58. }
  59. ptr = ptr->next;
  60. }
  61. return 1;
  62. }
  63. /*
  64. * Return list of all contacts for all currently registered
  65. * users in all domains. Caller must provide buffer of
  66. * sufficient length for fitting all those contacts. In the
  67. * case when buffer was exhausted, the function returns
  68. * estimated amount of additional space needed, in this
  69. * case the caller is expected to repeat the call using
  70. * this value as the hint.
  71. *
  72. * Information is packed into the buffer as follows:
  73. *
  74. * +------------+----------+-----+------------+----------+-----+
  75. * |contact1.len|contact1.s|sock1|contact2.len|contact2.s|sock2|
  76. * +------------+----------+-----+------------+----------+-----+
  77. * |.............................|contactN.len|contactN.s|sockN|
  78. * +------------+----------+-----+------------+----------+-----+
  79. * |000000000000|
  80. * +------------+
  81. */
  82. int get_all_ucontacts(void *buf, int len, unsigned int flags)
  83. {
  84. dlist_t *p;
  85. urecord_t *r;
  86. ucontact_t *c;
  87. void *cp;
  88. int shortage;
  89. cp = buf;
  90. shortage = 0;
  91. /* Reserve space for terminating 0000 */
  92. len -= sizeof(c->c.len);
  93. for (p = root; p != NULL; p = p->next) {
  94. lock_udomain(p->d);
  95. if (p->d->d_ll.n <= 0) {
  96. unlock_udomain(p->d);
  97. continue;
  98. }
  99. for (r = p->d->d_ll.first; r != NULL; r = r->d_ll.next) {
  100. for (c = r->contacts; c != NULL; c = c->next) {
  101. if (c->c.len <= 0)
  102. continue;
  103. /*
  104. * List only contacts that have all requested
  105. * flags set
  106. */
  107. if ((c->flags & flags) != flags)
  108. continue;
  109. /* List only contacts with matching server id */
  110. if (c->server_id != server_id)
  111. continue;
  112. if (c->received.s) {
  113. if (len >= (int)(sizeof(c->received.len) +
  114. c->received.len + sizeof(c->sock))) {
  115. memcpy(cp, &c->received.len, sizeof(c->received.len));
  116. cp = (char*)cp + sizeof(c->received.len);
  117. memcpy(cp, c->received.s, c->received.len);
  118. cp = (char*)cp + c->received.len;
  119. memcpy(cp, &c->sock, sizeof(c->sock));
  120. cp = (char*)cp + sizeof(c->sock);
  121. len -= sizeof(c->received.len) + c->received.len +
  122. sizeof(c->sock);
  123. } else {
  124. shortage += sizeof(c->received.len) +
  125. c->received.len + sizeof(c->sock);
  126. }
  127. } else {
  128. if (len >= (int)(sizeof(c->c.len) + c->c.len +
  129. sizeof(c->sock))) {
  130. memcpy(cp, &c->c.len, sizeof(c->c.len));
  131. cp = (char*)cp + sizeof(c->c.len);
  132. memcpy(cp, c->c.s, c->c.len);
  133. cp = (char*)cp + c->c.len;
  134. memcpy(cp, &c->sock, sizeof(c->sock));
  135. cp = (char*)cp + sizeof(c->sock);
  136. len -= sizeof(c->c.len) + c->c.len + sizeof(c->sock);
  137. } else {
  138. shortage += sizeof(c->c.len) + c->c.len +
  139. sizeof(c->sock);
  140. }
  141. }
  142. }
  143. }
  144. unlock_udomain(p->d);
  145. }
  146. /* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
  147. if (len >= 0)
  148. memset(cp, 0, sizeof(c->c.len));
  149. /* Shouldn't happen */
  150. if (shortage > 0 && len > shortage) {
  151. abort();
  152. }
  153. shortage -= len;
  154. return shortage > 0 ? shortage : 0;
  155. }
  156. /*
  157. * Create a new domain structure
  158. * Returns 0 if everything went OK, otherwise value < 0
  159. * is returned
  160. */
  161. static inline int new_dlist(str* _n, dlist_t** _d)
  162. {
  163. dlist_t* ptr;
  164. ptr = (dlist_t*)shm_malloc(sizeof(dlist_t));
  165. if (ptr == 0) {
  166. LOG(L_ERR, "new_dlist(): No memory left\n");
  167. return -1;
  168. }
  169. memset(ptr, 0, sizeof(dlist_t));
  170. ptr->name.s = (char*)shm_malloc(_n->len + 1);
  171. if (ptr->name.s == 0) {
  172. LOG(L_ERR, "new_dlist(): No memory left 2\n");
  173. shm_free(ptr);
  174. return -2;
  175. }
  176. memcpy(ptr->name.s, _n->s, _n->len);
  177. ptr->name.s[_n->len] = '\0';
  178. ptr->name.len = _n->len;
  179. if (new_udomain(&(ptr->name), &(ptr->d)) < 0) {
  180. LOG(L_ERR, "new_dlist(): Error while creating domain structure\n");
  181. shm_free(ptr->name.s);
  182. shm_free(ptr);
  183. return -3;
  184. }
  185. *_d = ptr;
  186. return 0;
  187. }
  188. /*
  189. * Function registers a new domain with usrloc
  190. * if the domain exists, pointer to existing structure
  191. * will be returned, otherwise a new domain will be
  192. * created
  193. */
  194. int register_udomain(const char* _n, udomain_t** _d)
  195. {
  196. dlist_t* d;
  197. str s;
  198. s.s = (char*)_n;
  199. s.len = strlen(_n);
  200. if (find_dlist(&s, &d) == 0) {
  201. *_d = d->d;
  202. return 0;
  203. }
  204. if (new_dlist(&s, &d) < 0) {
  205. LOG(L_ERR, "register_udomain(): Error while creating new domain\n");
  206. return -1;
  207. }
  208. /* Preload domain with data from database if we are gonna
  209. * to use database
  210. */
  211. if (db_mode != NO_DB) {
  212. db = db_ctx("usrloc");
  213. if (db == NULL) {
  214. ERR("Error while initializing database layer\n");
  215. goto err;
  216. }
  217. if (db_add_db(db, db_url.s) < 0) goto err;
  218. if (db_connect(db) < 0) goto err;
  219. if (preload_udomain(d->d) < 0) {
  220. LOG(L_ERR, "register_udomain(): Error while preloading domain '%.*s'\n",
  221. s.len, ZSW(s.s));
  222. goto err;
  223. }
  224. db_disconnect(db);
  225. db_ctx_free(db);
  226. db = NULL;
  227. }
  228. d->next = root;
  229. root = d;
  230. *_d = d->d;
  231. return 0;
  232. err:
  233. if (db) {
  234. db_disconnect(db);
  235. db_ctx_free(db);
  236. db = NULL;
  237. }
  238. free_udomain(d->d);
  239. shm_free(d->name.s);
  240. shm_free(d);
  241. return -1;
  242. }
  243. /*
  244. * Free all allocated memory
  245. */
  246. void free_all_udomains(void)
  247. {
  248. dlist_t* ptr;
  249. while(root) {
  250. ptr = root;
  251. root = root->next;
  252. free_udomain(ptr->d);
  253. shm_free(ptr->name.s);
  254. shm_free(ptr);
  255. }
  256. }
  257. /*
  258. * Just for debugging
  259. */
  260. void print_all_udomains(FILE* _f)
  261. {
  262. dlist_t* ptr;
  263. ptr = root;
  264. fprintf(_f, "===Domain list===\n");
  265. while(ptr) {
  266. print_udomain(_f, ptr->d);
  267. ptr = ptr->next;
  268. }
  269. fprintf(_f, "===/Domain list===\n");
  270. }
  271. /*
  272. * Run timer handler of all domains
  273. */
  274. int synchronize_all_udomains(void)
  275. {
  276. int res = 0;
  277. dlist_t* ptr;
  278. get_act_time(); /* Get and save actual time */
  279. ptr = root;
  280. while(ptr) {
  281. res |= timer_udomain(ptr->d);
  282. ptr = ptr->next;
  283. }
  284. return res;
  285. }
  286. /*
  287. * Find a particular domain
  288. */
  289. int find_domain(str* _d, udomain_t** _p)
  290. {
  291. dlist_t* d;
  292. if (find_dlist(_d, &d) == 0) {
  293. *_p = d->d;
  294. return 0;
  295. }
  296. return 1;
  297. }