kamailio-basic-kemi-ruby.rb 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. ## Kamailio - equivalent of routing blocks in Ruby
  2. ##
  3. ## KSR - the new dynamic object exporting Kamailio functions
  4. ## Relevant remarks:
  5. ## KSR.x.exit() is not exported in ruby as per KEMI docs, so we use native exit
  6. ## Module names are capitalised and referenced with double colons - e.g. it's KSR::HDR.append instead of KSR.hdr.append in other KEMI languages
  7. ## Global variables corresponding to defined values (e.g., flags) in kamailio.cfg
  8. $FLT_ACC = 1
  9. $FLT_ACCMISSED = 2
  10. $FLT_ACCFAILED = 3
  11. $FLT_NATS = 5
  12. $FLB_NATB = 6
  13. $FLB_NATSIPPING = 7
  14. def ksr_request_route()
  15. # Per request initial checks
  16. ksr_route_reqinit()
  17. ksr_route_natdetect()
  18. if KSR.is_CANCEL() then
  19. if KSR::TM.t_check_trans() > 0 then
  20. ksr_route_relay()
  21. end
  22. return
  23. end
  24. # Retransmissions
  25. if !KSR.is_ACK() then
  26. if KSR::TMX.t_precheck_trans() > 0 then
  27. KSR::TM.t_check_trans()
  28. return
  29. end
  30. return if KSR::TM.t_check_trans() == 0
  31. end
  32. # Handle requests within SIP dialogs
  33. ksr_route_withindlg()
  34. # -- only initial requests (no To tag)
  35. # Authentication
  36. ksr_route_auth()
  37. # Record routing for dialog forming requests (in case they are routed)
  38. KSR::HDR.remove("Route")
  39. if KSR.is_method_in("IS") then
  40. KSR::RR.record_route()
  41. end
  42. KSR.setflag($FLT_ACC) if KSR.is_INVITE()
  43. # Dispatch to external
  44. ksr_route_sipout()
  45. # Registrations
  46. ksr_route_registrar()
  47. if KSR::COREX.has_ruri_user() < 0 then
  48. # request with no Username in RURI
  49. KSR::SL.sl_send_reply(484, "Address Incomplete");
  50. return;
  51. end
  52. # User location service
  53. ksr_route_location()
  54. return
  55. end
  56. def ksr_route_relay()
  57. if KSR.is_method_in("IBSU") then
  58. if KSR::TM.t_is_set("branch_route") < 0 then
  59. KSR::TM.t_on_branch("ksr_branch_manage")
  60. end
  61. end
  62. if KSR.is_method_in("ISU") then
  63. if KSR::TM.t_is_set("onreply_route") < 0 then
  64. KSR::TM.t_on_reply("ksr_onreply_manage")
  65. end
  66. end
  67. if KSR.is_INVITE() then
  68. if KSR::TM.t_is_set("failure_route") < 0 then
  69. KSR::TM.t_on_failure("ksr_failure_manage")
  70. end
  71. end
  72. if KSR::TM.t_relay() < 0 then
  73. KSR::SL.sl_reply_error()
  74. end
  75. exit
  76. end
  77. def ksr_route_reqinit()
  78. # no connect for sending replies
  79. KSR.set_reply_no_connect();
  80. # enforce symmetric signaling
  81. # send back replies to the source address of request
  82. KSR.force_rport();
  83. if !KSR.is_myself_srcip() then
  84. srcip = KSR::KX.get_srcip();
  85. if KSR::HTABLE.sht_match_name("ipban", "eq", srcip) > 0 then
  86. # ip is already blocked
  87. KSR.dbg("request from blocked IP - " + KSR::KX.get_method() +
  88. " from " + KSR::KX.get_furi() + " (IP:" +
  89. srcip + ":" + KSR::KX.get_srcport() + ")\n");
  90. exit;
  91. end
  92. if KSR::PIKE.pike_check_req() < 0 then
  93. KSR.err("ALERT: pike blocking " + KSR.kx.get_method() +
  94. " from " + KSR::KX.get_furi() + " (IP:" +
  95. srcip + ":" + KSR.kx.get_srcport() + ")\n");
  96. KSR::HTABLE.sht_seti("ipban", srcip, 1);
  97. exit;
  98. end
  99. end
  100. if KSR::COREX.has_user_agent() > 0 then
  101. ua = KSR::PV.gete("$ua");
  102. if ua.include? 'friendly' or ua.include? 'scanner' or
  103. ua.include? 'sipcli' or ua.include? 'sipvicious' or
  104. ua.include? 'VaxSIPUserAgent' or ua.include? 'pplsip' then
  105. KSR::SL.sl_send_reply(200, "OK");
  106. exit
  107. end
  108. end
  109. if KSR::MAXFWD.process_maxfwd(10) < 0 then
  110. KSR::SL.sl_send_reply(483, "Too Many Hops");
  111. exit
  112. end
  113. if KSR.is_OPTIONS() and KSR.is_myself_ruri() and KSR::COREX.has_ruri_user() < 0 then
  114. KSR::SL.sl_send_reply(200, "Keepalive");
  115. exit
  116. end
  117. if KSR::SANITY.sanity_check(17895, 7) < 0 then
  118. KSR.err("Malformed SIP message from #{KSR::PV.get('$si')}:#{KSR::PV.get('$sp')}\n");
  119. exit
  120. end
  121. end
  122. def ksr_route_withindlg()
  123. return if KSR::SIPUTILS.has_totag() < 0
  124. if KSR::RR.loose_route() > 0 then
  125. ksr_route_dlguri()
  126. if KSR.is_BYE() then
  127. KSR.setflag($FLT_ACC)
  128. KSR.setflag($FLT_ACCFAILED)
  129. elsif KSR.is_ACK() then
  130. ksr_route_natmanage()
  131. elsif KSR.is_NOTIFY() then
  132. KSR::RR.record_route()
  133. end
  134. ksr_route_relay()
  135. exit
  136. end
  137. if KSR.is_ACK() then
  138. if KSR::TM.t_check_trans() > 0 then
  139. ksr_route_relay()
  140. exit
  141. else
  142. exit
  143. end
  144. end
  145. #KSR.info("404ing within dialog")
  146. KSR::SL.sl_send_reply(404, "Not here");
  147. exit
  148. end
  149. # IP authorization and user authentication
  150. def ksr_route_auth()
  151. if !KSR.is_REGISTER() then
  152. # source IP allowed
  153. return if KSR::PERMISSIONS.allow_source_address(1).to_i > 0
  154. end
  155. if KSR.is_REGISTER() or KSR.is_myself_furi() then
  156. # auth requests
  157. if KSR::AUTH_DB.auth_check(KSR::PV.get("$fd"), "subscriber", 1).to_i < 0 then
  158. KSR::AUTH.auth_challenge(KSR::PV.get("$fd"), 0)
  159. exit
  160. end
  161. # user authenticated - remove auth header
  162. KSR::AUTH.consume_credentials() if !KSR.is_method_in("RP")
  163. end
  164. # if caller is not local subscriber, then check if it calls
  165. # a local destination, otherwise deny, not an open relay here
  166. if !KSR.is_myself_furi() && !KSR.is_myself_ruri() then
  167. KSR::SL.sl_send_reply(403, "Not relaying")
  168. exit
  169. end
  170. return
  171. end
  172. def ksr_route_natdetect()
  173. KSR.force_rport()
  174. if KSR::NATHELPER.nat_uac_test(19) > 0 then
  175. if KSR.is_REGISTER() then
  176. KSR::NATHELPER.fix_nated_register()
  177. elsif KSR::SIPUTILS.is_first_hop() > 0 then
  178. KSR::NATHELPER.set_contact_alias()
  179. end
  180. KSR.setflag($FLT_NATS)
  181. end
  182. return
  183. end
  184. def ksr_route_natmanage()
  185. if KSR::SIPUTILS.is_request() > 0 then
  186. if KSR::SIPUTILS.has_totag() > 0 then
  187. if KSR::RR.check_route_param("nat=yes") > 0 then
  188. KSR.info("Natmanage - nat=yes")
  189. KSR.setbflag($FLB_NATB)
  190. end
  191. end
  192. end
  193. #KSR.info("Natmanage - returning if NAT flags set")
  194. return if !KSR.isflagset($FLT_NATS) and !KSR.isbflagset($FLB_NATB)
  195. #KSR.info("Natmanage - RTPPROXY from here on")
  196. KSR::RTPPROXY::RTPPROXY_manage("co");
  197. if KSR::SIPUTILS.is_request() > 0 then
  198. if !KSR::SIPUTILS.has_totag() then
  199. if KSR::TMX.t_is_branch_route() > 0 then
  200. KSR::RR.add_rr_param(";nat=yes")
  201. end
  202. end
  203. end
  204. if KSR::SIPUTILS.is_reply() > 0 then
  205. if KSR.isbflagset($FLB_NATB) then
  206. KSR::NATHELPER.set_contact_alias()
  207. end
  208. end
  209. return
  210. end
  211. def ksr_route_dlguri()
  212. KSR::NATHELPER.handle_ruri_alias() if !KSR.isdsturiset()
  213. return
  214. end
  215. def ksr_branch_manage()
  216. KSR.dbg("new branch [#{KSR::PV.get("$T_branch_idx")}] to #{KSR::PV.get("$ru")}\n")
  217. ksr_route_natmanage()
  218. return
  219. end
  220. def ksr_onreply_manage()
  221. scode = KSR::PV.get("$rs");
  222. KSR.dbg("Reply status code is #{scode}")
  223. ksr_route_natmanage() if scode > 100 and scode <= 299
  224. return
  225. end
  226. def ksr_reply_route()
  227. #scode = KSR::PV.get("$rs");
  228. return
  229. end
  230. def ksr_onsend_route()
  231. return
  232. end
  233. def ksr_failure_manage()
  234. ksr_route_natmanage()
  235. return if KSR::TM.t_is_canceled() > 0
  236. return
  237. end
  238. def ksr_dialog_event(evname)
  239. KSR.info("===== dialog module triggered event: #{evname}");
  240. return
  241. end
  242. def ksr_tm_event(evname)
  243. KSR.info("===== TM module triggered event: #{evname}");
  244. return
  245. end
  246. def ksr_route_sipout()
  247. return if KSR.is_myself_ruri()
  248. KSR::HDR.append("P-Hint: outbound\r\n")
  249. ksr_route_relay()
  250. exit
  251. end
  252. def ksr_route_registrar()
  253. return if !KSR.is_REGISTER()
  254. if KSR.isflagset($FLT_NATS) then
  255. KSR.setbflag($FLB_NATB)
  256. # do SIP NAT pinging
  257. KSR.setbflag($FLB_NATSIPPING)
  258. end
  259. KSR.info("saving loc")
  260. if KSR::REGISTRAR.save("location", 0).to_i < 0 then
  261. KSR::SL.sl_reply_error()
  262. end
  263. exit
  264. end
  265. def ksr_route_location()
  266. rc = KSR::REGISTRAR.lookup("location").to_i
  267. if rc < 0 then
  268. KSR::TM.t_newtran()
  269. if rc == -1 or rc == -3 then
  270. KSR::SL.sl_send_reply(404, "Not Found")
  271. exit
  272. elsif rc == -2 then
  273. KSR::SL.sl_send_reply(405, "Method Not Allowed")
  274. exit
  275. end
  276. end
  277. # when routing via usrloc, log the missed calls also
  278. KSR.setflag($FLT_ACCMISSED) if KSR.is_INVITE()
  279. ksr_route_relay()
  280. exit
  281. end