Sipper 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,141 @@
1
+ require 'request'
2
+ require 'response'
3
+ require 'sipper_configurator'
4
+ require 'util/sipper_util'
5
+ require 'sip_headers/header'
6
+
7
+ # Maintains the route set and remote target for the dialog, also encapsulating the logic for
8
+ # target refresh and strict router manipulation.
9
+
10
+ class DialogRoutes
11
+
12
+ LRREGX = /;lr/.freeze
13
+
14
+ def initialize(pre_existing=nil)
15
+ prex = pre_existing || SipperConfigurator[:PreExistingRouteSet]
16
+ if prex
17
+ prex.each do |rt|
18
+ raise ArgumentError, "Only loose routes can be preloaded routes" unless rt.to_s =~ LRREGX
19
+ end
20
+ end
21
+ _assign_route_set(prex || [])
22
+ @remote_target = nil
23
+ @route_learned = false
24
+ @target_refreshed = false
25
+ end
26
+
27
+ def _assign_route_set(rarr)
28
+ @route_set = rarr.map do |r|
29
+ unless r.class == SipHeaders::Route
30
+ SipHeaders::Route.new.assign(r.to_s)
31
+ else
32
+ r
33
+ end
34
+ end
35
+ end
36
+
37
+ def request_received(request)
38
+ if SipperConfigurator[:TargetRefreshMethods].include? request.method
39
+ _update_rt(request)
40
+ end
41
+ return if @route_learned
42
+ if SipperConfigurator[:DialogCreatingMethods].include? request.method
43
+ if request[:record_route]
44
+ _assign_route_set(request.record_routes)
45
+ else
46
+ _assign_route_set([])
47
+ end
48
+ @route_learned = true
49
+ end
50
+ end
51
+
52
+
53
+ def response_received(response)
54
+ if SipperConfigurator[:TargetRefreshMethods].include?(response.get_request_method) && response.code != 100
55
+ _update_rt(response)
56
+ end
57
+ return if @route_learned
58
+ if SipperConfigurator[:DialogCreatingMethods].include? response.get_request_method
59
+ if response[:record_route]
60
+ _assign_route_set(response.record_routes.reverse)
61
+ else
62
+ _assign_route_set([])
63
+ end
64
+ @route_learned = true if response.code >= 200
65
+ end
66
+ end
67
+
68
+
69
+
70
+ # Returns the Request URI and route header values. [remote_target, [routes]], if there is no
71
+ # route set then an empty array for routes is returned.
72
+ # e.g. [remote_target, [], bool]
73
+ # The last element of the array is a boolean use_ruri which is true of the request uri should
74
+ # be used to determine the destination of the request, otherwise top route header should be
75
+ # used.
76
+ #
77
+ # RFC 3261 12.2.1.1
78
+ # The UAC uses the remote target and route set to build the Request-URI and Route header field
79
+ # of the request.
80
+ #
81
+ # If the route set is empty, the UAC MUST place the remote target URI into the
82
+ # Request-URI. The UAC MUST NOT add a Route header field to the request.
83
+ #
84
+ # If the route set is not empty, and the first URI in the route set contains the lr parameter
85
+ # (see Section 19.1.1), the UAC MUST place the remote target URI into the Request-URI and MUST
86
+ # include a Route header field containing the route set values in order, including all parameters.
87
+ #
88
+ # If the route set is not empty, and its first URI does not contain the lr parameter, the UAC MUST
89
+ # place the first URI from the route set into the Request-URI, stripping any parameters that are
90
+ # not allowed in a Request-URI. The UAC MUST add a Route header field containing the remainder
91
+ # of the route set values in order, including all parameters.
92
+ # The UAC MUST then place the remote target URI into the Route header field as the last value.
93
+ # todo - see what needs to be stripped while placing top route in ruri
94
+ def get_ruri_and_routes
95
+ _find_targets(@remote_target, @route_set)
96
+ end
97
+
98
+ # This will typically be used for initial request only when the controller changes the
99
+ # route headers or pushes new route headers. Here we completely ignore the @route_set and
100
+ # just go by the route headers. Note that the pre_existing route headers would already
101
+ # have been added to the request when the request was first created.
102
+ def get_ruri_and_routes_for_pushed_routes(request)
103
+ if rs=request[:route]
104
+ return _find_targets(@remote_target, rs)
105
+ else
106
+ return get_ruri_and_routes
107
+ end
108
+ end
109
+
110
+ def _find_targets(rt, rs)
111
+ if rs.empty?
112
+ [rt, [], true]
113
+ else
114
+ if rs[0].uri.has_param?(:lr)
115
+ [rt, rs, false]
116
+ else
117
+ [rs[0].uri, rs[1..-1]+[rt], true]
118
+ end
119
+ end
120
+ end
121
+
122
+ def _update_rt(msg)
123
+ self.remote_target = msg.contact.uri if msg.contact
124
+ end
125
+
126
+ def remote_target=(rt)
127
+ if @remote_target && @remote_target==rt
128
+ @target_refreshed = false
129
+ return
130
+ end
131
+ @remote_target = rt
132
+ @target_refreshed = true
133
+ end
134
+
135
+ def target_refreshed?
136
+ @target_refreshed
137
+ end
138
+
139
+ private :_update_rt, :_assign_route_set
140
+
141
+ end
@@ -0,0 +1,632 @@
1
+ require 'util/sipper_util'
2
+ require 'ruby_ext/object'
3
+ require 'facets/core/hash/reverse_merge'
4
+ require 'sip_logger'
5
+ require 'ruby_ext/mutable_class'
6
+ require 'sip_headers/sipuri'
7
+
8
+ module SipHeaders
9
+
10
+ # Base Header class
11
+ class Header
12
+ include SipLogger
13
+ # name is set in Message
14
+ attr_accessor :name
15
+ attr_accessor :frozen_str, :header_value, :header_params, :default_parse
16
+ protected :header_value, :header_params, :default_parse
17
+
18
+ alias_method :old_dup, :dup
19
+
20
+ ASSIGN = /=$/.freeze
21
+
22
+ def dup
23
+ obj = self.old_dup
24
+ obj.frozen_str = self.frozen_str.dup
25
+ obj.header_value = self.header_value.dup
26
+ obj.header_params = self.header_params.dup
27
+ obj.default_parse = self.default_parse.dup
28
+ obj
29
+ end
30
+
31
+
32
+ def to_s
33
+ if @frozen_str
34
+ @frozen_str
35
+ else
36
+ _format
37
+ end
38
+ end
39
+
40
+ def to_str
41
+ to_s
42
+ end
43
+
44
+ def freeze
45
+ @frozen_str = _format unless @frozen_str
46
+ super
47
+ end
48
+
49
+ def ==(other)
50
+ return true if self.object_id==other.object_id
51
+ self.to_s == other.to_s
52
+ end
53
+
54
+ # Returns the complete formatted header
55
+ # this is the default format method.
56
+ def _format
57
+ return nil unless self.header_value
58
+ str = self.header_value.dup
59
+ if self.header_params
60
+ self.header_params.each do |k,v|
61
+ if v
62
+ if v == ""
63
+ str << ";" << k
64
+ else
65
+ str << ";" << k << "=" << v.to_s
66
+ end
67
+ end
68
+ end
69
+ end
70
+ str
71
+ end
72
+ private :_format
73
+
74
+
75
+ # returns just the value of the header, sans params
76
+ def header_value
77
+ @header_value
78
+ end
79
+
80
+ # returns a hash of parameters
81
+ def header_params
82
+ @header_params
83
+ end
84
+
85
+ def cache_and_clear(val_str, iv_arr)
86
+ @frozen_str = val_str
87
+ @header_params = {}
88
+ clear_ivs(iv_arr)
89
+ end
90
+ protected :cache_and_clear
91
+
92
+ def assign(val_str, parse=true)
93
+ @default_parse = true
94
+ unless parse
95
+ cache_and_clear(val_str, [:@header_value])
96
+ else
97
+ @frozen_str = nil
98
+ @header_value, @header_params = SipperUtil.parameterize_header(val_str)
99
+ end
100
+ self
101
+ end
102
+
103
+ def default_parse?
104
+ @default_parse
105
+ end
106
+
107
+ def method_missing(m, *a)
108
+ if (md=(ASSIGN.match(m.to_s)))
109
+ name = md.pre_match
110
+ else
111
+ name = m.to_s
112
+ end
113
+ meta = class << self; self; end
114
+ meta.send(:define_method, name) { self.header_params[name] }
115
+ meta.send(:define_method, :"#{name}=") { |x| self.header_params[name] = x }
116
+ self.send m, *a
117
+ rescue => e
118
+ loge(e.backtrace.join("\n"))
119
+ end
120
+
121
+ def [](param)
122
+ @header_params[param.to_s]
123
+ end
124
+
125
+ def []= (param, val)
126
+ @header_params[param.to_s] = val
127
+ end
128
+
129
+ def has_param?(key)
130
+ @header_params.has_key?(key.to_s)
131
+ end
132
+
133
+
134
+ # for logging
135
+ def classname
136
+ "sipheaders_header"
137
+ end
138
+
139
+ end #Header Class
140
+
141
+ # To implement a new header have a method
142
+ # - assign() which parses the val_str, have
143
+ # - header_value() that returns a formatted value of the header without any params
144
+ # - in addition to have any specfic attribute accessor special to the header.
145
+
146
+
147
+ # Via class
148
+ # ---------
149
+ # Via = ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm)
150
+ # via-parm = sent-protocol LWS sent-by *( SEMI via-params )
151
+ # via-params = via-ttl / via-maddr
152
+ # / via-received / via-branch
153
+ # / via-extension
154
+ # via-ttl = "ttl" EQUAL ttl
155
+ # via-maddr = "maddr" EQUAL host
156
+ # via-received = "received" EQUAL (IPv4address / IPv6address)
157
+ # via-branch = "branch" EQUAL token
158
+ # via-extension = generic-param
159
+ # sent-protocol = protocol-name SLASH protocol-version
160
+ # SLASH transport
161
+ # protocol-name = "SIP" / token
162
+ # protocol-version = token
163
+ # transport = "UDP" / "TCP" / "TLS" / "SCTP"
164
+ # / other-transport
165
+ # sent-by = host [ COLON port ]
166
+ # ttl = 1*3DIGIT ; 0 to 255
167
+ # -----------
168
+ # Example - Via: SIP/2.0/UDP 172.17.31.207:6062;branch=z9hG4bK-1-0
169
+
170
+ class Via < Header
171
+
172
+ attr_accessor :protocol, :version, :transport, :sent_by_ip, :sent_by_port
173
+
174
+ PROTO_REGX = /(.+?)\/(.+?)\/(.+)$/
175
+ SENT_WPORT_REGX = /(.+?):(.+?);/
176
+ SENT_WOPORT_REGX = /(.+?);/
177
+
178
+ def initialize
179
+ @name = "Via"
180
+ super
181
+ end
182
+
183
+ def dup
184
+ obj = super
185
+ obj.protocol = self.protocol.dup
186
+ obj.version = self.version.dup
187
+ obj.transport = self.transport.dup
188
+ obj.sent_by_ip = self.sent_by_ip.dup
189
+ obj.sent_by_port = self.sent_by_port.dup
190
+ obj
191
+ end
192
+
193
+ def header_value
194
+ return nil unless @protocol
195
+ str = sprintf("%s/%s/%s %s", @protocol, @version, @transport, @sent_by_ip)
196
+ str << ":" << @sent_by_port if @sent_by_port
197
+ str
198
+ end
199
+
200
+
201
+ def assign(val_str, parse=true)
202
+ unless parse
203
+ cache_and_clear(val_str,
204
+ [:@protocol, :@version, :@transport, :@sent_by_ip, :@sent_by_port])
205
+ else
206
+ @frozen_str = nil
207
+ sent_protocol, sent_by_plus = val_str.split(" ")
208
+ m = PROTO_REGX.match(sent_protocol.strip)
209
+ @protocol = m[1]
210
+ @version = m[2]
211
+ @transport = m[3]
212
+ m = SENT_WPORT_REGX.match(sent_by_plus.strip)
213
+ if m
214
+ @sent_by_ip = m[1]
215
+ @sent_by_port = m[2]
216
+ else
217
+ m = SENT_WOPORT_REGX.match(sent_by_plus.strip)
218
+ if m
219
+ @sent_by_ip = m[1]
220
+ end
221
+ end
222
+ @header_params = SipperUtil.parameterize_header(val_str)[1]
223
+ end # parse or do not parse
224
+ self
225
+ end # assign method
226
+ end # via class
227
+
228
+
229
+ # Address header like To, From, Contact, Reply-To etc.
230
+ #
231
+ # To header
232
+ # ---------
233
+ # To = ( "To" / "t" ) HCOLON ( name-addr
234
+ # / addr-spec ) *( SEMI to-param )
235
+ # to-param = tag-param / generic-param
236
+ # name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
237
+ # addr-spec = SIP-URI / SIPS-URI / absoluteURI
238
+ #
239
+ # --------------
240
+ # Example
241
+ # To: Bob <sip:bob@biloxi.com>;tag=a6c85cf
242
+ #
243
+ class AddressHeader < Header
244
+ attr_accessor :display_name, :uri
245
+ attr_accessor :only_addr_spec
246
+ protected :only_addr_spec
247
+
248
+ DISPLAY_NAME_REGX = /^[\w ]*?</
249
+ URI_EXTRACT_REGX = /<.+?>/
250
+
251
+ def dup
252
+ obj = super
253
+ obj.display_name = self.display_name.dup
254
+ obj.uri = self.uri.dup
255
+ obj.only_addr_spec = self.only_addr_spec.dup
256
+ obj
257
+ end
258
+
259
+ def header_value
260
+ return nil unless @uri
261
+ if @display_name && @display_name.length>0
262
+ sprintf("%s <%s>", @display_name, @uri.to_s)
263
+ else
264
+ sprintf("<%s>", @uri.to_s)
265
+ end
266
+ end
267
+
268
+
269
+ def assign(val_str, parse=true)
270
+ unless parse
271
+ cache_and_clear(val_str,
272
+ [:@display_name, :@uri ])
273
+ else
274
+ @frozen_str = nil
275
+ m = DISPLAY_NAME_REGX.match(val_str)
276
+ if m
277
+ @display_name = m[0][0...-1].strip if m[0].length > 1
278
+ else
279
+ @display_name = ""
280
+ end
281
+ @uri, remainder = _extract_uri(val_str)
282
+ if remainder
283
+ @header_params = SipperUtil.parameterize_header(remainder)[1]
284
+ else
285
+ @header_params = {}
286
+ end
287
+ end # parse or assign
288
+ self
289
+ end # assign method
290
+
291
+ def _extract_uri(str)
292
+ if m = URI_EXTRACT_REGX.match(str)
293
+ #[m[0][1...-1], m.post_match]
294
+ [URI::SipUri.new.assign(m[0][1...-1]), m.post_match]
295
+ else
296
+ @only_addr_spec = true
297
+ #[str, nil]
298
+ [URI::SipUri.new.assign(str), nil]
299
+ end
300
+ end
301
+
302
+ private :_extract_uri
303
+
304
+ end
305
+
306
+ class To < AddressHeader
307
+ def initialize
308
+ @name = "To"
309
+ super
310
+ end
311
+ end
312
+
313
+ class From < AddressHeader
314
+ def initialize
315
+ @name = "From"
316
+ super
317
+ end
318
+ end
319
+
320
+
321
+ class Route < AddressHeader
322
+ def initialize
323
+ @name = "Route"
324
+ super
325
+ end
326
+ end
327
+
328
+ class RecordRoute < AddressHeader
329
+ def initialize
330
+ @name = "Record-Route"
331
+ super
332
+ end
333
+ end
334
+
335
+ class ReferTo < AddressHeader
336
+ def initialize
337
+ @name = "Refer-To"
338
+ super
339
+ end
340
+ end
341
+
342
+
343
+
344
+ class Contact < AddressHeader
345
+
346
+ def initialize
347
+ @name = "Contact"
348
+ super
349
+ end
350
+
351
+ def header_value
352
+ return nil unless @uri
353
+ if @display_name && @display_name.length>0
354
+ sprintf("%s <%s>", @display_name, @uri.to_s)
355
+ else
356
+ if @uri.to_s == "*"
357
+ "*"
358
+ else
359
+ sprintf("<%s>", @uri.to_s)
360
+ end
361
+ end
362
+ end
363
+ end
364
+
365
+ class PAssertedIdentity < AddressHeader
366
+
367
+ def initialize
368
+ @name = "P-Asserted-Identity"
369
+ super
370
+ end
371
+
372
+ end
373
+
374
+ # From RFC 2617
375
+ # challenge = "Digest" digest-challenge
376
+ # digest-challenge = 1#( realm | [ domain ] | nonce |
377
+ #[ opaque ] |[ stale ] | [ algorithm ] |
378
+ #[ qop-options ] | [auth-param] )
379
+ #domain = "domain" "=" <"> URI ( 1*SP URI ) <">
380
+ #URI = absoluteURI | abs_path
381
+ #nonce = "nonce" "=" nonce-value
382
+ #nonce-value = quoted-string
383
+ #opaque = "opaque" "=" quoted-string
384
+ #stale = "stale" "=" ( "true" | "false" )
385
+ #algorithm = "algorithm" "=" ( "MD5" | "MD5-sess" |
386
+ #token )
387
+ #qop-options = "qop" "=" <"> 1#qop-value <">
388
+ #qop-value = "auth" | "auth-int" | token
389
+ #
390
+ # Example --
391
+ # WWW-Authenticate: Digest realm="atlanta.com",
392
+ # domain="sip:boxesbybob.com", qop="auth",
393
+ # nonce="f84f1cec41e6cbe5aea9c8e88d359",
394
+ # opaque="", stale=FALSE, algorithm=MD5
395
+ # ------
396
+ # Example --
397
+ # Proxy-Authenticate: Digest realm="atlanta.com",
398
+ # domain="sip:ss1.carrier.com", qop="auth",
399
+ # nonce="f84f1cec41e6cbe5aea9c8e88d359",
400
+ # opaque="", stale=FALSE, algorithm=MD5
401
+
402
+ class Authenticate < Header
403
+ attr_accessor :scheme, :realm, :domain, :nonce, :opaque, :stale, :algorithm,
404
+ :qop
405
+
406
+ def initialize
407
+ @name = "Authenticate"
408
+ super
409
+ end
410
+
411
+ def dup
412
+ obj = super
413
+ obj.scheme = self.scheme.dup
414
+ obj.realm = self.realm.dup
415
+ obj.domain = self.domain.dup
416
+ obj.nonce = self.nonce.dup
417
+ obj.opaque = self.opaque.dup
418
+ obj.stale = self.stale.dup
419
+ obj.algorithm = self.algorithm.dup
420
+ obj.qop = self.qop.dup
421
+ obj
422
+ end
423
+
424
+ def header_value
425
+ return nil unless self.realm
426
+ str = sprintf("%s realm=%s", @scheme, self.realm)
427
+ str << ", domain=" << self.domain if self.domain
428
+ str << ", qop=" << self.qop if self.qop
429
+ str << ", nonce=" << self.nonce if self.nonce
430
+ str << ", opaque=" << self.opaque if self.opaque
431
+ str << ", stale=" << self.stale.to_s.upcase if self.stale
432
+ str << ", algorithm=" << self.algorithm if self.algorithm
433
+ str
434
+ end
435
+
436
+
437
+ def assign(val_str, parse=true)
438
+ unless parse
439
+ cache_and_clear(val_str,
440
+ [:realm, :domain, :nonce, :opaque, :stale, :algorithm, :qop])
441
+ else
442
+ @frozen_str = nil
443
+ @scheme, challenge = val_str.split(" ", 2)
444
+ challenge.split(",").each do |x|
445
+ k, v = x.split("=", 2)
446
+ self.send((k.strip+"=").to_sym, v.strip)
447
+ end
448
+ @header_params = {}
449
+
450
+ end # parse or assign
451
+ self
452
+ end # assign method
453
+ end
454
+
455
+ # -- See SipperUtil.classify
456
+ # ++
457
+ class WwwAuthenticate < Authenticate
458
+ def initialize
459
+ @name = "WWW-Authenticate"
460
+ super
461
+ end
462
+ end
463
+
464
+ class ProxyAuthenticate < Authenticate
465
+
466
+ def initialize
467
+ @name = "Proxy-Authenticate"
468
+ super
469
+ end
470
+
471
+ end
472
+
473
+
474
+ # Authorization header
475
+ # credentials = "Digest" digest-response
476
+ # digest-response = 1#( username | realm | nonce | digest-uri
477
+ # | response | [ algorithm ] | [cnonce] |
478
+ # [opaque] | [message-qop] |
479
+ # [nonce-count] | [auth-param] )
480
+ # username = "username" "=" username-value
481
+ # username-value = quoted-string
482
+ # digest-uri = "uri" "=" digest-uri-value
483
+ # digest-uri-value = request-uri ; As specified by HTTP/1.1
484
+ # message-qop = "qop" "=" qop-value
485
+ # cnonce = "cnonce" "=" cnonce-value
486
+ # cnonce-value = nonce-value
487
+ # nonce-count = "nc" "=" nc-value
488
+ # nc-value = 8LHEX
489
+ # response = "response" "=" request-digest
490
+ # request-digest = <"> 32LHEX <">
491
+ # LHEX = "0" | "1" | "2" | "3" |
492
+ # "4" | "5" | "6" | "7" |
493
+ # "8" | "9" | "a" | "b" |
494
+ # "c" | "d" | "e" | "f"
495
+ #
496
+ # Example -------------------
497
+ # Authorization: Digest username="bob",
498
+ # realm="biloxi.com",
499
+ # nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
500
+ # uri="sip:bob@biloxi.com",
501
+ # qop=auth,
502
+ # nc=00000001,
503
+ # cnonce="0a4f113b",
504
+ # response="6629fae49393a05397450978507c4ef1",
505
+ # opaque="5ccc069c403ebaf9f0171e9517f40e41"
506
+ # ------------------------------
507
+ class Authorization < Header
508
+ attr_accessor :scheme, :username, :realm, :nonce, :uri, :nc, :opaque, :algorithm,
509
+ :qop, :cnonce, :response
510
+
511
+ def initialize
512
+ @name = "Authorization"
513
+ super
514
+ end
515
+
516
+ def dup
517
+ obj = super
518
+ obj.scheme = self.scheme.dup
519
+ obj.username = self.username.dup
520
+ obj.realm = self.realm.dup
521
+ obj.nonce = self.nonce.dup
522
+ obj.uri = self.uri.dup
523
+ obj.nc = self.nc.dup
524
+ obj.opaque = self.opaque.dup
525
+ obj.algorithm = self.algorithm.dup
526
+ obj.qop = self.qop.dup
527
+ obj.cnonce = self.cnonce.dup
528
+ obj.response = self.response.dup
529
+ obj
530
+ end
531
+
532
+ def header_value
533
+ return nil unless self.username
534
+ str = sprintf("%s username=%s", @scheme, self.username)
535
+ str << ", realm=" << self.realm if self.realm
536
+ str << ", nonce=" << self.nonce if self.nonce
537
+ str << ", uri=" << self.uri.to_s if self.uri.to_s
538
+ str << ", qop=" << self.qop if self.qop
539
+ str << ", nc=" << self.nc if self.nc
540
+ str << ", cnonce=" << self.cnonce if self.cnonce
541
+ str << ", response=" << self.response if self.response
542
+ str << ", opaque=" << self.opaque if self.opaque
543
+ str << ", algorithm=" << self.algorithm if self.algorithm
544
+ str
545
+ end
546
+
547
+
548
+ def assign(val_str, parse=true)
549
+ unless parse
550
+ cache_and_clear(val_str,
551
+ [:realm, :username, :nonce, :uri, :nc, :opaque, :algorithm, :qop, :cnonce, :response])
552
+ else
553
+ @frozen_str = nil
554
+ @scheme, rest = val_str.split(" ", 2)
555
+ rest.split(",").each do |x|
556
+ k, v = x.split("=", 2)
557
+ if k =~ /uri/
558
+ self.send((k.strip+"=").to_sym, URI::SipUri.new.assign(v.strip))
559
+ else
560
+ self.send((k.strip+"=").to_sym, v.strip)
561
+ end
562
+ end
563
+ @header_params = {}
564
+ end # parse or assign
565
+ self
566
+ end # assign method
567
+
568
+ end
569
+
570
+ class ProxyAuthorization < Authorization
571
+ def initialize
572
+ @name = "Proxy-Authorization"
573
+ super
574
+ end
575
+ end
576
+
577
+ # AuthenticationInfo = "Authentication-Info" ":" auth-info
578
+ # auth-info = 1#(nextnonce | [ message-qop ]
579
+ # | [ response-auth ] | [ cnonce ]
580
+ # | [nonce-count] )
581
+ # nextnonce = "nextnonce" "=" nonce-value
582
+ # response-auth = "rspauth" "=" response-digest
583
+ # response-digest = <"> *LHEX <">
584
+ # example Authentication-Info: nextnonce="47364c23432d2e131a5fb210812c"
585
+ class AuthenticationInfo < Header
586
+ attr_accessor :nextnonce, :nc, :rspauth, :qop, :cnonce
587
+
588
+ def initialize
589
+ @name = "Authentication-Info"
590
+ super
591
+ end
592
+ def dup
593
+ obj = super
594
+ obj.nextnonce = self.nextnonce.dup
595
+ obj.nc = self.nc.dup
596
+ obj.rspauth = self.rspauth.dup
597
+ obj.qop = self.qop.dup
598
+ obj.cnonce = self.cnonce.dup
599
+ obj
600
+ end
601
+
602
+ def header_value
603
+ return nil unless self.nextnonce
604
+ str = ""
605
+ str << "nextnonce=" << self.nextnonce if self.nextnonce
606
+ str << ", qop=" << self.qop if self.qop
607
+ str << ", nc=" << self.nc if self.nc
608
+ str << ", cnonce=" << self.cnonce if self.cnonce
609
+ str << ", response=" << self.response if self.response
610
+ str << ", rspauth=" << self.rspauth if self.rspauth
611
+ str
612
+ end
613
+
614
+
615
+ def assign(val_str, parse=true)
616
+ unless parse
617
+ cache_and_clear(val_str,
618
+ [:nextnonce, :nc, :rspauth, :qop, :cnonce])
619
+ else
620
+ @frozen_str = nil
621
+ val_str.split(",").each do |x|
622
+ k, v = x.split("=", 2)
623
+ self.send((k.strip+"=").to_sym, v.strip)
624
+ end
625
+ @header_params = {}
626
+ end # parse or assign
627
+ self
628
+ end # assign method
629
+
630
+ end # auth info header
631
+
632
+ end # module