oversip 0.9.0
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/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
|
+
|