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.
- data/README.md +28 -4
- data/bin/oversip +1 -1
- data/etc/proxies.conf +10 -0
- data/etc/server.rb +13 -9
- data/ext/utils/haproxy_protocol.c +0 -3
- data/ext/utils/outbound_utils.c +1 -1
- data/ext/utils/utils_ruby.c +0 -1
- data/ext/websocket_http_parser/ws_http_parser.c +940 -1903
- data/ext/websocket_http_parser/ws_http_parser.h +1 -0
- data/lib/oversip/config_validators.rb +2 -2
- data/lib/oversip/launcher.rb +275 -240
- data/lib/oversip/master_process.rb +7 -2
- data/lib/oversip/proxies_config.rb +8 -1
- data/lib/oversip/sip/client.rb +304 -0
- data/lib/oversip/sip/client_transaction.rb +31 -36
- data/lib/oversip/sip/core.rb +7 -4
- data/lib/oversip/sip/launcher.rb +30 -30
- data/lib/oversip/sip/listeners/connection.rb +4 -0
- data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +1 -0
- data/lib/oversip/sip/listeners/ipv4_tls_server.rb +1 -0
- data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +1 -0
- data/lib/oversip/sip/listeners/ipv4_udp_server.rb +1 -0
- data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +1 -0
- data/lib/oversip/sip/listeners/ipv6_tls_server.rb +1 -0
- data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +1 -0
- data/lib/oversip/sip/listeners/ipv6_udp_server.rb +1 -0
- data/lib/oversip/sip/listeners/tcp_client.rb +26 -0
- data/lib/oversip/sip/listeners/tcp_connection.rb +7 -1
- data/lib/oversip/sip/listeners/tcp_server.rb +1 -1
- data/lib/oversip/sip/listeners/tls_client.rb +28 -24
- data/lib/oversip/sip/listeners/tls_server.rb +25 -8
- data/lib/oversip/sip/listeners/tls_tunnel_connection.rb +1 -24
- data/lib/oversip/sip/message.rb +2 -2
- data/lib/oversip/sip/message_processor.rb +23 -13
- data/lib/oversip/sip/{grammar/name_addr.rb → name_addr.rb} +11 -0
- data/lib/oversip/sip/proxy.rb +53 -227
- data/lib/oversip/sip/request.rb +15 -11
- data/lib/oversip/sip/response.rb +3 -3
- data/lib/oversip/sip/rfc3263.rb +2 -3
- data/lib/oversip/sip/tags.rb +1 -1
- data/lib/oversip/sip/transport_manager.rb +6 -5
- data/lib/oversip/sip/uac.rb +93 -0
- data/lib/oversip/sip/uac_request.rb +82 -0
- data/lib/oversip/sip/{grammar/uri.rb → uri.rb} +22 -0
- data/lib/oversip/version.rb +3 -3
- data/lib/oversip/websocket/launcher.rb +25 -25
- data/lib/oversip/websocket/listeners/connection.rb +4 -0
- data/lib/oversip/websocket/listeners/ipv4_ws_server.rb +1 -0
- data/lib/oversip/websocket/listeners/ipv4_wss_server.rb +1 -0
- data/lib/oversip/websocket/listeners/ipv4_wss_tunnel_server.rb +1 -0
- data/lib/oversip/websocket/listeners/ipv6_ws_server.rb +1 -0
- data/lib/oversip/websocket/listeners/ipv6_wss_server.rb +1 -0
- data/lib/oversip/websocket/listeners/ipv6_wss_tunnel_server.rb +1 -0
- data/lib/oversip/websocket/listeners/ws_server.rb +55 -26
- data/lib/oversip/websocket/listeners/wss_server.rb +26 -9
- data/lib/oversip/websocket/listeners/wss_tunnel_server.rb +14 -11
- data/lib/oversip/websocket/ws_framing.rb +6 -2
- data/lib/oversip.rb +3 -1
- data/test/test_http_parser.rb +3 -3
- data/test/test_uri.rb +18 -12
- metadata +91 -77
data/lib/oversip/sip/proxy.rb
CHANGED
@@ -1,62 +1,19 @@
|
|
1
1
|
module OverSIP::SIP
|
2
2
|
|
3
|
-
class Proxy
|
4
|
-
|
5
|
-
include ::OverSIP::Logger
|
6
|
-
|
7
|
-
def initialize proxy_profile=:default_proxy
|
8
|
-
unless (@proxy_conf = ::OverSIP.proxies[proxy_profile.to_sym])
|
9
|
-
raise ::OverSIP::RuntimeError, "proxy '#{proxy_profile}' is not defined in Proxies Configuration file"
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
|
14
|
-
def on_provisional_response &block
|
15
|
-
@on_provisional_response_block = block
|
16
|
-
end
|
17
|
-
|
18
|
-
def on_success_response &block
|
19
|
-
@on_success_response_block = block
|
20
|
-
end
|
21
|
-
|
22
|
-
def on_failure_response &block
|
23
|
-
@on_failure_response_block = block
|
24
|
-
end
|
25
|
-
|
26
|
-
def on_canceled &block
|
27
|
-
@on_canceled_block = block
|
28
|
-
end
|
29
|
-
|
30
|
-
def on_invite_timeout &block
|
31
|
-
@on_invite_timeout_block = block
|
32
|
-
end
|
33
|
-
|
34
|
-
def on_error &block
|
35
|
-
@on_error_block = block
|
36
|
-
end
|
37
|
-
|
38
|
-
def on_target &block
|
39
|
-
@on_target_block = block
|
40
|
-
end
|
3
|
+
class Proxy < Client
|
41
4
|
|
42
5
|
# If called, current response within the called callback won't be forwarded.
|
43
6
|
def drop_response
|
44
7
|
@drop_response = true
|
45
8
|
end
|
46
9
|
|
47
|
-
# It must only be called within the on_target() callback. By calling this method,
|
48
|
-
# the request routing is aborted, no more DNS targets are tryed, a local 403 response
|
49
|
-
# is generated and on_error() callback is called with status 403.
|
50
|
-
def abort_routing
|
51
|
-
@aborted = true
|
52
|
-
end
|
53
10
|
|
54
11
|
def route request, dst_host=nil, dst_port=nil, dst_transport=nil
|
55
12
|
unless (@request = request).is_a? ::OverSIP::SIP::Request
|
56
13
|
raise ::OverSIP::RuntimeError, "request must be a OverSIP::SIP::Request instance"
|
57
14
|
end
|
58
15
|
|
59
|
-
@log_id = "Proxy #{@
|
16
|
+
@log_id = "Proxy #{@conf[:name]} #{@request.via_branch_id}"
|
60
17
|
|
61
18
|
# Create the server transaction if it doesn't exist yet.
|
62
19
|
@server_transaction = @request.server_transaction or case @request.sip_method
|
@@ -79,7 +36,7 @@ module OverSIP::SIP
|
|
79
36
|
# set then don't honor the Outbound connection).
|
80
37
|
|
81
38
|
if @request.incoming_outbound_requested? and not dst_host
|
82
|
-
@client_transaction = (::OverSIP::SIP::ClientTransaction.get_class @request).new self, @request, @
|
39
|
+
@client_transaction = (::OverSIP::SIP::ClientTransaction.get_class @request).new self, @request, @conf, @request.route_outbound_flow_token
|
83
40
|
|
84
41
|
if @client_transaction.connection
|
85
42
|
add_routing_headers
|
@@ -88,7 +45,7 @@ module OverSIP::SIP
|
|
88
45
|
unless @request.sip_method == :ACK
|
89
46
|
log_system_debug "flow failed" if $oversip_debug
|
90
47
|
|
91
|
-
@on_error_block && @on_error_block.call(430, "Flow Failed")
|
48
|
+
@on_error_block && @on_error_block.call(430, "Flow Failed", :flow_failed)
|
92
49
|
unless @drop_response
|
93
50
|
@request.reply 430, "Flow Failed"
|
94
51
|
else
|
@@ -139,56 +96,14 @@ module OverSIP::SIP
|
|
139
96
|
end
|
140
97
|
|
141
98
|
# Loockup in the DNS cache of this proxy.
|
142
|
-
|
143
|
-
dns_cache_entry = "#{dst_host}|#{dst_port}|#{dst_transport}|#{dst_scheme}"
|
144
|
-
if (result = @proxy_conf[:dns_cache][dns_cache_entry])
|
145
|
-
log_system_debug "destination found in the DNS cache" if $oversip_debug
|
146
|
-
if result.is_a? ::Symbol
|
147
|
-
rfc3263_failed result
|
148
|
-
else
|
149
|
-
rfc3263_succeeded result
|
150
|
-
end
|
151
|
-
return
|
152
|
-
end
|
153
|
-
else
|
154
|
-
dns_cache_entry = nil
|
155
|
-
end
|
99
|
+
result = check_dns_cache dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
|
156
100
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
# Async success.
|
164
|
-
dns_query.callback do |result|
|
165
|
-
# Store the result in the DNS cache.
|
166
|
-
if dns_cache_entry
|
167
|
-
@proxy_conf[:dns_cache][dns_cache_entry] = result
|
168
|
-
::EM.add_timer(@proxy_conf[:dns_cache_time]) { @proxy_conf[:dns_cache].delete dns_cache_entry }
|
169
|
-
end
|
170
|
-
rfc3263_succeeded result
|
171
|
-
end
|
172
|
-
# Async error.
|
173
|
-
dns_query.errback do |result|
|
174
|
-
# Store the result in the DNS cache.
|
175
|
-
if dns_cache_entry
|
176
|
-
@proxy_conf[:dns_cache][dns_cache_entry] = result
|
177
|
-
::EM.add_timer(@proxy_conf[:dns_cache_time]) { @proxy_conf[:dns_cache].delete dns_cache_entry }
|
178
|
-
end
|
179
|
-
rfc3263_failed result
|
180
|
-
end
|
181
|
-
# Instant error.
|
182
|
-
when ::Symbol
|
183
|
-
# Store the result in the DNS cache.
|
184
|
-
if dns_cache_entry
|
185
|
-
@proxy_conf[:dns_cache][dns_cache_entry] = result
|
186
|
-
::EM.add_timer(@proxy_conf[:dns_cache_time]) { @proxy_conf[:dns_cache].delete dns_cache_entry }
|
187
|
-
end
|
188
|
-
rfc3263_failed result
|
189
|
-
# Instant success so it's not a domain (no DNS performed).
|
190
|
-
else
|
191
|
-
rfc3263_succeeded result
|
101
|
+
case result
|
102
|
+
when true
|
103
|
+
return
|
104
|
+
else # It can be String or nil, so use it as dns_cache_key param.
|
105
|
+
# Perform RFC 3263 procedures.
|
106
|
+
do_dns result, @request.via_branch_id, dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
|
192
107
|
end
|
193
108
|
|
194
109
|
end # def route
|
@@ -206,7 +121,7 @@ module OverSIP::SIP
|
|
206
121
|
@on_success_response_block && @on_success_response_block.call(response)
|
207
122
|
elsif response.status_code >= 300 && ! @canceled
|
208
123
|
if response.status_code == 503
|
209
|
-
if @
|
124
|
+
if @conf[:dns_failover_on_503]
|
210
125
|
try_next_target nil, nil, response
|
211
126
|
return
|
212
127
|
else
|
@@ -239,22 +154,7 @@ module OverSIP::SIP
|
|
239
154
|
end
|
240
155
|
|
241
156
|
|
242
|
-
|
243
|
-
try_next_target 408, "Client Timeout"
|
244
|
-
end
|
245
|
-
|
246
|
-
|
247
|
-
def connection_failed
|
248
|
-
try_next_target 500, "Connection Error"
|
249
|
-
end
|
250
|
-
|
251
|
-
|
252
|
-
def tls_validation_failed
|
253
|
-
try_next_target 500, "TLS Validation Failed"
|
254
|
-
end
|
255
|
-
|
256
|
-
|
257
|
-
# Timer C for INVITE.
|
157
|
+
# Timer C for INVITE (method called by the client transaction).
|
258
158
|
def invite_timeout
|
259
159
|
@on_invite_timeout_block && @on_invite_timeout_block.call
|
260
160
|
|
@@ -265,6 +165,7 @@ module OverSIP::SIP
|
|
265
165
|
end
|
266
166
|
|
267
167
|
|
168
|
+
|
268
169
|
private
|
269
170
|
|
270
171
|
|
@@ -278,7 +179,7 @@ module OverSIP::SIP
|
|
278
179
|
|
279
180
|
# NOTE: As per RFC 6665 the proxy MUST add Record-Route to in-dialog NOTIFY's.
|
280
181
|
if (@request.initial? and @request.record_routing_aware?) or @request.sip_method == :NOTIFY
|
281
|
-
do_record_routing = @
|
182
|
+
do_record_routing = @conf[:do_record_routing]
|
282
183
|
|
283
184
|
# Request has no previous RR/Path and current proxy performs record-routing.
|
284
185
|
# So add RR/Path.
|
@@ -329,7 +230,13 @@ module OverSIP::SIP
|
|
329
230
|
@request.insert_header "Path", @request.connection.class.record_route
|
330
231
|
else
|
331
232
|
@request.in_rr = :path
|
332
|
-
|
233
|
+
# The request comes via UDP or via a connection made by the client.
|
234
|
+
if @request.connection.class.outbound_listener?
|
235
|
+
@request.insert_header "Path", @request.connection.class.record_route
|
236
|
+
# The request comes via a TCP/TLS connection made by OverSIP.
|
237
|
+
else
|
238
|
+
@request.insert_header "Path", @request.connection.record_route
|
239
|
+
end
|
333
240
|
end
|
334
241
|
|
335
242
|
# Record-Route for INVITE, SUBSCRIBE, REFER and in-dialog NOTIFY.
|
@@ -346,7 +253,13 @@ module OverSIP::SIP
|
|
346
253
|
@request.insert_header "Record-Route", @request.connection.class.record_route
|
347
254
|
else
|
348
255
|
@request.in_rr = :rr
|
349
|
-
|
256
|
+
# The request comes via UDP or via a connection made by the client.
|
257
|
+
if @request.connection.class.outbound_listener?
|
258
|
+
@request.insert_header "Record-Route", @request.connection.class.record_route
|
259
|
+
# The request comes via a TCP/TLS connection made by OverSIP.
|
260
|
+
else
|
261
|
+
@request.insert_header "Record-Route", @request.connection.record_route
|
262
|
+
end
|
350
263
|
end
|
351
264
|
|
352
265
|
end
|
@@ -355,129 +268,42 @@ module OverSIP::SIP
|
|
355
268
|
end # add_routing_headers
|
356
269
|
|
357
270
|
|
358
|
-
def
|
359
|
-
#
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
@targets = result.randomize # Array of Targets.
|
370
|
-
|
371
|
-
# This can contain Target and SrvTargets entries.
|
372
|
-
when RFC3263::MultiTargets
|
373
|
-
log_system_debug "result is MultiTargets => flatting:" if $oversip_debug
|
374
|
-
@targets = result.flatten # Array of Targets.
|
375
|
-
|
376
|
-
end
|
377
|
-
|
378
|
-
try_next_target
|
379
|
-
end # rfc3263_succeeded
|
380
|
-
|
381
|
-
|
382
|
-
def try_next_target status=nil, reason=nil, full_response=nil
|
383
|
-
# Single target.
|
384
|
-
if @target and @num_target == 0
|
385
|
-
log_system_debug "using single target: #{@target}" if $oversip_debug
|
386
|
-
use_target @target
|
387
|
-
@num_target = 1
|
388
|
-
|
389
|
-
# Multiple targets (so @targets is set).
|
390
|
-
elsif @targets and @num_target < @targets.size
|
391
|
-
log_system_debug "using target #{@num_target+1} of #{@targets.size}: #{@targets[@num_target]}" if $oversip_debug
|
392
|
-
use_target @targets[@num_target]
|
393
|
-
@num_target += 1
|
271
|
+
def no_more_targets status, reason, full_response, code
|
272
|
+
# If we have received a [3456]XX response from downstream then run @on_failure_block.
|
273
|
+
if full_response
|
274
|
+
@on_failure_response_block && @on_failure_response_block.call(full_response)
|
275
|
+
unless @drop_response
|
276
|
+
# If the response is 503 convert it into 500 (RFC 3261 16.7).
|
277
|
+
full_response.status_code = 500 if full_response.status_code == 503
|
278
|
+
@request.reply_full full_response
|
279
|
+
else
|
280
|
+
@drop_response = false
|
281
|
+
end
|
394
282
|
|
395
|
-
#
|
283
|
+
# If not, generate the response according to the given status and reason.
|
396
284
|
else
|
397
|
-
|
398
|
-
|
399
|
-
@
|
400
|
-
unless @drop_response
|
401
|
-
# If the response is 503 convert it into 500 (RFC 3261 16.7).
|
402
|
-
full_response.status_code = 500 if full_response.status_code == 503
|
403
|
-
@request.reply_full full_response
|
404
|
-
else
|
405
|
-
@drop_response = false
|
406
|
-
end
|
407
|
-
|
408
|
-
# If not, generate the response according to the given status and reason.
|
285
|
+
@on_error_block && @on_error_block.call(status, reason, code)
|
286
|
+
unless @drop_response
|
287
|
+
@request.reply status, reason
|
409
288
|
else
|
410
|
-
@
|
411
|
-
unless @drop_response
|
412
|
-
@request.reply status, reason
|
413
|
-
else
|
414
|
-
@drop_response = false
|
415
|
-
end
|
416
|
-
|
289
|
+
@drop_response = false
|
417
290
|
end
|
291
|
+
|
418
292
|
end
|
419
|
-
end #
|
293
|
+
end # no_more_targets
|
420
294
|
|
421
295
|
|
422
|
-
def
|
423
|
-
|
424
|
-
@on_target_block && @on_target_block.call(target.ip_type, target.ip, target.port, target.transport)
|
296
|
+
def do_dns_fail status, reason, code
|
297
|
+
@on_error_block && @on_error_block.call(status, reason, code)
|
425
298
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
@aborted = @target = @targets = nil
|
431
|
-
try_next_target 403, "Destination Not Allowed"
|
432
|
-
return
|
299
|
+
unless @drop_response
|
300
|
+
@request.reply status, reason unless @request.sip_method == :ACK
|
301
|
+
else
|
302
|
+
@drop_response = false
|
433
303
|
end
|
434
|
-
|
435
|
-
@client_transaction = (::OverSIP::SIP::ClientTransaction.get_class @request).new self, @request, @proxy_conf, target.transport, target.ip, target.ip_type, target.port
|
436
|
-
add_routing_headers
|
437
|
-
@client_transaction.send_request
|
438
304
|
end
|
439
305
|
|
440
306
|
|
441
|
-
def rfc3263_failed error
|
442
|
-
case error
|
443
|
-
when :rfc3263_domain_not_found
|
444
|
-
log_system_debug "no resolution" if $oversip_debug
|
445
|
-
status = 404
|
446
|
-
reason = "No DNS Resolution"
|
447
|
-
when :rfc3263_unsupported_scheme
|
448
|
-
log_system_debug "unsupported URI scheme" if $oversip_debug
|
449
|
-
status = 416
|
450
|
-
reason = "Unsupported URI scheme"
|
451
|
-
when :rfc3263_unsupported_transport
|
452
|
-
log_system_debug "unsupported transport" if $oversip_debug
|
453
|
-
status = 478
|
454
|
-
reason = "Unsupported Transport"
|
455
|
-
when :rfc3263_wrong_transport
|
456
|
-
log_system_debug "wrong URI transport" if $oversip_debug
|
457
|
-
status = 478
|
458
|
-
reason = "Wrong URI Transport"
|
459
|
-
when :rfc3263_no_ipv4
|
460
|
-
log_system_debug "destination requires unsupported IPv4" if $oversip_debug
|
461
|
-
status = 478
|
462
|
-
reason = "Destination Requires Unsupported IPv4"
|
463
|
-
when :rfc3263_no_ipv6
|
464
|
-
log_system_debug "destination requires unsupported IPv6" if $oversip_debug
|
465
|
-
status = 478
|
466
|
-
reason = "Destination Requires Unsupported IPv6"
|
467
|
-
when :rfc3263_no_dns
|
468
|
-
log_system_debug "destination requires unsupported DNS query" if $oversip_debug
|
469
|
-
status = 478
|
470
|
-
reason = "Destination Requires Unsupported DNS Query"
|
471
|
-
end
|
472
|
-
|
473
|
-
@on_error_block && @on_error_block.call(status, reason)
|
474
|
-
unless @drop_response
|
475
|
-
@request.reply status, reason unless @request.sip_method == :ACK
|
476
|
-
else
|
477
|
-
@drop_response = false
|
478
|
-
end
|
479
|
-
end # def rfc3263_failed
|
480
|
-
|
481
307
|
end # class Proxy
|
482
308
|
|
483
309
|
end
|
data/lib/oversip/sip/request.rb
CHANGED
@@ -38,36 +38,40 @@ module OverSIP::SIP
|
|
38
38
|
|
39
39
|
|
40
40
|
def reply status_code, reason_phrase=nil, extra_headers=[], body=nil
|
41
|
+
if @sip_method == :ACK
|
42
|
+
log_system_error "attemtp to reply to an ACK aborted"
|
43
|
+
return false
|
44
|
+
end
|
41
45
|
return false unless @server_transaction.receive_response(status_code) if @server_transaction
|
42
46
|
|
43
47
|
reason_phrase ||= REASON_PHARSE[status_code] || REASON_PHARSE_NOT_SET
|
44
48
|
|
45
49
|
if status_code > 100
|
46
|
-
@internal_to_tag ||= @to_tag || ( @server_transaction ? SecureRandom.hex(6) : OverSIP::SIP::Tags.totag_for_sl_reply )
|
50
|
+
@internal_to_tag ||= @to_tag || ( @server_transaction ? ::SecureRandom.hex(6) : ::OverSIP::SIP::Tags.totag_for_sl_reply )
|
47
51
|
end
|
48
52
|
|
49
53
|
response = "SIP/2.0 #{status_code} #{reason_phrase}\r\n"
|
50
54
|
|
51
55
|
@hdr_via.each do |hdr|
|
52
|
-
response << "Via: " << hdr <<
|
56
|
+
response << "Via: " << hdr << CRLF
|
53
57
|
end
|
54
58
|
|
55
|
-
response << "From: " << @hdr_from <<
|
59
|
+
response << "From: " << @hdr_from << CRLF
|
56
60
|
|
57
61
|
response << "To: " << @hdr_to
|
58
62
|
response << ";tag=#{@internal_to_tag}" if @internal_to_tag
|
59
|
-
response <<
|
63
|
+
response << CRLF
|
60
64
|
|
61
|
-
response << "Call-ID: " << @call_id <<
|
62
|
-
response << "CSeq: " << @cseq.to_s << " " << @sip_method.to_s <<
|
65
|
+
response << "Call-ID: " << @call_id << CRLF
|
66
|
+
response << "CSeq: " << @cseq.to_s << " " << @sip_method.to_s << CRLF
|
63
67
|
response << "Content-Length: #{body ? body.bytesize : "0"}\r\n"
|
64
68
|
|
65
69
|
extra_headers.each do |header|
|
66
|
-
response << header.to_s <<
|
70
|
+
response << header.to_s << CRLF
|
67
71
|
end if extra_headers
|
68
72
|
|
69
|
-
response << HDR_SERVER <<
|
70
|
-
response <<
|
73
|
+
response << HDR_SERVER << CRLF
|
74
|
+
response << CRLF
|
71
75
|
|
72
76
|
response << body if body
|
73
77
|
|
@@ -129,9 +133,9 @@ module OverSIP::SIP
|
|
129
133
|
@headers["Contact"] = [ @contact.to_s << (@contact_params ? @contact_params : "") ]
|
130
134
|
end
|
131
135
|
|
132
|
-
@headers.each do |
|
136
|
+
@headers.each do |name, values|
|
133
137
|
values.each do |value|
|
134
|
-
msg <<
|
138
|
+
msg << name << ": #{value}\r\n"
|
135
139
|
end
|
136
140
|
end
|
137
141
|
|
data/lib/oversip/sip/response.rb
CHANGED
@@ -18,12 +18,12 @@ module OverSIP::SIP
|
|
18
18
|
@headers["From"] = [ request.hdr_from ] if request.from_was_modified
|
19
19
|
if request.to_was_modified
|
20
20
|
hdr_to = @to_tag ? "#{request.hdr_to};tag=#{@to_tag}" : request.hdr_to
|
21
|
-
@headers["To"] = [ hdr_to ]
|
21
|
+
@headers["To"] = [ hdr_to ]
|
22
22
|
end
|
23
23
|
|
24
|
-
@headers.each do |
|
24
|
+
@headers.each do |name, values|
|
25
25
|
values.each do |value|
|
26
|
-
msg <<
|
26
|
+
msg << name << ": #{value}\r\n"
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
data/lib/oversip/sip/rfc3263.rb
CHANGED
@@ -216,7 +216,7 @@ module OverSIP::SIP
|
|
216
216
|
dns_transport = :udp
|
217
217
|
# "sips" is not possible in UDP.
|
218
218
|
else
|
219
|
-
return :
|
219
|
+
return :rfc3263_unsupported_transport
|
220
220
|
end
|
221
221
|
when :tcp
|
222
222
|
case (dns_transport = ( @uri_scheme == :sips ? :tls : :tcp ))
|
@@ -271,7 +271,6 @@ module OverSIP::SIP
|
|
271
271
|
elsif @uri_transport
|
272
272
|
if @use_srv
|
273
273
|
if (targets = resolve_SRV(@uri_host, @uri_scheme, dns_transport))
|
274
|
-
### TODO: Esto es nuevo para mejora. Antes devolvía siempre el segundo caso.
|
275
274
|
if targets.size == 1
|
276
275
|
@on_success_block && @on_success_block.call(targets[0])
|
277
276
|
else
|
@@ -415,7 +414,7 @@ module OverSIP::SIP
|
|
415
414
|
|
416
415
|
end
|
417
416
|
|
418
|
-
end
|
417
|
+
end # @@fiber_pool.spawn
|
419
418
|
|
420
419
|
nil
|
421
420
|
end
|
data/lib/oversip/sip/tags.rb
CHANGED
@@ -31,7 +31,7 @@ module OverSIP::SIP
|
|
31
31
|
|
32
32
|
def self.create_antiloop_id request
|
33
33
|
# It produces a 32 chars string.
|
34
|
-
::Digest::MD5.hexdigest "#{ANTILOOP_CONST}#{request.ruri.
|
34
|
+
::Digest::MD5.hexdigest "#{ANTILOOP_CONST}#{request.ruri.to_s}#{request.call_id}#{request.routes[0].uri if request.routes}"
|
35
35
|
end
|
36
36
|
|
37
37
|
end
|
@@ -9,7 +9,7 @@ module OverSIP::SIP
|
|
9
9
|
|
10
10
|
|
11
11
|
# Get an existing connection or create a new one (TCP/TLS).
|
12
|
-
# For UDP it always
|
12
|
+
# For UDP it always returns the single UDP reactor instance.
|
13
13
|
# client_transaction is passed when creating a new clien transaction. In case the
|
14
14
|
# outgoing connection is a TCP/TLS client connection and it's not connected yet,
|
15
15
|
# the client transaction is stored in the @pending_client_transactions of the client
|
@@ -62,9 +62,10 @@ module OverSIP::SIP
|
|
62
62
|
|
63
63
|
# NOTE: Should never happen.
|
64
64
|
unless conn
|
65
|
-
|
66
|
-
raise "no connection (nil) retrieved from TransportManager.get_connection(), FIXME, it should never occur!!!"
|
65
|
+
::OverSIP::Launcher.fatal "no connection retrieved from TransportManager.get_connection(), FIXME, it should never occur!!!"
|
67
66
|
end
|
67
|
+
|
68
|
+
# Return the created/retrieved connection instance.
|
68
69
|
conn
|
69
70
|
end
|
70
71
|
|
@@ -92,7 +93,7 @@ module OverSIP::SIP
|
|
92
93
|
if flow_token.getbyte(0) == 95
|
93
94
|
# NOTE: Doing Base64.decode64 automatically removes the leading "_".
|
94
95
|
# NOTE: Previously when the Outbound flow token was generated, "=" was replaced with "-" so it becomes
|
95
|
-
# valid for a SIP URI param (
|
96
|
+
# valid for a SIP URI param (needed i.e. for the OutboundMangling module).
|
96
97
|
ip_type, ip, port = ::OverSIP::Utils.parse_outbound_udp_flow_token(::Base64.decode64 flow_token.gsub(/-/,"="))
|
97
98
|
|
98
99
|
case ip_type
|
@@ -105,7 +106,7 @@ module OverSIP::SIP
|
|
105
106
|
return false
|
106
107
|
end
|
107
108
|
|
108
|
-
#
|
109
|
+
# If not, the flow token has been generated for a TCP/TLS/WS/WSS connection so let's lookup
|
109
110
|
# it into the Outbound connection collection and return nil for IP and port.
|
110
111
|
else
|
111
112
|
@outbound_connections[flow_token]
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module OverSIP::SIP
|
2
|
+
|
3
|
+
class Uac < Client
|
4
|
+
|
5
|
+
|
6
|
+
def route request, dst_host=nil, dst_port=nil, dst_transport=nil
|
7
|
+
unless (@request = request).is_a? ::OverSIP::SIP::UacRequest or @request.is_a? ::OverSIP::SIP::Request
|
8
|
+
raise ::OverSIP::RuntimeError, "request must be a OverSIP::SIP::UacRequest or OverSIP::SIP::Request instance"
|
9
|
+
end
|
10
|
+
|
11
|
+
# The destination of the request is taken from:
|
12
|
+
# - dst_xxx fields if given.
|
13
|
+
# - The request.ruri if it is an OverSIP::SIP::Uri or OverSIP::SIP::NameAddr.
|
14
|
+
# Otherwise raise an exception.
|
15
|
+
unless dst_host or request.ruri.is_a?(::OverSIP::SIP::Uri) or request.ruri.is_a?(::OverSIP::SIP::NameAddr)
|
16
|
+
raise ::OverSIP::RuntimeError, "if dst_host is not given then request.ruri must be an OverSIP::SIP::Uri or OverSIP::SIP::NameAddr instance"
|
17
|
+
end
|
18
|
+
|
19
|
+
@log_id = "UAC (proxy #{@conf[:name]})"
|
20
|
+
|
21
|
+
# Force the destination.
|
22
|
+
if dst_host
|
23
|
+
dst_scheme = :sip
|
24
|
+
dst_host_type = ::OverSIP::Utils.ip_type(dst_host) || :domain
|
25
|
+
|
26
|
+
# Or use the Request URI.
|
27
|
+
else
|
28
|
+
dst_scheme = request.ruri.scheme
|
29
|
+
dst_host = request.ruri.host
|
30
|
+
dst_host_type = request.ruri.host_type
|
31
|
+
dst_port = request.ruri.port
|
32
|
+
dst_transport = request.ruri.transport_param
|
33
|
+
end
|
34
|
+
|
35
|
+
# If the destination uri_host is an IPv6 reference, convert it to real IPv6.
|
36
|
+
if dst_host_type == :ipv6_reference
|
37
|
+
dst_host = ::OverSIP::Utils.normalize_ipv6(dst_host, true)
|
38
|
+
dst_host_type = :ipv6
|
39
|
+
end
|
40
|
+
|
41
|
+
# Loockup in the DNS cache of this proxy.
|
42
|
+
result = check_dns_cache dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
|
43
|
+
|
44
|
+
case result
|
45
|
+
when true
|
46
|
+
return
|
47
|
+
else # It can be String or nil, so use it as dns_cache_key param.
|
48
|
+
# Perform RFC 3263 procedures.
|
49
|
+
do_dns result, @request.via_branch_id, dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
|
50
|
+
end
|
51
|
+
|
52
|
+
end # def send
|
53
|
+
|
54
|
+
|
55
|
+
def receive_response response
|
56
|
+
log_system_debug "received response #{response.status_code}" if $oversip_debug
|
57
|
+
|
58
|
+
if response.status_code < 200
|
59
|
+
@on_provisional_response_block && @on_provisional_response_block.call(response)
|
60
|
+
elsif response.status_code >= 200 && response.status_code <= 299
|
61
|
+
@on_success_response_block && @on_success_response_block.call(response)
|
62
|
+
elsif response.status_code >= 300
|
63
|
+
if response.status_code == 503
|
64
|
+
if @conf[:dns_failover_on_503]
|
65
|
+
try_next_target nil, nil, response
|
66
|
+
return
|
67
|
+
else
|
68
|
+
@on_failure_response_block && @on_failure_response_block.call(response)
|
69
|
+
end
|
70
|
+
else
|
71
|
+
@on_failure_response_block && @on_failure_response_block.call(response)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
|
81
|
+
def no_more_targets status, reason, full_response, code
|
82
|
+
# If we have received a [3456]XX response from downstream then run @on_failure_block.
|
83
|
+
if full_response
|
84
|
+
@on_failure_response_block && @on_failure_response_block.call(full_response)
|
85
|
+
# If not, generate the response according to the given status and reason.
|
86
|
+
else
|
87
|
+
@on_error_block && @on_error_block.call(status, reason, code)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end # class Uac
|
92
|
+
|
93
|
+
end
|