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.
- data/sipper/README.rb +26 -0
- data/sipper/b2bua_controller.rb +163 -0
- data/sipper/b2bua_session_mixin.rb +24 -0
- data/sipper/base_controller.rb +425 -0
- data/sipper/bin/common.rb +42 -0
- data/sipper/bin/generate.rb +70 -0
- data/sipper/bin/project.rb +44 -0
- data/sipper/bin/run.rb +85 -0
- data/sipper/bin/run_smoke.rb +8 -0
- data/sipper/config/log4r.xml +71 -0
- data/sipper/controller_class_loader.rb +29 -0
- data/sipper/controller_selector.rb +119 -0
- data/sipper/controllers/invite_controller.rb +30 -0
- data/sipper/controllers/order.yaml +3 -0
- data/sipper/custom_message.rb +4 -0
- data/sipper/detached_session.rb +11 -0
- data/sipper/docs/manual.txt +1621 -0
- data/sipper/generators/README +12 -0
- data/sipper/generators/gen_controller.rb +228 -0
- data/sipper/generators/gen_project.rb +45 -0
- data/sipper/generators/gen_test.rb +72 -0
- data/sipper/generators/project_template_dir/Rakefile +56 -0
- data/sipper/generators/project_template_dir/config/sipper.cfg +31 -0
- data/sipper/generators/project_template_dir/controllers/README.txt +2 -0
- data/sipper/generators/project_template_dir/dot_sipper.proj +2 -0
- data/sipper/generators/project_template_dir/logs/README.txt +2 -0
- data/sipper/generators/project_template_dir/tests/README.txt +2 -0
- data/sipper/lib/smc/statemap.rb +194 -0
- data/sipper/logs/dialog_info_store +0 -0
- data/sipper/logs/r.cmd +6 -0
- data/sipper/logs/r.sh +6 -0
- data/sipper/media/sipper_media_client.rb +268 -0
- data/sipper/media/sipper_media_event.rb +43 -0
- data/sipper/media/sipper_media_manager.rb +145 -0
- data/sipper/media/sipper_media_proxy.rb +60 -0
- data/sipper/media/sipper_offer_answer.rb +285 -0
- data/sipper/message.rb +512 -0
- data/sipper/modified_pattern_formatter.rb +119 -0
- data/sipper/proxy_controller.rb +143 -0
- data/sipper/registration.rb +52 -0
- data/sipper/request.rb +109 -0
- data/sipper/response.rb +123 -0
- data/sipper/ruby_ext/module.rb +27 -0
- data/sipper/ruby_ext/mutable_class.rb +17 -0
- data/sipper/ruby_ext/object.rb +38 -0
- data/sipper/ruby_ext/pqueue.rb +190 -0
- data/sipper/ruby_ext/snapshot.rb +201 -0
- data/sipper/ruby_ext/string.rb +18 -0
- data/sipper/ruby_ext/time.rb +9 -0
- data/sipper/run/run_sipper1.rb +28 -0
- data/sipper/run/run_sipper2.rb +56 -0
- data/sipper/sdp/sdp.rb +257 -0
- data/sipper/sdp/sdp_generator.rb +131 -0
- data/sipper/sdp/sdp_parser.rb +136 -0
- data/sipper/session.rb +1952 -0
- data/sipper/session_manager.rb +170 -0
- data/sipper/session_recorder.rb +190 -0
- data/sipper/session_state/DialogState.sm +54 -0
- data/sipper/session_state/DialogState_sm.rb +337 -0
- data/sipper/session_state/dialog_routes.rb +141 -0
- data/sipper/sip_headers/header.rb +632 -0
- data/sipper/sip_headers/sipuri.rb +352 -0
- data/sipper/sip_logger.rb +65 -0
- data/sipper/sip_message_router.rb +231 -0
- data/sipper/sip_test_driver_controller.rb +10 -0
- data/sipper/sipper.rb +329 -0
- data/sipper/sipper_assertions.rb +21 -0
- data/sipper/sipper_configurator.rb +376 -0
- data/sipper/sipper_http/sipper_http_request_dispatcher.rb +71 -0
- data/sipper/sipper_http/sipper_http_response.rb +25 -0
- data/sipper/stray_message_manager.rb +40 -0
- data/sipper/test_completion_signaling_helper.rb +77 -0
- data/sipper/transaction/Ict.sm +59 -0
- data/sipper/transaction/Ict_sm.rb +430 -0
- data/sipper/transaction/Ist.sm +74 -0
- data/sipper/transaction/Ist_sm.rb +460 -0
- data/sipper/transaction/Nict.sm +51 -0
- data/sipper/transaction/Nict_sm.rb +325 -0
- data/sipper/transaction/Nist.sm +59 -0
- data/sipper/transaction/Nist_sm.rb +356 -0
- data/sipper/transaction/invite_client_transaction.rb +274 -0
- data/sipper/transaction/invite_server_transaction.rb +319 -0
- data/sipper/transaction/non_invite_client_transaction.rb +230 -0
- data/sipper/transaction/non_invite_server_transaction.rb +263 -0
- data/sipper/transaction/state_machine_wrapper.rb +58 -0
- data/sipper/transaction/transaction.rb +212 -0
- data/sipper/transport/base_transport.rb +84 -0
- data/sipper/transport/rel_unrel.rb +19 -0
- data/sipper/transport/transport_and_route_resolver.rb +67 -0
- data/sipper/transport/udp_transport.rb +156 -0
- data/sipper/transport_manager.rb +33 -0
- data/sipper/udp_session.rb +17 -0
- data/sipper/util/command_element.rb +62 -0
- data/sipper/util/compact_converter.rb +50 -0
- data/sipper/util/counter.rb +26 -0
- data/sipper/util/digest/digest_authorizer.rb +204 -0
- data/sipper/util/expectation_parser.rb +164 -0
- data/sipper/util/locator.rb +31 -0
- data/sipper/util/message_fill.rb +58 -0
- data/sipper/util/persistence/ps_sipper_map.rb +63 -0
- data/sipper/util/persistence/sipper_map.rb +41 -0
- data/sipper/util/sipper_util.rb +305 -0
- data/sipper/util/timer/sip_timer_helper.rb +26 -0
- data/sipper/util/timer/timer_manager.rb +80 -0
- data/sipper/util/timer/timer_task.rb +56 -0
- data/sipper/util/validations.rb +44 -0
- data/sipper/version.rb +10 -0
- data/sipper_test/_test_media_uas.rb +79 -0
- data/sipper_test/base_test_case.rb +31 -0
- data/sipper_test/c_134.txt +7 -0
- data/sipper_test/driven_sip_test_case.rb +96 -0
- data/sipper_test/gold.txt +10 -0
- data/sipper_test/gold_res.txt +8 -0
- data/sipper_test/gold_sub.txt +9 -0
- data/sipper_test/hello_sipper.au +0 -0
- data/sipper_test/in_sipper.au +0 -0
- data/sipper_test/nonrr_proxy.rb +17 -0
- data/sipper_test/order_tests.yaml +4 -0
- data/sipper_test/rake_res.txt +399 -0
- data/sipper_test/rr_proxy.rb +17 -0
- data/sipper_test/run_test.cmd +94 -0
- data/sipper_test/sip_test_case.rb +104 -0
- data/sipper_test/test2xx_retransmission.rb +80 -0
- data/sipper_test/test2xx_retransmission_with_limit.rb +81 -0
- data/sipper_test/test2xx_retransmission_with_nist.rb +91 -0
- data/sipper_test/test2xx_retransmission_with_txns.rb +94 -0
- data/sipper_test/test_address_header.rb +66 -0
- data/sipper_test/test_b2bua1.rb +130 -0
- data/sipper_test/test_b2bua2.rb +120 -0
- data/sipper_test/test_b2bua3.rb +160 -0
- data/sipper_test/test_b2bua4.rb +130 -0
- data/sipper_test/test_base_controller.rb +110 -0
- data/sipper_test/test_base_transport.rb +37 -0
- data/sipper_test/test_cancel.rb +21 -0
- data/sipper_test/test_cancel_after2xx.rb +81 -0
- data/sipper_test/test_cancel_retransmission.rb +105 -0
- data/sipper_test/test_cancel_with481.rb +83 -0
- data/sipper_test/test_cancel_with487.rb +70 -0
- data/sipper_test/test_cancel_with_ist_without_nist.rb +99 -0
- data/sipper_test/test_cancel_with_nist.rb +84 -0
- data/sipper_test/test_cancel_without487.rb +77 -0
- data/sipper_test/test_command_element.rb +38 -0
- data/sipper_test/test_compact_converter.rb +33 -0
- data/sipper_test/test_controller_class_loader.rb +37 -0
- data/sipper_test/test_controller_selector.rb +53 -0
- data/sipper_test/test_controller_using_compact_headers.rb +74 -0
- data/sipper_test/test_controller_using_header_order.rb +85 -0
- data/sipper_test/test_controller_using_ict.rb +64 -0
- data/sipper_test/test_controller_using_ict_with_non_success.rb +72 -0
- data/sipper_test/test_controller_using_ict_with_tcbh.rb +24 -0
- data/sipper_test/test_controller_using_ict_with_tcbh_no_action.rb +24 -0
- data/sipper_test/test_controller_using_ist.rb +70 -0
- data/sipper_test/test_controller_using_ist_with_tcbh.rb +24 -0
- data/sipper_test/test_controller_using_nict.rb +115 -0
- data/sipper_test/test_controller_using_nict_with_tcbh.rb +24 -0
- data/sipper_test/test_controller_using_nist.rb +63 -0
- data/sipper_test/test_controller_using_pre_existing_rs0.rb +73 -0
- data/sipper_test/test_controller_using_pre_existing_rs1.rb +75 -0
- data/sipper_test/test_controller_using_pre_existing_rs2.rb +71 -0
- data/sipper_test/test_controller_using_route_set.rb +86 -0
- data/sipper_test/test_controller_with_sdp.rb +80 -0
- data/sipper_test/test_controllers/cancel/order.yaml +2 -0
- data/sipper_test/test_controllers/cancel/uac_cancel_controller.rb +35 -0
- data/sipper_test/test_controllers/cancel/uas_cancel_controller.rb +25 -0
- data/sipper_test/test_controllers/class_loading/ordered/first_ordered_controller.rb +5 -0
- data/sipper_test/test_controllers/class_loading/ordered/order.yaml +3 -0
- data/sipper_test/test_controllers/class_loading/ordered/recond_ordered_controller.rb +6 -0
- data/sipper_test/test_controllers/class_loading/ordered/second_ordered_controller.rb +6 -0
- data/sipper_test/test_controllers/class_loading/unordered/first_unordered_controller.rb +7 -0
- data/sipper_test/test_controllers/class_loading/unordered/second_unordered_controller.rb +6 -0
- data/sipper_test/test_controllers/ctrl_trhandler/lib/transport_filters/my_transport_handler.rb +22 -0
- data/sipper_test/test_controllers/ctrl_trhandler/uac_tr_handler_controller.rb +27 -0
- data/sipper_test/test_controllers/ctrl_trhandler/uas_tr_handler_controller.rb +21 -0
- data/sipper_test/test_controllers/ete/order.yaml +1 -0
- data/sipper_test/test_controllers/ete/uac_controller.rb +39 -0
- data/sipper_test/test_controllers/ete/uas_controller.rb +34 -0
- data/sipper_test/test_controllers/extensions/extension_uac_controller.rb +24 -0
- data/sipper_test/test_controllers/extensions/extension_uas_controller.rb +35 -0
- data/sipper_test/test_controllers/extensions/lib/sipper_extensions/my_from_extension.rb +16 -0
- data/sipper_test/test_controllers/ict_tcbh/lib/transaction_handlers/app_ict_handler.rb +23 -0
- data/sipper_test/test_controllers/ict_tcbh/uac_ict_tcbh_controller.rb +27 -0
- data/sipper_test/test_controllers/ict_tcbh/uac_ict_tcbh_no_action_controller.rb +28 -0
- data/sipper_test/test_controllers/ict_tcbh/uas_ict_tcbh_controller.rb +29 -0
- data/sipper_test/test_controllers/ict_tcbh/uas_ict_tcbh_no_action_controller.rb +31 -0
- data/sipper_test/test_controllers/ist_tcbh/lib/app_ist_handler.rb +13 -0
- data/sipper_test/test_controllers/ist_tcbh/uac_ist_tcbh_controller.rb +22 -0
- data/sipper_test/test_controllers/ist_tcbh/uas_ist_tcbh_controller.rb +31 -0
- data/sipper_test/test_controllers/multi_trhandlers/lib/transport_filters/in_order.yaml +2 -0
- data/sipper_test/test_controllers/multi_trhandlers/lib/transport_filters/my_transport_handler1.rb +21 -0
- data/sipper_test/test_controllers/multi_trhandlers/lib/transport_filters/my_transport_handler2.rb +21 -0
- data/sipper_test/test_controllers/multi_trhandlers/lib/transport_filters/out_order.yaml +2 -0
- data/sipper_test/test_controllers/multi_trhandlers/uac_multi_tr_handler_controller.rb +27 -0
- data/sipper_test/test_controllers/multi_trhandlers/uas_multi_tr_handler_controller.rb +29 -0
- data/sipper_test/test_controllers/multiple/lib/blank_test.rb +2 -0
- data/sipper_test/test_controllers/multiple/uac_info_controller.rb +21 -0
- data/sipper_test/test_controllers/multiple/uac_msg_controller.rb +20 -0
- data/sipper_test/test_controllers/multiple/uas_info_controller.rb +15 -0
- data/sipper_test/test_controllers/multiple/uas_msg_controller.rb +14 -0
- data/sipper_test/test_controllers/nict_tcbh/lib/transaction_handlers/app_nict_handler.rb +13 -0
- data/sipper_test/test_controllers/nict_tcbh/uac_nict_tcbh_controller.rb +26 -0
- data/sipper_test/test_controllers/nict_tcbh/uas_nict_tcbh_controller.rb +20 -0
- data/sipper_test/test_controllers/state_machine_based/lib/CreditControl.sm +43 -0
- data/sipper_test/test_controllers/state_machine_based/lib/CreditControl_sm.rb +194 -0
- data/sipper_test/test_controllers/state_machine_based/order.yaml +1 -0
- data/sipper_test/test_controllers/state_machine_based/uac_message_controller.rb +34 -0
- data/sipper_test/test_controllers/state_machine_based/uas_message_controller.rb +44 -0
- data/sipper_test/test_controllers/stray_message/lib/sipper_extensions/my_stray_handler.rb +9 -0
- data/sipper_test/test_controllers/stray_message/stray_uac_controller.rb +24 -0
- data/sipper_test/test_controllers/stray_message/stray_uas_controller.rb +31 -0
- data/sipper_test/test_controllers/string/order.yaml +1 -0
- data/sipper_test/test_controllers/string/uac_controller.rb +29 -0
- data/sipper_test/test_controllers/string/uas_controller.rb +22 -0
- data/sipper_test/test_controllers/test_controller.rb +24 -0
- data/sipper_test/test_detached_session1.rb +78 -0
- data/sipper_test/test_dialog_routes.rb +139 -0
- data/sipper_test/test_digest_challenge1.rb +89 -0
- data/sipper_test/test_digest_challenge2.rb +90 -0
- data/sipper_test/test_dynamic_parse.rb +249 -0
- data/sipper_test/test_empty_sdp.rb +89 -0
- data/sipper_test/test_ete.rb +37 -0
- data/sipper_test/test_expectation_parser.rb +76 -0
- data/sipper_test/test_extensions.rb +28 -0
- data/sipper_test/test_freeze.rb +81 -0
- data/sipper_test/test_generated.rb +90 -0
- data/sipper_test/test_header_parameters.rb +75 -0
- data/sipper_test/test_header_parse.rb +141 -0
- data/sipper_test/test_http_client1.rb +84 -0
- data/sipper_test/test_http_client2.rb +90 -0
- data/sipper_test/test_ict_with_timeout.rb +62 -0
- data/sipper_test/test_in_dialog_request.rb +61 -0
- data/sipper_test/test_inline_controller.rb +67 -0
- data/sipper_test/test_invite_client_transaction.rb +272 -0
- data/sipper_test/test_invite_replace.rb +147 -0
- data/sipper_test/test_invite_retransmission.rb +90 -0
- data/sipper_test/test_invite_server_transaction.rb +208 -0
- data/sipper_test/test_lower_cseq.rb +79 -0
- data/sipper_test/test_media.rb +52 -0
- data/sipper_test/test_message.rb +392 -0
- data/sipper_test/test_method_specific_response_handling.rb +81 -0
- data/sipper_test/test_multi_homed1.rb +127 -0
- data/sipper_test/test_multi_homed2.rb +109 -0
- data/sipper_test/test_multi_homed_duplicate.rb +87 -0
- data/sipper_test/test_multi_homed_with_detached.rb +88 -0
- data/sipper_test/test_multiple.rb +49 -0
- data/sipper_test/test_multiple_contacts.rb +89 -0
- data/sipper_test/test_non2xx_retransmission_with_ist.rb +87 -0
- data/sipper_test/test_non_invite_client_transaction.rb +210 -0
- data/sipper_test/test_non_invite_retransmission.rb +91 -0
- data/sipper_test/test_non_invite_server_transaction.rb +202 -0
- data/sipper_test/test_offer_answer_prack.rb +103 -0
- data/sipper_test/test_pickup.rb +258 -0
- data/sipper_test/test_prack.rb +105 -0
- data/sipper_test/test_prack_store_and_dispatch.rb +101 -0
- data/sipper_test/test_prack_timer.rb +105 -0
- data/sipper_test/test_ps_sipper_map.rb +56 -0
- data/sipper_test/test_re_invite_uas_ongoing_ict.rb +81 -0
- data/sipper_test/test_re_invite_uas_ongoing_ist.rb +84 -0
- data/sipper_test/test_re_invite_with_ongoing_ict.rb +101 -0
- data/sipper_test/test_re_invite_with_ongoing_ist.rb +89 -0
- data/sipper_test/test_recorder_swap.rb +157 -0
- data/sipper_test/test_refer.rb +121 -0
- data/sipper_test/test_registeration_clearing.rb +97 -0
- data/sipper_test/test_registrar.rb +109 -0
- data/sipper_test/test_registration_controller.rb +73 -0
- data/sipper_test/test_registration_timeout.rb +90 -0
- data/sipper_test/test_remote_controller.rb +39 -0
- data/sipper_test/test_remote_target_update_on2xx.rb +140 -0
- data/sipper_test/test_request.rb +106 -0
- data/sipper_test/test_response.rb +40 -0
- data/sipper_test/test_response_without_to_tag.rb +92 -0
- data/sipper_test/test_rport.rb +88 -0
- data/sipper_test/test_sdp.rb +91 -0
- data/sipper_test/test_sdp_parser.rb +145 -0
- data/sipper_test/test_session.rb +276 -0
- data/sipper_test/test_session_callback_handler.rb +68 -0
- data/sipper_test/test_session_lifetime.rb +66 -0
- data/sipper_test/test_session_manager.rb +141 -0
- data/sipper_test/test_session_recorder.rb +145 -0
- data/sipper_test/test_session_state_user_defined.rb +84 -0
- data/sipper_test/test_session_states.rb +91 -0
- data/sipper_test/test_simple_dialog_state.rb +86 -0
- data/sipper_test/test_simple_re_invite.rb +86 -0
- data/sipper_test/test_sip_uri.rb +234 -0
- data/sipper_test/test_sipper_util.rb +45 -0
- data/sipper_test/test_smc_controller.rb +17 -0
- data/sipper_test/test_smoke.rb +80 -0
- data/sipper_test/test_stray.rb +28 -0
- data/sipper_test/test_stray_inline.rb +89 -0
- data/sipper_test/test_stray_res_acked.rb +103 -0
- data/sipper_test/test_stray_respond.rb +104 -0
- data/sipper_test/test_stray_retry.rb +92 -0
- data/sipper_test/test_stray_retry_failure.rb +93 -0
- data/sipper_test/test_stray_retry_initial.rb +100 -0
- data/sipper_test/test_strict_router_with_angled.rb +84 -0
- data/sipper_test/test_string_record.rb +31 -0
- data/sipper_test/test_subscribe_notify.rb +141 -0
- data/sipper_test/test_subscribe_notify_client_timeout.rb +158 -0
- data/sipper_test/test_subscribe_notify_dialog.rb +146 -0
- data/sipper_test/test_subscribe_notify_expires.rb +155 -0
- data/sipper_test/test_subscribe_notify_multiple_subscription.rb +157 -0
- data/sipper_test/test_subscribe_notify_server_timeout.rb +144 -0
- data/sipper_test/test_subsequent_unsent.rb +88 -0
- data/sipper_test/test_target_refresh_proxy_detached.rb +128 -0
- data/sipper_test/test_target_refresh_proxy_udp.rb +130 -0
- data/sipper_test/test_target_refresh_rr_proxy_udp.rb +133 -0
- data/sipper_test/test_target_refresh_with_new_port.rb +158 -0
- data/sipper_test/test_target_refresh_with_proxy1.rb +113 -0
- data/sipper_test/test_target_refresh_with_rr_update_proxy.rb +145 -0
- data/sipper_test/test_target_refresh_with_update_proxy.rb +144 -0
- data/sipper_test/test_target_refresh_with_update_proxy2.rb +139 -0
- data/sipper_test/test_timer_manager.rb +71 -0
- data/sipper_test/test_timer_task.rb +60 -0
- data/sipper_test/test_transport_handler.rb +19 -0
- data/sipper_test/test_transport_multi_handler.rb +18 -0
- data/sipper_test/test_udp_transport.rb +119 -0
- data/sipper_test/test_unparsed.rb +70 -0
- data/sipper_test/test_validations.rb +69 -0
- data/sipper_test/test_with_rr_proxy.rb +111 -0
- data/sipper_test/testmediacontroller.rb +71 -0
- data/sipper_test/tracing.rb +23 -0
- data/sipper_test/transaction_test_helper.rb +176 -0
- data/sipper_test/transport_filters.rb +26 -0
- data/sipper_test/ts_sipper.rb +91 -0
- data/sipper_test/ts_smoke.rb +3 -0
- data/sipper_test/tt.cmd +20 -0
- 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
|