oversip_p 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+