oversip 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS.txt +11 -0
- data/LICENSE.txt +22 -0
- data/README.md +16 -0
- data/Rakefile +55 -0
- data/bin/oversip +182 -0
- data/ext/common/c_util.h +74 -0
- data/ext/common/ruby_c_util.h +88 -0
- data/ext/sip_parser/common_headers.h +209 -0
- data/ext/sip_parser/ext_help.h +18 -0
- data/ext/sip_parser/extconf.rb +3 -0
- data/ext/sip_parser/sip_parser.c +29649 -0
- data/ext/sip_parser/sip_parser.h +227 -0
- data/ext/sip_parser/sip_parser_ruby.c +1292 -0
- data/ext/stud/extconf.rb +27 -0
- data/ext/stud/stud.tar.gz +0 -0
- data/ext/stun/ext_help.h +16 -0
- data/ext/stun/extconf.rb +3 -0
- data/ext/stun/stun_ruby.c +391 -0
- data/ext/utils/ext_help.h +14 -0
- data/ext/utils/extconf.rb +3 -0
- data/ext/utils/haproxy_protocol.c +6163 -0
- data/ext/utils/haproxy_protocol.h +27 -0
- data/ext/utils/ip_utils.c +5952 -0
- data/ext/utils/ip_utils.h +61 -0
- data/ext/utils/outbound_utils.c +3227 -0
- data/ext/utils/outbound_utils.h +27 -0
- data/ext/utils/utils_ruby.c +384 -0
- data/ext/utils/utils_ruby.h +75 -0
- data/ext/websocket_framing_utils/ext_help.h +18 -0
- data/ext/websocket_framing_utils/extconf.rb +3 -0
- data/ext/websocket_framing_utils/ws_framing_utils.h +46 -0
- data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
- data/ext/websocket_http_parser/ext_help.h +18 -0
- data/ext/websocket_http_parser/extconf.rb +3 -0
- data/ext/websocket_http_parser/ws_http_parser.c +2598 -0
- data/ext/websocket_http_parser/ws_http_parser.h +86 -0
- data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
- data/lib/oversip/config.rb +541 -0
- data/lib/oversip/config_validators.rb +126 -0
- data/lib/oversip/errors.rb +7 -0
- data/lib/oversip/fiber_pool.rb +56 -0
- data/lib/oversip/launcher.rb +507 -0
- data/lib/oversip/logger.rb +170 -0
- data/lib/oversip/master_process.rb +67 -0
- data/lib/oversip/posix_mq.rb +121 -0
- data/lib/oversip/proxies_config.rb +169 -0
- data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
- data/lib/oversip/sip/client_transaction.rb +587 -0
- data/lib/oversip/sip/constants.rb +87 -0
- data/lib/oversip/sip/grammar/name_addr.rb +27 -0
- data/lib/oversip/sip/grammar/uri.rb +116 -0
- data/lib/oversip/sip/launcher.rb +180 -0
- data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tls_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_udp_server.rb +20 -0
- data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tls_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_udp_server.rb +20 -0
- data/lib/oversip/sip/listeners/reactor.rb +39 -0
- data/lib/oversip/sip/listeners/tcp_client.rb +73 -0
- data/lib/oversip/sip/listeners/tcp_reactor.rb +185 -0
- data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
- data/lib/oversip/sip/listeners/tls_client.rb +117 -0
- data/lib/oversip/sip/listeners/tls_server.rb +70 -0
- data/lib/oversip/sip/listeners/tls_tunnel_reactor.rb +113 -0
- data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
- data/lib/oversip/sip/listeners/udp_reactor.rb +213 -0
- data/lib/oversip/sip/listeners.rb +28 -0
- data/lib/oversip/sip/logic.rb +14 -0
- data/lib/oversip/sip/message.rb +168 -0
- data/lib/oversip/sip/message_processor.rb +202 -0
- data/lib/oversip/sip/modules/core.rb +200 -0
- data/lib/oversip/sip/modules/registrar_without_path.rb +75 -0
- data/lib/oversip/sip/modules/user_assertion.rb +123 -0
- data/lib/oversip/sip/proxy.rb +460 -0
- data/lib/oversip/sip/request.rb +128 -0
- data/lib/oversip/sip/response.rb +30 -0
- data/lib/oversip/sip/rfc3263.rb +646 -0
- data/lib/oversip/sip/server_transaction.rb +295 -0
- data/lib/oversip/sip/sip.rb +74 -0
- data/lib/oversip/sip/tags.rb +39 -0
- data/lib/oversip/sip/timers.rb +55 -0
- data/lib/oversip/sip/transport_manager.rb +129 -0
- data/lib/oversip/syslogger_process.rb +119 -0
- data/lib/oversip/tls.rb +179 -0
- data/lib/oversip/utils.rb +25 -0
- data/lib/oversip/version.rb +23 -0
- data/lib/oversip/websocket/constants.rb +56 -0
- data/lib/oversip/websocket/default_policy.rb +19 -0
- data/lib/oversip/websocket/http_request.rb +63 -0
- data/lib/oversip/websocket/launcher.rb +207 -0
- data/lib/oversip/websocket/listeners/ipv4_tcp_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv4_tls_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv4_tls_tunnel_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv6_tcp_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv6_tls_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv6_tls_tunnel_server.rb +15 -0
- data/lib/oversip/websocket/listeners/tcp_server.rb +265 -0
- data/lib/oversip/websocket/listeners/tls_server.rb +69 -0
- data/lib/oversip/websocket/listeners/tls_tunnel_server.rb +100 -0
- data/lib/oversip/websocket/listeners.rb +12 -0
- data/lib/oversip/websocket/ws_app.rb +75 -0
- data/lib/oversip/websocket/ws_apps/ipv4_ws_sip_app.rb +21 -0
- data/lib/oversip/websocket/ws_apps/ipv4_wss_sip_app.rb +21 -0
- data/lib/oversip/websocket/ws_apps/ipv6_ws_sip_app.rb +21 -0
- data/lib/oversip/websocket/ws_apps/ipv6_wss_sip_app.rb +22 -0
- data/lib/oversip/websocket/ws_apps/ws_autobahn_app.rb +23 -0
- data/lib/oversip/websocket/ws_apps/ws_sip_app.rb +156 -0
- data/lib/oversip/websocket/ws_apps.rb +9 -0
- data/lib/oversip/websocket/ws_framing.rb +597 -0
- data/lib/oversip.rb +59 -0
- data/test/oversip_test_helper.rb +20 -0
- data/test/test_http_parser.rb +73 -0
- data/test/test_sip_parser.rb +139 -0
- metadata +256 -0
@@ -0,0 +1,646 @@
|
|
1
|
+
module OverSIP::SIP
|
2
|
+
|
3
|
+
module RFC3263
|
4
|
+
|
5
|
+
Target = ::Struct.new(:transport, :ip, :ip_type, :port)
|
6
|
+
|
7
|
+
class Target
|
8
|
+
def to_s
|
9
|
+
if self[2] == :ipv4
|
10
|
+
"#{self[0]}:#{self[1]}:#{self[3]}"
|
11
|
+
else
|
12
|
+
"#{self[0]}:[#{self[1]}]:#{self[3]}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# This is the object returned by Query#resolve.
|
18
|
+
class SrvTargets < ::Array
|
19
|
+
|
20
|
+
# Returns a SrvRandomizedTargets instance.
|
21
|
+
def randomize
|
22
|
+
ordered_targets = SrvRandomizedTargets.allocate
|
23
|
+
|
24
|
+
self.each do |entries|
|
25
|
+
if entries.size == 1
|
26
|
+
entries[0].targets.each {|e| ordered_targets << e}
|
27
|
+
else
|
28
|
+
randomize_entries(entries.select {|e| e.weight > 0}, ordered_targets)
|
29
|
+
entries.select {|e| e.weight.zero?}.shuffle.each {|e| ordered_targets << e[1]}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
return ordered_targets
|
34
|
+
end
|
35
|
+
|
36
|
+
def randomize_entries(entries, ordered_targets)
|
37
|
+
total_weight = 0
|
38
|
+
entries.each {|e| total_weight += e[0]}
|
39
|
+
rnd = rand(total_weight)
|
40
|
+
|
41
|
+
i=0
|
42
|
+
entries.each do |entry|
|
43
|
+
if rnd < entry.weight
|
44
|
+
entry.targets.each {|v| ordered_targets << v}
|
45
|
+
entries.delete_at i
|
46
|
+
break
|
47
|
+
else
|
48
|
+
rnd -= entry.weight
|
49
|
+
i += 1
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
randomize_entries(entries, ordered_targets) unless entries.size.zero?
|
54
|
+
end
|
55
|
+
private :randomize_entries
|
56
|
+
|
57
|
+
end # class SrvTargets
|
58
|
+
|
59
|
+
SrvWeightTarget = ::Struct.new(:weight, :targets)
|
60
|
+
|
61
|
+
# This is the object the method SrvTargets#randomize returns.
|
62
|
+
class SrvRandomizedTargets < ::Array ; end
|
63
|
+
|
64
|
+
class MultiTargets < ::Array
|
65
|
+
attr_accessor :has_srv_weight_targets
|
66
|
+
|
67
|
+
def flatten
|
68
|
+
return self unless @has_srv_weight_targets
|
69
|
+
|
70
|
+
targets = []
|
71
|
+
self.each do |entry|
|
72
|
+
if entry.is_a? RFC3263::Target
|
73
|
+
targets << entry
|
74
|
+
# If not, it's a SrvTargets.
|
75
|
+
else
|
76
|
+
targets.concat entry.randomize
|
77
|
+
end
|
78
|
+
end
|
79
|
+
targets
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
# Some constans for efficience.
|
85
|
+
UDP = "udp"
|
86
|
+
TCP = "tcp"
|
87
|
+
TLS = "tls"
|
88
|
+
SIP =" sip"
|
89
|
+
SIPS = "sips"
|
90
|
+
SIP_D2U = "SIP+D2U"
|
91
|
+
SIP_D2T = "SIP+D2T"
|
92
|
+
SIPS_D2T = "SIPS+D2T"
|
93
|
+
TRANSPORT_TO_SERVICE = { :tls=>SIPS_D2T, :tcp=>SIP_D2T, :udp=>SIP_D2U }
|
94
|
+
|
95
|
+
|
96
|
+
def self.module_init
|
97
|
+
nameservers = ::OverSIP.configuration[:core][:nameservers]
|
98
|
+
::EM::Udns.nameservers = nameservers if nameservers
|
99
|
+
@@resolver = ::EM::Udns::Resolver.new
|
100
|
+
::OverSIP::SIP::RFC3263::Query.class_init
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
def self.run
|
105
|
+
::EM::Udns.run @@resolver
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
def self.resolver
|
110
|
+
@@resolver
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
class Query
|
115
|
+
include ::OverSIP::Logger
|
116
|
+
|
117
|
+
def self.class_init
|
118
|
+
@@fiber_pool = ::OverSIP::FiberPool.new 50
|
119
|
+
end
|
120
|
+
|
121
|
+
def initialize dns_conf, id, uri_scheme, uri_host, uri_host_type, uri_port=nil, uri_transport=nil
|
122
|
+
@id = id
|
123
|
+
@uri_scheme = uri_scheme
|
124
|
+
@uri_host = uri_host
|
125
|
+
@uri_host_type = uri_host_type
|
126
|
+
@uri_port = uri_port
|
127
|
+
@uri_transport = uri_transport
|
128
|
+
|
129
|
+
@use_dns = dns_conf[:use_dns]
|
130
|
+
@transport_preference = dns_conf[:transport_preference]
|
131
|
+
|
132
|
+
@has_sip_ipv4 = dns_conf[:has_sip_ipv4]
|
133
|
+
@has_sip_ipv6 = dns_conf[:has_sip_ipv6]
|
134
|
+
@has_sip_udp = dns_conf[:has_sip_udp]
|
135
|
+
@has_sip_tcp = dns_conf[:has_sip_tcp]
|
136
|
+
@has_sip_tls = dns_conf[:has_sip_tls]
|
137
|
+
|
138
|
+
# Just initialize these attributes if URI host is a domain.
|
139
|
+
if uri_host_type == :domain
|
140
|
+
@ip_type_preference = dns_conf[:ip_type_preference]
|
141
|
+
@force_transport_preference = dns_conf[:force_transport_preference]
|
142
|
+
@use_naptr = dns_conf[:use_naptr]
|
143
|
+
@use_srv = dns_conf[:use_srv]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def log_id
|
148
|
+
@log_id ||= ("RFC3263" << " " << @id)
|
149
|
+
end
|
150
|
+
|
151
|
+
def callback &block
|
152
|
+
@on_success_block = block
|
153
|
+
end
|
154
|
+
|
155
|
+
def errback &block
|
156
|
+
@on_error_block = block
|
157
|
+
end
|
158
|
+
|
159
|
+
# This method can return:
|
160
|
+
# - Target: in case host is a IP.
|
161
|
+
# - SrvTargets: in case SRV took place. Then the client must use SrvTargets#randomize
|
162
|
+
# and get a SrvRandomizedTargets (an Array of Target entries).
|
163
|
+
# - MultiTargets: so each element can be one of the above elements.
|
164
|
+
# - nil: result will be retrieved via callback/errback.
|
165
|
+
# - Symbol: there is some error (domain does not exist, no records, IP is IPv6
|
166
|
+
# but we don't support it, invalid transport...).
|
167
|
+
def resolve
|
168
|
+
if not @use_dns and @uri_host_type == :domain
|
169
|
+
return :rfc3263_no_dns
|
170
|
+
end
|
171
|
+
|
172
|
+
case @uri_scheme
|
173
|
+
when :sip
|
174
|
+
when :sips
|
175
|
+
# If URI scheme is :sips and we don't support TLS then reject it.
|
176
|
+
return :rfc3263_unsupported_scheme unless @has_sip_tls
|
177
|
+
else
|
178
|
+
return :rfc3263_unsupported_scheme
|
179
|
+
end
|
180
|
+
|
181
|
+
dns_transport = nil
|
182
|
+
dns_port = @uri_port
|
183
|
+
|
184
|
+
# dns_transport means the transport type taken from the destination SIP URI.
|
185
|
+
# If @uri_scheme is :sips and no @uri_transport is given (or it's :tcp), then
|
186
|
+
# dns_transport is :tls.
|
187
|
+
# So dns_transport can be :udp, :tcp or :tls, while @uri_transport should not be
|
188
|
+
# :tls (according to RFC 3261) in case scheme is :sips, and maybe :udp, :tcp, :sctp
|
189
|
+
# or whatever token. In case scheme is :sip then @uri_transport can be :tls so
|
190
|
+
# dns_transport would be :tls.
|
191
|
+
|
192
|
+
### First select @transport.
|
193
|
+
|
194
|
+
# If it's a domain with no port nor ;transport, then
|
195
|
+
# transport will be inspected later with NAPTR.
|
196
|
+
if not @uri_transport and ( @uri_host_type != :domain or @uri_port )
|
197
|
+
case @uri_scheme
|
198
|
+
when :sip
|
199
|
+
if @has_sip_udp
|
200
|
+
dns_transport = :udp
|
201
|
+
# In case we don't support UDP then use TCP (why not? local policy).
|
202
|
+
elsif @has_sip_tcp
|
203
|
+
dns_transport = :tcp
|
204
|
+
else
|
205
|
+
return :rfc3263_unsupported_transport
|
206
|
+
end
|
207
|
+
when :sips
|
208
|
+
dns_transport = :tls
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# If the URI has ;transport param, then set dns_transport.
|
213
|
+
if @uri_transport
|
214
|
+
case @uri_transport
|
215
|
+
when :udp
|
216
|
+
return :rfc3263_unsupported_transport unless @has_sip_udp
|
217
|
+
if @uri_scheme == :sip
|
218
|
+
dns_transport = :udp
|
219
|
+
# "sips" is not possible in UDP.
|
220
|
+
else
|
221
|
+
return :rfc3263_wrong_transport
|
222
|
+
end
|
223
|
+
when :tcp
|
224
|
+
case (dns_transport = ( @uri_scheme == :sips ? :tls : :tcp ))
|
225
|
+
when :tcp ; return :rfc3263_unsupported_transport unless @has_sip_tcp
|
226
|
+
when :tls ; return :rfc3263_unsupported_transport unless @has_sip_tls
|
227
|
+
end
|
228
|
+
when :tls
|
229
|
+
return :rfc3263_unsupported_transport unless @has_sip_tls
|
230
|
+
dns_transport = :tls
|
231
|
+
else
|
232
|
+
return :rfc3263_unsupported_transport
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
# If URI host is an IP, no DNS query must be done (so no Ruby Fiber must be created).
|
237
|
+
unless @uri_host_type == :domain
|
238
|
+
if @uri_host_type == :ipv4 and not @has_sip_ipv4
|
239
|
+
return :rfc3263_no_ipv4
|
240
|
+
elsif @uri_host_type == :ipv6 and not @has_sip_ipv6
|
241
|
+
return :rfc3263_no_ipv6
|
242
|
+
end
|
243
|
+
|
244
|
+
dns_port ||= 5061 if dns_transport == :tls
|
245
|
+
dns_port ||= case @uri_scheme
|
246
|
+
when :sip ; 5060
|
247
|
+
when :sips ; 5061
|
248
|
+
end
|
249
|
+
|
250
|
+
return Target.new(dns_transport, @uri_host, @uri_host_type, dns_port)
|
251
|
+
end
|
252
|
+
|
253
|
+
|
254
|
+
# URI host is domain so at least a DNS query must be performed.
|
255
|
+
# Let's create/use a Fiber then.
|
256
|
+
@@fiber_pool.spawn do
|
257
|
+
|
258
|
+
# If URI port is specified perform DNS A/AAAA (then transport has been
|
259
|
+
# already set above).
|
260
|
+
if @uri_port
|
261
|
+
if (targets = resolve_A_AAAA(dns_transport, @uri_host, dns_port))
|
262
|
+
if targets.size == 1
|
263
|
+
@on_success_block && @on_success_block.call(targets[0])
|
264
|
+
else
|
265
|
+
@on_success_block && @on_success_block.call(targets)
|
266
|
+
end
|
267
|
+
else
|
268
|
+
@on_error_block && @on_error_block.call(:rfc3263_domain_not_found)
|
269
|
+
end
|
270
|
+
|
271
|
+
|
272
|
+
# If the URI has no port but has ;transport param, then DNS SRV takes place.
|
273
|
+
elsif @uri_transport
|
274
|
+
if @use_srv
|
275
|
+
if (targets = resolve_SRV(@uri_host, @uri_scheme, dns_transport))
|
276
|
+
### TODO: Esto es nuevo para mejora. Antes devolvía siempre el segundo caso.
|
277
|
+
if targets.size == 1
|
278
|
+
@on_success_block && @on_success_block.call(targets[0])
|
279
|
+
else
|
280
|
+
@on_success_block && @on_success_block.call(targets)
|
281
|
+
end
|
282
|
+
else
|
283
|
+
@on_error_block && @on_error_block.call(:rfc3263_domain_not_found)
|
284
|
+
end
|
285
|
+
|
286
|
+
# If @use_srv is false then perform A/AAAA queries.
|
287
|
+
else
|
288
|
+
log_system_debug "SRV is dissabled, performing A/AAAA queries" if $oversip_debug
|
289
|
+
|
290
|
+
port = 5061 if dns_transport == :tls
|
291
|
+
port ||= case @uri_scheme
|
292
|
+
when :sip ; 5060
|
293
|
+
when :sips ; 5061
|
294
|
+
end
|
295
|
+
|
296
|
+
if (targets = resolve_A_AAAA(dns_transport, @uri_host, port))
|
297
|
+
if targets.size == 1
|
298
|
+
@on_success_block && @on_success_block.call(targets[0])
|
299
|
+
else
|
300
|
+
@on_success_block && @on_success_block.call(targets)
|
301
|
+
end
|
302
|
+
else
|
303
|
+
@on_error_block && @on_error_block.call(:rfc3263_domain_not_found)
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
307
|
+
|
308
|
+
|
309
|
+
# If not, the URI has no port neither ;transport param. NAPTR is required.
|
310
|
+
else
|
311
|
+
# If @use_naptr is false then NAPTR must not be performed.
|
312
|
+
if ! @use_naptr
|
313
|
+
if @use_srv
|
314
|
+
log_system_debug "NAPTR is dissabled, performing SRV queries" if $oversip_debug
|
315
|
+
continue_with_SRV
|
316
|
+
|
317
|
+
# If @use_srv is false then perform A/AAAA queries.
|
318
|
+
else
|
319
|
+
log_system_debug "NAPTR and SRV are dissabled, performing A/AAAA queries" if $oversip_debug
|
320
|
+
case @uri_scheme
|
321
|
+
when :sip
|
322
|
+
if @has_sip_udp
|
323
|
+
dns_transport = :udp
|
324
|
+
port = 5060
|
325
|
+
# In case we don't support UDP then use TCP (why not? local policy).
|
326
|
+
elsif @has_sip_tcp
|
327
|
+
dns_transport = :tcp
|
328
|
+
port = 5060
|
329
|
+
else
|
330
|
+
@on_error_block && @on_error_block.call(:rfc3263_unsupported_transport)
|
331
|
+
end
|
332
|
+
when :sips
|
333
|
+
dns_transport = :tls
|
334
|
+
port = 5061
|
335
|
+
end
|
336
|
+
|
337
|
+
if (targets = resolve_A_AAAA(dns_transport, @uri_host, port))
|
338
|
+
if targets.size == 1
|
339
|
+
@on_success_block && @on_success_block.call(targets[0])
|
340
|
+
else
|
341
|
+
@on_success_block && @on_success_block.call(targets)
|
342
|
+
end
|
343
|
+
else
|
344
|
+
@on_error_block && @on_error_block.call(:rfc3263_domain_not_found)
|
345
|
+
end
|
346
|
+
|
347
|
+
end
|
348
|
+
|
349
|
+
# There are NAPTR records so inspect them (note that there still could be no valid SIP NAPTR records
|
350
|
+
# so SRV should take place).
|
351
|
+
elsif (naptrs = sync_resolve_NAPTR(@uri_host))
|
352
|
+
|
353
|
+
# If URI scheme is :sips just SIPS+D2T must be searched.
|
354
|
+
naptrs.select! do |naptr|
|
355
|
+
naptr.flags.downcase == "s" and
|
356
|
+
( (@has_sip_tls and naptr.service.upcase == SIPS_D2T) or
|
357
|
+
(@uri_scheme == :sip and @has_sip_tcp and naptr.service.upcase == SIP_D2T) or
|
358
|
+
(@uri_scheme == :sip and @has_sip_udp and naptr.service.upcase == SIP_D2U) )
|
359
|
+
end
|
360
|
+
|
361
|
+
# There are NAPTR records, but not for SIP (or not for SIPS+D2T in case the URI scheme is :sips).
|
362
|
+
# So perform SRV queries.
|
363
|
+
if naptrs.empty?
|
364
|
+
log_system_debug "cannot get valid NAPTR SIP records, performing SRV queries" if $oversip_debug
|
365
|
+
continue_with_SRV
|
366
|
+
|
367
|
+
# There are NAPTR records for SIP.
|
368
|
+
else
|
369
|
+
# @force_transport_preference is false so let's use NAPTR preferences.
|
370
|
+
unless @force_transport_preference
|
371
|
+
# Order based on RR order and preference (just a bit).
|
372
|
+
ordered_naptrs = naptrs.sort { |x,y| (x.order <=> y.order).nonzero? or y.preference <=> x.preference }
|
373
|
+
|
374
|
+
# @force_transport_preference is true so let's use @transport_preference for ordering the records.
|
375
|
+
else
|
376
|
+
ordered_naptrs = []
|
377
|
+
@transport_preference.each do |transport|
|
378
|
+
service = TRANSPORT_TO_SERVICE[transport]
|
379
|
+
ordered_naptrs.concat(naptrs.select { |naptr| naptr.service.upcase == service })
|
380
|
+
end
|
381
|
+
|
382
|
+
end
|
383
|
+
|
384
|
+
srv_targets = MultiTargets.allocate
|
385
|
+
ordered_naptrs.each do |naptr|
|
386
|
+
naptr_transport = case naptr.service.upcase
|
387
|
+
when SIPS_D2T ; :tls
|
388
|
+
when SIP_D2T ; :tcp
|
389
|
+
when SIP_D2U ; :udp
|
390
|
+
end
|
391
|
+
if (result = resolve_SRV(naptr.replacement, nil, nil, naptr_transport))
|
392
|
+
case result
|
393
|
+
when RFC3263::SrvTargets
|
394
|
+
srv_targets << result
|
395
|
+
srv_targets.has_srv_weight_targets = true
|
396
|
+
# A RFC3263::MultiTargets or an array of RFC3263::Target.
|
397
|
+
when RFC3263::MultiTargets, ::Array
|
398
|
+
srv_targets.concat result
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
if srv_targets.size == 1
|
404
|
+
@on_success_block && @on_success_block.call(srv_targets[0])
|
405
|
+
else
|
406
|
+
@on_success_block && @on_success_block.call(srv_targets)
|
407
|
+
end
|
408
|
+
|
409
|
+
end
|
410
|
+
|
411
|
+
# There are not NAPTR records, so try SRV records in preference order.
|
412
|
+
else
|
413
|
+
log_system_debug "no NAPTR records, performing SRV queries" if $oversip_debug
|
414
|
+
continue_with_SRV
|
415
|
+
|
416
|
+
end
|
417
|
+
|
418
|
+
end
|
419
|
+
|
420
|
+
end
|
421
|
+
|
422
|
+
nil
|
423
|
+
end
|
424
|
+
|
425
|
+
|
426
|
+
def continue_with_SRV
|
427
|
+
srv_targets = MultiTargets.allocate
|
428
|
+
@transport_preference.each do |transport|
|
429
|
+
next if @uri_scheme == :sips and (transport == :udp or transport == :tcp)
|
430
|
+
|
431
|
+
if (result = resolve_SRV(@uri_host, @uri_scheme, transport, transport))
|
432
|
+
case result
|
433
|
+
when RFC3263::SrvTargets
|
434
|
+
srv_targets << result
|
435
|
+
srv_targets.has_srv_weight_targets = true
|
436
|
+
# A RFC3263::MultiTargets or an array of RFC3263::Target.
|
437
|
+
when RFC3263::MultiTargets, ::Array
|
438
|
+
srv_targets.concat result
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
if srv_targets.size == 1
|
444
|
+
@on_success_block && @on_success_block.call(srv_targets[0])
|
445
|
+
|
446
|
+
elsif srv_targets.size > 1
|
447
|
+
@on_success_block && @on_success_block.call(srv_targets)
|
448
|
+
|
449
|
+
# If not, make A/AAAA query.
|
450
|
+
else
|
451
|
+
log_system_debug "no valid SRV targets, performing A/AAAA queries" if $oversip_debug
|
452
|
+
case @uri_scheme
|
453
|
+
when :sip
|
454
|
+
transport = :udp if @has_sip_udp
|
455
|
+
transport ||= :tcp if @has_sip_tcp
|
456
|
+
unless transport
|
457
|
+
@on_error_block && @on_error_block.call(:rfc3263_unsupported_transport)
|
458
|
+
return
|
459
|
+
end
|
460
|
+
port = 5060
|
461
|
+
when :sips
|
462
|
+
transport = :tls
|
463
|
+
port = 5061
|
464
|
+
end
|
465
|
+
|
466
|
+
if targets = resolve_A_AAAA(transport, @uri_host, port)
|
467
|
+
if targets.size == 1
|
468
|
+
@on_success_block && @on_success_block.call(targets[0])
|
469
|
+
else
|
470
|
+
@on_success_block && @on_success_block.call(targets)
|
471
|
+
end
|
472
|
+
else
|
473
|
+
@on_error_block && @on_error_block.call(:rfc3263_domain_not_found)
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|
477
|
+
private :continue_with_SRV
|
478
|
+
|
479
|
+
|
480
|
+
def resolve_A_AAAA transport, domain, port
|
481
|
+
ips = {}
|
482
|
+
|
483
|
+
# DNS A.
|
484
|
+
if @has_sip_ipv4
|
485
|
+
ips[:ipv4] = sync_resolve_A(domain)
|
486
|
+
end
|
487
|
+
|
488
|
+
# DNS AAAA.
|
489
|
+
if @has_sip_ipv6
|
490
|
+
ips[:ipv6] = sync_resolve_AAAA(domain)
|
491
|
+
end
|
492
|
+
|
493
|
+
targets = MultiTargets.allocate
|
494
|
+
@ip_type_preference.each do |ip_type|
|
495
|
+
ips[ip_type].each do |ip|
|
496
|
+
targets << RFC3263::Target.new(transport, ip, ip_type, port)
|
497
|
+
end if ips[ip_type]
|
498
|
+
end
|
499
|
+
|
500
|
+
return case targets.size
|
501
|
+
when 0 ; nil
|
502
|
+
else ; targets
|
503
|
+
end
|
504
|
+
|
505
|
+
end
|
506
|
+
private :resolve_A_AAAA
|
507
|
+
|
508
|
+
|
509
|
+
def resolve_SRV domain, scheme=nil, transport=nil, naptr_transport=nil
|
510
|
+
# If there is not SRV records, perform A/AAAA query for the URI host.
|
511
|
+
unless srvs = sync_resolve_SRV(domain, scheme, transport)
|
512
|
+
# If the query comes from the NAPTR section don't do A/AAAA.
|
513
|
+
return nil if naptr_transport
|
514
|
+
|
515
|
+
port = 5061 if transport == :tls
|
516
|
+
port ||= case scheme
|
517
|
+
when :sip ; 5060
|
518
|
+
when :sips ; 5061
|
519
|
+
end
|
520
|
+
|
521
|
+
return resolve_A_AAAA(transport, domain, port)
|
522
|
+
|
523
|
+
# There are SRV records, so perform A/AAAA queries for every record.
|
524
|
+
else
|
525
|
+
srv_targets = SrvTargets.allocate
|
526
|
+
|
527
|
+
srvs.each do |srv|
|
528
|
+
srv_targets[srv.priority] ||= []
|
529
|
+
|
530
|
+
if targets = resolve_A_AAAA(naptr_transport || transport, srv.domain, srv.port)
|
531
|
+
srv_targets[srv.priority] << SrvWeightTarget.new(srv.weight, targets)
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
# Remove multiple array entries with null value and return nil if got SRV RR have
|
536
|
+
# domain with no A/AAAA resolution.
|
537
|
+
srv_targets.select! {|e| e and e.size > 0}
|
538
|
+
|
539
|
+
return nil if srv_targets.empty?
|
540
|
+
|
541
|
+
if srv_targets.size == 1 and srv_targets[0].size == 1
|
542
|
+
return srv_targets[0][0].targets
|
543
|
+
else
|
544
|
+
return srv_targets
|
545
|
+
end
|
546
|
+
end
|
547
|
+
end
|
548
|
+
private :resolve_SRV
|
549
|
+
|
550
|
+
|
551
|
+
def sync_resolve_NAPTR domain
|
552
|
+
f = Fiber.current
|
553
|
+
|
554
|
+
query = RFC3263.resolver.submit_NAPTR domain
|
555
|
+
query.callback do |result|
|
556
|
+
log_system_debug "DNS NAPTR succeeded for '#{domain}'" if $oversip_debug
|
557
|
+
f.resume result
|
558
|
+
end
|
559
|
+
query.errback do |result|
|
560
|
+
log_system_debug "DNS NAPTR error resolving '#{domain}': #{result}" if $oversip_debug
|
561
|
+
f.resume nil
|
562
|
+
end
|
563
|
+
|
564
|
+
Fiber.yield
|
565
|
+
end
|
566
|
+
private :sync_resolve_NAPTR
|
567
|
+
|
568
|
+
|
569
|
+
def sync_resolve_SRV domain, service=nil, protocol=nil
|
570
|
+
f = Fiber.current
|
571
|
+
|
572
|
+
if service == :sip and protocol == :tls
|
573
|
+
service = SIPS
|
574
|
+
elsif service
|
575
|
+
service = service.to_s
|
576
|
+
end
|
577
|
+
|
578
|
+
protocol = case protocol
|
579
|
+
when :udp ; UDP
|
580
|
+
when :tcp, :tls ; TCP
|
581
|
+
end
|
582
|
+
|
583
|
+
query = RFC3263.resolver.submit_SRV domain, service, protocol
|
584
|
+
query.callback do |result|
|
585
|
+
if service
|
586
|
+
log_system_debug "DNS SRV succeeded for domain '#{domain}', service '#{service}' and protocol '#{protocol}'" if $oversip_debug
|
587
|
+
else
|
588
|
+
log_system_debug "DNS SRV succeeded for '#{domain}'" if $oversip_debug
|
589
|
+
end
|
590
|
+
f.resume result
|
591
|
+
end
|
592
|
+
query.errback do |result|
|
593
|
+
if service
|
594
|
+
log_system_debug "DNS SRV error resolving domain '#{domain}', service '#{service}' and protocol '#{protocol}': #{result}" if $oversip_debug
|
595
|
+
else
|
596
|
+
log_system_debug "DNS SRV error resolving '#{domain}': #{result}" if $oversip_debug
|
597
|
+
end
|
598
|
+
f.resume nil
|
599
|
+
end
|
600
|
+
|
601
|
+
Fiber.yield
|
602
|
+
end
|
603
|
+
private :sync_resolve_SRV
|
604
|
+
|
605
|
+
|
606
|
+
def sync_resolve_A domain
|
607
|
+
f = Fiber.current
|
608
|
+
|
609
|
+
query = RFC3263.resolver.submit_A domain
|
610
|
+
query.callback do |result|
|
611
|
+
log_system_debug "DNS A succeeded for domain '#{domain}'" if $oversip_debug
|
612
|
+
f.resume result
|
613
|
+
end
|
614
|
+
query.errback do |result|
|
615
|
+
log_system_debug "DNS A error resolving domain '#{domain}': #{result}" if $oversip_debug
|
616
|
+
f.resume nil
|
617
|
+
end
|
618
|
+
|
619
|
+
Fiber.yield
|
620
|
+
end
|
621
|
+
private :sync_resolve_A
|
622
|
+
|
623
|
+
|
624
|
+
def sync_resolve_AAAA domain
|
625
|
+
f = Fiber.current
|
626
|
+
|
627
|
+
query = RFC3263.resolver.submit_AAAA domain
|
628
|
+
query.callback do |result|
|
629
|
+
log_system_debug "DNS AAAA succeeded for domain '#{domain}'" if $oversip_debug
|
630
|
+
f.resume result
|
631
|
+
end
|
632
|
+
query.errback do |result|
|
633
|
+
log_system_debug "DNS AAAA error resolving domain '#{domain}': #{result}" if $oversip_debug
|
634
|
+
f.resume nil
|
635
|
+
end
|
636
|
+
|
637
|
+
Fiber.yield
|
638
|
+
end
|
639
|
+
private :sync_resolve_AAAA
|
640
|
+
|
641
|
+
end # class Query
|
642
|
+
|
643
|
+
end # module RFC3263
|
644
|
+
|
645
|
+
end
|
646
|
+
|