Sipper 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (326) hide show
  1. data/sipper/README.rb +26 -0
  2. data/sipper/b2bua_controller.rb +163 -0
  3. data/sipper/b2bua_session_mixin.rb +24 -0
  4. data/sipper/base_controller.rb +425 -0
  5. data/sipper/bin/common.rb +42 -0
  6. data/sipper/bin/generate.rb +70 -0
  7. data/sipper/bin/project.rb +44 -0
  8. data/sipper/bin/run.rb +85 -0
  9. data/sipper/bin/run_smoke.rb +8 -0
  10. data/sipper/config/log4r.xml +71 -0
  11. data/sipper/controller_class_loader.rb +29 -0
  12. data/sipper/controller_selector.rb +119 -0
  13. data/sipper/controllers/invite_controller.rb +30 -0
  14. data/sipper/controllers/order.yaml +3 -0
  15. data/sipper/custom_message.rb +4 -0
  16. data/sipper/detached_session.rb +11 -0
  17. data/sipper/docs/manual.txt +1621 -0
  18. data/sipper/generators/README +12 -0
  19. data/sipper/generators/gen_controller.rb +228 -0
  20. data/sipper/generators/gen_project.rb +45 -0
  21. data/sipper/generators/gen_test.rb +72 -0
  22. data/sipper/generators/project_template_dir/Rakefile +56 -0
  23. data/sipper/generators/project_template_dir/config/sipper.cfg +31 -0
  24. data/sipper/generators/project_template_dir/controllers/README.txt +2 -0
  25. data/sipper/generators/project_template_dir/dot_sipper.proj +2 -0
  26. data/sipper/generators/project_template_dir/logs/README.txt +2 -0
  27. data/sipper/generators/project_template_dir/tests/README.txt +2 -0
  28. data/sipper/lib/smc/statemap.rb +194 -0
  29. data/sipper/logs/dialog_info_store +0 -0
  30. data/sipper/logs/r.cmd +6 -0
  31. data/sipper/logs/r.sh +6 -0
  32. data/sipper/media/sipper_media_client.rb +268 -0
  33. data/sipper/media/sipper_media_event.rb +43 -0
  34. data/sipper/media/sipper_media_manager.rb +145 -0
  35. data/sipper/media/sipper_media_proxy.rb +60 -0
  36. data/sipper/media/sipper_offer_answer.rb +285 -0
  37. data/sipper/message.rb +512 -0
  38. data/sipper/modified_pattern_formatter.rb +119 -0
  39. data/sipper/proxy_controller.rb +143 -0
  40. data/sipper/registration.rb +52 -0
  41. data/sipper/request.rb +109 -0
  42. data/sipper/response.rb +123 -0
  43. data/sipper/ruby_ext/module.rb +27 -0
  44. data/sipper/ruby_ext/mutable_class.rb +17 -0
  45. data/sipper/ruby_ext/object.rb +38 -0
  46. data/sipper/ruby_ext/pqueue.rb +190 -0
  47. data/sipper/ruby_ext/snapshot.rb +201 -0
  48. data/sipper/ruby_ext/string.rb +18 -0
  49. data/sipper/ruby_ext/time.rb +9 -0
  50. data/sipper/run/run_sipper1.rb +28 -0
  51. data/sipper/run/run_sipper2.rb +56 -0
  52. data/sipper/sdp/sdp.rb +257 -0
  53. data/sipper/sdp/sdp_generator.rb +131 -0
  54. data/sipper/sdp/sdp_parser.rb +136 -0
  55. data/sipper/session.rb +1952 -0
  56. data/sipper/session_manager.rb +170 -0
  57. data/sipper/session_recorder.rb +190 -0
  58. data/sipper/session_state/DialogState.sm +54 -0
  59. data/sipper/session_state/DialogState_sm.rb +337 -0
  60. data/sipper/session_state/dialog_routes.rb +141 -0
  61. data/sipper/sip_headers/header.rb +632 -0
  62. data/sipper/sip_headers/sipuri.rb +352 -0
  63. data/sipper/sip_logger.rb +65 -0
  64. data/sipper/sip_message_router.rb +231 -0
  65. data/sipper/sip_test_driver_controller.rb +10 -0
  66. data/sipper/sipper.rb +329 -0
  67. data/sipper/sipper_assertions.rb +21 -0
  68. data/sipper/sipper_configurator.rb +376 -0
  69. data/sipper/sipper_http/sipper_http_request_dispatcher.rb +71 -0
  70. data/sipper/sipper_http/sipper_http_response.rb +25 -0
  71. data/sipper/stray_message_manager.rb +40 -0
  72. data/sipper/test_completion_signaling_helper.rb +77 -0
  73. data/sipper/transaction/Ict.sm +59 -0
  74. data/sipper/transaction/Ict_sm.rb +430 -0
  75. data/sipper/transaction/Ist.sm +74 -0
  76. data/sipper/transaction/Ist_sm.rb +460 -0
  77. data/sipper/transaction/Nict.sm +51 -0
  78. data/sipper/transaction/Nict_sm.rb +325 -0
  79. data/sipper/transaction/Nist.sm +59 -0
  80. data/sipper/transaction/Nist_sm.rb +356 -0
  81. data/sipper/transaction/invite_client_transaction.rb +274 -0
  82. data/sipper/transaction/invite_server_transaction.rb +319 -0
  83. data/sipper/transaction/non_invite_client_transaction.rb +230 -0
  84. data/sipper/transaction/non_invite_server_transaction.rb +263 -0
  85. data/sipper/transaction/state_machine_wrapper.rb +58 -0
  86. data/sipper/transaction/transaction.rb +212 -0
  87. data/sipper/transport/base_transport.rb +84 -0
  88. data/sipper/transport/rel_unrel.rb +19 -0
  89. data/sipper/transport/transport_and_route_resolver.rb +67 -0
  90. data/sipper/transport/udp_transport.rb +156 -0
  91. data/sipper/transport_manager.rb +33 -0
  92. data/sipper/udp_session.rb +17 -0
  93. data/sipper/util/command_element.rb +62 -0
  94. data/sipper/util/compact_converter.rb +50 -0
  95. data/sipper/util/counter.rb +26 -0
  96. data/sipper/util/digest/digest_authorizer.rb +204 -0
  97. data/sipper/util/expectation_parser.rb +164 -0
  98. data/sipper/util/locator.rb +31 -0
  99. data/sipper/util/message_fill.rb +58 -0
  100. data/sipper/util/persistence/ps_sipper_map.rb +63 -0
  101. data/sipper/util/persistence/sipper_map.rb +41 -0
  102. data/sipper/util/sipper_util.rb +305 -0
  103. data/sipper/util/timer/sip_timer_helper.rb +26 -0
  104. data/sipper/util/timer/timer_manager.rb +80 -0
  105. data/sipper/util/timer/timer_task.rb +56 -0
  106. data/sipper/util/validations.rb +44 -0
  107. data/sipper/version.rb +10 -0
  108. data/sipper_test/_test_media_uas.rb +79 -0
  109. data/sipper_test/base_test_case.rb +31 -0
  110. data/sipper_test/c_134.txt +7 -0
  111. data/sipper_test/driven_sip_test_case.rb +96 -0
  112. data/sipper_test/gold.txt +10 -0
  113. data/sipper_test/gold_res.txt +8 -0
  114. data/sipper_test/gold_sub.txt +9 -0
  115. data/sipper_test/hello_sipper.au +0 -0
  116. data/sipper_test/in_sipper.au +0 -0
  117. data/sipper_test/nonrr_proxy.rb +17 -0
  118. data/sipper_test/order_tests.yaml +4 -0
  119. data/sipper_test/rake_res.txt +399 -0
  120. data/sipper_test/rr_proxy.rb +17 -0
  121. data/sipper_test/run_test.cmd +94 -0
  122. data/sipper_test/sip_test_case.rb +104 -0
  123. data/sipper_test/test2xx_retransmission.rb +80 -0
  124. data/sipper_test/test2xx_retransmission_with_limit.rb +81 -0
  125. data/sipper_test/test2xx_retransmission_with_nist.rb +91 -0
  126. data/sipper_test/test2xx_retransmission_with_txns.rb +94 -0
  127. data/sipper_test/test_address_header.rb +66 -0
  128. data/sipper_test/test_b2bua1.rb +130 -0
  129. data/sipper_test/test_b2bua2.rb +120 -0
  130. data/sipper_test/test_b2bua3.rb +160 -0
  131. data/sipper_test/test_b2bua4.rb +130 -0
  132. data/sipper_test/test_base_controller.rb +110 -0
  133. data/sipper_test/test_base_transport.rb +37 -0
  134. data/sipper_test/test_cancel.rb +21 -0
  135. data/sipper_test/test_cancel_after2xx.rb +81 -0
  136. data/sipper_test/test_cancel_retransmission.rb +105 -0
  137. data/sipper_test/test_cancel_with481.rb +83 -0
  138. data/sipper_test/test_cancel_with487.rb +70 -0
  139. data/sipper_test/test_cancel_with_ist_without_nist.rb +99 -0
  140. data/sipper_test/test_cancel_with_nist.rb +84 -0
  141. data/sipper_test/test_cancel_without487.rb +77 -0
  142. data/sipper_test/test_command_element.rb +38 -0
  143. data/sipper_test/test_compact_converter.rb +33 -0
  144. data/sipper_test/test_controller_class_loader.rb +37 -0
  145. data/sipper_test/test_controller_selector.rb +53 -0
  146. data/sipper_test/test_controller_using_compact_headers.rb +74 -0
  147. data/sipper_test/test_controller_using_header_order.rb +85 -0
  148. data/sipper_test/test_controller_using_ict.rb +64 -0
  149. data/sipper_test/test_controller_using_ict_with_non_success.rb +72 -0
  150. data/sipper_test/test_controller_using_ict_with_tcbh.rb +24 -0
  151. data/sipper_test/test_controller_using_ict_with_tcbh_no_action.rb +24 -0
  152. data/sipper_test/test_controller_using_ist.rb +70 -0
  153. data/sipper_test/test_controller_using_ist_with_tcbh.rb +24 -0
  154. data/sipper_test/test_controller_using_nict.rb +115 -0
  155. data/sipper_test/test_controller_using_nict_with_tcbh.rb +24 -0
  156. data/sipper_test/test_controller_using_nist.rb +63 -0
  157. data/sipper_test/test_controller_using_pre_existing_rs0.rb +73 -0
  158. data/sipper_test/test_controller_using_pre_existing_rs1.rb +75 -0
  159. data/sipper_test/test_controller_using_pre_existing_rs2.rb +71 -0
  160. data/sipper_test/test_controller_using_route_set.rb +86 -0
  161. data/sipper_test/test_controller_with_sdp.rb +80 -0
  162. data/sipper_test/test_controllers/cancel/order.yaml +2 -0
  163. data/sipper_test/test_controllers/cancel/uac_cancel_controller.rb +35 -0
  164. data/sipper_test/test_controllers/cancel/uas_cancel_controller.rb +25 -0
  165. data/sipper_test/test_controllers/class_loading/ordered/first_ordered_controller.rb +5 -0
  166. data/sipper_test/test_controllers/class_loading/ordered/order.yaml +3 -0
  167. data/sipper_test/test_controllers/class_loading/ordered/recond_ordered_controller.rb +6 -0
  168. data/sipper_test/test_controllers/class_loading/ordered/second_ordered_controller.rb +6 -0
  169. data/sipper_test/test_controllers/class_loading/unordered/first_unordered_controller.rb +7 -0
  170. data/sipper_test/test_controllers/class_loading/unordered/second_unordered_controller.rb +6 -0
  171. data/sipper_test/test_controllers/ctrl_trhandler/lib/transport_filters/my_transport_handler.rb +22 -0
  172. data/sipper_test/test_controllers/ctrl_trhandler/uac_tr_handler_controller.rb +27 -0
  173. data/sipper_test/test_controllers/ctrl_trhandler/uas_tr_handler_controller.rb +21 -0
  174. data/sipper_test/test_controllers/ete/order.yaml +1 -0
  175. data/sipper_test/test_controllers/ete/uac_controller.rb +39 -0
  176. data/sipper_test/test_controllers/ete/uas_controller.rb +34 -0
  177. data/sipper_test/test_controllers/extensions/extension_uac_controller.rb +24 -0
  178. data/sipper_test/test_controllers/extensions/extension_uas_controller.rb +35 -0
  179. data/sipper_test/test_controllers/extensions/lib/sipper_extensions/my_from_extension.rb +16 -0
  180. data/sipper_test/test_controllers/ict_tcbh/lib/transaction_handlers/app_ict_handler.rb +23 -0
  181. data/sipper_test/test_controllers/ict_tcbh/uac_ict_tcbh_controller.rb +27 -0
  182. data/sipper_test/test_controllers/ict_tcbh/uac_ict_tcbh_no_action_controller.rb +28 -0
  183. data/sipper_test/test_controllers/ict_tcbh/uas_ict_tcbh_controller.rb +29 -0
  184. data/sipper_test/test_controllers/ict_tcbh/uas_ict_tcbh_no_action_controller.rb +31 -0
  185. data/sipper_test/test_controllers/ist_tcbh/lib/app_ist_handler.rb +13 -0
  186. data/sipper_test/test_controllers/ist_tcbh/uac_ist_tcbh_controller.rb +22 -0
  187. data/sipper_test/test_controllers/ist_tcbh/uas_ist_tcbh_controller.rb +31 -0
  188. data/sipper_test/test_controllers/multi_trhandlers/lib/transport_filters/in_order.yaml +2 -0
  189. data/sipper_test/test_controllers/multi_trhandlers/lib/transport_filters/my_transport_handler1.rb +21 -0
  190. data/sipper_test/test_controllers/multi_trhandlers/lib/transport_filters/my_transport_handler2.rb +21 -0
  191. data/sipper_test/test_controllers/multi_trhandlers/lib/transport_filters/out_order.yaml +2 -0
  192. data/sipper_test/test_controllers/multi_trhandlers/uac_multi_tr_handler_controller.rb +27 -0
  193. data/sipper_test/test_controllers/multi_trhandlers/uas_multi_tr_handler_controller.rb +29 -0
  194. data/sipper_test/test_controllers/multiple/lib/blank_test.rb +2 -0
  195. data/sipper_test/test_controllers/multiple/uac_info_controller.rb +21 -0
  196. data/sipper_test/test_controllers/multiple/uac_msg_controller.rb +20 -0
  197. data/sipper_test/test_controllers/multiple/uas_info_controller.rb +15 -0
  198. data/sipper_test/test_controllers/multiple/uas_msg_controller.rb +14 -0
  199. data/sipper_test/test_controllers/nict_tcbh/lib/transaction_handlers/app_nict_handler.rb +13 -0
  200. data/sipper_test/test_controllers/nict_tcbh/uac_nict_tcbh_controller.rb +26 -0
  201. data/sipper_test/test_controllers/nict_tcbh/uas_nict_tcbh_controller.rb +20 -0
  202. data/sipper_test/test_controllers/state_machine_based/lib/CreditControl.sm +43 -0
  203. data/sipper_test/test_controllers/state_machine_based/lib/CreditControl_sm.rb +194 -0
  204. data/sipper_test/test_controllers/state_machine_based/order.yaml +1 -0
  205. data/sipper_test/test_controllers/state_machine_based/uac_message_controller.rb +34 -0
  206. data/sipper_test/test_controllers/state_machine_based/uas_message_controller.rb +44 -0
  207. data/sipper_test/test_controllers/stray_message/lib/sipper_extensions/my_stray_handler.rb +9 -0
  208. data/sipper_test/test_controllers/stray_message/stray_uac_controller.rb +24 -0
  209. data/sipper_test/test_controllers/stray_message/stray_uas_controller.rb +31 -0
  210. data/sipper_test/test_controllers/string/order.yaml +1 -0
  211. data/sipper_test/test_controllers/string/uac_controller.rb +29 -0
  212. data/sipper_test/test_controllers/string/uas_controller.rb +22 -0
  213. data/sipper_test/test_controllers/test_controller.rb +24 -0
  214. data/sipper_test/test_detached_session1.rb +78 -0
  215. data/sipper_test/test_dialog_routes.rb +139 -0
  216. data/sipper_test/test_digest_challenge1.rb +89 -0
  217. data/sipper_test/test_digest_challenge2.rb +90 -0
  218. data/sipper_test/test_dynamic_parse.rb +249 -0
  219. data/sipper_test/test_empty_sdp.rb +89 -0
  220. data/sipper_test/test_ete.rb +37 -0
  221. data/sipper_test/test_expectation_parser.rb +76 -0
  222. data/sipper_test/test_extensions.rb +28 -0
  223. data/sipper_test/test_freeze.rb +81 -0
  224. data/sipper_test/test_generated.rb +90 -0
  225. data/sipper_test/test_header_parameters.rb +75 -0
  226. data/sipper_test/test_header_parse.rb +141 -0
  227. data/sipper_test/test_http_client1.rb +84 -0
  228. data/sipper_test/test_http_client2.rb +90 -0
  229. data/sipper_test/test_ict_with_timeout.rb +62 -0
  230. data/sipper_test/test_in_dialog_request.rb +61 -0
  231. data/sipper_test/test_inline_controller.rb +67 -0
  232. data/sipper_test/test_invite_client_transaction.rb +272 -0
  233. data/sipper_test/test_invite_replace.rb +147 -0
  234. data/sipper_test/test_invite_retransmission.rb +90 -0
  235. data/sipper_test/test_invite_server_transaction.rb +208 -0
  236. data/sipper_test/test_lower_cseq.rb +79 -0
  237. data/sipper_test/test_media.rb +52 -0
  238. data/sipper_test/test_message.rb +392 -0
  239. data/sipper_test/test_method_specific_response_handling.rb +81 -0
  240. data/sipper_test/test_multi_homed1.rb +127 -0
  241. data/sipper_test/test_multi_homed2.rb +109 -0
  242. data/sipper_test/test_multi_homed_duplicate.rb +87 -0
  243. data/sipper_test/test_multi_homed_with_detached.rb +88 -0
  244. data/sipper_test/test_multiple.rb +49 -0
  245. data/sipper_test/test_multiple_contacts.rb +89 -0
  246. data/sipper_test/test_non2xx_retransmission_with_ist.rb +87 -0
  247. data/sipper_test/test_non_invite_client_transaction.rb +210 -0
  248. data/sipper_test/test_non_invite_retransmission.rb +91 -0
  249. data/sipper_test/test_non_invite_server_transaction.rb +202 -0
  250. data/sipper_test/test_offer_answer_prack.rb +103 -0
  251. data/sipper_test/test_pickup.rb +258 -0
  252. data/sipper_test/test_prack.rb +105 -0
  253. data/sipper_test/test_prack_store_and_dispatch.rb +101 -0
  254. data/sipper_test/test_prack_timer.rb +105 -0
  255. data/sipper_test/test_ps_sipper_map.rb +56 -0
  256. data/sipper_test/test_re_invite_uas_ongoing_ict.rb +81 -0
  257. data/sipper_test/test_re_invite_uas_ongoing_ist.rb +84 -0
  258. data/sipper_test/test_re_invite_with_ongoing_ict.rb +101 -0
  259. data/sipper_test/test_re_invite_with_ongoing_ist.rb +89 -0
  260. data/sipper_test/test_recorder_swap.rb +157 -0
  261. data/sipper_test/test_refer.rb +121 -0
  262. data/sipper_test/test_registeration_clearing.rb +97 -0
  263. data/sipper_test/test_registrar.rb +109 -0
  264. data/sipper_test/test_registration_controller.rb +73 -0
  265. data/sipper_test/test_registration_timeout.rb +90 -0
  266. data/sipper_test/test_remote_controller.rb +39 -0
  267. data/sipper_test/test_remote_target_update_on2xx.rb +140 -0
  268. data/sipper_test/test_request.rb +106 -0
  269. data/sipper_test/test_response.rb +40 -0
  270. data/sipper_test/test_response_without_to_tag.rb +92 -0
  271. data/sipper_test/test_rport.rb +88 -0
  272. data/sipper_test/test_sdp.rb +91 -0
  273. data/sipper_test/test_sdp_parser.rb +145 -0
  274. data/sipper_test/test_session.rb +276 -0
  275. data/sipper_test/test_session_callback_handler.rb +68 -0
  276. data/sipper_test/test_session_lifetime.rb +66 -0
  277. data/sipper_test/test_session_manager.rb +141 -0
  278. data/sipper_test/test_session_recorder.rb +145 -0
  279. data/sipper_test/test_session_state_user_defined.rb +84 -0
  280. data/sipper_test/test_session_states.rb +91 -0
  281. data/sipper_test/test_simple_dialog_state.rb +86 -0
  282. data/sipper_test/test_simple_re_invite.rb +86 -0
  283. data/sipper_test/test_sip_uri.rb +234 -0
  284. data/sipper_test/test_sipper_util.rb +45 -0
  285. data/sipper_test/test_smc_controller.rb +17 -0
  286. data/sipper_test/test_smoke.rb +80 -0
  287. data/sipper_test/test_stray.rb +28 -0
  288. data/sipper_test/test_stray_inline.rb +89 -0
  289. data/sipper_test/test_stray_res_acked.rb +103 -0
  290. data/sipper_test/test_stray_respond.rb +104 -0
  291. data/sipper_test/test_stray_retry.rb +92 -0
  292. data/sipper_test/test_stray_retry_failure.rb +93 -0
  293. data/sipper_test/test_stray_retry_initial.rb +100 -0
  294. data/sipper_test/test_strict_router_with_angled.rb +84 -0
  295. data/sipper_test/test_string_record.rb +31 -0
  296. data/sipper_test/test_subscribe_notify.rb +141 -0
  297. data/sipper_test/test_subscribe_notify_client_timeout.rb +158 -0
  298. data/sipper_test/test_subscribe_notify_dialog.rb +146 -0
  299. data/sipper_test/test_subscribe_notify_expires.rb +155 -0
  300. data/sipper_test/test_subscribe_notify_multiple_subscription.rb +157 -0
  301. data/sipper_test/test_subscribe_notify_server_timeout.rb +144 -0
  302. data/sipper_test/test_subsequent_unsent.rb +88 -0
  303. data/sipper_test/test_target_refresh_proxy_detached.rb +128 -0
  304. data/sipper_test/test_target_refresh_proxy_udp.rb +130 -0
  305. data/sipper_test/test_target_refresh_rr_proxy_udp.rb +133 -0
  306. data/sipper_test/test_target_refresh_with_new_port.rb +158 -0
  307. data/sipper_test/test_target_refresh_with_proxy1.rb +113 -0
  308. data/sipper_test/test_target_refresh_with_rr_update_proxy.rb +145 -0
  309. data/sipper_test/test_target_refresh_with_update_proxy.rb +144 -0
  310. data/sipper_test/test_target_refresh_with_update_proxy2.rb +139 -0
  311. data/sipper_test/test_timer_manager.rb +71 -0
  312. data/sipper_test/test_timer_task.rb +60 -0
  313. data/sipper_test/test_transport_handler.rb +19 -0
  314. data/sipper_test/test_transport_multi_handler.rb +18 -0
  315. data/sipper_test/test_udp_transport.rb +119 -0
  316. data/sipper_test/test_unparsed.rb +70 -0
  317. data/sipper_test/test_validations.rb +69 -0
  318. data/sipper_test/test_with_rr_proxy.rb +111 -0
  319. data/sipper_test/testmediacontroller.rb +71 -0
  320. data/sipper_test/tracing.rb +23 -0
  321. data/sipper_test/transaction_test_helper.rb +176 -0
  322. data/sipper_test/transport_filters.rb +26 -0
  323. data/sipper_test/ts_sipper.rb +91 -0
  324. data/sipper_test/ts_smoke.rb +3 -0
  325. data/sipper_test/tt.cmd +20 -0
  326. metadata +455 -0
@@ -0,0 +1,512 @@
1
+ require 'sip_logger'
2
+ require 'ruby_ext/string'
3
+ require 'util/timer/timer_task'
4
+ require 'sip_headers/header'
5
+ require 'util/compact_converter'
6
+ require 'util/sipper_util'
7
+ require 'media/sipper_media_event'
8
+ require 'sipper_http/sipper_http_response'
9
+
10
+ class Message
11
+
12
+ include SipLogger
13
+ include Enumerable
14
+
15
+ attr_accessor :incoming, :rcvd_from_info, :rcvd_at_info, :transaction
16
+
17
+ attr_reader :sdp
18
+
19
+ SIP_VER_PATT = /((?i)sip)\/[0-9]+\.[0-9]+/
20
+ TAGP_C = /(tag=)(.*?);/
21
+ TAGP_E = /(tag=)(.*?)$/
22
+
23
+ def initialize(*hh)
24
+ @headers = {}
25
+ define_from_hash hh[0] unless hh[0].nil?
26
+ #populated only for incoming messages
27
+ @rcvd_from_info = nil
28
+ @separate_mv_hdrs ||= []
29
+ end
30
+
31
+ def attributes
32
+ @attrs ||= {}
33
+ end
34
+
35
+ def is_request?
36
+ self.class == Request
37
+ end
38
+
39
+ def is_response?
40
+ self.class == Response
41
+ end
42
+
43
+ def Message.parse msg
44
+ # If the message is a SIP message received on wire then it of the form
45
+ #["msg", ["AF_INET", 33302, "localhost.localdomain", "127.0.0.1"]]
46
+ # otherwise it could be a timer task
47
+ return msg if msg.class <= SIP::TimerTask
48
+ return msg if msg.class <= Media::SipperMediaEvent
49
+ return msg if msg.class <= SipperHttp::SipperHttpResponse
50
+ msg_arr = msg[0].split("\n")
51
+ #SipLogger['siplog::message'].debug("In Message.parse_msg, rcvd from info is #{msg[1]}")
52
+ idx = SIP_VER_PATT =~ msg_arr[0]
53
+ raise ArgumentError, "Not a SIP message" unless idx
54
+ case
55
+ when idx==0
56
+ SipLogger['siplog::message'].debug("Parsing received response")
57
+ r = Response.parse msg_arr
58
+ when idx > 0
59
+ SipLogger['siplog::message'].debug("Parsing received request")
60
+ r = Request.parse( msg_arr, :received_ip=>msg[1][3], :received_port=>msg[1][1] )
61
+ else
62
+ raise ArgumentError, "Not a SIP message"
63
+ end
64
+ r.rcvd_from_info = msg[1] #["AF_INET", 33302, "localhost.localdomain", "127.0.0.1"]
65
+ r.rcvd_at_info = msg[2] #[ip, port]
66
+ return r
67
+ end
68
+
69
+
70
+ def each &block
71
+ @headers.each(&block)
72
+ end
73
+
74
+ def each_header &block
75
+ @headers.each_key(&block)
76
+ end
77
+
78
+ def each_value &block
79
+ @headers.each_value(&block)
80
+ end
81
+
82
+ def define_from_hash(header_hash)
83
+ logi("Defining headers from hash #{header_hash}")
84
+ header_hash.each { |k,v| self.send((k.to_s<<"=").to_sym, v)}
85
+ end
86
+
87
+ # The method to copy headers from a message.If you provide the particular headers,
88
+ # it will copy only those headers, else will copy all the headers.
89
+ def copy_from(from_msg, *hdrs)
90
+ logd("copy_from: copying headers #{hdrs.join(",")}")
91
+ if hdrs[0] == :_sipper_all
92
+ from_msg.each {|k,v| self[k] = v}
93
+ else
94
+ hdrs.each {|x| self[x] = from_msg[x] if from_msg[x]}
95
+ end
96
+
97
+ self
98
+ end
99
+
100
+ # This method is used to assign arbitrary values to any headers including
101
+ # system headers.The first argument is a symbol indicating the header name
102
+ # and second argument is the value.
103
+ def assign_unparsed(hdr_name, arg)
104
+ unless self.respond_to? hdr_name.to_sym
105
+ self.send((hdr_name.to_s+"=").to_sym, arg) { "do not call" }
106
+ end
107
+ @headers[hdr_name.to_sym] = if arg.nil?
108
+ nil
109
+ else
110
+ if arg.is_a?(SipHeaders::Header)
111
+ a
112
+ elsif arg.is_a?(Array)
113
+ a = arg.dup
114
+ else
115
+ a = arg.split(",")
116
+ end
117
+ unless hdr_name.to_s == "content"
118
+ b = a.map do |z|
119
+ _find_parser_and_parse(hdr_name.to_sym, z, false)
120
+ end # map
121
+ else
122
+ b = a
123
+ end # unless content
124
+ b
125
+ end
126
+ end
127
+
128
+ def method_missing(m,*a, &block)
129
+ if (md=(/=$/.match(m.to_s)))
130
+ m_name = md.pre_match
131
+ m_name_plural = m_name+"s"
132
+ Message.class_eval do
133
+
134
+ define_method(m_name.to_sym) do # accessor
135
+ if @headers[m_name.to_sym]
136
+ val = @headers[m_name.to_sym][0] || ''
137
+ else
138
+ nil
139
+ end
140
+ end
141
+
142
+ define_method(m_name_plural.to_sym) do # accessor for mv headers
143
+ @headers[m_name.to_sym]
144
+ end
145
+
146
+ define_method(("add_"+m_name).to_sym) do |arg| #append at the end
147
+ (@headers[m_name.to_sym] ||= []) << _find_parser_and_parse(m_name.to_sym, arg, true)
148
+ self
149
+ end
150
+
151
+ define_method(m) do |arg| #mutator
152
+ s_name = m_name.to_sym
153
+ if @headers[s_name] &&
154
+ @headers[s_name][0].respond_to?(:frozen_str) &&
155
+ @headers[s_name][0].frozen_str
156
+ then
157
+ return @headers[s_name]
158
+ end
159
+ @headers[s_name] = if arg.nil?
160
+ nil
161
+ else
162
+ if arg.is_a?(SipHeaders::Header)
163
+ a = [arg]
164
+ elsif arg.is_a?(Array)
165
+ a = arg.dup
166
+ elsif (m_name =~ /authenticat/ || m_name =~ /authorization/) # auth headers have "," in hdr values
167
+ a = [arg]
168
+ elsif m_name == "content"
169
+ a = arg.split("\r\n").map { |y| y.strip }
170
+ else
171
+ a = arg.split(",").map { |y| y.strip }
172
+ end
173
+ unless (m_name == "content")
174
+ b = a.map do |z|
175
+ _find_parser_and_parse(s_name, z, true)
176
+ end # map
177
+ else
178
+ b = a
179
+ end # unless content
180
+ b
181
+ end # assign from if
182
+ end # define_method
183
+
184
+ define_method(("pop_"+m_name).to_sym) do #pop top
185
+ if @headers[m_name.to_sym]
186
+ p = @headers[m_name.to_sym].shift
187
+ if @headers[m_name.to_sym].length == 0
188
+ @headers[m_name.to_sym] = nil
189
+ end
190
+ return p
191
+ else
192
+ nil
193
+ end
194
+ end
195
+
196
+ define_method(("push_"+m_name).to_sym) do |arg| #push top
197
+ if @headers[m_name.to_sym] && (hdr_sz=@headers[m_name.to_sym].size) > 0
198
+ @headers[m_name.to_sym].reverse! if hdr_sz > 1
199
+ @headers[m_name.to_sym].push(_find_parser_and_parse(m_name.to_sym, arg, true))
200
+ @headers[m_name.to_sym].reverse!
201
+ else
202
+ (@headers[m_name.to_sym] ||= []) << _find_parser_and_parse(m_name.to_sym, arg, true)
203
+ end
204
+ self
205
+ end
206
+
207
+ end #class_eval
208
+
209
+ logi("Adding header #{m}")
210
+ unless block_given?
211
+ send(m, *a, &block)
212
+ end
213
+ else
214
+ raise NoMethodError, "#{m}"
215
+ end
216
+ end
217
+
218
+ def [](hdr)
219
+ @headers[hdr]
220
+ end
221
+
222
+ def []= (hdr, val)
223
+ self.send((hdr.to_s+"=").to_sym, val)
224
+ end
225
+
226
+ def _find_parser_and_parse(hname, val, parse_option)
227
+ SipperUtil.find_parser_and_parse(hname, val, parse_option)
228
+ end
229
+ private :_find_parser_and_parse
230
+
231
+
232
+ # This method is to be invoked when the header is created but the content
233
+ # is not parsed. The string provided in "val" is directly written as the
234
+ # header content. The consequence is also a by-passing of any validations.
235
+ def assign_header_without_parse(hdr, val)
236
+ if self.respond_to?(hdr)
237
+ self.send(hdr, val) { false }
238
+ else
239
+ self.method_missing((hdr.to_s+"=").to_sym, val) { false }
240
+ end
241
+ end
242
+
243
+ def content_len
244
+ if @headers.has_key? :content
245
+ return @headers[:content].join("\r\n").length+2 # for the last element \r\n which doesnt add in join
246
+ else
247
+ return 0
248
+ end
249
+ end
250
+
251
+ # extracts the from tag from the message without a full parse of the header.
252
+ def from_tag
253
+ self.from.tag
254
+ end
255
+
256
+ # extracts the to tag from the message without a full parse of the header.
257
+ def to_tag
258
+ self.to.tag
259
+ end
260
+
261
+ # takes a full From/To header and just returns the value of the tag
262
+ def tag str
263
+ m = TAGP_C.match(str)
264
+ m = TAGP_E.match(str) unless m
265
+ if m
266
+ return m[2]
267
+ else
268
+ return nil
269
+ end
270
+ end
271
+
272
+
273
+ def parse_headers arr
274
+ if logger.debug?
275
+ #logd("In parse headers with array :")
276
+ #arr.each_with_index {|x,i| logd("## arr[#{i}] = #{x}")}
277
+ end
278
+ content_idx = -1
279
+ arr.each_with_index do |str, idx|
280
+ logd("parsing header : "+str)
281
+ if !str || str.strip.length == 0 # \r\n\r\n before content
282
+ content_idx = idx+1
283
+ break
284
+ end
285
+ h = str.split(":",2)
286
+ str_dc=h[0].strip.downcase
287
+ #todo think about a lookup at the message level of the
288
+ #header names and a symbols for fast processing.
289
+ str_dc = SipperUtil::CompactConverter.get_expanded(str_dc) if str_dc.size==1 && SipperUtil::CompactConverter.has_expanded_form?(str_dc)
290
+ hn = SipperUtil.methodize(str_dc) # header name
291
+ if @headers[hn.to_sym]
292
+ self.send(("add_"+hn.to_s).to_sym, h[1])
293
+ else
294
+ self.send((hn.to_s+"=").to_sym, h[1])
295
+ end
296
+ end
297
+ @headers[:content_length][0].freeze if @headers[:content_length]
298
+ #logd("content_idx = #{content_idx} and arr.length = #{arr.length}")
299
+ parse_content arr[content_idx..-1] if ((content_idx>0) && (content_idx< arr.length))
300
+ end
301
+
302
+ # Each value in the header hash is an array for MV, content is also a single array.
303
+ #
304
+ # 18.3 Framing
305
+ # In the case of message-oriented transports (such as UDP), if the message has a
306
+ # Content-Length header field, the message body is assumed to contain that many bytes.
307
+ # If there are additional bytes in the transport packet beyond the end of the body,
308
+ # they MUST be discarded. If the transport packet ends before the end of the message
309
+ # body, this is considered an error. If the message is a response, it MUST be discarded.
310
+ # If the message is a request, the element SHOULD generate a 400 (Bad Request) response.
311
+ # If the message has no Content-Length header field, the message body is assumed to end at
312
+ # the end of the transport packet.
313
+ # In the case of stream-oriented transports such as TCP, the Content-Length header field
314
+ # indicates the size of the body. The Content-Length header field MUST be used with
315
+ # stream oriented transports .
316
+ #
317
+ def parse_content arr
318
+ # see comment above on framing
319
+ if SipperConfigurator[:ProtocolCompliance]=='strict'
320
+ s = 0
321
+ len = self.content_length.to_s.to_i
322
+ self[:content] = arr.map do |x|
323
+ if s+x.length <= len
324
+ s+=x.length
325
+ x.strip
326
+ else
327
+ ws = x.length - x.strip.length
328
+ en = len-s-ws # consider white spaces upfront, as we will add \r\n while formatting
329
+ s = len # to stop loop
330
+ if en>0
331
+ x[0...en].strip
332
+ else
333
+ nil
334
+ end
335
+ end
336
+ end
337
+ self[:content] = self[:content].select {|x| x } # non nil
338
+ else # lax compliance
339
+ self[:content] = arr.map {|x| x.strip}
340
+ end
341
+ logw "Actual content length #{content_len} different from Content-Length header #{content_length}" if content_len != content_length.to_s.to_i
342
+ end
343
+
344
+ # todo test this feature
345
+ def format_as_separate_headers_for_mv(*hdrs)
346
+ @separate_mv_hdrs ||= []
347
+ @separate_mv_hdrs += hdrs
348
+ end
349
+
350
+ def header_order=(hoarr)
351
+ @header_order_arr = hoarr
352
+ end
353
+
354
+ def compact_headers=(charr)
355
+ @compact_headers = charr
356
+ end
357
+
358
+ def _header_name(k)
359
+ if @compact_headers && ((@compact_headers.include?(:all_headers)||@compact_headers.include?(k)) && SipperUtil::CompactConverter.has_compact_form?(k))
360
+ SipperUtil::CompactConverter.get_compact(k)
361
+ else
362
+ SipperUtil.headerize(k)
363
+ end
364
+ end
365
+
366
+
367
+ # gives the transaction id for the message. If the message is a RFC3261 message
368
+ # then the branch is taken otherwise it is computed from the message.
369
+ def txn_id
370
+ #todo check for magic cookie and evaluate the txn_id if the message is
371
+ #not a 3261 message
372
+ self.via.branch
373
+ end
374
+
375
+ # Returns the body of the message, which is another name for content but
376
+ # message.content does not return proper contents of the message. Instead
377
+ # message.contents (note the s in the end) returns the contents as an array.
378
+ # This method however returns the properly formatted message body.
379
+ def body
380
+ b = nil
381
+ if @headers[:content]
382
+ b = ""
383
+ @headers[:content].each {|x| b << x << "\r\n"}
384
+ end
385
+ b
386
+ end
387
+
388
+ def sdp=(sdp)
389
+ @sdp = sdp
390
+ sdp_csv_content = @sdp.format_sdp("\r\n")
391
+ self.content = sdp_csv_content
392
+ self.content_type = 'application/sdp'
393
+ end
394
+
395
+ # takes [body] and type as two arguments
396
+ def set_body(b, type)
397
+ self.content = b.join("\r\n")
398
+ self.content_type = type
399
+ end
400
+
401
+ def _format_message(smsg)
402
+ if @header_order_arr
403
+ ordered_headers = @header_order_arr + (@headers.keys - @header_order_arr)
404
+ else
405
+ ordered_headers = @headers.keys
406
+ end
407
+ ordered_headers.each do |k|
408
+ next if k == :content
409
+ v = @headers[k]
410
+ next if v.nil? # nil valued headers are hidden and popped headers leave []
411
+ if @separate_mv_hdrs && @separate_mv_hdrs.include?(k)
412
+ v.each {|val| smsg << _header_name(k) << ":" << " " << val.to_s << "\r\n" }
413
+ else
414
+ smsg << _header_name(k) << ":" << " " << (v.map {|val| val.to_s}).join(", ") << "\r\n"
415
+ end
416
+ end
417
+
418
+ smsg << "\r\n"
419
+ if ((_cl=content_len) > 0)
420
+ smsg << self.body
421
+ end
422
+ smsg
423
+ end
424
+
425
+ def short_to_s
426
+ if is_request?
427
+ self.method
428
+ elsif is_response?
429
+ self.code.to_s
430
+ end
431
+ end
432
+
433
+ private :tag, :_header_name
434
+ protected :_format_message
435
+
436
+ end
437
+
438
+ unless defined? PRIMED
439
+ addr = "sip:nasir@sipper.com"
440
+ f = "foo"
441
+ m = Message.new
442
+ m.accept = f
443
+ m.accept_contact = f
444
+ m.accept_encoding = f
445
+ m.accept_language = f
446
+ m.allow = f
447
+ m.authentication_info = 'nextnonce="d", qop=auth, nc=00000001, cnonce="0", rspauth="6"'
448
+ m.authorization = 'Digest username="b", realm="b.com", nonce="d", uri="sip:b@b.c", qop=auth, nc=00000001, cnonce="0", response="6", opaque="5"'
449
+ m.call_id = f
450
+ m.call_info = f
451
+ m.contact = addr
452
+ m.content_disposition = f
453
+ m.content_encoding = f
454
+ m.content_language = f
455
+ m.content_length = "1"
456
+ m.content_type = f
457
+ m.cseq = "1"
458
+ m.date = f
459
+ m.error_info = f
460
+ m.event = f
461
+ m.expires = "1"
462
+ m.from = addr
463
+ m.hide = f
464
+ m.history_info = f
465
+ m.identity = f
466
+ m.identity_info = f
467
+ m.in_reply_to = f
468
+ m.join = f
469
+ m.max_forwards = "1"
470
+ m.mime_version = f
471
+ m.min_expires = "1"
472
+ m.min_se = "1"
473
+ m.organization = f
474
+ m.p_asserted_identity = addr
475
+ m.p_charging_vector = f
476
+ m.p_visited_network_id = f
477
+ m.path = addr
478
+ m.priority = "1"
479
+ m.privacy = f
480
+ m.proxy_authenticate = 'Digest realm="a.c", domain="sip:s.c", nonce="f", stale=FALSE, algorithm=MD5'
481
+ m.proxy_authorization = 'Digest username="b", realm="b.com", nonce="d", uri="sip:b@b.c", qop=auth, nc=00000001, cnonce="0", response="6", opaque="5"'
482
+ m.proxy_require = f
483
+ m.rack = f
484
+ m.reason = f
485
+ m.record_route = addr
486
+ m.refer_sub = "false"
487
+ m.refer_to = addr
488
+ m.referred_by = addr
489
+ m.reject_contact = f
490
+ m.replaces = f
491
+ m.reply_to = addr
492
+ m.request_disposition = f
493
+ m.require = f
494
+ m.retry_after = "1"
495
+ m.route = addr
496
+ m.rseq = "1"
497
+ m.server = f
498
+ m.service_route = addr
499
+ m.session_expires = f
500
+ m.subject = f
501
+ m.subscription_state = f
502
+ m.supported = f
503
+ m.target_dialog = f
504
+ m.timestamp = f
505
+ m.to = addr
506
+ m.unsupported = f
507
+ m.user_agent = f
508
+ m.via = "SIP/2.0/UDP 127.0.0.1:6061;branch=z9hG4bK-2352-1-0"
509
+ m.warning = f
510
+ m.www_authenticate = 'Digest realm="a.c", domain="sip:s.c", nonce="f", stale=FALSE, algorithm=MD5'
511
+ PRIMED = true
512
+ end