oversip 1.2.1 → 1.3.0.dev1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/README.md +28 -4
  2. data/bin/oversip +1 -1
  3. data/etc/proxies.conf +10 -0
  4. data/etc/server.rb +13 -9
  5. data/ext/utils/haproxy_protocol.c +0 -3
  6. data/ext/utils/outbound_utils.c +1 -1
  7. data/ext/utils/utils_ruby.c +0 -1
  8. data/ext/websocket_http_parser/ws_http_parser.c +940 -1903
  9. data/ext/websocket_http_parser/ws_http_parser.h +1 -0
  10. data/lib/oversip/config_validators.rb +2 -2
  11. data/lib/oversip/launcher.rb +275 -240
  12. data/lib/oversip/master_process.rb +7 -2
  13. data/lib/oversip/proxies_config.rb +8 -1
  14. data/lib/oversip/sip/client.rb +304 -0
  15. data/lib/oversip/sip/client_transaction.rb +31 -36
  16. data/lib/oversip/sip/core.rb +7 -4
  17. data/lib/oversip/sip/launcher.rb +30 -30
  18. data/lib/oversip/sip/listeners/connection.rb +4 -0
  19. data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +1 -0
  20. data/lib/oversip/sip/listeners/ipv4_tls_server.rb +1 -0
  21. data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +1 -0
  22. data/lib/oversip/sip/listeners/ipv4_udp_server.rb +1 -0
  23. data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +1 -0
  24. data/lib/oversip/sip/listeners/ipv6_tls_server.rb +1 -0
  25. data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +1 -0
  26. data/lib/oversip/sip/listeners/ipv6_udp_server.rb +1 -0
  27. data/lib/oversip/sip/listeners/tcp_client.rb +26 -0
  28. data/lib/oversip/sip/listeners/tcp_connection.rb +7 -1
  29. data/lib/oversip/sip/listeners/tcp_server.rb +1 -1
  30. data/lib/oversip/sip/listeners/tls_client.rb +28 -24
  31. data/lib/oversip/sip/listeners/tls_server.rb +25 -8
  32. data/lib/oversip/sip/listeners/tls_tunnel_connection.rb +1 -24
  33. data/lib/oversip/sip/message.rb +2 -2
  34. data/lib/oversip/sip/message_processor.rb +23 -13
  35. data/lib/oversip/sip/{grammar/name_addr.rb → name_addr.rb} +11 -0
  36. data/lib/oversip/sip/proxy.rb +53 -227
  37. data/lib/oversip/sip/request.rb +15 -11
  38. data/lib/oversip/sip/response.rb +3 -3
  39. data/lib/oversip/sip/rfc3263.rb +2 -3
  40. data/lib/oversip/sip/tags.rb +1 -1
  41. data/lib/oversip/sip/transport_manager.rb +6 -5
  42. data/lib/oversip/sip/uac.rb +93 -0
  43. data/lib/oversip/sip/uac_request.rb +82 -0
  44. data/lib/oversip/sip/{grammar/uri.rb → uri.rb} +22 -0
  45. data/lib/oversip/version.rb +3 -3
  46. data/lib/oversip/websocket/launcher.rb +25 -25
  47. data/lib/oversip/websocket/listeners/connection.rb +4 -0
  48. data/lib/oversip/websocket/listeners/ipv4_ws_server.rb +1 -0
  49. data/lib/oversip/websocket/listeners/ipv4_wss_server.rb +1 -0
  50. data/lib/oversip/websocket/listeners/ipv4_wss_tunnel_server.rb +1 -0
  51. data/lib/oversip/websocket/listeners/ipv6_ws_server.rb +1 -0
  52. data/lib/oversip/websocket/listeners/ipv6_wss_server.rb +1 -0
  53. data/lib/oversip/websocket/listeners/ipv6_wss_tunnel_server.rb +1 -0
  54. data/lib/oversip/websocket/listeners/ws_server.rb +55 -26
  55. data/lib/oversip/websocket/listeners/wss_server.rb +26 -9
  56. data/lib/oversip/websocket/listeners/wss_tunnel_server.rb +14 -11
  57. data/lib/oversip/websocket/ws_framing.rb +6 -2
  58. data/lib/oversip.rb +3 -1
  59. data/test/test_http_parser.rb +3 -3
  60. data/test/test_uri.rb +18 -12
  61. metadata +91 -77
@@ -18,6 +18,8 @@ gem "escape_utils", ">= 0.2.4"
18
18
  require "escape_utils"
19
19
  gem "posix-spawn", ">= 0.3.6"
20
20
  require "posix-spawn"
21
+ gem "em-synchrony", ">=1.0.2"
22
+ require "em-synchrony"
21
23
 
22
24
 
23
25
  # OverSIP files.
@@ -29,8 +31,8 @@ require "oversip/sip/core.rb"
29
31
  require "oversip/sip/message.rb"
30
32
  require "oversip/sip/request.rb"
31
33
  require "oversip/sip/response.rb"
32
- require "oversip/sip/grammar/uri.rb"
33
- require "oversip/sip/grammar/name_addr.rb"
34
+ require "oversip/sip/uri.rb"
35
+ require "oversip/sip/name_addr.rb"
34
36
  require "oversip/sip/message_processor.rb"
35
37
  require "oversip/sip/listeners.rb"
36
38
  require "oversip/sip/launcher.rb"
@@ -40,7 +42,10 @@ require "oversip/sip/transport_manager.rb"
40
42
  require "oversip/sip/timers.rb"
41
43
  require "oversip/sip/tags.rb"
42
44
  require "oversip/sip/rfc3263.rb"
45
+ require "oversip/sip/client.rb"
43
46
  require "oversip/sip/proxy.rb"
47
+ require "oversip/sip/uac.rb"
48
+ require "oversip/sip/uac_request.rb"
44
49
 
45
50
  require "oversip/websocket/websocket.rb"
46
51
  require "oversip/websocket/ws_http_parser.so"
@@ -14,6 +14,8 @@ module OverSIP
14
14
  :use_dns => true,
15
15
  :use_dns_cache => true,
16
16
  :dns_cache_time => 300,
17
+ :use_blacklist => true,
18
+ :blacklist_time => 10,
17
19
  :use_naptr => true,
18
20
  :use_srv => true,
19
21
  :transport_preference => ["tls", "tcp", "udp"],
@@ -31,6 +33,8 @@ module OverSIP
31
33
  :use_dns => :boolean,
32
34
  :use_dns_cache => :boolean,
33
35
  :dns_cache_time => [ :fixnum, [ :greater_equal_than, 300 ] ],
36
+ :use_blacklist => :boolean,
37
+ :blacklist_time => [ :fixnum, [ :greater_equal_than, 2 ], [ :minor_equal_than, 600 ] ],
34
38
  :use_naptr => :boolean,
35
39
  :use_srv => :boolean,
36
40
  :transport_preference => [ [ :choices, %w{tls tcp udp}], :multi_value, :non_empty ],
@@ -163,7 +167,10 @@ module OverSIP
163
167
  @proxies[proxy][:has_sip_tls] = @proxies[proxy][:transport_preference].include?(:tls)
164
168
 
165
169
  # Add a hash for the DNS cache.
166
- @proxies[proxy][:dns_cache] = {} if @proxies[proxy][:use_dns_cache]
170
+ @proxies[proxy][:dns_cache] = {}
171
+
172
+ # Add a hash for the blacklist.
173
+ @proxies[proxy][:blacklist] = {}
167
174
  end
168
175
  end
169
176
 
@@ -0,0 +1,304 @@
1
+ module OverSIP::SIP
2
+
3
+ class Client
4
+
5
+ include ::OverSIP::Logger
6
+
7
+ attr_reader :current_target
8
+
9
+ def initialize proxy_profile=:default_proxy
10
+ unless (@conf = ::OverSIP.proxies[proxy_profile.to_sym])
11
+ raise ::OverSIP::RuntimeError, "proxy profile '#{proxy_profile}' is not defined"
12
+ end
13
+ end
14
+
15
+ def on_provisional_response &block
16
+ @on_provisional_response_block = block
17
+ end
18
+
19
+ def on_success_response &block
20
+ @on_success_response_block = block
21
+ end
22
+
23
+ def on_failure_response &block
24
+ @on_failure_response_block = block
25
+ end
26
+
27
+ def on_canceled &block
28
+ @on_canceled_block = block
29
+ end
30
+
31
+ def on_invite_timeout &block
32
+ @on_invite_timeout_block = block
33
+ end
34
+
35
+ def on_error &block
36
+ @on_error_block = block
37
+ end
38
+
39
+ def on_target &block
40
+ @on_target_block = block
41
+ end
42
+
43
+ # By calling this method the request routing is aborted, no more DNS targets are tryed,
44
+ # a local 403 response is generated and on_error() callback is called with status 403.
45
+ def abort_routing
46
+ @aborted = true
47
+ end
48
+
49
+ # Manually insert the last target into the blacklist. Optionally a timeout value can be given
50
+ # (otherwise the proxy blacklist_time is used). The timeout must be between 2 and 600 seconds.
51
+ # Also the SIP code and reason can be passed.
52
+ def add_target_to_blacklist timeout=nil, status_code=403, reason_phrase="Destination Blacklisted"
53
+ return false unless @current_target
54
+
55
+ if timeout
56
+ timeout = timeout.to_i
57
+ if timeout < 2 or timeout > 600
58
+ raise ::OverSIP::RuntimeError, "timeout must be between a and 600 seconds"
59
+ end
60
+ else
61
+ timeout = @conf[:blacklist_time]
62
+ end
63
+
64
+ blacklist_entry = @current_target.to_s
65
+ @conf[:blacklist][blacklist_entry] = [status_code, reason_phrase, nil, :destination_blacklisted]
66
+ ::EM.add_timer(timeout) { @conf[:blacklist].delete blacklist_entry }
67
+ end
68
+
69
+
70
+ ### Methods called by the client transaction.
71
+
72
+ def client_timeout
73
+ # Store the target and error in the blacklist.
74
+ if @conf[:use_blacklist]
75
+ blacklist_entry = @current_target.to_s
76
+ @conf[:blacklist][blacklist_entry] = [408, "Client Timeout", nil, :client_timeout]
77
+ ::EM.add_timer(@conf[:blacklist_time]) { @conf[:blacklist].delete blacklist_entry }
78
+ end
79
+
80
+ try_next_target 408, "Client Timeout", nil, :client_timeout
81
+ end
82
+
83
+ def connection_failed
84
+ # Store the target and error in the blacklist.
85
+ if @conf[:use_blacklist]
86
+ blacklist_entry = @current_target.to_s
87
+ @conf[:blacklist][blacklist_entry] = [500, "Connection Error", nil, :connection_error]
88
+ ::EM.add_timer(@conf[:blacklist_time]) { @conf[:blacklist].delete blacklist_entry }
89
+ end
90
+
91
+ try_next_target 500, "Connection Error", nil, :connection_error
92
+ end
93
+
94
+ def tls_validation_failed
95
+ # Store the target and error in the blacklist.
96
+ if @conf[:use_blacklist]
97
+ blacklist_entry = @current_target.to_s
98
+ @conf[:blacklist][blacklist_entry] = [500, "TLS Validation Failed", nil, :tls_validation_failed]
99
+ ::EM.add_timer(@conf[:blacklist_time]) { @conf[:blacklist].delete blacklist_entry }
100
+ end
101
+
102
+ try_next_target 500, "TLS Validation Failed", nil, :tls_validation_failed
103
+ end
104
+
105
+ # Timer C for INVITE.
106
+ def invite_timeout
107
+ @on_invite_timeout_block && @on_invite_timeout_block.call
108
+ end
109
+
110
+
111
+
112
+ private
113
+
114
+
115
+ def add_routing_headers
116
+ end
117
+
118
+
119
+ # Check the given URI into the DNS cache.
120
+ # - If the cache is not enabled it returns nil.
121
+ # - If present it returns true.
122
+ # - If not it returns dns_cache_key (String).
123
+ def check_dns_cache dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
124
+ if dst_host_type == :domain and @conf[:use_dns_cache]
125
+ dns_cache_key = "#{dst_scheme}|#{dst_host}|#{dst_port}|#{dst_transport}"
126
+ if (result = @conf[:dns_cache][dns_cache_key])
127
+ log_system_debug "destination found in the DNS cache" if $oversip_debug
128
+ if result.is_a? ::Symbol
129
+ rfc3263_failed result
130
+ else
131
+ rfc3263_succeeded result
132
+ end
133
+ return true
134
+ else
135
+ return dns_cache_key
136
+ end
137
+ else
138
+ return nil
139
+ end
140
+ end
141
+
142
+
143
+ def do_dns dns_cache_key, id, dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
144
+ # Perform RFC 3261 procedures.
145
+ dns_query = ::OverSIP::SIP::RFC3263::Query.new @conf, id, dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
146
+ case result = dns_query.resolve
147
+
148
+ # Async result so DNS took place.
149
+ when nil
150
+ # Async success.
151
+ dns_query.callback do |result|
152
+ # Store the result in the DNS cache.
153
+ if dns_cache_key
154
+ @conf[:dns_cache][dns_cache_key] = result
155
+ ::EM.add_timer(@conf[:dns_cache_time]) { @conf[:dns_cache].delete dns_cache_key }
156
+ end
157
+ rfc3263_succeeded result
158
+ end
159
+ # Async error.
160
+ dns_query.errback do |result|
161
+ # Store the result in the DNS cache.
162
+ if dns_cache_key
163
+ @conf[:dns_cache][dns_cache_key] = result
164
+ ::EM.add_timer(@conf[:dns_cache_time]) { @conf[:dns_cache].delete dns_cache_key }
165
+ end
166
+ rfc3263_failed result
167
+ end
168
+ # Instant error.
169
+ when ::Symbol
170
+ # Store the result in the DNS cache.
171
+ if dns_cache_key
172
+ @conf[:dns_cache][dns_cache_key] = result
173
+ ::EM.add_timer(@conf[:dns_cache_time]) { @conf[:dns_cache].delete dns_cache_key }
174
+ end
175
+ rfc3263_failed result
176
+ # Instant success so it's not a domain (no DNS performed).
177
+ else
178
+ rfc3263_succeeded result
179
+ end
180
+ end
181
+
182
+
183
+ def rfc3263_succeeded result
184
+ # After RFC 3263 (DNS) resolution we get N targets.
185
+ @num_target = 0 # First target is 0 (rather than 1).
186
+ @target = @targets = nil # Avoid conflicts if same Proxy is used for serial forking to a new destination.
187
+
188
+ case result
189
+
190
+ when RFC3263::Target
191
+ @target = result # Single Target.
192
+
193
+ when RFC3263::SrvTargets
194
+ log_system_debug "DNS result has multiple values, randomizing" if $oversip_debug
195
+ @targets = result.randomize # Array of Targets.
196
+
197
+ # This can contain Target and SrvTargets entries.
198
+ when RFC3263::MultiTargets
199
+ log_system_debug "DNS result has multiple values, randomizing" if $oversip_debug
200
+ @targets = result.flatten # Array of Targets.
201
+
202
+ end
203
+
204
+ try_next_target
205
+ end # rfc3263_succeeded
206
+
207
+
208
+ def try_next_target status=nil, reason=nil, full_response=nil, code=nil
209
+ # Single target.
210
+ if @target and @num_target == 0
211
+ @current_target = @target
212
+ log_system_debug "trying single target: #{@current_target}" if $oversip_debug
213
+ @num_target = 1
214
+ use_target @current_target
215
+
216
+ # Multiple targets (so @targets is set).
217
+ elsif @targets and @num_target < @targets.size
218
+ @current_target = @targets[@num_target]
219
+ log_system_debug "trying target #{@num_target+1} of #{@targets.size}: #{@current_target}" if $oversip_debug
220
+ @num_target += 1
221
+ use_target @current_target
222
+
223
+ # No more targets.
224
+ else
225
+ no_more_targets status, reason, full_response, code
226
+ end
227
+ end # try_next_target
228
+
229
+
230
+ def use_target target
231
+ # Lookup the target in the blacklist.
232
+ if @conf[:blacklist].any? and (blacklist_entry = @conf[:blacklist][target.to_s])
233
+ log_system_notice "destination found in the blacklist" if $oversip_debug
234
+ try_next_target blacklist_entry[0], blacklist_entry[1], blacklist_entry[2], blacklist_entry[3]
235
+ return
236
+ end
237
+
238
+ # Call the on_target() callback if set by the user.
239
+ @on_target_block && @on_target_block.call(target)
240
+
241
+ # If the user has called to proxy.abort_routing() then stop next targets
242
+ # and call to on_error() callback.
243
+ if @aborted
244
+ log_system_notice "routing aborted for target #{target}"
245
+ @aborted = @target = @targets = nil
246
+ try_next_target 403, "Destination Aborted", nil, :destination_aborted
247
+ return
248
+ end
249
+
250
+ @client_transaction = (::OverSIP::SIP::ClientTransaction.get_class @request).new self, @request, @conf, target.transport, target.ip, target.ip_type, target.port
251
+ add_routing_headers
252
+ @client_transaction.send_request
253
+ end
254
+
255
+
256
+ def no_more_targets status, reason, full_response, code
257
+ end
258
+
259
+
260
+ def rfc3263_failed error
261
+ case error
262
+ when :rfc3263_domain_not_found
263
+ log_system_debug "no resolution" if $oversip_debug
264
+ status = 404
265
+ reason = "No DNS Resolution"
266
+ code = :no_dns_resolution
267
+ when :rfc3263_unsupported_scheme
268
+ log_system_debug "unsupported URI scheme" if $oversip_debug
269
+ status = 416
270
+ reason = "Unsupported URI scheme"
271
+ code = :unsupported_uri_scheme
272
+ when :rfc3263_unsupported_transport
273
+ log_system_debug "unsupported transport" if $oversip_debug
274
+ status = 478
275
+ reason = "Unsupported Transport"
276
+ code = :unsupported_transport
277
+ when :rfc3263_no_ipv4
278
+ log_system_debug "destination requires unsupported IPv4" if $oversip_debug
279
+ status = 478
280
+ reason = "Destination Requires Unsupported IPv4"
281
+ code = :no_ipv4
282
+ when :rfc3263_no_ipv6
283
+ log_system_debug "destination requires unsupported IPv6" if $oversip_debug
284
+ status = 478
285
+ reason = "Destination Requires Unsupported IPv6"
286
+ code = :no_ipv6
287
+ when :rfc3263_no_dns
288
+ log_system_debug "destination requires unsupported DNS query" if $oversip_debug
289
+ status = 478
290
+ reason = "Destination Requires Unsupported DNS Query"
291
+ code = :no_dns
292
+ end
293
+
294
+ do_dns_fail status, reason, code
295
+ end # def rfc3263_failed
296
+
297
+
298
+ def do_dns_fail status, reason, code
299
+ @on_error_block && @on_error_block.call(status, reason, code)
300
+ end
301
+
302
+ end # class Client
303
+
304
+ end
@@ -22,7 +22,7 @@ module OverSIP::SIP
22
22
  @transaction_id = ::SecureRandom.hex(4) << @request.antiloop_id
23
23
 
24
24
  # A client transaction for using an existing Outbound connection.
25
- if transport.is_a? String
25
+ if transport.is_a? ::String
26
26
  @connection, @ip, @port = ::OverSIP::SIP::TransportManager.get_outbound_connection transport
27
27
  if @connection
28
28
  @server_klass = @connection.class
@@ -59,10 +59,13 @@ module OverSIP::SIP
59
59
  end
60
60
 
61
61
  # Ensure the request has Content-Length. Add it otherwise.
62
- if @request.body
63
- @request.headers["Content-Length"] = [ @request.body.bytesize.to_s ]
64
- else
65
- @request.headers["Content-Length"] = HDR_ARRAY_CONTENT_LENGTH_0
62
+ # NOTE: Don't do this for UAcRequest instances!
63
+ if @request.is_a? ::OverSIP::SIP::Request
64
+ if @request.body
65
+ @request.headers["Content-Length"] = [ @request.body.bytesize.to_s ]
66
+ else
67
+ @request.headers["Content-Length"] = HDR_ARRAY_CONTENT_LENGTH_0
68
+ end
66
69
  end
67
70
 
68
71
  end # def initialize
@@ -107,24 +110,20 @@ module OverSIP::SIP
107
110
  when :both_outbound_rr
108
111
  @out_rr = :rr
109
112
  @request.insert_header "Record-Route", "<sip:" << @request.route_outbound_flow_token << @server_klass.outbound_record_route_fragment
110
- end
111
-
112
- @request_leg_b = @request.to_s
113
+ end if @request.in_rr
113
114
 
114
- # NOTE: This cannot return false as the connection has been retrieved from the corresponding hash,
115
- # and when a connection is terminated its value is automatically deleted from such hash.
116
- @connection.send_sip_msg @request_leg_b, @ip, @port
115
+ @outgoing_request_str = @request.to_s
117
116
 
118
117
  @request.delete_header_top "Via"
119
118
  if @out_rr == :rr
120
119
  @request.delete_header_top "Record-Route"
121
120
  end
122
121
 
122
+ @connection.send_sip_msg @outgoing_request_str, @ip, @port
123
+
123
124
  start_timer_A if @transport == :udp
124
125
  start_timer_B
125
126
  start_timer_C
126
-
127
- true
128
127
  end
129
128
 
130
129
  def start_timer_A
@@ -177,7 +176,7 @@ module OverSIP::SIP
177
176
  end
178
177
 
179
178
  def retransmit_request
180
- @connection.send_sip_msg @request_leg_b, @ip, @port
179
+ @connection.send_sip_msg @outgoing_request_str, @ip, @port
181
180
  end
182
181
 
183
182
  def receive_response response
@@ -284,21 +283,21 @@ module OverSIP::SIP
284
283
  @ack << "Via: #{@top_via}\r\n"
285
284
 
286
285
  @request.hdr_route.each do |route|
287
- @ack << "Route: " << route << "\r\n"
286
+ @ack << "Route: " << route << CRLF
288
287
  end if @request.hdr_route
289
288
 
290
- @ack << "From: " << @request.hdr_from << "\r\n"
289
+ @ack << "From: " << @request.hdr_from << CRLF
291
290
  @ack << "To: " << @request.hdr_to
292
291
  unless @request.to_tag
293
292
  @ack << ";tag=#{response.to_tag}" if response.to_tag
294
293
  end
295
- @ack << "\r\n"
294
+ @ack << CRLF
296
295
 
297
- @ack << "Call-ID: " << @request.call_id << "\r\n"
296
+ @ack << "Call-ID: " << @request.call_id << CRLF
298
297
  @ack << "CSeq: " << @request.cseq.to_s << " ACK\r\n"
299
298
  @ack << "Content-Length: 0\r\n"
300
- @ack << HDR_USER_AGENT << "\r\n"
301
- @ack << "\r\n"
299
+ @ack << HDR_USER_AGENT << CRLF
300
+ @ack << CRLF
302
301
  end
303
302
 
304
303
  log_system_debug "sending ACK for [3456]XX response" if $oversip_debug
@@ -315,21 +314,21 @@ module OverSIP::SIP
315
314
  @cancel << "Via: #{@top_via}\r\n"
316
315
 
317
316
  @request.hdr_route.each do |route|
318
- @cancel << "Route: " << route << "\r\n"
317
+ @cancel << "Route: " << route << CRLF
319
318
  end if @request.hdr_route
320
319
 
321
320
  # RFC 3326. Copy Reason headers if present in the received CANCEL.
322
321
  cancel.header_all("Reason").each do |reason|
323
- @cancel << "Reason: " << reason << "\r\n"
322
+ @cancel << "Reason: " << reason << CRLF
324
323
  end if cancel
325
324
 
326
- @cancel << "From: " << @request.hdr_from << "\r\n"
327
- @cancel << "To: " << @request.hdr_to << "\r\n"
328
- @cancel << "Call-ID: " << @request.call_id << "\r\n"
325
+ @cancel << "From: " << @request.hdr_from << CRLF
326
+ @cancel << "To: " << @request.hdr_to << CRLF
327
+ @cancel << "Call-ID: " << @request.call_id << CRLF
329
328
  @cancel << "CSeq: " << @request.cseq.to_s << " CANCEL\r\n"
330
329
  @cancel << "Content-Length: 0\r\n"
331
- @cancel << HDR_USER_AGENT << "\r\n"
332
- @cancel << "\r\n"
330
+ @cancel << HDR_USER_AGENT << CRLF
331
+ @cancel << CRLF
333
332
 
334
333
  # Just send the ACK inmediately if the branch has replied a 1XX response.
335
334
  send_cancel if @state == :proceeding
@@ -437,11 +436,9 @@ module OverSIP::SIP
437
436
  when :both_outbound_path
438
437
  @out_rr = :rr
439
438
  @request.insert_header "Path", "<sip:" << @request.route_outbound_flow_token << @server_klass.outbound_path_fragment
440
- end
441
-
442
- @request_leg_b = @request.to_s
439
+ end if @core.is_a? ::OverSIP::SIP::Proxy
443
440
 
444
- @connection.send_sip_msg @request_leg_b, @ip, @port
441
+ @outgoing_request_str = @request.to_s
445
442
 
446
443
  @request.delete_header_top "Via"
447
444
  case @out_rr
@@ -451,10 +448,10 @@ module OverSIP::SIP
451
448
  @request.delete_header_top "Path"
452
449
  end
453
450
 
451
+ @connection.send_sip_msg @outgoing_request_str, @ip, @port
452
+
454
453
  start_timer_E if @transport == :udp
455
454
  start_timer_F
456
-
457
- true
458
455
  end
459
456
 
460
457
  def start_timer_E
@@ -493,7 +490,7 @@ module OverSIP::SIP
493
490
  end
494
491
 
495
492
  def retransmit_request
496
- @connection.send_sip_msg @request_leg_b, @ip, @port
493
+ @connection.send_sip_msg @outgoing_request_str, @ip, @port
497
494
  end
498
495
 
499
496
  def receive_response response
@@ -570,8 +567,6 @@ module OverSIP::SIP
570
567
  @request.insert_header "Via", "#{@server_klass.via_core};branch=z9hG4bK#{@transaction_id}"
571
568
 
572
569
  @connection.send_sip_msg @request.to_s, @ip, @port
573
-
574
- true
575
570
  end
576
571
 
577
572
  def connection_failed
@@ -63,13 +63,16 @@ module OverSIP::SIP
63
63
 
64
64
  # Outgoing initial request asking for Outbound. Just valid when:
65
65
  # - It's an initial request.
66
+ # - The request comes via UDP or comes via TCP/TLS/WS/WSS but through a connection
67
+ # opened by the peer (and not by OverSIP).
66
68
  # - Single Via (so there is no a proxy in front of us).
67
69
  # - It's an INVITE, REGISTER, SUBSCRIBE or REFER request.
68
70
  # - Has a preloaded top Route with ;ob param pointing to us, or has Contact with ;ob, or
69
- # it's a REGISTER with ;+sip.instance.
71
+ # it's a REGISTER with ;+sip.instance..
70
72
  #
71
73
  if (
72
- initial? and (
74
+ initial? and
75
+ @connection.class.outbound_listener? and (
73
76
  @force_outgoing_outbound or (
74
77
  @num_vias == 1 and
75
78
  outbound_aware? and (
@@ -164,8 +167,8 @@ module OverSIP::SIP
164
167
  def connection_outbound_flow_token
165
168
  @connection_outbound_flow_token ||= if @transport == :udp
166
169
  # NOTE: Add "_" so later we can figure that this is for UDP.
167
- # NOTE: Replace "=" with "-" so it can be added as a SIP URI param (when Contact mangling is used
168
- # if the registrar does not support Path).
170
+ # NOTE: Replace "=" with "-" so it can be added as a SIP URI param (needed i.e.
171
+ # for the OutboundMangling module).
169
172
  "_" << ::Base64.strict_encode64("#{@source_ip}_#{@source_port}").gsub(/=/,"-")
170
173
  else
171
174
  @connection.outbound_flow_token