ul_rpc.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /*
  2. * $Id$
  3. *
  4. * Usrloc module interface
  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 <stdio.h>
  30. #include "../../dprint.h"
  31. #include "../../ut.h"
  32. #include "../../globals.h"
  33. #include "dlist.h"
  34. #include "utime.h"
  35. #include "ul_mod.h"
  36. #include "ul_rpc.h"
  37. static inline void rpc_find_domain(str* _name, udomain_t** _d)
  38. {
  39. dlist_t* ptr;
  40. ptr = root;
  41. while(ptr) {
  42. if ((ptr->name.len == _name->len) &&
  43. !memcmp(ptr->name.s, _name->s, _name->len)) {
  44. break;
  45. }
  46. ptr = ptr->next;
  47. }
  48. if (ptr) {
  49. *_d = ptr->d;
  50. } else {
  51. *_d = 0;
  52. }
  53. }
  54. static inline int add_contact(udomain_t* _d, str* _u, str* _c, time_t _e, qvalue_t _q, int _f, int sid)
  55. {
  56. urecord_t* r;
  57. ucontact_t* c = 0;
  58. int res;
  59. str cid;
  60. str ua;
  61. str aor = STR_NULL;
  62. if (_e == 0 && !(_f & FL_PERMANENT)) {
  63. LOG(L_ERR, "rpc_add_contact(): expires == 0 and not persistent contact, giving up\n");
  64. return -1;
  65. }
  66. get_act_time();
  67. res = get_urecord(_d, _u, &r);
  68. if (res < 0) {
  69. LOG(L_ERR, "rpc_add_contact(): Error while getting record\n");
  70. return -2;
  71. }
  72. if (res > 0) { /* Record not found */
  73. if (insert_urecord(_d, _u, &r) < 0) {
  74. LOG(L_ERR, "rpc_add_contact(): Error while creating new urecord\n");
  75. return -3;
  76. }
  77. } else {
  78. if (get_ucontact(r, _c, &c) < 0) {
  79. LOG(L_ERR, "rpc_add_contact(): Error while obtaining ucontact\n");
  80. return -4;
  81. }
  82. }
  83. cid.s = "RPC-Call-ID";
  84. cid.len = strlen(cid.s);
  85. ua.s = "SER-RPC";
  86. ua.len = strlen(ua.s);
  87. if (c) {
  88. if (update_ucontact(c, &aor, _c, _e + act_time, _q, &cid, 42, _f, FL_NONE, &ua, 0, 0, 0,
  89. sid == -1 ? server_id : sid) < 0) {
  90. LOG(L_ERR, "rpc_add_contact(): Error while updating contact\n");
  91. release_urecord(r);
  92. return -5;
  93. }
  94. } else {
  95. if (insert_ucontact(r, &aor, _c, _e + act_time, _q, &cid, 42, _f, &c, &ua, 0, 0, 0,
  96. sid == -1 ? server_id : sid) < 0) {
  97. LOG(L_ERR, "rpc_add_contact(): Error while inserting contact\n");
  98. release_urecord(r);
  99. return -6;
  100. }
  101. }
  102. release_urecord(r);
  103. return 0;
  104. }
  105. static const char* rpc_stats_doc[2] = {
  106. "Print usrloc statistics",
  107. 0
  108. };
  109. static void rpc_stats(rpc_t* rpc, void* c)
  110. {
  111. dlist_t* ptr;
  112. void* handle;
  113. ptr = root;
  114. while(ptr) {
  115. rpc->add(c, "{", &handle);
  116. rpc->struct_add(handle, "Sdd",
  117. "domain", ptr->d->name,
  118. "users", ptr->d->users,
  119. "expired", ptr->d->expired);
  120. ptr = ptr->next;
  121. }
  122. }
  123. static const char* rpc_delete_uid_doc[2] = {
  124. "Delete all registered contacts for address of record.",
  125. 0
  126. };
  127. static void rpc_delete_uid(rpc_t* rpc, void* c)
  128. {
  129. udomain_t* d;
  130. str uid, t;
  131. if (rpc->scan(c, "SS", &t, &uid) < 2) return;
  132. rpc_find_domain(&t, &d);
  133. if (d) {
  134. lock_udomain(d);
  135. if (delete_urecord(d, &uid) < 0) {
  136. ERR("Error while deleting user %.*s\n", uid.len, uid.s);
  137. unlock_udomain(d);
  138. rpc->fault(c, 500, "Error While Deleting Record");
  139. return;
  140. }
  141. unlock_udomain(d);
  142. } else {
  143. rpc->fault(c, 400, "Table Not Found");
  144. }
  145. }
  146. static const char* rpc_delete_contact_doc[2] = {
  147. "Delete a contact if it exists.",
  148. 0
  149. };
  150. static void rpc_delete_contact(rpc_t* rpc, void* ctx)
  151. {
  152. udomain_t* d;
  153. urecord_t* r;
  154. ucontact_t* con;
  155. str uid, t, c;
  156. int res;
  157. if (rpc->scan(ctx, "SSS", &t, &uid, &c) < 3) return;
  158. rpc_find_domain(&t, &d);
  159. if (d) {
  160. lock_udomain(d);
  161. res = get_urecord(d, &uid, &r);
  162. if (res < 0) {
  163. rpc->fault(ctx, 500, "Error While Searching Table");
  164. ERR("Error while looking for uid %.*s in table %.*s\n", uid.len, uid.s, t.len, t.s);
  165. unlock_udomain(d);
  166. return;
  167. }
  168. if (res > 0) {
  169. rpc->fault(ctx, 404, "AOR Not Found");
  170. unlock_udomain(d);
  171. return;
  172. }
  173. res = get_ucontact(r, &c, &con);
  174. if (res < 0) {
  175. rpc->fault(ctx, 500, "Error While Searching for Contact");
  176. ERR("Error while looking for contact %.*s\n", c.len, c.s);
  177. unlock_udomain(d);
  178. return;
  179. }
  180. if (res > 0) {
  181. rpc->fault(ctx, 404, "Contact Not Found");
  182. unlock_udomain(d);
  183. return;
  184. }
  185. if (delete_ucontact(r, con) < 0) {
  186. rpc->fault(ctx, 500, "Error While Deleting Contact");
  187. unlock_udomain(d);
  188. return;
  189. }
  190. release_urecord(r);
  191. unlock_udomain(d);
  192. } else {
  193. rpc->fault(ctx, 404, "Table Not Found");
  194. }
  195. }
  196. static const char* rpc_dump_doc[2] = {
  197. "Print all registered contacts.",
  198. 0
  199. };
  200. static void rpc_dump(rpc_t* rpc, void* c)
  201. {
  202. rpc->fault(c, 500, "Not Yet Implemented");
  203. }
  204. static const char* rpc_dump_file_doc[2] = {
  205. "Print all registered contacts into a file.",
  206. 0
  207. };
  208. static void rpc_dump_file(rpc_t* rpc, void* c)
  209. {
  210. str filename;
  211. FILE *file;
  212. if (rpc->scan(c, "S", &filename) < 1) {
  213. return;
  214. }
  215. DBG("dumping to file '%.*s'.\n", filename.len, ZSW(filename.s));
  216. if (! (file = fopen(filename.s, "w"))) {
  217. ERR("failed to open file `%s'.\n", filename.s);
  218. rpc->fault(rpc, 500, "failed to open file `%s'.\n", filename.s);
  219. return;
  220. }
  221. print_all_udomains(file);
  222. fclose(file);
  223. }
  224. static const char* rpc_flush_doc[2] = {
  225. "Flush cache into database.",
  226. 0
  227. };
  228. static void rpc_flush(rpc_t* rpc, void* c)
  229. {
  230. synchronize_all_udomains();
  231. }
  232. static const char* rpc_add_contact_doc[2] = {
  233. "Create a new contact.",
  234. 0
  235. };
  236. static void rpc_add_contact(rpc_t* rpc, void* c)
  237. {
  238. udomain_t* d;
  239. int expires, flags, sid;
  240. double q;
  241. qvalue_t qval;
  242. str table, uid, contact;
  243. if (rpc->scan(c, "SSSdfd", &table, &uid, &contact, &expires, &q, &flags) < 6) return;
  244. qval = double2q(q);
  245. if (rpc->scan(c, "d", &sid) < 1) sid = -1;
  246. rpc_find_domain(&table, &d);
  247. if (d) {
  248. lock_udomain(d);
  249. if (add_contact(d, &uid, &contact, expires, qval, flags, sid) < 0) {
  250. unlock_udomain(d);
  251. ERR("Error while adding contact ('%.*s','%.*s') in table '%.*s'\n",
  252. uid.len, ZSW(uid.s), contact.len, ZSW(contact.s), table.len, ZSW(table.s));
  253. rpc->fault(c, 500, "Error while adding Contact");
  254. return;
  255. }
  256. unlock_udomain(d);
  257. } else {
  258. rpc->fault(c, 400, "Table Not Found");
  259. }
  260. }
  261. /*
  262. * Build Contact HF for reply
  263. */
  264. static inline int print_contacts(rpc_t* rpc, void* ctx, ucontact_t* _c)
  265. {
  266. int cnt = 0;
  267. void* handle;
  268. while(_c) {
  269. if (VALID_CONTACT(_c, act_time)) {
  270. cnt++;
  271. if (rpc->add(ctx, "{", &handle) < 0) return -1;
  272. rpc->struct_add(handle, "SfdSS",
  273. "contact", &_c->c,
  274. "q", q2double(_c->q),
  275. "expires", (int)(_c->expires - act_time),
  276. "ua", &_c->user_agent,
  277. "recv", &_c->received);
  278. }
  279. _c = _c->next;
  280. }
  281. return cnt;
  282. }
  283. static const char* rpc_show_contacts_doc[2] = {
  284. "List all registered contacts for address of record",
  285. 0
  286. };
  287. static void rpc_show_contacts(rpc_t* rpc, void* c)
  288. {
  289. udomain_t* d;
  290. urecord_t* r;
  291. int res;
  292. str t, uid;
  293. if (rpc->scan(c, "SS", &t, &uid) < 2) return;
  294. rpc_find_domain(&t, &d);
  295. if (d) {
  296. lock_udomain(d);
  297. res = get_urecord(d, &uid, &r);
  298. if (res < 0) {
  299. rpc->fault(c, 500, "Error While Searching AOR");
  300. ERR("Error while looking for username %.*s in table %.*s\n", uid.len, uid.s, t.len, t.s);
  301. unlock_udomain(d);
  302. return;
  303. }
  304. if (res > 0) {
  305. rpc->fault(c, 404, "AOR Not Found");
  306. unlock_udomain(d);
  307. return;
  308. }
  309. get_act_time();
  310. if (!print_contacts(rpc, c, r->contacts)) {
  311. unlock_udomain(d);
  312. rpc->fault(c, 404, "No Registered Contacts Found");
  313. return;
  314. }
  315. unlock_udomain(d);
  316. } else {
  317. rpc->fault(c, 400, "Table Not Found");
  318. }
  319. }
  320. rpc_export_t ul_rpc[] = {
  321. {"usrloc.stats", rpc_stats, rpc_stats_doc, RET_ARRAY},
  322. {"usrloc.delete_uid", rpc_delete_uid, rpc_delete_uid_doc, 0},
  323. {"usrloc.delete_contact", rpc_delete_contact, rpc_delete_contact_doc, 0},
  324. {"usrloc.dump", rpc_dump, rpc_dump_doc, 0},
  325. {"usrloc.dump_file", rpc_dump_file, rpc_dump_file_doc, 0},
  326. {"usrloc.flush", rpc_flush, rpc_flush_doc, 0},
  327. {"usrloc.add_contact", rpc_add_contact, rpc_add_contact_doc, 0},
  328. {"usrloc.show_contacts", rpc_show_contacts, rpc_show_contacts_doc, RET_ARRAY},
  329. {0, 0, 0, 0}
  330. };