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
@@ -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/
|
33
|
-
require "oversip/sip/
|
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] = {}
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
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 @
|
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 <<
|
286
|
+
@ack << "Route: " << route << CRLF
|
288
287
|
end if @request.hdr_route
|
289
288
|
|
290
|
-
@ack << "From: " << @request.hdr_from <<
|
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 <<
|
294
|
+
@ack << CRLF
|
296
295
|
|
297
|
-
@ack << "Call-ID: " << @request.call_id <<
|
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 <<
|
301
|
-
@ack <<
|
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 <<
|
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 <<
|
322
|
+
@cancel << "Reason: " << reason << CRLF
|
324
323
|
end if cancel
|
325
324
|
|
326
|
-
@cancel << "From: " << @request.hdr_from <<
|
327
|
-
@cancel << "To: " << @request.hdr_to <<
|
328
|
-
@cancel << "Call-ID: " << @request.call_id <<
|
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 <<
|
332
|
-
@cancel <<
|
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
|
-
@
|
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 @
|
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
|
data/lib/oversip/sip/core.rb
CHANGED
@@ -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 (
|
168
|
-
#
|
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
|