oversip 1.2.1 → 1.3.0.dev1

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.
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