oversip 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/AUTHORS.txt +11 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +16 -0
  4. data/Rakefile +55 -0
  5. data/bin/oversip +182 -0
  6. data/ext/common/c_util.h +74 -0
  7. data/ext/common/ruby_c_util.h +88 -0
  8. data/ext/sip_parser/common_headers.h +209 -0
  9. data/ext/sip_parser/ext_help.h +18 -0
  10. data/ext/sip_parser/extconf.rb +3 -0
  11. data/ext/sip_parser/sip_parser.c +29649 -0
  12. data/ext/sip_parser/sip_parser.h +227 -0
  13. data/ext/sip_parser/sip_parser_ruby.c +1292 -0
  14. data/ext/stud/extconf.rb +27 -0
  15. data/ext/stud/stud.tar.gz +0 -0
  16. data/ext/stun/ext_help.h +16 -0
  17. data/ext/stun/extconf.rb +3 -0
  18. data/ext/stun/stun_ruby.c +391 -0
  19. data/ext/utils/ext_help.h +14 -0
  20. data/ext/utils/extconf.rb +3 -0
  21. data/ext/utils/haproxy_protocol.c +6163 -0
  22. data/ext/utils/haproxy_protocol.h +27 -0
  23. data/ext/utils/ip_utils.c +5952 -0
  24. data/ext/utils/ip_utils.h +61 -0
  25. data/ext/utils/outbound_utils.c +3227 -0
  26. data/ext/utils/outbound_utils.h +27 -0
  27. data/ext/utils/utils_ruby.c +384 -0
  28. data/ext/utils/utils_ruby.h +75 -0
  29. data/ext/websocket_framing_utils/ext_help.h +18 -0
  30. data/ext/websocket_framing_utils/extconf.rb +3 -0
  31. data/ext/websocket_framing_utils/ws_framing_utils.h +46 -0
  32. data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
  33. data/ext/websocket_http_parser/ext_help.h +18 -0
  34. data/ext/websocket_http_parser/extconf.rb +3 -0
  35. data/ext/websocket_http_parser/ws_http_parser.c +2598 -0
  36. data/ext/websocket_http_parser/ws_http_parser.h +86 -0
  37. data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
  38. data/lib/oversip/config.rb +541 -0
  39. data/lib/oversip/config_validators.rb +126 -0
  40. data/lib/oversip/errors.rb +7 -0
  41. data/lib/oversip/fiber_pool.rb +56 -0
  42. data/lib/oversip/launcher.rb +507 -0
  43. data/lib/oversip/logger.rb +170 -0
  44. data/lib/oversip/master_process.rb +67 -0
  45. data/lib/oversip/posix_mq.rb +121 -0
  46. data/lib/oversip/proxies_config.rb +169 -0
  47. data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
  48. data/lib/oversip/sip/client_transaction.rb +587 -0
  49. data/lib/oversip/sip/constants.rb +87 -0
  50. data/lib/oversip/sip/grammar/name_addr.rb +27 -0
  51. data/lib/oversip/sip/grammar/uri.rb +116 -0
  52. data/lib/oversip/sip/launcher.rb +180 -0
  53. data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
  54. data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +21 -0
  55. data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
  56. data/lib/oversip/sip/listeners/ipv4_tls_server.rb +21 -0
  57. data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +21 -0
  58. data/lib/oversip/sip/listeners/ipv4_udp_server.rb +20 -0
  59. data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
  60. data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +21 -0
  61. data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
  62. data/lib/oversip/sip/listeners/ipv6_tls_server.rb +21 -0
  63. data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +21 -0
  64. data/lib/oversip/sip/listeners/ipv6_udp_server.rb +20 -0
  65. data/lib/oversip/sip/listeners/reactor.rb +39 -0
  66. data/lib/oversip/sip/listeners/tcp_client.rb +73 -0
  67. data/lib/oversip/sip/listeners/tcp_reactor.rb +185 -0
  68. data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
  69. data/lib/oversip/sip/listeners/tls_client.rb +117 -0
  70. data/lib/oversip/sip/listeners/tls_server.rb +70 -0
  71. data/lib/oversip/sip/listeners/tls_tunnel_reactor.rb +113 -0
  72. data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
  73. data/lib/oversip/sip/listeners/udp_reactor.rb +213 -0
  74. data/lib/oversip/sip/listeners.rb +28 -0
  75. data/lib/oversip/sip/logic.rb +14 -0
  76. data/lib/oversip/sip/message.rb +168 -0
  77. data/lib/oversip/sip/message_processor.rb +202 -0
  78. data/lib/oversip/sip/modules/core.rb +200 -0
  79. data/lib/oversip/sip/modules/registrar_without_path.rb +75 -0
  80. data/lib/oversip/sip/modules/user_assertion.rb +123 -0
  81. data/lib/oversip/sip/proxy.rb +460 -0
  82. data/lib/oversip/sip/request.rb +128 -0
  83. data/lib/oversip/sip/response.rb +30 -0
  84. data/lib/oversip/sip/rfc3263.rb +646 -0
  85. data/lib/oversip/sip/server_transaction.rb +295 -0
  86. data/lib/oversip/sip/sip.rb +74 -0
  87. data/lib/oversip/sip/tags.rb +39 -0
  88. data/lib/oversip/sip/timers.rb +55 -0
  89. data/lib/oversip/sip/transport_manager.rb +129 -0
  90. data/lib/oversip/syslogger_process.rb +119 -0
  91. data/lib/oversip/tls.rb +179 -0
  92. data/lib/oversip/utils.rb +25 -0
  93. data/lib/oversip/version.rb +23 -0
  94. data/lib/oversip/websocket/constants.rb +56 -0
  95. data/lib/oversip/websocket/default_policy.rb +19 -0
  96. data/lib/oversip/websocket/http_request.rb +63 -0
  97. data/lib/oversip/websocket/launcher.rb +207 -0
  98. data/lib/oversip/websocket/listeners/ipv4_tcp_server.rb +15 -0
  99. data/lib/oversip/websocket/listeners/ipv4_tls_server.rb +15 -0
  100. data/lib/oversip/websocket/listeners/ipv4_tls_tunnel_server.rb +15 -0
  101. data/lib/oversip/websocket/listeners/ipv6_tcp_server.rb +15 -0
  102. data/lib/oversip/websocket/listeners/ipv6_tls_server.rb +15 -0
  103. data/lib/oversip/websocket/listeners/ipv6_tls_tunnel_server.rb +15 -0
  104. data/lib/oversip/websocket/listeners/tcp_server.rb +265 -0
  105. data/lib/oversip/websocket/listeners/tls_server.rb +69 -0
  106. data/lib/oversip/websocket/listeners/tls_tunnel_server.rb +100 -0
  107. data/lib/oversip/websocket/listeners.rb +12 -0
  108. data/lib/oversip/websocket/ws_app.rb +75 -0
  109. data/lib/oversip/websocket/ws_apps/ipv4_ws_sip_app.rb +21 -0
  110. data/lib/oversip/websocket/ws_apps/ipv4_wss_sip_app.rb +21 -0
  111. data/lib/oversip/websocket/ws_apps/ipv6_ws_sip_app.rb +21 -0
  112. data/lib/oversip/websocket/ws_apps/ipv6_wss_sip_app.rb +22 -0
  113. data/lib/oversip/websocket/ws_apps/ws_autobahn_app.rb +23 -0
  114. data/lib/oversip/websocket/ws_apps/ws_sip_app.rb +156 -0
  115. data/lib/oversip/websocket/ws_apps.rb +9 -0
  116. data/lib/oversip/websocket/ws_framing.rb +597 -0
  117. data/lib/oversip.rb +59 -0
  118. data/test/oversip_test_helper.rb +20 -0
  119. data/test/test_http_parser.rb +73 -0
  120. data/test/test_sip_parser.rb +139 -0
  121. 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
+