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