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
data/sipper/message.rb
ADDED
|
@@ -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
|