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