Class: OverSIP::SIP::RFC3263::Query
- Inherits:
-
Object
- Object
- OverSIP::SIP::RFC3263::Query
- Includes:
- Logger
- Defined in:
- lib/oversip/sip/rfc3263.rb
Class Method Summary collapse
Instance Method Summary collapse
- #callback(&block) ⇒ Object
- #errback(&block) ⇒ Object
-
#initialize(dns_conf, id, uri_scheme, uri_host, uri_host_type, uri_port = nil, uri_transport = nil) ⇒ Query
constructor
A new instance of Query.
-
#resolve ⇒ Object
This method can return: - Target: in case host is a IP.
Methods included from Logger
fg_system_msg2str, load_methods, #log_id
Constructor Details
#initialize(dns_conf, id, uri_scheme, uri_host, uri_host_type, uri_port = nil, uri_transport = nil) ⇒ Query
Returns a new instance of Query.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/oversip/sip/rfc3263.rb', line 121 def initialize dns_conf, id, uri_scheme, uri_host, uri_host_type, uri_port=nil, uri_transport=nil @id = id @uri_scheme = uri_scheme @uri_host = uri_host @uri_host_type = uri_host_type @uri_port = uri_port @uri_transport = uri_transport @log_id ||= ("RFC3263" << " " << @id) @use_dns = dns_conf[:use_dns] @transport_preference = dns_conf[:transport_preference] @has_sip_ipv4 = dns_conf[:has_sip_ipv4] @has_sip_ipv6 = dns_conf[:has_sip_ipv6] @has_sip_udp = dns_conf[:has_sip_udp] @has_sip_tcp = dns_conf[:has_sip_tcp] @has_sip_tls = dns_conf[:has_sip_tls] # Just initialize these attributes if URI host is a domain. if uri_host_type == :domain @ip_type_preference = dns_conf[:ip_type_preference] @force_transport_preference = dns_conf[:force_transport_preference] @use_naptr = dns_conf[:use_naptr] @use_srv = dns_conf[:use_srv] end end |
Class Method Details
Instance Method Details
#callback(&block) ⇒ Object
149 150 151 |
# File 'lib/oversip/sip/rfc3263.rb', line 149 def callback &block @on_success_block = block end |
#errback(&block) ⇒ Object
153 154 155 |
# File 'lib/oversip/sip/rfc3263.rb', line 153 def errback &block @on_error_block = block end |
#resolve ⇒ Object
This method can return:
-
Target: in case host is a IP.
-
SrvTargets: in case SRV took place. Then the client must use SrvTargets#randomize and get a SrvRandomizedTargets (an Array of Target entries).
-
MultiTargets: so each element can be one of the above elements.
-
nil: result will be retrieved via callback/errback.
-
Symbol: there is some error (domain does not exist, no records, IP is IPv6 but we don’t support it, invalid transport…).
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'lib/oversip/sip/rfc3263.rb', line 165 def resolve if not @use_dns and @uri_host_type == :domain return :rfc3263_no_dns end case @uri_scheme when :sip when :sips # If URI scheme is :sips and we don't support TLS then reject it. return :rfc3263_unsupported_scheme unless @has_sip_tls else return :rfc3263_unsupported_scheme end dns_transport = nil dns_port = @uri_port # dns_transport means the transport type taken from the destination SIP URI. # If @uri_scheme is :sips and no @uri_transport is given (or it's :tcp), then # dns_transport is :tls. # So dns_transport can be :udp, :tcp or :tls, while @uri_transport should not be # :tls (according to RFC 3261) in case scheme is :sips, and maybe :udp, :tcp, :sctp # or whatever token. In case scheme is :sip then @uri_transport can be :tls so # dns_transport would be :tls. ### First select @transport. # If it's a domain with no port nor ;transport, then # transport will be inspected later with NAPTR. if not @uri_transport and ( @uri_host_type != :domain or @uri_port ) case @uri_scheme when :sip if @has_sip_udp dns_transport = :udp # In case we don't support UDP then use TCP (why not? local policy). elsif @has_sip_tcp dns_transport = :tcp else return :rfc3263_unsupported_transport end when :sips dns_transport = :tls end end # If the URI has ;transport param, then set dns_transport. if @uri_transport case @uri_transport when :udp return :rfc3263_unsupported_transport unless @has_sip_udp if @uri_scheme == :sip dns_transport = :udp # "sips" is not possible in UDP. else return :rfc3263_unsupported_transport end when :tcp case (dns_transport = ( @uri_scheme == :sips ? :tls : :tcp )) when :tcp ; return :rfc3263_unsupported_transport unless @has_sip_tcp when :tls ; return :rfc3263_unsupported_transport unless @has_sip_tls end when :tls return :rfc3263_unsupported_transport unless @has_sip_tls dns_transport = :tls else return :rfc3263_unsupported_transport end end # If URI host is an IP, no DNS query must be done (so no Ruby Fiber must be created). unless @uri_host_type == :domain if @uri_host_type == :ipv4 and not @has_sip_ipv4 return :rfc3263_no_ipv4 elsif @uri_host_type == :ipv6 and not @has_sip_ipv6 return :rfc3263_no_ipv6 end dns_port ||= 5061 if dns_transport == :tls dns_port ||= case @uri_scheme when :sip ; 5060 when :sips ; 5061 end return Target.new(dns_transport, @uri_host, @uri_host_type, dns_port) end # URI host is domain so at least a DNS query must be performed. # Let's create/use a Fiber then. @@fiber_pool.spawn do # If URI port is specified perform DNS A/AAAA (then transport has been # already set above). if @uri_port if (targets = resolve_A_AAAA(dns_transport, @uri_host, dns_port)) if targets.size == 1 @on_success_block && @on_success_block.call(targets[0]) else @on_success_block && @on_success_block.call(targets) end else @on_error_block && @on_error_block.call(:rfc3263_domain_not_found) end # If the URI has no port but has ;transport param, then DNS SRV takes place. elsif @uri_transport if @use_srv if (targets = resolve_SRV(@uri_host, @uri_scheme, dns_transport)) if targets.size == 1 @on_success_block && @on_success_block.call(targets[0]) else @on_success_block && @on_success_block.call(targets) end else @on_error_block && @on_error_block.call(:rfc3263_domain_not_found) end # If @use_srv is false then perform A/AAAA queries. else log_system_debug "SRV is disabled, performing A/AAAA queries" if $oversip_debug port = 5061 if dns_transport == :tls port ||= case @uri_scheme when :sip ; 5060 when :sips ; 5061 end if (targets = resolve_A_AAAA(dns_transport, @uri_host, port)) if targets.size == 1 @on_success_block && @on_success_block.call(targets[0]) else @on_success_block && @on_success_block.call(targets) end else @on_error_block && @on_error_block.call(:rfc3263_domain_not_found) end end # If not, the URI has no port neither ;transport param. NAPTR is required. else # If @use_naptr is false then NAPTR must not be performed. if ! @use_naptr if @use_srv log_system_debug "NAPTR is disabled, performing SRV queries" if $oversip_debug continue_with_SRV # If @use_srv is false then perform A/AAAA queries. else log_system_debug "NAPTR and SRV are disabled, performing A/AAAA queries" if $oversip_debug case @uri_scheme when :sip if @has_sip_udp dns_transport = :udp port = 5060 # In case we don't support UDP then use TCP (why not? local policy). elsif @has_sip_tcp dns_transport = :tcp port = 5060 else @on_error_block && @on_error_block.call(:rfc3263_unsupported_transport) end when :sips dns_transport = :tls port = 5061 end if (targets = resolve_A_AAAA(dns_transport, @uri_host, port)) if targets.size == 1 @on_success_block && @on_success_block.call(targets[0]) else @on_success_block && @on_success_block.call(targets) end else @on_error_block && @on_error_block.call(:rfc3263_domain_not_found) end end # There are NAPTR records so inspect them (note that there still could be no valid SIP NAPTR records # so SRV should take place). elsif (naptrs = sync_resolve_NAPTR(@uri_host)) # If URI scheme is :sips just SIPS+D2T must be searched. naptrs.select! do |naptr| naptr.flags.downcase == "s" and ( (@has_sip_tls and naptr.service.upcase == SIPS_D2T) or (@uri_scheme == :sip and @has_sip_tcp and naptr.service.upcase == SIP_D2T) or (@uri_scheme == :sip and @has_sip_udp and naptr.service.upcase == SIP_D2U) ) end # There are NAPTR records, but not for SIP (or not for SIPS+D2T in case the URI scheme is :sips). # So perform SRV queries. if naptrs.empty? log_system_debug "cannot get valid NAPTR SIP records, performing SRV queries" if $oversip_debug continue_with_SRV # There are NAPTR records for SIP. else # @force_transport_preference is false so let's use NAPTR preferences. unless @force_transport_preference # Order based on RR order and preference (just a bit). ordered_naptrs = naptrs.sort { |x,y| (x.order <=> y.order).nonzero? or y.preference <=> x.preference } # @force_transport_preference is true so let's use @transport_preference for ordering the records. else ordered_naptrs = [] @transport_preference.each do |transport| service = TRANSPORT_TO_SERVICE[transport] ordered_naptrs.concat(naptrs.select { |naptr| naptr.service.upcase == service }) end end srv_targets = MultiTargets.allocate ordered_naptrs.each do |naptr| naptr_transport = case naptr.service.upcase when SIPS_D2T ; :tls when SIP_D2T ; :tcp when SIP_D2U ; :udp end if (result = resolve_SRV(naptr.replacement, nil, nil, naptr_transport)) case result when RFC3263::SrvTargets srv_targets << result srv_targets.has_srv_weight_targets = true # A RFC3263::MultiTargets or an array of RFC3263::Target. when RFC3263::MultiTargets, ::Array srv_targets.concat result end end end if srv_targets.size == 1 @on_success_block && @on_success_block.call(srv_targets[0]) else @on_success_block && @on_success_block.call(srv_targets) end end # There are not NAPTR records, so try SRV records in preference order. else log_system_debug "no NAPTR records, performing SRV queries" if $oversip_debug continue_with_SRV end end end # @@fiber_pool.spawn nil end |