avp_dialogs.cfg 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. debug=3
  2. memdbg=5
  3. server_signature=0
  4. sip_warning=0
  5. check_via=yes;
  6. dns=no;
  7. rev_dns=no;
  8. children=4;
  9. tcp_children=4;
  10. tcp_max_connections=2048;
  11. port=5060
  12. loadmodule "/home/kubartv/SER/lib/ser/modules/sl.so";
  13. #loadmodule "/home/kubartv/SER/lib/ser/modules/maxfwd.so";
  14. loadmodule "/home/kubartv/SER/lib/ser/modules/tm.so";
  15. loadmodule "/home/kubartv/SER/lib/ser/modules/rr.so";
  16. #loadmodule "/home/kubartv/SER/lib/ser/modules/xmlrpc.so";
  17. loadmodule "/home/kubartv/SER/lib/ser/modules/mysql.so";
  18. loadmodule "/home/kubartv/SER/lib/ser/modules/domain.so";
  19. loadmodule "/home/kubartv/SER/lib/ser/modules/uri_db.so";
  20. loadmodule "/home/kubartv/SER/lib/ser/modules/avp.so";
  21. loadmodule "/home/kubartv/SER/lib/ser/modules/avp_db.so";
  22. loadmodule "/home/kubartv/SER/lib/ser/modules/usrloc.so";
  23. loadmodule "/home/kubartv/SER/lib/ser/modules/registrar.so";
  24. loadmodule "/home/kubartv/SER/lib/ser/modules/xprint.so";
  25. loadmodule "/home/kubartv/SER/lib/ser/modules/eval.so";
  26. loadmodule "/home/kubartv/SER/lib/ser/modules/gflags.so"
  27. #modparam("maxfwd", "max_limit", 70);
  28. modparam("usrloc", "db_mode", 1);
  29. modparam("usrloc|avp_db", "db_url", "mysql://ser:[email protected]/ser")
  30. modparam("avp_db", "attr_group", "id=dlg,flag=dialog_flag,table=dlg_attrs,key_column=dlg_id");
  31. modparam("gflags", "load_global_attrs", 1);
  32. avpflags dialog_flag;
  33. route["create_dialog"] {
  34. # sets attributes needed by dialog (stored when processing reply)
  35. $dlg_caller = @contact;
  36. $dlg_caller_cseq = @cseq.num;
  37. $dlg_status = "new";
  38. $dlg_init_method = @cseq.method;
  39. $dir = "caller2callee";
  40. t_on_reply("dialog_creation_reply");
  41. return 1;
  42. }
  43. onreply_route["dialog_creation_reply"] {
  44. xplog("L_ERR", "dialog creation reply (%rs, %@cseq.method) [%@from.tag, %@to.tag]\n");
  45. $res = @msg.response.code;
  46. xplog("L_ERR", " ... response: %$res\n");
  47. if (([email protected]) || (@to.tag=="")) {
  48. # don't create dialog from response without to tag
  49. break;
  50. }
  51. if ($res < 101) {
  52. xplog("L_ERR", " ... I won't create dialog from 100 response.\n");
  53. break;
  54. }
  55. del_attr("$id"); # xlset_attr works strange when the attribute already exists
  56. xlset_attr("$id", "call-id:%@call_id caller_tag:%@from.tag callee_tag:%@to.tag");
  57. if ($res > 299) {
  58. xplog("L_ERR", " ... dialog terminated\n");
  59. remove_extra_attrs("dlg", "$id");
  60. break;
  61. }
  62. xplog("L_ERR", " ... creating dialog '%$id'\n");
  63. # generate dialog id
  64. lock_extra_attrs("dlg", "$id");
  65. # TODO: try to load the dialog (early dialog may exist)?
  66. # update dialog data
  67. if (($dlg_status == "new") && ($res < 200)) {
  68. # early response may arrive after final one
  69. $dlg_callee = @contact;
  70. $dlg_status = "early";
  71. xplog("L_ERR", " ... creating early dialog\n");
  72. }
  73. if ($res >= 200) {
  74. $dlg_callee = @contact;
  75. $dlg_status = "confirmed";
  76. $dlg_confirmed_at = @sys.now.local;
  77. xplog("L_ERR", " ... confirming dialog\n");
  78. }
  79. route("save_dialog");
  80. }
  81. route["save_dialog"] {
  82. if ($dlg_status == "destroyed") {
  83. xplog("L_ERR", " ... destroying dialog %$id\n");
  84. # use this if you want to delete destroyed dialogs:
  85. # remove_extra_attrs("dlg", "$id");
  86. # else if you want leave them in DB (with the time of termination)
  87. $dlg_destroyed_at = @sys.now.local;
  88. # set flag for attributes with name beggining with dlg_
  89. setavpflag("$f./^dlg_/", "dialog_flag");
  90. save_extra_attrs("dlg", "$id");
  91. }
  92. else {
  93. # set flag for attributes with name beggining with dlg_
  94. setavpflag("$f./^dlg_/", "dialog_flag");
  95. save_extra_attrs("dlg", "$id");
  96. }
  97. unlock_extra_attrs("dlg", "$id");
  98. }
  99. route["load_dialog_data"] {
  100. lock_extra_attrs("dlg", "$id");
  101. del_attr("$dlg_init_method"); # used as flag of succesful read of data
  102. # delete all used dlg attrs (because load_extra_attrs doesn't delete them itself before adding)
  103. del_attr("$dlg_init_method");
  104. del_attr("$dlg_caller");
  105. del_attr("$dlg_callee");
  106. del_attr("$dlg_caller_cseq");
  107. del_attr("$dlg_callee_cseq");
  108. del_attr("$dlg_status");
  109. load_extra_attrs("dlg", "$id");
  110. if (!$dlg_init_method) {
  111. # dialog was not loaded
  112. unlock_extra_attrs("dlg", "$id");
  113. return -1;
  114. }
  115. return 1;
  116. }
  117. route["load_dialog"] {
  118. # tries to load dialog according tags and callid
  119. # try to load dialog
  120. del_attr("$id"); # xlset_attr works strange when the attribute already exists
  121. xlset_attr("$id", "call-id:%@call_id caller_tag:%@from.tag callee_tag:%@to.tag");
  122. if (route("load_dialog_data")) {
  123. $dir = "caller2callee";
  124. return 1;
  125. }
  126. # try to load dialog in other direction
  127. del_attr("$id"); # xlset_attr works strange when the attribute already exists
  128. xlset_attr("$id", "call-id:%@call_id caller_tag:%@to.tag callee_tag:%@from.tag");
  129. if (route("load_dialog_data")) {
  130. $dir = "callee2caller";
  131. return 1;
  132. }
  133. $id = "error";
  134. return -1;
  135. }
  136. route["update_dialog_reply"] {
  137. if ((@cseq.method == "INVITE") || (@cseq.method == "UPDATE")) {
  138. # target refresh for INVITE dialogs
  139. if ($dir == "caller2calle") { # if request from caller
  140. $dlg_callee = @contact; # update callee's contact (response!)
  141. }
  142. else {
  143. $dlg_caller = @contact;
  144. }
  145. }
  146. if (@cseq.method=="BYE") {
  147. $dlg_status = "destroyed"; # will be removed in save_dialog
  148. }
  149. }
  150. route["update_dialog"] {
  151. if ((@cseq.method == "INVITE") || (@cseq.method == "UPDATE")) {
  152. # target refresh for INVITE dialogs
  153. if ($dir == "caller2calle") { # if request from caller
  154. $dlg_caller = @contact; # update caller's contact (request!)
  155. }
  156. else {
  157. $dlg_callee = @contact;
  158. }
  159. }
  160. if ($dir == "caller2callee") { # if request from caller
  161. # TODO: verify CSeq before modifying and return 500 if lower than last one
  162. $dlg_caller_cseq = @cseq.num;
  163. }
  164. else {
  165. # TODO: verify CSeq before modifying and return 500 if lower than last one
  166. $dlg_callee_cseq = @cseq.num;
  167. }
  168. if (method=="BYE") {
  169. $dlg_status = "pre-destroyed"; # to see that BYE already went through
  170. }
  171. return 1;
  172. }
  173. route["trace_dialog"] {
  174. xplog("L_ERR", " ... dialog '%$id'\n");
  175. xplog("L_ERR", " -> initial method: %$dlg_init_method\n");
  176. xplog("L_ERR", " -> request dir: %$dir\n");
  177. xplog("L_ERR", " -> caller: %$dlg_caller\n");
  178. xplog("L_ERR", " -> caller's CSeq: %$dlg_caller_cseq\n");
  179. xplog("L_ERR", " -> callee: %$dlg_callee\n");
  180. xplog("L_ERR", " -> callee's CSeq: %$dlg_callee_cseq\n");
  181. xplog("L_ERR", " -> status: %$dlg_status\n");
  182. return 1;
  183. }
  184. onreply_route["dialog_reply"] {
  185. if ($id) {
  186. xplog("L_ERR", "In-dialog reply (%rs, %@cseq.method) [%@to.tag, %@from.tag]\n");
  187. if (!route("load_dialog")) {
  188. xplog("L_ERR", "Can't load dialog data\n");
  189. }
  190. else {
  191. route("update_dialog_reply");
  192. route("trace_dialog");
  193. route("save_dialog");
  194. }
  195. }
  196. }
  197. route {
  198. if (method=="SUBSCRIBE") {
  199. # here we support only INVITE/BYE dialogs
  200. sl_reply("400", "Unsupported");
  201. break;
  202. }
  203. if (!lookup_domain("$td", "@to.uri.host")) {
  204. sl_send_reply("404", "Domain Not Found");
  205. break;
  206. }
  207. if (!lookup_user("To")) {
  208. sl_send_reply("404", "Unknown user");
  209. break;
  210. }
  211. if (method=="REGISTER") {
  212. save("location");
  213. break;
  214. };
  215. xplog("L_ERR", "----> processing request %@cseq.method\n");
  216. if (!lookup_domain("$fd", "@from.uri.host")) {
  217. sl_send_reply("404", "From domain Not Found");
  218. break;
  219. }
  220. if (!lookup_user("From")) {
  221. sl_send_reply("404", "Unknown user in From");
  222. break;
  223. }
  224. if (method != "REGISTER") record_route();
  225. # dialog needs transactions
  226. if (!t_newtran()) {
  227. sl_send_reply("500", "Can not start transaction");
  228. drop;
  229. }
  230. # dialog creation/loading
  231. if ([email protected] || (@to.tag == "")) {
  232. # initial request or non-dialog message
  233. if (method=="INVITE") {
  234. route("create_dialog");
  235. # we don't save the dialog here because AVPs will be set
  236. # when reply comes and the dialog will be stored then
  237. }
  238. else {
  239. xplog("L_ERR", "Non-dialog message: %@cseq\n");
  240. }
  241. }
  242. else {
  243. # message within dialog
  244. if (route("load_dialog")) {
  245. route("update_dialog");
  246. route("trace_dialog");
  247. route("save_dialog");
  248. t_on_reply("dialog_reply");
  249. }
  250. else {
  251. xplog("L_ERR", "Message within unknown dialog: %@cseq, to_tag=%@to.tag from_tag=%@from.tag\n");
  252. }
  253. }
  254. if (loose_route()) {
  255. route(1);
  256. break;
  257. }
  258. if (!lookup("location")) {
  259. t_reply("404", "Not Found");
  260. break;
  261. };
  262. route(1);
  263. }
  264. route[1]
  265. {
  266. xplog("L_ERR", "<---- request %@cseq.method processed\n");
  267. # send it out now; use stateful forwarding as it works reliably
  268. # even for UDP2TCP
  269. if (!t_relay()) {
  270. sl_reply_error();
  271. };
  272. }