README 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. UID AVP DB Module
  2. Jiri Kuthan
  3. FhG FOKUS
  4. <[email protected]>
  5. Copyright © 2004, 2005 FhG FOKUS
  6. _________________________________________________________________
  7. Table of Contents
  8. 1. Admin Guide
  9. 1. Overview
  10. 2. Dependencies
  11. 3. Parameters
  12. 3.1. db_url (string)
  13. 3.2. user_attrs_table (string)
  14. 3.3. uri_attrs_table (string)
  15. 3.4. uid_column (string)
  16. 3.5. username_column (string)
  17. 3.6. did_column (string)
  18. 3.7. name (string)
  19. 3.8. value_column (string)
  20. 3.9. type_column (string)
  21. 3.10. flags_column (string)
  22. 3.11. scheme_column (string)
  23. 3.12. attr_group (string)
  24. 3.13. auto_unlock_extra_attrs (string)
  25. 4. Functions
  26. 4.1. load_attrs (track, id)
  27. 4.2. load_extra_attrs (group_id, id)
  28. 4.3. save_extra_attrs (group_id, id)
  29. 4.4. remove_extra_attrs (group_id, id)
  30. 4.5. lock_extra_attrs (group_id, id)
  31. 4.6. unlock_extra_attrs (group_id, id)
  32. 5. Example extra attributes usage
  33. List of Examples
  34. 1.1. attribute group definition
  35. Chapter 1. Admin Guide
  36. Table of Contents
  37. 1. Overview
  38. 2. Dependencies
  39. 3. Parameters
  40. 3.1. db_url (string)
  41. 3.2. user_attrs_table (string)
  42. 3.3. uri_attrs_table (string)
  43. 3.4. uid_column (string)
  44. 3.5. username_column (string)
  45. 3.6. did_column (string)
  46. 3.7. name (string)
  47. 3.8. value_column (string)
  48. 3.9. type_column (string)
  49. 3.10. flags_column (string)
  50. 3.11. scheme_column (string)
  51. 3.12. attr_group (string)
  52. 3.13. auto_unlock_extra_attrs (string)
  53. 4. Functions
  54. 4.1. load_attrs (track, id)
  55. 4.2. load_extra_attrs (group_id, id)
  56. 4.3. save_extra_attrs (group_id, id)
  57. 4.4. remove_extra_attrs (group_id, id)
  58. 4.5. lock_extra_attrs (group_id, id)
  59. 4.6. unlock_extra_attrs (group_id, id)
  60. 5. Example extra attributes usage
  61. 1. Overview
  62. This module contains several functions that can be used to manipulate
  63. the contents of AVPs (Attribute-Value pairs). The AVPs are variables
  64. attached to the SIP message being processed. Each variable has its
  65. name and value. AVPs can be used to store arbitrary data or as a means
  66. of inter-module comminication.
  67. You may also want to check the avpops module which is more flexible
  68. and contains more functions. In future SER releases the avp module
  69. will be probably deprecated in favor of avpops module.
  70. Domain module operates in caching mode. Domain module reads the
  71. default values of AVPs into cache memory when the module is loaded.
  72. After that default values is re-read only when module is given
  73. avp_list_reload fifo command. Any changes in usr_preferences_types
  74. table must thus be followed by avp_list_reload command in order to
  75. reflect them in module behavior.
  76. 2. Dependencies
  77. A database module, such as mysql, postgres, or dbtext.
  78. 3. Parameters
  79. 3.1. db_url (string)
  80. 3.2. user_attrs_table (string)
  81. 3.3. uri_attrs_table (string)
  82. 3.4. uid_column (string)
  83. 3.5. username_column (string)
  84. 3.6. did_column (string)
  85. 3.7. name (string)
  86. 3.8. value_column (string)
  87. 3.9. type_column (string)
  88. 3.10. flags_column (string)
  89. 3.11. scheme_column (string)
  90. 3.12. attr_group (string)
  91. 3.13. auto_unlock_extra_attrs (string)
  92. 3.1. db_url (string)
  93. The URL of the database to be used.
  94. Default value is "mysql://ser:heslo@localhost/ser".
  95. 3.2. user_attrs_table (string)
  96. Name of the table with user attributes.
  97. Default value is "user_attrs".
  98. 3.3. uri_attrs_table (string)
  99. Name of the table with uri attributes.
  100. Default value is "uri_attrs".
  101. 3.4. uid_column (string)
  102. Name of the column that stores UID in the user attributes table.
  103. Default value is "uid".
  104. 3.5. username_column (string)
  105. Name of the column containing the username of the subscriber in uri
  106. attributes table.
  107. Default value is "username".
  108. 3.6. did_column (string)
  109. Name of the column in uri attributes table containing the ID of domain
  110. that the subscriber belongs to.
  111. Default value is "did".
  112. 3.7. name (string)
  113. The name of the column containing attribute names.
  114. Default value is "name".
  115. 3.8. value_column (string)
  116. The name of the column containing attribute values.
  117. Default value is "value".
  118. 3.9. type_column (string)
  119. The name of the column containing attribute value type.
  120. Default value is "type".
  121. 3.10. flags_column (string)
  122. The name of the column containing attribute flags.
  123. Default value is "flags".
  124. 3.11. scheme_column (string)
  125. The name of the column containing subscriber's scheme in uri
  126. attributes.
  127. Default value is "scheme".
  128. 3.12. attr_group (string)
  129. 'Extra attribute' group definition. It can be repeated to define more
  130. attribute groups.
  131. The group definition contains one or more assignments in the form
  132. key=value. Possible keys are:
  133. id
  134. Attribute group identifier. Must be set.
  135. table
  136. Table name used for storing attributes from this attribute
  137. group. Must be set.
  138. flag
  139. Attribute flag name used to mark attributes in this group. Must
  140. be set.
  141. key_column
  142. Column name holding key. Default value is "id".
  143. name_column
  144. Column name used for storing attribute name. Default value is
  145. "name".
  146. value_column
  147. Column name used for storing attribute value. Default value is
  148. "value".
  149. type_column
  150. Column name used for storing attribute type. Default value is
  151. "type".
  152. flags_column
  153. Column name used for storing attribute flags. Default value is
  154. "flags".
  155. None defined by default.
  156. Example 1.1. attribute group definition
  157. modparam("avp_db", "attr_group", "id=dlg,flag=dialog_flag,table=dlg_attrs,key_c
  158. olumn=dlg_id");
  159. Table used for these attributes:
  160. mysql> describe dlg_attrs;
  161. +--------+------------------+------+-----+---------+-------+
  162. | Field | Type | Null | Key | Default | Extra |
  163. +--------+------------------+------+-----+---------+-------+
  164. | dlg_id | varchar(256) | NO | MUL | | |
  165. | name | varchar(32) | NO | | | |
  166. | value | varchar(255) | YES | | NULL | |
  167. | type | int(11) | NO | | 0 | |
  168. | flags | int(10) unsigned | NO | | 0 | |
  169. +--------+------------------+------+-----+---------+-------+
  170. 5 rows in set (0.00 sec)
  171. Setting flags from code (all attrs beginning with "dlg_"):
  172. avpflags dialog_flag;
  173. ...
  174. route {
  175. ...
  176. setavpflag("$f./^dlg_/", "dialog_flag");
  177. ...
  178. }
  179. 3.13. auto_unlock_extra_attrs (string)
  180. Determines the action when any of the 'extra attributes' lock is
  181. detected when routing script execution was finished. When the value of
  182. this parameter is zero (default) BUG level message is logged, but the
  183. lock is kept, so another process trying to obtain the lock might get
  184. stuck. If the value is nonzero, DEBUG level message is sent to the log
  185. and all the locks are released.
  186. Default value is 0.
  187. 4. Functions
  188. 4.1. load_attrs (track, id)
  189. 4.2. load_extra_attrs (group_id, id)
  190. 4.3. save_extra_attrs (group_id, id)
  191. 4.4. remove_extra_attrs (group_id, id)
  192. 4.5. lock_extra_attrs (group_id, id)
  193. 4.6. unlock_extra_attrs (group_id, id)
  194. 4.1. load_attrs (track, id)
  195. Loads attributes from the database.
  196. track
  197. $fu
  198. Load user attributes into from track. In this case the
  199. second parameter is UID used to search attributes.
  200. $tu
  201. Load user attributes into to track. In this case the
  202. second parameter is UID used to search attributes.
  203. $fr
  204. Load uri attributes into from track. In this case the
  205. second parameter is URI used to search attributes.
  206. $tr
  207. Load uri attributes into to track. In this case the
  208. second parameter is URI used to search attributes.
  209. id
  210. Identifier used for searching attributes. When searching for
  211. user attributes it is UID, when searchnig uri attributes it is
  212. URI.
  213. 4.2. load_extra_attrs (group_id, id)
  214. Loads 'extra attributes' stored by previous call to save_extra_attrs.
  215. group_id
  216. Identifies attribute group, see Section 3.12, "attr_group
  217. (string)".
  218. id
  219. Identifies attributes which should be loaded.
  220. 4.3. save_extra_attrs (group_id, id)
  221. Saves 'extra attributes' flagged by group flag under given id.
  222. group_id
  223. Identifies attribute group, see Section 3.12, "attr_group
  224. (string)".
  225. id
  226. Identifier stored with flagged attributes.
  227. 4.4. remove_extra_attrs (group_id, id)
  228. Removes all extra attributes with given id.
  229. group_id
  230. Identifies attribute group, see Section 3.12, "attr_group
  231. (string)".
  232. id
  233. Identifies attributes which should be removed.
  234. 4.5. lock_extra_attrs (group_id, id)
  235. Locks extra attributes. Currently locks whole attribute group (not
  236. only id).
  237. group_id
  238. Identifies attribute group, see Section 3.12, "attr_group
  239. (string)".
  240. id
  241. Identifies attributes which should be locked.
  242. 4.6. unlock_extra_attrs (group_id, id)
  243. Unlocks extra attributes. Currently unlocks whole attribute group (not
  244. only id).
  245. group_id
  246. Identifies attribute group, see Section 3.12, "attr_group
  247. (string)".
  248. id
  249. Identifies attributes which should be unlocked.
  250. 5. Example extra attributes usage
  251. debug=3
  252. memdbg=5
  253. server_signature=0
  254. sip_warning=0
  255. check_via=yes;
  256. dns=no;
  257. rev_dns=no;
  258. children=4;
  259. tcp_children=4;
  260. tcp_max_connections=2048;
  261. port=5060
  262. loadmodule "/home/kubartv/SER/lib/ser/modules/sl.so";
  263. #loadmodule "/home/kubartv/SER/lib/ser/modules/maxfwd.so";
  264. loadmodule "/home/kubartv/SER/lib/ser/modules/tm.so";
  265. loadmodule "/home/kubartv/SER/lib/ser/modules/rr.so";
  266. #loadmodule "/home/kubartv/SER/lib/ser/modules/xmlrpc.so";
  267. loadmodule "/home/kubartv/SER/lib/ser/modules/mysql.so";
  268. loadmodule "/home/kubartv/SER/lib/ser/modules/domain.so";
  269. loadmodule "/home/kubartv/SER/lib/ser/modules/uri_db.so";
  270. loadmodule "/home/kubartv/SER/lib/ser/modules/avp.so";
  271. loadmodule "/home/kubartv/SER/lib/ser/modules/avp_db.so";
  272. loadmodule "/home/kubartv/SER/lib/ser/modules/usrloc.so";
  273. loadmodule "/home/kubartv/SER/lib/ser/modules/registrar.so";
  274. loadmodule "/home/kubartv/SER/lib/ser/modules/xprint.so";
  275. loadmodule "/home/kubartv/SER/lib/ser/modules/eval.so";
  276. loadmodule "/home/kubartv/SER/lib/ser/modules/gflags.so"
  277. #modparam("maxfwd", "max_limit", 70);
  278. modparam("usrloc", "db_mode", 1);
  279. modparam("usrloc|avp_db", "db_url", "mysql://ser:[email protected]/ser")
  280. modparam("avp_db", "attr_group", "id=dlg,flag=dialog_flag,table=dlg_attrs,key_c
  281. olumn=dlg_id");
  282. modparam("gflags", "load_global_attrs", 1);
  283. avpflags dialog_flag;
  284. route["create_dialog"] {
  285. # sets attributes needed by dialog (stored when processing reply)
  286. $dlg_caller = @contact;
  287. $dlg_caller_cseq = @cseq.num;
  288. $dlg_status = "new";
  289. $dlg_init_method = @cseq.method;
  290. $dir = "caller2callee";
  291. t_on_reply("dialog_creation_reply");
  292. return 1;
  293. }
  294. onreply_route["dialog_creation_reply"] {
  295. xplog("L_ERR", "dialog creation reply (%rs, %@cseq.method) [%@from.tag,
  296. %@to.tag]\n");
  297. $res = @msg.response.code;
  298. xplog("L_ERR", " ... response: %$res\n");
  299. if (([email protected]) || (@to.tag=="")) {
  300. # don't create dialog from response without to tag
  301. break;
  302. }
  303. if ($res < 101) {
  304. xplog("L_ERR", " ... I won't create dialog from 100 response.\n
  305. ");
  306. break;
  307. }
  308. del_attr("$id"); # xlset_attr works strange when the attribute already
  309. exists
  310. xlset_attr("$id", "call-id:%@call_id caller_tag:%@from.tag callee_tag:%
  311. @to.tag");
  312. if ($res > 299) {
  313. xplog("L_ERR", " ... dialog terminated\n");
  314. remove_extra_attrs("dlg", "$id");
  315. break;
  316. }
  317. xplog("L_ERR", " ... creating dialog '%$id'\n");
  318. # generate dialog id
  319. lock_extra_attrs("dlg", "$id");
  320. # TODO: try to load the dialog (early dialog may exist)?
  321. # update dialog data
  322. if (($dlg_status == "new") && ($res < 200)) {
  323. # early response may arrive after final one
  324. $dlg_callee = @contact;
  325. $dlg_status = "early";
  326. xplog("L_ERR", " ... creating early dialog\n");
  327. }
  328. if ($res >= 200) {
  329. $dlg_callee = @contact;
  330. $dlg_status = "confirmed";
  331. $dlg_confirmed_at = @sys.now.local;
  332. xplog("L_ERR", " ... confirming dialog\n");
  333. }
  334. route("save_dialog");
  335. }
  336. route["save_dialog"] {
  337. if ($dlg_status == "destroyed") {
  338. xplog("L_ERR", " ... destroying dialog %$id\n");
  339. # use this if you want to delete destroyed dialogs:
  340. # remove_extra_attrs("dlg", "$id");
  341. # else if you want leave them in DB (with the time of terminati
  342. on)
  343. $dlg_destroyed_at = @sys.now.local;
  344. # set flag for attributes with name beggining with dlg_
  345. setavpflag("$f./^dlg_/", "dialog_flag");
  346. save_extra_attrs("dlg", "$id");
  347. }
  348. else {
  349. # set flag for attributes with name beggining with dlg_
  350. setavpflag("$f./^dlg_/", "dialog_flag");
  351. save_extra_attrs("dlg", "$id");
  352. }
  353. unlock_extra_attrs("dlg", "$id");
  354. }
  355. route["load_dialog_data"] {
  356. lock_extra_attrs("dlg", "$id");
  357. del_attr("$dlg_init_method"); # used as flag of succesful read of data
  358. # delete all used dlg attrs (because load_extra_attrs doesn't delete th
  359. em itself before adding)
  360. del_attr("$dlg_init_method");
  361. del_attr("$dlg_caller");
  362. del_attr("$dlg_callee");
  363. del_attr("$dlg_caller_cseq");
  364. del_attr("$dlg_callee_cseq");
  365. del_attr("$dlg_status");
  366. load_extra_attrs("dlg", "$id");
  367. if (!$dlg_init_method) {
  368. # dialog was not loaded
  369. unlock_extra_attrs("dlg", "$id");
  370. return -1;
  371. }
  372. return 1;
  373. }
  374. route["load_dialog"] {
  375. # tries to load dialog according tags and callid
  376. # try to load dialog
  377. del_attr("$id"); # xlset_attr works strange when the attribute already
  378. exists
  379. xlset_attr("$id", "call-id:%@call_id caller_tag:%@from.tag callee_tag:%
  380. @to.tag");
  381. if (route("load_dialog_data")) {
  382. $dir = "caller2callee";
  383. return 1;
  384. }
  385. # try to load dialog in other direction
  386. del_attr("$id"); # xlset_attr works strange when the attribute already
  387. exists
  388. xlset_attr("$id", "call-id:%@call_id caller_tag:%@to.tag callee_tag:%@f
  389. rom.tag");
  390. if (route("load_dialog_data")) {
  391. $dir = "callee2caller";
  392. return 1;
  393. }
  394. $id = "error";
  395. return -1;
  396. }
  397. route["update_dialog_reply"] {
  398. if ((@cseq.method == "INVITE") || (@cseq.method == "UPDATE")) {
  399. # target refresh for INVITE dialogs
  400. if ($dir == "caller2calle") { # if request from caller
  401. $dlg_callee = @contact; # update callee's contact (resp
  402. onse!)
  403. }
  404. else {
  405. $dlg_caller = @contact;
  406. }
  407. }
  408. if (@cseq.method=="BYE") {
  409. $dlg_status = "destroyed"; # will be removed in save_dialog
  410. }
  411. }
  412. route["update_dialog"] {
  413. if ((@cseq.method == "INVITE") || (@cseq.method == "UPDATE")) {
  414. # target refresh for INVITE dialogs
  415. if ($dir == "caller2calle") { # if request from caller
  416. $dlg_caller = @contact; # update caller's contact (requ
  417. est!)
  418. }
  419. else {
  420. $dlg_callee = @contact;
  421. }
  422. }
  423. if ($dir == "caller2callee") { # if request from caller
  424. # TODO: verify CSeq before modifying and return 500 if lower th
  425. an last one
  426. $dlg_caller_cseq = @cseq.num;
  427. }
  428. else {
  429. # TODO: verify CSeq before modifying and return 500 if lower th
  430. an last one
  431. $dlg_callee_cseq = @cseq.num;
  432. }
  433. if (method=="BYE") {
  434. $dlg_status = "pre-destroyed"; # to see that BYE already went t
  435. hrough
  436. }
  437. return 1;
  438. }
  439. route["trace_dialog"] {
  440. xplog("L_ERR", " ... dialog '%$id'\n");
  441. xplog("L_ERR", " -> initial method: %$dlg_init_method\n");
  442. xplog("L_ERR", " -> request dir: %$dir\n");
  443. xplog("L_ERR", " -> caller: %$dlg_caller\n");
  444. xplog("L_ERR", " -> caller's CSeq: %$dlg_caller_cseq\n");
  445. xplog("L_ERR", " -> callee: %$dlg_callee\n");
  446. xplog("L_ERR", " -> callee's CSeq: %$dlg_callee_cseq\n");
  447. xplog("L_ERR", " -> status: %$dlg_status\n");
  448. return 1;
  449. }
  450. onreply_route["dialog_reply"] {
  451. if ($id) {
  452. xplog("L_ERR", "In-dialog reply (%rs, %@cseq.method) [%@to.tag,
  453. %@from.tag]\n");
  454. if (!route("load_dialog")) {
  455. xplog("L_ERR", "Can't load dialog data\n");
  456. }
  457. else {
  458. route("update_dialog_reply");
  459. route("trace_dialog");
  460. route("save_dialog");
  461. }
  462. }
  463. }
  464. route {
  465. if (method=="SUBSCRIBE") {
  466. # here we support only INVITE/BYE dialogs
  467. sl_reply("400", "Unsupported");
  468. break;
  469. }
  470. if (!lookup_domain("$td", "@to.uri.host")) {
  471. sl_send_reply("404", "Domain Not Found");
  472. break;
  473. }
  474. if (!lookup_user("To")) {
  475. sl_send_reply("404", "Unknown user");
  476. break;
  477. }
  478. if (method=="REGISTER") {
  479. save("location");
  480. break;
  481. };
  482. xplog("L_ERR", "----> processing request %@cseq.method\n");
  483. if (!lookup_domain("$fd", "@from.uri.host")) {
  484. sl_send_reply("404", "From domain Not Found");
  485. break;
  486. }
  487. if (!lookup_user("From")) {
  488. sl_send_reply("404", "Unknown user in From");
  489. break;
  490. }
  491. if (method != "REGISTER") record_route();
  492. # dialog needs transactions
  493. if (!t_newtran()) {
  494. sl_send_reply("500", "Can not start transaction");
  495. drop;
  496. }
  497. # dialog creation/loading
  498. if ([email protected] || (@to.tag == "")) {
  499. # initial request or non-dialog message
  500. if (method=="INVITE") {
  501. route("create_dialog");
  502. # we don't save the dialog here because AVPs will be se
  503. t
  504. # when reply comes and the dialog will be stored then
  505. }
  506. else {
  507. xplog("L_ERR", "Non-dialog message: %@cseq\n");
  508. }
  509. }
  510. else {
  511. # message within dialog
  512. if (route("load_dialog")) {
  513. route("update_dialog");
  514. route("trace_dialog");
  515. route("save_dialog");
  516. t_on_reply("dialog_reply");
  517. }
  518. else {
  519. xplog("L_ERR", "Message within unknown dialog: %@cseq,
  520. to_tag=%@to.tag from_tag=%@from.tag\n");
  521. }
  522. }
  523. if (loose_route()) {
  524. route(1);
  525. break;
  526. }
  527. if (!lookup("location")) {
  528. t_reply("404", "Not Found");
  529. break;
  530. };
  531. route(1);
  532. }
  533. route[1]
  534. {
  535. xplog("L_ERR", "<---- request %@cseq.method processed\n");
  536. # send it out now; use stateful forwarding as it works reliably
  537. # even for UDP2TCP
  538. if (!t_relay()) {
  539. sl_reply_error();
  540. };
  541. }