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