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,33 @@
|
|
|
1
|
+
require 'transport/udp_transport'
|
|
2
|
+
|
|
3
|
+
class TransportManager
|
|
4
|
+
|
|
5
|
+
attr_reader :transports
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@transports = []
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def add_transport tp
|
|
12
|
+
@transports << tp
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
#["AF_INET", 33302, "localhost.localdomain", "127.0.0.1"]
|
|
16
|
+
def get_transport_for(transport_info)
|
|
17
|
+
@transports[0] #todo have the MH logic here
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# todo find a way to return a different
|
|
21
|
+
# this return transport suitable for sending to ip / port
|
|
22
|
+
def get_udp_transport_for(ip, port)
|
|
23
|
+
@transports[0]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# This returns a transport that matches the ip and port as given
|
|
27
|
+
def get_udp_transport_with(ip, port)
|
|
28
|
+
@transports.each do |tr|
|
|
29
|
+
return tr if (tr.ip == ip && tr.port == port)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'session'
|
|
2
|
+
require 'sip_logger'
|
|
3
|
+
|
|
4
|
+
class UdpSession < Session
|
|
5
|
+
include SipLogger
|
|
6
|
+
|
|
7
|
+
def initialize(rip, rp, rs, session_limit=nil, specified_transport = nil)
|
|
8
|
+
if specified_transport
|
|
9
|
+
tp = SIP::Locator[:Tm].get_udp_transport_with(specified_transport[0], specified_transport[1])
|
|
10
|
+
else
|
|
11
|
+
tp = SIP::Locator[:Tm].get_udp_transport_for(rip, rp) if rip && rp
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
super(tp, rip, rp, rs, session_limit)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# This is a generator helper class addding some commad level fucntionality in the generated
|
|
2
|
+
# code from the generate module.
|
|
3
|
+
|
|
4
|
+
require 'sip_logger'
|
|
5
|
+
require 'strscan'
|
|
6
|
+
require 'util/sipper_util'
|
|
7
|
+
require 'ruby_ext/string'
|
|
8
|
+
require 'ruby_ext/object'
|
|
9
|
+
|
|
10
|
+
require 'facets/core/string/first_char'
|
|
11
|
+
|
|
12
|
+
module SipperUtil
|
|
13
|
+
|
|
14
|
+
# One command element is like "@sleep 500" where the requirement is to add a sleep element for 500ms
|
|
15
|
+
# in the genarted code.
|
|
16
|
+
# Since a CommandElement is used alongside the ExpectationElement we have a direction attribute
|
|
17
|
+
# returning "@" sign.
|
|
18
|
+
# There is no space after @ sign for commands. The commands are methods defined on this class.
|
|
19
|
+
|
|
20
|
+
class CommandElement
|
|
21
|
+
|
|
22
|
+
include SipLogger
|
|
23
|
+
include SipperUtil
|
|
24
|
+
|
|
25
|
+
# Command id is a general purpose id which can be used to identify/differentiate
|
|
26
|
+
# commands.
|
|
27
|
+
attr_reader :command_str, :command, :command_id, :direction
|
|
28
|
+
|
|
29
|
+
@@id_counter = 0
|
|
30
|
+
|
|
31
|
+
def initialize(str)
|
|
32
|
+
s = StringScanner.new(str)
|
|
33
|
+
m = nil
|
|
34
|
+
@direction = s.getch
|
|
35
|
+
log_and_raise "Improper direction in cmd str", ArgumentError unless @direction == "@"
|
|
36
|
+
m = s.scan_until(/$/)
|
|
37
|
+
@command, *args = m.split
|
|
38
|
+
log_and_raise "Bad command str, no command", ArgumentError unless @command
|
|
39
|
+
@command_id = "id" + String(@@id_counter+=1)
|
|
40
|
+
@command_str = self.send @command.to_sym, *args
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# The command to make the flow sleep for specified amount of milliseconds.
|
|
44
|
+
# e.g. "@sleep_ms 500"
|
|
45
|
+
def sleep_ms(ms)
|
|
46
|
+
flt_ms = Float(ms)
|
|
47
|
+
log_and_raise "Negative argument is not allowed", ArgumentError if flt_ms < 0
|
|
48
|
+
"sleep #{flt_ms/1000.0}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Command to set a timer for this time, on expiration of this timer the next command or
|
|
52
|
+
# action is taken.
|
|
53
|
+
def set_timer(ms)
|
|
54
|
+
flt_ms = Float(ms)
|
|
55
|
+
log_and_raise "Negative argument is not allowed", ArgumentError if flt_ms < 0
|
|
56
|
+
"session.schedule_timer_for(\"#{@command_id}\", #{flt_ms})"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'facets/core/hash/inverse'
|
|
2
|
+
require 'util/sipper_util'
|
|
3
|
+
|
|
4
|
+
module SipperUtil
|
|
5
|
+
|
|
6
|
+
class CompactConverter
|
|
7
|
+
# Ref : http://www.iana.org/assignments/sip-parameters
|
|
8
|
+
COMP_TO_EXPANDED = {
|
|
9
|
+
"a" => "accept_contact",
|
|
10
|
+
"u" => "allow_events",
|
|
11
|
+
"i" => "call_id",
|
|
12
|
+
"m" => "contact",
|
|
13
|
+
"e" => "content_encoding",
|
|
14
|
+
"l" => "content_length",
|
|
15
|
+
"c" => "content_type",
|
|
16
|
+
"o" => "event",
|
|
17
|
+
"f" => "from",
|
|
18
|
+
"y" => "identity",
|
|
19
|
+
"n" => "identity_info",
|
|
20
|
+
"r" => "refer_to",
|
|
21
|
+
"b" => "referred_by",
|
|
22
|
+
"j" => "reject_contact",
|
|
23
|
+
"d" => "request_disposition",
|
|
24
|
+
"x" => "session_expires",
|
|
25
|
+
"s" => "subject",
|
|
26
|
+
"k" => "supported",
|
|
27
|
+
"t" => "to",
|
|
28
|
+
"v" => "via"
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
EXPANDED_TO_COMP = COMP_TO_EXPANDED.invert
|
|
32
|
+
|
|
33
|
+
def self.get_compact(ex_hdr)
|
|
34
|
+
EXPANDED_TO_COMP[SipperUtil.methodize(ex_hdr.to_s)]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.get_expanded(c_hdr)
|
|
38
|
+
SipperUtil.headerize(COMP_TO_EXPANDED[c_hdr.to_s.downcase])
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.has_compact_form?(ex_hdr)
|
|
42
|
+
EXPANDED_TO_COMP.has_key?(SipperUtil.methodize(ex_hdr.to_s))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.has_expanded_form?(c_hdr)
|
|
46
|
+
COMP_TO_EXPANDED.has_key?(c_hdr.to_s.downcase)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'monitor'
|
|
2
|
+
require 'singleton'
|
|
3
|
+
|
|
4
|
+
module SipperUtil
|
|
5
|
+
class Counter
|
|
6
|
+
include Singleton
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
@@class_lock = Monitor.new
|
|
10
|
+
@@counter = 0
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def next
|
|
14
|
+
@@class_lock.synchronize do
|
|
15
|
+
@@counter += 1
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def reset
|
|
20
|
+
@@class_lock.synchronize do
|
|
21
|
+
@@counter = 0
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
require 'util/sipper_util'
|
|
2
|
+
require 'digest/md5'
|
|
3
|
+
require 'base64'
|
|
4
|
+
require 'sipper_configurator'
|
|
5
|
+
require 'sip_headers/header'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Digest authorizer is a stateful entity that maintains the state from previous challenges and
|
|
9
|
+
# calculates the digest according to RFC.
|
|
10
|
+
module SipperUtil
|
|
11
|
+
class DigestAuthorizer
|
|
12
|
+
|
|
13
|
+
attr_writer :salt
|
|
14
|
+
|
|
15
|
+
def initialize(salt=nil)
|
|
16
|
+
@same_challenge = true
|
|
17
|
+
@salt = salt || SipperConfigurator[:DigestSalt] || "sipper_rocks"
|
|
18
|
+
@nonce_count_table = {}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Generated by UAC to respond to the challenge
|
|
22
|
+
def create_authorization_header(c, proxy, u, p, lsr)
|
|
23
|
+
@same_challenge = (@c.nonce == c.nonce) if @c
|
|
24
|
+
@c = c
|
|
25
|
+
@u = u
|
|
26
|
+
@p = p
|
|
27
|
+
@lsr = lsr
|
|
28
|
+
@cnonce = create_nonce
|
|
29
|
+
if @nonce_count_table[@c.nonce]
|
|
30
|
+
@nonce_count_table[@c.nonce] += 1
|
|
31
|
+
else
|
|
32
|
+
@nonce_count_table[@c.nonce] = 1
|
|
33
|
+
end
|
|
34
|
+
if proxy
|
|
35
|
+
atn_hdr = SipHeaders::ProxyAuthorization.new
|
|
36
|
+
else
|
|
37
|
+
atn_hdr = SipHeaders::Authorization.new
|
|
38
|
+
end
|
|
39
|
+
atn_hdr.scheme = @c.scheme
|
|
40
|
+
atn_hdr.username = quote_str @u
|
|
41
|
+
atn_hdr.realm = @c.realm
|
|
42
|
+
atn_hdr.nonce = @c.nonce
|
|
43
|
+
atn_hdr.uri = quote_str @lsr.uri.to_s
|
|
44
|
+
atn_hdr.nc = nonce_count()
|
|
45
|
+
atn_hdr.opaque = @c.opaque
|
|
46
|
+
atn_hdr.algorithm = @c.algorithm
|
|
47
|
+
atn_hdr.qop = @c.qop
|
|
48
|
+
atn_hdr.cnonce = quote_str @cnonce
|
|
49
|
+
atn_hdr.response = quote_str digest_response()
|
|
50
|
+
return atn_hdr
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def concat(*args)
|
|
57
|
+
args.join ':'
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Calculate H() as specified, this is just a simple hash.
|
|
61
|
+
# RFC 2617 : For the "MD5" and "MD5-sess" algorithms
|
|
62
|
+
# H(data) = MD5(data)
|
|
63
|
+
def h(data)
|
|
64
|
+
Digest::MD5.hexdigest data
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# RFC 2617 : KD(secret, data) = H(concat(secret, ":", data)
|
|
69
|
+
def kd(secret, data)
|
|
70
|
+
h concat(secret, data)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def user_string
|
|
75
|
+
concat(@u, unquote_str(@c.realm), @p)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# A1
|
|
80
|
+
# RFC 2617 3.2.2.2 A1
|
|
81
|
+
|
|
82
|
+
# If the "algorithm" directive's value is "MD5" or is unspecified, then
|
|
83
|
+
# A1 is:
|
|
84
|
+
#
|
|
85
|
+
# A1 = unq(username-value) ":" unq(realm-value) ":" passwd
|
|
86
|
+
# where
|
|
87
|
+
# passwd = < user's password >
|
|
88
|
+
#
|
|
89
|
+
# If the "algorithm" directive's value is "MD5-sess", then A1 is
|
|
90
|
+
# calculated only once - on the first request by the client following
|
|
91
|
+
# receipt of a WWW-Authenticate challenge from the server. It uses the
|
|
92
|
+
# server nonce from that challenge, and the first client nonce value to
|
|
93
|
+
# construct A1 as follows:
|
|
94
|
+
#
|
|
95
|
+
# A1 = H( unq(username-value) ":" unq(realm-value)
|
|
96
|
+
# ":" passwd )
|
|
97
|
+
# ":" unq(nonce-value) ":" unq(cnonce-value)
|
|
98
|
+
#
|
|
99
|
+
# This creates a 'session key' for the authentication of subsequent
|
|
100
|
+
# requests and responses which is different for each "authentication
|
|
101
|
+
# session", thus limiting the amount of material hashed with any one
|
|
102
|
+
# key.
|
|
103
|
+
def a1
|
|
104
|
+
if @c.algorithm == 'MD5-sess'
|
|
105
|
+
if @same_challenge
|
|
106
|
+
@a1_sess = concat(h(user_string), unquote_str(@c.nonce), unquote_str(@cnonce)) unless @a1_sess
|
|
107
|
+
@a1_sess
|
|
108
|
+
else
|
|
109
|
+
@a1_sess = concat(h(user_string), unquote_str(@c.nonce), unquote_str(@cnonce))
|
|
110
|
+
end
|
|
111
|
+
else
|
|
112
|
+
user_string
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# 3.2.2.3 A2
|
|
118
|
+
|
|
119
|
+
# If the "qop" directive's value is "auth" or is unspecified, then A2
|
|
120
|
+
# is:
|
|
121
|
+
#
|
|
122
|
+
# A2 = Method ":" digest-uri-value
|
|
123
|
+
# If the "qop" value is "auth-int", then A2 is:
|
|
124
|
+
#
|
|
125
|
+
# A2 = Method ":" digest-uri-value ":" H(entity-body)
|
|
126
|
+
#
|
|
127
|
+
# From 3261
|
|
128
|
+
# As a clarification to the calculation of the A2 value for
|
|
129
|
+
# message integrity assurance in the Digest authentication
|
|
130
|
+
# scheme, implementers should assume, when the entity-body is
|
|
131
|
+
# empty (that is, when SIP messages have no body) that the hash
|
|
132
|
+
# of the entity-body resolves to the MD5 hash of an empty
|
|
133
|
+
# string, or:
|
|
134
|
+
# H(entity-body) = MD5("") =
|
|
135
|
+
# "d41d8cd98f00b204e9800998ecf8427e"
|
|
136
|
+
def a2
|
|
137
|
+
if @c.qop && @c.qop == 'auth-int'
|
|
138
|
+
concat(@lsr.method, @lsr.uri.to_s, h(b=@lsr.body ? b : ""))
|
|
139
|
+
else
|
|
140
|
+
concat(@lsr.method, @lsr.uri.to_s)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# If the "qop" value is "auth" or "auth-int":
|
|
147
|
+
# request-digest = <"> < KD ( H(A1), unq(nonce-value)
|
|
148
|
+
# ":" nc-value
|
|
149
|
+
# ":" unq(cnonce-value)
|
|
150
|
+
# ":" unq(qop-value)
|
|
151
|
+
# ":" H(A2)
|
|
152
|
+
# ) <">
|
|
153
|
+
# If the "qop" directive is not present (this construction is for
|
|
154
|
+
# compatibility with RFC 2069):
|
|
155
|
+
# request-digest =
|
|
156
|
+
# <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) >
|
|
157
|
+
# <">
|
|
158
|
+
def digest_response
|
|
159
|
+
if @c.qop.nil?
|
|
160
|
+
kd(h(a1), concat(unquote_str(@c.nonce), h(a2)))
|
|
161
|
+
else
|
|
162
|
+
kd(h(a1), concat(unquote_str(@c.nonce),
|
|
163
|
+
nonce_count(),
|
|
164
|
+
unquote_str(@cnonce), unquote_str(@c.qop), h(a2)))
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def create_nonce
|
|
170
|
+
now = Time.now
|
|
171
|
+
time = now.strftime("%Y-%m-%d %H:%M:%S").to_s + ':' + now.usec.to_s
|
|
172
|
+
Base64.encode64(
|
|
173
|
+
concat(time, h(concat(time, @salt)))
|
|
174
|
+
).gsub("\n", '')[0..-3]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def create_opaque
|
|
178
|
+
s = []; 16.times { s << rand(127).chr }
|
|
179
|
+
h s.join
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def nonce_count
|
|
185
|
+
(@nonce_count_table[@c.nonce]).to_s(16).rjust 8, '0'
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def quote_str(str)
|
|
189
|
+
qs = '"'
|
|
190
|
+
qs << str << '"'
|
|
191
|
+
qs
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def unquote_str(str)
|
|
195
|
+
if str[0].chr == '"'
|
|
196
|
+
str[1...-1]
|
|
197
|
+
else
|
|
198
|
+
str
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
end # class
|
|
203
|
+
|
|
204
|
+
end # module
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
|
|
2
|
+
# 1. Wilcard for responses only 2xx, 1xx, 18x etc for responses
|
|
3
|
+
# 2. Alteration "< INVITE|SUBSCRIBE" optional request
|
|
4
|
+
# 3. Repetition "> INVITE {2,2}" have exactly 2. "< 18x {2,3}" have 2 or 3. "> 18x {,3}" at most 3"
|
|
5
|
+
# "> INVITE {0,}" variable. "< BYE {1,} at least 1.
|
|
6
|
+
# 4. For wildcard responses the first character in the message MUST be a number like 1xx is valid as
|
|
7
|
+
# is 41x but xxx or x00 is not valid. Character 'x' is used a wildcard.
|
|
8
|
+
# 5. The neutral expectation, the one recorded by the controller is recorded with the direction element
|
|
9
|
+
# "!" and the string should not contain any spaces.
|
|
10
|
+
# An element is satisfied if the minimum requirement is met for that.
|
|
11
|
+
# BNF Grammar is "DIRECTION MSGEXPRESSION|MSGEXPREESION REPETITION"
|
|
12
|
+
|
|
13
|
+
require 'sip_logger'
|
|
14
|
+
require 'strscan'
|
|
15
|
+
require 'util/sipper_util'
|
|
16
|
+
require 'ruby_ext/string'
|
|
17
|
+
require 'ruby_ext/object'
|
|
18
|
+
|
|
19
|
+
require 'facets/core/string/first_char'
|
|
20
|
+
|
|
21
|
+
module SipperUtil
|
|
22
|
+
|
|
23
|
+
# one expectation element is like "< INVITE {1,2}" or "> 1xx {0,}"
|
|
24
|
+
class ExpectationElement
|
|
25
|
+
|
|
26
|
+
include SipLogger
|
|
27
|
+
include SipperUtil
|
|
28
|
+
|
|
29
|
+
Directions = ["<", ">", "!", "@"]
|
|
30
|
+
MAX_REPEAT = 10000
|
|
31
|
+
|
|
32
|
+
attr_accessor :messages, :direction, :range, :satisfied
|
|
33
|
+
|
|
34
|
+
def initialize(str)
|
|
35
|
+
s = StringScanner.new(str)
|
|
36
|
+
m = nil
|
|
37
|
+
@direction = s.getch
|
|
38
|
+
log_and_raise "Improper direction in exp str", ArgumentError unless Directions.include?(@direction)
|
|
39
|
+
log_and_raise "Bad exp str, no space", ArgumentError unless s.scan(/\s+/) # space
|
|
40
|
+
if s.exist?(/\s+/)
|
|
41
|
+
m = s.scan_until(/\s+/).strip
|
|
42
|
+
else
|
|
43
|
+
m = s.scan_until(/$/)
|
|
44
|
+
end
|
|
45
|
+
@messages = m.split("|")
|
|
46
|
+
log_and_raise "Bad exp str, no message", ArgumentError unless @messages
|
|
47
|
+
# Enforce that wildcard is used rather than a check for say 200|202 etc for responses
|
|
48
|
+
if @messages[0] =~ /^\d/ && @messages.length>0
|
|
49
|
+
1.upto @messages.length-1 do |n|
|
|
50
|
+
log_and_raise "Bad exp str, use wildcard instead of |", ArgumentError if @messages[0][0] == @messages[n][0]
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
if s.eos?
|
|
54
|
+
@range = Range.new(1,1)
|
|
55
|
+
else
|
|
56
|
+
rep = s.scan_until(/$/)
|
|
57
|
+
log_and_raise "Bad repetition in exp str", ArgumentError unless(rep.first_char(1)=="{" && rep.last_char(1)=="}")
|
|
58
|
+
rep_str = rep[1...-1]
|
|
59
|
+
min, max = rep_str.split(",")
|
|
60
|
+
min = 0 unless (min && min.size>0)
|
|
61
|
+
max = MAX_REPEAT unless (max && max.size>0)
|
|
62
|
+
min = Integer(min)
|
|
63
|
+
max = Integer(max)
|
|
64
|
+
@range = Range.new(min, max)
|
|
65
|
+
end
|
|
66
|
+
@satisfied = false
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class ExpectationParser
|
|
74
|
+
# expectations
|
|
75
|
+
attr_accessor :exps
|
|
76
|
+
|
|
77
|
+
def parse(ex_ary)
|
|
78
|
+
@exps = []
|
|
79
|
+
ex_ary.each {|str| @exps << ExpectationElement.new(str) }
|
|
80
|
+
@idx = 0
|
|
81
|
+
@match_count = 0
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# input string is "> INVITE" or "< 100" etc.
|
|
85
|
+
def match(str)
|
|
86
|
+
d, m = str.split(" ")
|
|
87
|
+
_match(d, m)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# A recorded message will have a direction and message itself.
|
|
91
|
+
def _match(dir, message)
|
|
92
|
+
return [false, nil] if @idx >= @exps.length
|
|
93
|
+
matched = true
|
|
94
|
+
matched = false if dir != @exps[@idx].direction
|
|
95
|
+
if matched
|
|
96
|
+
if dir == ::SipperUtil::ExpectationElement::Directions[2] # "!"
|
|
97
|
+
matched = _match_neutral(message)
|
|
98
|
+
elsif message.first_char(1).int?
|
|
99
|
+
matched = _match_response(message)
|
|
100
|
+
else
|
|
101
|
+
matched = _match_request(message)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
if matched
|
|
105
|
+
@match_count += 1
|
|
106
|
+
return [true, nil] if @match_count < @exps[@idx].range.min
|
|
107
|
+
return [false,_unmatched_expectation] if @match_count > @exps[@idx].range.max
|
|
108
|
+
if @exps[@idx].range.include? @match_count
|
|
109
|
+
@exps[@idx].satisfied = true
|
|
110
|
+
return [true, nil]
|
|
111
|
+
end
|
|
112
|
+
else
|
|
113
|
+
if (@exps[@idx].satisfied || @exps[@idx].range.min == 0)
|
|
114
|
+
@idx += 1
|
|
115
|
+
@match_count = 0
|
|
116
|
+
return _match(dir, message) # match next
|
|
117
|
+
else
|
|
118
|
+
return [false,_unmatched_expectation]
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def _match_response(res)
|
|
124
|
+
return false if res.length != 3
|
|
125
|
+
matched = true
|
|
126
|
+
@exps[@idx].messages.each do |m|
|
|
127
|
+
return false unless m.first_char(1).int?
|
|
128
|
+
matched = true
|
|
129
|
+
0.upto(2) do |n|
|
|
130
|
+
unless m[n,1]=="x"
|
|
131
|
+
if m[n] != res[n]
|
|
132
|
+
matched = false
|
|
133
|
+
break
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
return true if matched
|
|
138
|
+
end
|
|
139
|
+
return matched
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def _match_request(req)
|
|
143
|
+
@exps[@idx].messages.each do |m|
|
|
144
|
+
return true if m == req
|
|
145
|
+
end
|
|
146
|
+
return false
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def _match_neutral(txt)
|
|
150
|
+
@exps[@idx].messages.each do |m|
|
|
151
|
+
return true if m == txt
|
|
152
|
+
end
|
|
153
|
+
return false
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def _unmatched_expectation
|
|
157
|
+
"#{@exps[@idx].direction} #{@exps[@idx].messages.join(' or ')} between #{@exps[@idx].range.min} and #{@exps[@idx].range.max}"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
private :_unmatched_expectation, :_match_response, :_match_request, :_match
|
|
161
|
+
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
end
|