imc_mng.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /*
  2. * $Id$
  3. *
  4. * imc module - instant messaging conferencing implementation
  5. *
  6. * Copyright (C) 2006 Voice Sistem S.R.L.
  7. *
  8. * This file is part of Kamailio, a free SIP server.
  9. *
  10. * Kamailio 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. * Kamailio is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * History:
  25. * ---------
  26. * 2006-10-06 first version (anca)
  27. */
  28. #include <string.h>
  29. #include <unistd.h>
  30. #include <stdio.h>
  31. #include "../../mem/mem.h"
  32. #include "../../mem/shm_mem.h"
  33. #include "../../dprint.h"
  34. #include "../../hashes.h"
  35. #include "imc_mng.h"
  36. /* imc hash table */
  37. extern imc_hentry_p _imc_htable;
  38. extern int imc_hash_size;
  39. extern char imc_cmd_start_char;
  40. #define imc_get_hentry(_hid, _size) ((_hid)&(_size-1))
  41. /**
  42. * hash thable init
  43. */
  44. int imc_htable_init(void)
  45. {
  46. int i;
  47. if(imc_hash_size<=0)
  48. {
  49. LM_ERR("invalid hash table size\n");
  50. return -1;
  51. }
  52. _imc_htable = (imc_hentry_p)shm_malloc(imc_hash_size*sizeof(imc_hentry_t));
  53. if(_imc_htable == NULL)
  54. {
  55. LM_ERR("no more shm memory\n");
  56. return -1;
  57. }
  58. memset(_imc_htable, 0, imc_hash_size*sizeof(imc_hentry_t));
  59. for(i=0; i<imc_hash_size; i++)
  60. {
  61. if (lock_init(&_imc_htable[i].lock)==0)
  62. {
  63. LM_CRIT("failed to initialize lock [%d]\n", i);
  64. goto error;
  65. }
  66. }
  67. return 0;
  68. error:
  69. if(_imc_htable!=NULL)
  70. {
  71. shm_free(_imc_htable);
  72. _imc_htable = NULL;
  73. }
  74. return -1;
  75. }
  76. /**
  77. * destroy hash table
  78. */
  79. int imc_htable_destroy(void)
  80. {
  81. int i;
  82. imc_room_p irp = NULL, irp_temp=NULL;
  83. if(_imc_htable==NULL)
  84. return -1;
  85. for(i=0; i<imc_hash_size; i++)
  86. {
  87. lock_destroy(&_imc_htable[i].lock);
  88. if(_imc_htable[i].rooms==NULL)
  89. continue;
  90. irp = _imc_htable[i].rooms;
  91. while(irp){
  92. irp_temp = irp->next;
  93. imc_del_room(&irp->name, &irp->domain);
  94. irp = irp_temp;
  95. }
  96. }
  97. shm_free(_imc_htable);
  98. _imc_htable = NULL;
  99. return 0;
  100. }
  101. /**
  102. * add room
  103. */
  104. imc_room_p imc_add_room(str* name, str* domain, int flags)
  105. {
  106. imc_room_p irp = NULL;
  107. int size;
  108. int hidx;
  109. if(name == NULL || name->s==NULL || name->len<=0
  110. || domain == NULL || domain->s==NULL || domain->len<=0)
  111. {
  112. LM_ERR("invalid parameters\n");
  113. return NULL;
  114. }
  115. /* struct size + "sip:" + name len + "@" + domain len + '\0' */
  116. size = sizeof(imc_room_t) + (name->len+domain->len+6)*sizeof(char);
  117. irp = (imc_room_p)shm_malloc(size);
  118. if(irp==NULL)
  119. {
  120. LM_ERR("no more shm memory left\n");
  121. return NULL;
  122. }
  123. memset(irp, 0, size);
  124. irp->uri.len = 4 /*sip:*/ + name->len + 1 /*@*/ + domain->len;
  125. irp->uri.s = (char*)(((char*)irp)+sizeof(imc_room_t));
  126. memcpy(irp->uri.s, "sip:", 4);
  127. memcpy(irp->uri.s+4, name->s, name->len);
  128. irp->uri.s[4+name->len] = '@';
  129. memcpy(irp->uri.s+5+name->len, domain->s, domain->len);
  130. irp->uri.s[irp->uri.len] = '\0';
  131. irp->name.len = name->len;
  132. irp->name.s = irp->uri.s+4;
  133. irp->domain.len = domain->len;
  134. irp->domain.s = irp->uri.s+5+name->len;
  135. irp->flags = flags;
  136. irp->hashid = core_case_hash(&irp->name, &irp->domain, 0);
  137. hidx = imc_get_hentry(irp->hashid, imc_hash_size);
  138. lock_get(&_imc_htable[hidx].lock);
  139. if(_imc_htable[hidx].rooms!=NULL)
  140. {
  141. irp->next = _imc_htable[hidx].rooms;
  142. _imc_htable[hidx].rooms->prev = irp;
  143. _imc_htable[hidx].rooms = irp;
  144. } else {
  145. _imc_htable[hidx].rooms = irp;
  146. }
  147. return irp;
  148. }
  149. /**
  150. * release room
  151. */
  152. int imc_release_room(imc_room_p room)
  153. {
  154. unsigned int hidx;
  155. if(room==NULL)
  156. {
  157. LM_ERR("invalid parameters\n");
  158. return -1;
  159. }
  160. hidx = imc_get_hentry(room->hashid, imc_hash_size);
  161. lock_release(&_imc_htable[hidx].lock);
  162. return 0;
  163. }
  164. /**
  165. * search room
  166. */
  167. imc_room_p imc_get_room(str* name, str* domain)
  168. {
  169. imc_room_p irp = NULL;
  170. unsigned int hashid;
  171. int hidx;
  172. if(name == NULL || name->s==NULL || name->len<=0
  173. || domain == NULL || domain->s==NULL || domain->len<=0)
  174. {
  175. LM_ERR("invalid parameters\n");
  176. return NULL;
  177. }
  178. hashid = core_case_hash(name, domain, 0);
  179. hidx = imc_get_hentry(hashid, imc_hash_size);
  180. lock_get(&_imc_htable[hidx].lock);
  181. irp = _imc_htable[hidx].rooms;
  182. while(irp)
  183. {
  184. if(irp->hashid==hashid && irp->name.len==name->len
  185. && irp->domain.len==domain->len
  186. && !strncasecmp(irp->name.s, name->s, name->len)
  187. && !strncasecmp(irp->domain.s, domain->s, domain->len))
  188. {
  189. return irp;
  190. }
  191. irp = irp->next;
  192. }
  193. /* no room */
  194. lock_release(&_imc_htable[hidx].lock);
  195. return NULL;
  196. }
  197. /**
  198. * delete room
  199. */
  200. int imc_del_room(str* name, str* domain)
  201. {
  202. imc_room_p irp = NULL;
  203. imc_member_p imp=NULL, imp_temp=NULL;
  204. unsigned int hashid;
  205. int hidx;
  206. if(name == NULL || name->s==NULL || name->len<=0
  207. || domain == NULL || domain->s==NULL || domain->len<=0)
  208. {
  209. LM_ERR("invalid parameters\n");
  210. return -1;
  211. }
  212. hashid = core_case_hash(name, domain, 0);
  213. hidx = imc_get_hentry(hashid, imc_hash_size);
  214. lock_get(&_imc_htable[hidx].lock);
  215. irp = _imc_htable[hidx].rooms;
  216. while(irp)
  217. {
  218. if(irp->hashid==hashid && irp->name.len==name->len
  219. && irp->domain.len==domain->len
  220. && !strncasecmp(irp->name.s, name->s, name->len)
  221. && !strncasecmp(irp->domain.s, domain->s, domain->len))
  222. {
  223. if(irp->prev==NULL)
  224. _imc_htable[hidx].rooms = irp->next;
  225. else
  226. irp->prev->next = irp->next;
  227. if(irp->next!=NULL)
  228. irp->next->prev = irp->prev;
  229. /* delete members */
  230. imp = irp->members;
  231. while(imp){
  232. imp_temp = imp->next;
  233. shm_free(imp);
  234. imp = imp_temp;
  235. }
  236. shm_free(irp);
  237. goto done;
  238. }
  239. irp = irp->next;
  240. }
  241. done:
  242. lock_release(&_imc_htable[hidx].lock);
  243. return 0;
  244. }
  245. /**
  246. * add member
  247. */
  248. imc_member_p imc_add_member(imc_room_p room, str* user, str* domain, int flags)
  249. {
  250. imc_member_p imp = NULL;
  251. int size;
  252. if(room==NULL || user == NULL || user->s==NULL || user->len<=0
  253. || domain == NULL || domain->s==NULL || domain->len<=0)
  254. {
  255. LM_ERR("invalid parameters\n");
  256. return NULL;
  257. }
  258. /* struct size + "sip:" + user name len + "@" + domain len + '\0' */
  259. size = sizeof(imc_member_t) + (user->len+domain->len+6)*sizeof(char);
  260. imp = (imc_member_p)shm_malloc(size);
  261. if(imp== NULL)
  262. {
  263. LM_ERR("out of shm memory\n");
  264. return NULL;
  265. }
  266. memset(imp, 0, size);
  267. imp->uri.len = 4 /*sip:*/ + user->len + 1 /*@*/ + domain->len;
  268. imp->uri.s = (char*)(((char*)imp)+sizeof(imc_member_t));
  269. memcpy(imp->uri.s, "sip:", 4);
  270. memcpy(imp->uri.s+4, user->s, user->len);
  271. imp->uri.s[4+user->len] = '@';
  272. memcpy(imp->uri.s+5+user->len, domain->s, domain->len);
  273. imp->uri.s[imp->uri.len] = '\0';
  274. LM_DBG("[uri]= %.*s\n", imp->uri.len, imp->uri.s);
  275. imp->user.len = user->len;
  276. imp->user.s = imp->uri.s+4;
  277. LM_DBG("[user]= %.*s\n", imp->user.len, imp->user.s);
  278. imp->domain.len = domain->len;
  279. imp->domain.s = imp->uri.s+5+user->len;
  280. imp->flags = flags;
  281. imp->hashid = core_case_hash(&imp->user, &imp->domain, 0);
  282. room->nr_of_members++;
  283. if(room->members==NULL)
  284. room->members = imp;
  285. else {
  286. imp->next = room->members->next;
  287. if((room->members)->next!=NULL)
  288. ((room->members)->next)->prev = imp;
  289. imp->prev = room->members;
  290. room->members->next=imp;
  291. }
  292. return imp;
  293. }
  294. /**
  295. * search memeber
  296. */
  297. imc_member_p imc_get_member(imc_room_p room, str* user, str* domain)
  298. {
  299. imc_member_p imp = NULL;
  300. unsigned int hashid;
  301. if(room==NULL || user == NULL || user->s==NULL || user->len<=0
  302. || domain == NULL || domain->s==NULL || domain->len<=0)
  303. {
  304. LM_ERR("invalid parameters\n");
  305. return NULL;
  306. }
  307. hashid = core_case_hash(user, domain, 0);
  308. imp = room->members;
  309. while(imp)
  310. {
  311. if(imp->hashid==hashid && imp->user.len==user->len
  312. && imp->domain.len==domain->len
  313. && !strncasecmp(imp->user.s, user->s, user->len)
  314. && !strncasecmp(imp->domain.s, domain->s, domain->len))
  315. {
  316. LM_DBG("found member\n");
  317. return imp;
  318. }
  319. imp = imp->next;
  320. }
  321. return NULL;
  322. }
  323. /**
  324. * delete member
  325. */
  326. int imc_del_member(imc_room_p room, str* user, str* domain)
  327. {
  328. imc_member_p imp = NULL;
  329. unsigned int hashid;
  330. if(room==NULL || user == NULL || user->s==NULL || user->len<=0
  331. || domain == NULL || domain->s==NULL || domain->len<=0)
  332. {
  333. LM_ERR("invalid parameters\n");
  334. return -1;
  335. }
  336. hashid = core_case_hash(user, domain, 0);
  337. imp = room->members;
  338. while(imp)
  339. {
  340. if(imp->hashid==hashid && imp->user.len==user->len
  341. && imp->domain.len==domain->len
  342. && !strncasecmp(imp->user.s, user->s, user->len)
  343. && !strncasecmp(imp->domain.s, domain->s, domain->len))
  344. {
  345. if(imp->prev==NULL)
  346. room->members = imp->next;
  347. else
  348. imp->prev->next = imp->next;
  349. if(imp->next!=NULL)
  350. imp->next->prev = imp->prev;
  351. shm_free(imp);
  352. room->nr_of_members--;
  353. return 0;
  354. }
  355. imp = imp->next;
  356. }
  357. return 0;
  358. }