oversip_p 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +22 -0
  3. data/LICENSE +25 -0
  4. data/README.md +43 -0
  5. data/Rakefile +54 -0
  6. data/bin/oversip +184 -0
  7. data/etc/oversip.conf +274 -0
  8. data/etc/proxies.conf +145 -0
  9. data/etc/server.rb +315 -0
  10. data/etc/tls/ca/cacert.pem +3894 -0
  11. data/etc/tls/demo-tls.oversip.net.crt +17 -0
  12. data/etc/tls/demo-tls.oversip.net.key +15 -0
  13. data/etc/tls/upgrade-cacert.sh +12 -0
  14. data/etc/tls/utils/create-cert.rb +162 -0
  15. data/etc/tls/utils/get-sip-identities.rb +95 -0
  16. data/ext/common/c_util.h +74 -0
  17. data/ext/common/ruby_c_util.h +88 -0
  18. data/ext/sip_parser/common_headers.h +210 -0
  19. data/ext/sip_parser/ext_help.h +18 -0
  20. data/ext/sip_parser/extconf.rb +3 -0
  21. data/ext/sip_parser/sip_message_parser.c +29741 -0
  22. data/ext/sip_parser/sip_parser.h +250 -0
  23. data/ext/sip_parser/sip_parser_ruby.c +1370 -0
  24. data/ext/sip_parser/sip_uri_parser.c +39699 -0
  25. data/ext/stud/extconf.rb +43 -0
  26. data/ext/stun/ext_help.h +16 -0
  27. data/ext/stun/extconf.rb +3 -0
  28. data/ext/stun/stun_ruby.c +394 -0
  29. data/ext/utils/ext_help.h +14 -0
  30. data/ext/utils/extconf.rb +3 -0
  31. data/ext/utils/haproxy_protocol.c +6163 -0
  32. data/ext/utils/haproxy_protocol.h +27 -0
  33. data/ext/utils/ip_utils.c +5952 -0
  34. data/ext/utils/ip_utils.h +64 -0
  35. data/ext/utils/outbound_utils.c +3227 -0
  36. data/ext/utils/outbound_utils.h +27 -0
  37. data/ext/utils/utils_ruby.c +392 -0
  38. data/ext/utils/utils_ruby.h +76 -0
  39. data/ext/websocket_framing_utils/ext_help.h +18 -0
  40. data/ext/websocket_framing_utils/extconf.rb +3 -0
  41. data/ext/websocket_framing_utils/ws_framing_utils.h +47 -0
  42. data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
  43. data/ext/websocket_http_parser/ext_help.h +18 -0
  44. data/ext/websocket_http_parser/extconf.rb +3 -0
  45. data/ext/websocket_http_parser/ws_http_parser.c +1635 -0
  46. data/ext/websocket_http_parser/ws_http_parser.h +87 -0
  47. data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
  48. data/lib/oversip/config.rb +597 -0
  49. data/lib/oversip/config_validators.rb +126 -0
  50. data/lib/oversip/default_server.rb +52 -0
  51. data/lib/oversip/errors.rb +10 -0
  52. data/lib/oversip/fiber_pool.rb +56 -0
  53. data/lib/oversip/launcher.rb +635 -0
  54. data/lib/oversip/logger.rb +84 -0
  55. data/lib/oversip/modules/outbound_mangling.rb +56 -0
  56. data/lib/oversip/modules/user_assertion.rb +73 -0
  57. data/lib/oversip/proxies_config.rb +189 -0
  58. data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
  59. data/lib/oversip/sip/client.rb +428 -0
  60. data/lib/oversip/sip/client_transaction.rb +586 -0
  61. data/lib/oversip/sip/constants.rb +88 -0
  62. data/lib/oversip/sip/core.rb +217 -0
  63. data/lib/oversip/sip/launcher.rb +221 -0
  64. data/lib/oversip/sip/listeners/connection.rb +54 -0
  65. data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
  66. data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +22 -0
  67. data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
  68. data/lib/oversip/sip/listeners/ipv4_tls_server.rb +22 -0
  69. data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +22 -0
  70. data/lib/oversip/sip/listeners/ipv4_udp_server.rb +21 -0
  71. data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
  72. data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +22 -0
  73. data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
  74. data/lib/oversip/sip/listeners/ipv6_tls_server.rb +22 -0
  75. data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +22 -0
  76. data/lib/oversip/sip/listeners/ipv6_udp_server.rb +21 -0
  77. data/lib/oversip/sip/listeners/tcp_client.rb +97 -0
  78. data/lib/oversip/sip/listeners/tcp_connection.rb +202 -0
  79. data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
  80. data/lib/oversip/sip/listeners/tls_client.rb +125 -0
  81. data/lib/oversip/sip/listeners/tls_server.rb +88 -0
  82. data/lib/oversip/sip/listeners/tls_tunnel_connection.rb +89 -0
  83. data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
  84. data/lib/oversip/sip/listeners/udp_connection.rb +214 -0
  85. data/lib/oversip/sip/listeners.rb +24 -0
  86. data/lib/oversip/sip/message.rb +177 -0
  87. data/lib/oversip/sip/message_processor.rb +213 -0
  88. data/lib/oversip/sip/name_addr.rb +51 -0
  89. data/lib/oversip/sip/proxy.rb +324 -0
  90. data/lib/oversip/sip/request.rb +179 -0
  91. data/lib/oversip/sip/response.rb +37 -0
  92. data/lib/oversip/sip/rfc3263.rb +643 -0
  93. data/lib/oversip/sip/server_transaction.rb +295 -0
  94. data/lib/oversip/sip/sip.rb +76 -0
  95. data/lib/oversip/sip/tags.rb +39 -0
  96. data/lib/oversip/sip/timers.rb +55 -0
  97. data/lib/oversip/sip/transport_manager.rb +130 -0
  98. data/lib/oversip/sip/uac.rb +89 -0
  99. data/lib/oversip/sip/uac_request.rb +84 -0
  100. data/lib/oversip/sip/uri.rb +208 -0
  101. data/lib/oversip/syslog.rb +68 -0
  102. data/lib/oversip/system_callbacks.rb +45 -0
  103. data/lib/oversip/tls.rb +172 -0
  104. data/lib/oversip/utils.rb +30 -0
  105. data/lib/oversip/version.rb +21 -0
  106. data/lib/oversip/websocket/constants.rb +55 -0
  107. data/lib/oversip/websocket/http_request.rb +59 -0
  108. data/lib/oversip/websocket/launcher.rb +183 -0
  109. data/lib/oversip/websocket/listeners/connection.rb +51 -0
  110. data/lib/oversip/websocket/listeners/ipv4_ws_server.rb +22 -0
  111. data/lib/oversip/websocket/listeners/ipv4_wss_server.rb +22 -0
  112. data/lib/oversip/websocket/listeners/ipv4_wss_tunnel_server.rb +22 -0
  113. data/lib/oversip/websocket/listeners/ipv6_ws_server.rb +22 -0
  114. data/lib/oversip/websocket/listeners/ipv6_wss_server.rb +22 -0
  115. data/lib/oversip/websocket/listeners/ipv6_wss_tunnel_server.rb +22 -0
  116. data/lib/oversip/websocket/listeners/ws_server.rb +331 -0
  117. data/lib/oversip/websocket/listeners/wss_server.rb +88 -0
  118. data/lib/oversip/websocket/listeners/wss_tunnel_server.rb +133 -0
  119. data/lib/oversip/websocket/listeners.rb +13 -0
  120. data/lib/oversip/websocket/websocket.rb +13 -0
  121. data/lib/oversip/websocket/ws_framing.rb +545 -0
  122. data/lib/oversip/websocket/ws_sip_app.rb +120 -0
  123. data/lib/oversip.rb +127 -0
  124. data/test/oversip_test_helper.rb +19 -0
  125. data/test/test_http_parser.rb +73 -0
  126. data/test/test_name_addr.rb +27 -0
  127. data/test/test_name_addr_parser.rb +24 -0
  128. data/test/test_sip_message_parser.rb +168 -0
  129. data/test/test_sip_uri_parser.rb +56 -0
  130. data/test/test_uri.rb +68 -0
  131. data/thirdparty/stud/stud.tar.gz +0 -0
  132. metadata +334 -0
@@ -0,0 +1,213 @@
1
+ module OverSIP::SIP
2
+
3
+ module MessageProcessor
4
+
5
+ # Constants for efficiency.
6
+ MSG_TYPE = {
7
+ ::OverSIP::SIP::Request => "SIP request",
8
+ ::OverSIP::SIP::Response => "SIP response",
9
+ :outbound_keepalive => "Outbound keepalive"
10
+ }
11
+
12
+
13
+ def valid_message? parser
14
+ if header = parser.missing_core_header?
15
+ log_system_notice "ignoring #{MSG_TYPE[@msg.class]} missing #{header} header"
16
+ return false
17
+ elsif header = parser.duplicated_core_header?
18
+ log_system_notice "ignoring #{MSG_TYPE[@msg.class]} with duplicated #{header} header"
19
+ return false
20
+ end
21
+ return true
22
+ end
23
+ private :valid_message?
24
+
25
+
26
+ # Via ;received and ;rport stuff.
27
+ def add_via_received_rport
28
+ # - If ;rport is present ;received MUST also be set (RFC 3581).
29
+ # - If not add ;received according to RFC 3261 rules.
30
+ if @msg.via_rport?
31
+ via_received = @msg.source_ip
32
+ @msg.via_rport = @msg.source_port
33
+ else
34
+ via_received = (::OverSIP::Utils.compare_ips(@msg.via_sent_by_host, @msg.source_ip) ? nil : @msg.source_ip)
35
+ end
36
+
37
+ if via_received
38
+ via_params = ";branch=" << @msg.via_branch if @msg.via_branch
39
+ via_params << ";received=" << via_received if via_received
40
+ via_params << ";rport=" << @msg.via_rport.to_s if @msg.via_rport
41
+ via_params << ";alias" if @msg.via_alias?
42
+
43
+ if @msg.via_params
44
+ @msg.via_params.each { |k,v| via_params << ( v ? ";#{k}=#{v}" : ";#{k}" ) }
45
+ end
46
+
47
+ @msg.hdr_via[0] = "#{@msg.via_core_value}#{via_params}"
48
+ end
49
+ end
50
+ private :add_via_received_rport
51
+
52
+
53
+ # Reject the message in case it doesn't contain a Via branch compliant with RFC 3261
54
+ def check_via_branch
55
+ if @msg.via_branch_rfc3261
56
+ @msg.via_branch_id = @msg.via_branch[7..-1] # The branch without "z9hG4bK".
57
+ return true
58
+ end
59
+
60
+ if @msg.is_a? Request
61
+ unless @msg.sip_method == :ACK
62
+ log_system_notice "request doesn't contain a RFC 3261 Via branch => 400"
63
+ @msg.reply 400, "Via branch non RFC 3261 compliant"
64
+ else
65
+ log_system_notice "ACK doesn't contain a RFC 3261 Via branch, ignoring it"
66
+ end
67
+ else
68
+ log_system_notice "response doesn't contain a RFC 3261 Via branch, ignoring it"
69
+ end
70
+ false
71
+ end
72
+ private :check_via_branch
73
+
74
+
75
+ def process_request
76
+ # Run the user provided OverSIP::SipEvents.on_request() callback (unless the request
77
+ # it's a retransmission, a CANCEL or an ACK for a final non-2XX response).
78
+ unless check_transaction
79
+ # Check OverSIP status.
80
+ unless ::OverSIP.status == :running
81
+ case ::OverSIP.status
82
+ when :loading
83
+ @msg.reply 500, "Server Still Loading", [ "Retry-After: 5" ]
84
+ when :terminating
85
+ @msg.reply 500, "Server is Being Stopped"
86
+ end
87
+ return
88
+ end
89
+
90
+ # Create the antiloop identifier for this request.
91
+ @msg.antiloop_id = ::OverSIP::SIP::Tags.create_antiloop_id(@msg)
92
+
93
+ # Check loops.
94
+ if @msg.antiloop_id == @msg.via_branch_id[-32..-1]
95
+ @msg.reply 482, "Loop Detected"
96
+ return
97
+ end
98
+
99
+ # Initialize some attributes for the request.
100
+ @msg.tvars = {}
101
+ @msg.cvars = @msg.connection.cvars
102
+
103
+ # Run OverSIP::SipEvents.on_request within a fiber.
104
+ ::Fiber.new do
105
+ begin
106
+ ::OverSIP::SipEvents.on_request @msg
107
+ rescue ::Exception => e
108
+ log_system_error "error calling OverSIP::SipEvents.on_request() => 500:"
109
+ log_system_error e
110
+ @msg.reply 500, "Internal Error", ["Content-Type: text/plain"], "#{e.class}: #{e.message}"
111
+ end
112
+ end.resume
113
+ end
114
+ end
115
+ private :process_request
116
+
117
+
118
+ # Process a received response.
119
+ def process_response
120
+ case @msg.sip_method
121
+ when :INVITE
122
+ if client_transaction = @msg.connection.class.invite_client_transactions[@msg.via_branch_id]
123
+ client_transaction.receive_response(@msg)
124
+ return
125
+ end
126
+ when :ACK
127
+ when :CANCEL
128
+ if client_transaction = @msg.connection.class.invite_client_transactions[@msg.via_branch_id]
129
+ client_transaction.receive_response_to_cancel(@msg)
130
+ return
131
+ end
132
+ else
133
+ if client_transaction = @msg.connection.class.non_invite_client_transactions[@msg.via_branch_id]
134
+ client_transaction.receive_response(@msg)
135
+ return
136
+ end
137
+ end
138
+ log_system_debug "ignoring a response non matching a client transaction (#{@msg.sip_method} #{@msg.status_code})" if $oversip_debug
139
+ end
140
+ private :process_response
141
+
142
+
143
+ # Check transaction.
144
+ def check_transaction
145
+ case @msg.sip_method
146
+
147
+ when :INVITE
148
+ if server_transaction = @msg.connection.class.invite_server_transactions[@msg.via_branch_id]
149
+ # If the retranmission arrives via a different connection (for TCP/TLS/WS/WSS) then use
150
+ # the new one.
151
+ if @msg.connection == server_transaction.request.connection
152
+ log_system_debug "INVITE retransmission received" if $oversip_debug
153
+ else
154
+ log_system_debug "INVITE retransmission received via other connection, updating server transaction" if $oversip_debug
155
+ server_transaction.request.connection = @msg.connection
156
+ end
157
+ server_transaction.retransmit_last_response
158
+ return true
159
+ end
160
+
161
+ when :ACK
162
+ # If there is associated INVITE transaction (so it has been rejected)
163
+ # pass ACK to the transaction.
164
+ if server_transaction = @msg.connection.class.invite_server_transactions[@msg.via_branch_id]
165
+ server_transaction.receive_ack
166
+ return true
167
+ # Absorb ACK for statelessly generated final responses by us.
168
+ elsif ::OverSIP::SIP::Tags.check_totag_for_sl_reply(@msg.to_tag)
169
+ log_system_debug "absorving ACK for a stateless final response" if $oversip_debug
170
+ return true
171
+ else
172
+ log_system_debug "passing ACK to the core" if $oversip_debug
173
+ return false
174
+ end
175
+
176
+ when :CANCEL
177
+ if server_transaction = @msg.connection.class.invite_server_transactions[@msg.via_branch_id]
178
+ case state = server_transaction.state
179
+ when :proceeding
180
+ log_system_debug "CANCEL matches an INVITE server transaction in proceeding state => 200" if $oversip_debug
181
+ @msg.reply 200, "Cancelled"
182
+ server_transaction.receive_cancel(@msg)
183
+ else
184
+ log_system_debug "CANCEL matches an INVITE server transaction in #{state} state => 200" if $oversip_debug
185
+ @msg.reply 200, "Cancelled"
186
+ end
187
+ else
188
+ log_system_debug "CANCEL does not match an INVITE server transaction => 481" if $oversip_debug
189
+ @msg.reply 481
190
+ end
191
+ return true
192
+
193
+ else
194
+ if server_transaction = @msg.connection.class.non_invite_server_transactions[@msg.via_branch_id]
195
+ # If the retranmission arrives via a different connection (for TCP/TLS) then use
196
+ # the new one.
197
+ if @msg.connection == server_transaction.request.connection
198
+ log_system_debug "#{server_transaction.request.sip_method} retransmission received" if $oversip_debug
199
+ else
200
+ log_system_debug "#{server_transaction.request.sip_method} retransmission received via other connection, updating server transaction" if $oversip_debug
201
+ server_transaction.request.connection = @msg.connection
202
+ end
203
+ server_transaction.retransmit_last_response
204
+ return true
205
+ end
206
+
207
+ end
208
+ end # def check_transaction
209
+ private :check_transaction
210
+
211
+ end
212
+
213
+ end
@@ -0,0 +1,51 @@
1
+ module OverSIP::SIP
2
+
3
+ class NameAddr < OverSIP::SIP::Uri
4
+
5
+ attr_reader :display_name
6
+
7
+
8
+ def self.parse value
9
+ name_addr = ::OverSIP::SIP::MessageParser.parse_uri value, true
10
+ raise ::OverSIP::ParsingError, "invalid NameAddr #{value.inspect}" unless name_addr.is_a? (::OverSIP::SIP::NameAddr)
11
+ name_addr
12
+ end
13
+
14
+
15
+ def initialize display_name=nil, scheme=:sip, user=nil, host=nil, port=nil
16
+ @display_name = display_name
17
+ @scheme = scheme.to_sym
18
+ @user = user
19
+ @host = host
20
+ @host_type = ::OverSIP::Utils.ip_type(host) || :domain if host
21
+ @port = port
22
+
23
+ @name_addr_modified = true
24
+ @uri_modified = true
25
+ end
26
+
27
+ def display_name= value
28
+ @display_name = value
29
+ @name_addr_modified = true
30
+ end
31
+
32
+ def to_s
33
+ return @name_addr if @name_addr and not @name_addr_modified and not @uri_modified
34
+
35
+ @name_addr = ""
36
+ ( @name_addr << '"' << @display_name << '" ' ) if @display_name
37
+ @name_addr << "<" << uri << ">"
38
+
39
+ @name_addr_modified = false
40
+ @name_addr
41
+
42
+ end
43
+ alias :inspect :to_s
44
+
45
+ def modified?
46
+ @uri_modified or @name_addr_modified
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,324 @@
1
+ module OverSIP::SIP
2
+
3
+ class Proxy < Client
4
+
5
+ # If a SIP response is given then this method may offer other features such as replying 199.
6
+ def drop_response response=nil
7
+ @drop_response = true
8
+
9
+ # RFC 6228 (199 response).
10
+ # http://tools.ietf.org/html/rfc6228#section-6
11
+ if response and response.status_code >= 300 and
12
+ @request.sip_method == :INVITE and
13
+ @request.supported and @request.supported.include?("199")
14
+
15
+ @request.send :reply_199, response
16
+ end
17
+ end
18
+
19
+
20
+ def route request, dst_host=nil, dst_port=nil, dst_transport=nil
21
+ unless (@request = request).is_a? ::OverSIP::SIP::Request
22
+ raise ::OverSIP::RuntimeError, "request must be a OverSIP::SIP::Request instance"
23
+ end
24
+
25
+ @log_id = "Proxy #{@conf[:name]} #{@request.via_branch_id}"
26
+
27
+ # Create the server transaction if it doesn't exist yet.
28
+ @server_transaction = @request.server_transaction or case @request.sip_method
29
+ # Here it can arrive an INVITE, ACK-for-2XX and any method but CANCEL.
30
+ when :INVITE
31
+ InviteServerTransaction.new @request
32
+ when :ACK
33
+ else
34
+ NonInviteServerTransaction.new @request
35
+ end
36
+ @request.server_transaction ||= @server_transaction
37
+
38
+ # Set this core layer to the server transaction.
39
+ @request.server_transaction.core = self if @request.server_transaction
40
+
41
+ # NOTE: Routing can be based on incoming request for an Outbound (RFC 5626) connection
42
+ # or based on normal RFC 3263 procedures.
43
+
44
+ # If it's an incoming Outbound connection get the associated connection (but if dst_host is
45
+ # set then don't honor the Outbound connection).
46
+
47
+ if @request.incoming_outbound_requested? and not dst_host
48
+ @client_transaction = (::OverSIP::SIP::ClientTransaction.get_class @request).new self, @request, @conf, @request.route_outbound_flow_token
49
+
50
+ if @client_transaction.connection
51
+ add_routing_headers
52
+ @client_transaction.send_request
53
+ else
54
+ unless @request.sip_method == :ACK
55
+ log_system_debug "flow failed" if $oversip_debug
56
+
57
+ run_on_error_cbs 430, "Flow Failed", :flow_failed
58
+ unless @drop_response
59
+ @request.reply 430, "Flow Failed"
60
+ else
61
+ @drop_response = false
62
+ end
63
+ else
64
+ log_system_debug "flow failed for received ACK" if $oversip_debug
65
+ end
66
+ end
67
+
68
+ return
69
+ end
70
+
71
+
72
+ # If it's not an incoming Outbound connection (or explicit destination is set),
73
+ # let's perform RFC 3263 procedures.
74
+
75
+ # Check the request destination.
76
+ # If a destination is given use it. If not route based on request headers.
77
+
78
+ # Force the destination.
79
+ if dst_host
80
+ dst_scheme = :sip
81
+ dst_host_type = ::OverSIP::Utils.ip_type(dst_host) || :domain
82
+
83
+ # Or use top Route header.
84
+ elsif @request.routes
85
+ top_route = @request.routes[0]
86
+ dst_scheme = top_route.scheme
87
+ dst_host = top_route.host
88
+ dst_host_type = top_route.host_type
89
+ dst_port = top_route.port
90
+ dst_transport = top_route.transport_param
91
+
92
+ # Or use the Request URI.
93
+ else
94
+ dst_scheme = @request.ruri.scheme
95
+ dst_host = @request.ruri.host
96
+ dst_host_type = @request.ruri.host_type
97
+ dst_port = @request.ruri.port
98
+ dst_transport = @request.ruri.transport_param
99
+ end
100
+
101
+ # If the destination uri_host is an IPv6 reference, convert it to real IPv6.
102
+ if dst_host_type == :ipv6_reference
103
+ dst_host = ::OverSIP::Utils.normalize_ipv6(dst_host, true)
104
+ dst_host_type = :ipv6
105
+ end
106
+
107
+ # Loockup in the DNS cache of this proxy.
108
+ result = check_dns_cache dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
109
+
110
+ case result
111
+ when true
112
+ return
113
+ else # It can be String or nil, so use it as dns_cache_key param.
114
+ # Perform RFC 3263 procedures.
115
+ do_dns result, @request.via_branch_id, dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
116
+ end
117
+
118
+ end # def route
119
+
120
+
121
+ def receive_response response
122
+ log_system_debug "received response #{response.status_code}" if $oversip_debug
123
+
124
+ response.delete_header_top "Via"
125
+
126
+ if @request.server_transaction.valid_response? response.status_code
127
+ if response.status_code < 200 && ! @canceled
128
+ run_on_provisional_response_cbs response
129
+ elsif response.status_code >= 200 && response.status_code <= 299
130
+ run_on_success_response_cbs response
131
+ elsif response.status_code >= 300 && ! @canceled
132
+ if response.status_code == 503
133
+ if @conf[:dns_failover_on_503]
134
+ try_next_target nil, nil, response
135
+ return
136
+ else
137
+ # If the response is 503 convert it into 500 (RFC 3261 16.7).
138
+ response.status_code = 500
139
+ run_on_failure_response_cbs response
140
+ end
141
+ else
142
+ run_on_failure_response_cbs response
143
+ end
144
+ end
145
+ end
146
+
147
+ unless @drop_response
148
+ @request.reply_full response
149
+ else
150
+ @drop_response = false
151
+ end
152
+ end
153
+
154
+
155
+ # Since we don't implement parallel forking, directly send our CANCEL downstream.
156
+ def receive_cancel cancel
157
+ log_system_debug "server transaction canceled, cancelling pending client transaction" if $oversip_debug
158
+
159
+ @canceled = true
160
+ run_on_canceled_cbs
161
+
162
+ @client_transaction.do_cancel cancel
163
+ end
164
+
165
+
166
+ # Timer C for INVITE (method called by the client transaction).
167
+ def invite_timeout
168
+ run_on_invite_timeout_cbs
169
+
170
+ unless @drop_response
171
+ @request.reply 408, "INVITE Timeout"
172
+ end
173
+ @drop_response = true # Ignore the possible 487 got from the callee.
174
+ end
175
+
176
+
177
+
178
+ private
179
+
180
+
181
+ def add_routing_headers
182
+ # Don't add routing headers again if we are in DNS failover within the same Proxy instance.
183
+ # But we must run this method if it's an incoming request asking for Outbound usage (in this
184
+ # case @num_target is nil so the method continues).
185
+ return if @num_target and @num_target > 1
186
+
187
+ add_rr_path = false
188
+
189
+ # NOTE: As per RFC 6665 the proxy MUST add Record-Route to in-dialog NOTIFY's.
190
+ if (@request.initial? and @request.record_routing_aware?) or @request.sip_method == :NOTIFY or @conf[:record_route_all]
191
+ do_record_routing = @conf[:do_record_routing]
192
+
193
+ # Request has no previous RR/Path and current proxy performs record-routing.
194
+ # So add RR/Path.
195
+ if ! @request.in_rr && do_record_routing
196
+ add_rr_path = true
197
+
198
+ # Request has previous RR/Path and current proxy does not perform record-routing.
199
+ # So don't add RR/Path and remove the existing one.
200
+ elsif @request.in_rr && ! do_record_routing
201
+ case @request.in_rr
202
+ when :rr, :outgoing_outbound_rr, :incoming_outbound_rr, :both_outbound_rr
203
+ @request.delete_header_top "Record-Route"
204
+ when :path, :outgoing_outbound_path, :incoming_outbound_path, :both_outbound_path
205
+ @request.delete_header_top "Path"
206
+ end
207
+ @request.in_rr = nil
208
+
209
+ # Remaining cases are:
210
+ # - Request has previous RR/Path and current proxy performs record-routing.
211
+ # - Request has no previous RR/Path and current proxy does not perform record-routing.
212
+ # So don't add RR/Path.
213
+ end
214
+ end
215
+
216
+ unless @request.proxied
217
+ # Indicate that this request has been proxied (at least once).
218
+ @request.proxied = true
219
+
220
+ # Set the Max-Forwards header.
221
+ @request.headers["Max-Forwards"] = [ @request.new_max_forwards.to_s ] if @request.new_max_forwards
222
+ end
223
+
224
+ # Add Record-Route or Path header.
225
+ if add_rr_path
226
+ case @request.sip_method
227
+
228
+ # Path header (RFC 3327) for REGISTER.
229
+ when :REGISTER
230
+ if @request.outgoing_outbound_requested?
231
+ if @request.incoming_outbound_requested?
232
+ @request.in_rr = :both_outbound_path
233
+ else
234
+ @request.in_rr = :outgoing_outbound_path
235
+ end
236
+ @request.insert_header "Path", "<sip:" << @request.connection_outbound_flow_token << @request.connection.class.outbound_path_fragment
237
+ elsif @request.incoming_outbound_requested?
238
+ @request.in_rr = :incoming_outbound_path
239
+ @request.insert_header "Path", @request.connection.class.record_route
240
+ else
241
+ @request.in_rr = :path
242
+ # The request comes via UDP or via a connection made by the client.
243
+ if @request.connection.class.outbound_listener?
244
+ @request.insert_header "Path", @request.connection.class.record_route
245
+ # The request comes via a TCP/TLS connection made by OverSIP.
246
+ else
247
+ @request.insert_header "Path", @request.connection.record_route
248
+ end
249
+ end
250
+
251
+ # Record-Route for INVITE, SUBSCRIBE, REFER and in-dialog NOTIFY.
252
+ else
253
+ if @request.outgoing_outbound_requested?
254
+ if @request.incoming_outbound_requested?
255
+ @request.in_rr = :both_outbound_rr
256
+ else
257
+ @request.in_rr = :outgoing_outbound_rr
258
+ end
259
+ @request.insert_header "Record-Route", "<sip:" << @request.connection_outbound_flow_token << @request.connection.class.outbound_record_route_fragment
260
+ elsif @request.incoming_outbound_requested?
261
+ @request.in_rr = :incoming_outbound_rr
262
+ # The request comes via UDP or via a connection made by the client.
263
+ if @request.connection.class.outbound_listener?
264
+ @request.insert_header "Record-Route", @request.connection.class.record_route
265
+ # The request comes via a TCP/TLS connection made by OverSIP.
266
+ else
267
+ @request.insert_header "Record-Route", @request.connection.record_route
268
+ end
269
+ else
270
+ @request.in_rr = :rr
271
+ # The request comes via UDP or via a connection made by the client.
272
+ if @request.connection.class.outbound_listener?
273
+ @request.insert_header "Record-Route", "<sip:" << @request.connection_outbound_flow_token << @request.connection.class.outbound_record_route_fragment
274
+ # The request comes via a TCP/TLS connection made by OverSIP.
275
+ else
276
+ @request.insert_header "Record-Route", @request.connection.record_route
277
+ end
278
+ end
279
+
280
+ end
281
+ end
282
+
283
+ end # add_routing_headers
284
+
285
+
286
+ def no_more_targets status, reason, full_response, code
287
+ # If we have received a [3456]XX response from downstream then run @on_failure_response_cbs.
288
+ if full_response
289
+ run_on_failure_response_cbs full_response
290
+ unless @drop_response
291
+ # If the response is 503 convert it into 500 (RFC 3261 16.7).
292
+ full_response.status_code = 500 if full_response.status_code == 503
293
+ @request.reply_full full_response
294
+ else
295
+ @drop_response = false
296
+ end
297
+
298
+ # If not, generate the response according to the given status and reason.
299
+ else
300
+ run_on_error_cbs status, reason, code
301
+ unless @drop_response
302
+ @request.reply status, reason
303
+ else
304
+ @drop_response = false
305
+ end
306
+
307
+ end
308
+ end # no_more_targets
309
+
310
+
311
+ def do_dns_fail status, reason, code
312
+ run_on_error_cbs status, reason, code
313
+
314
+ unless @drop_response
315
+ @request.reply status, reason unless @request.sip_method == :ACK
316
+ else
317
+ @drop_response = false
318
+ end
319
+ end
320
+
321
+
322
+ end # class Proxy
323
+
324
+ end