1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
# frozen_string_literal: true
# rubocop:todo all
# Copyright (C) 2014-2020 MongoDB Inc.
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Mongo
class Address
# Sets up resolution with IPv6 support if the address is an ip
# address.
#
# @since 2.0.0
class IPv6
# @return [ String ] host The host.
attr_reader :host
# @return [ String ] host_name The original host name.
attr_reader :host_name
# @return [ Integer ] port The port.
attr_reader :port
# The regular expression to use to match an IPv6 ip address.
#
# @since 2.0.0
MATCH = Regexp.new('::').freeze
# Parse an IPv6 address into its host and port.
#
# @example Parse the address.
# IPv6.parse("[::1]:28011")
#
# @param [ String ] address The address to parse.
#
# @return [ Array<String, Integer> ] The host and port pair.
#
# @since 2.0.0
def self.parse(address)
# IPAddr's parser handles IP address only, not port.
# Therefore we need to handle the port ourselves
if address =~ /[\[\]]/
parts = address.match(/\A\[(.+)\](?::(\d+))?\z/)
if parts.nil?
raise ArgumentError, "Invalid IPv6 address: #{address}"
end
host = parts[1]
port = (parts[2] || 27017).to_i
else
host = address
port = 27017
end
# Validate host.
# This will raise IPAddr::InvalidAddressError
# on newer rubies which is a subclass of ArgumentError
# if host is invalid
begin
IPAddr.new(host)
rescue ArgumentError
raise ArgumentError, "Invalid IPv6 address: #{address}"
end
[ host, port ]
end
# Initialize the IPv6 resolver.
#
# @example Initialize the resolver.
# IPv6.new("::1", 28011, 'localhost')
#
# @param [ String ] host The host.
# @param [ Integer ] port The port.
#
# @since 2.0.0
def initialize(host, port, host_name=nil)
@host = host
@port = port
@host_name = host_name
end
# Get a socket for the provided address type, given the options.
#
# @example Get an IPv6 socket.
# ipv4.socket(5, :ssl => true)
#
# @param [ Float ] socket_timeout The socket timeout.
# @param [ Hash ] options The options.
#
# @option options [ Float ] :connect_timeout Connect timeout.
# @option options [ true | false ] :ssl Whether to use TLS.
# @option options [ String ] :ssl_ca_cert
# Same as the corresponding Client/Socket::SSL option.
# @option options [ Array<OpenSSL::X509::Certificate> ] :ssl_ca_cert_object
# Same as the corresponding Client/Socket::SSL option.
# @option options [ String ] :ssl_ca_cert_string
# Same as the corresponding Client/Socket::SSL option.
# @option options [ String ] :ssl_cert
# Same as the corresponding Client/Socket::SSL option.
# @option options [ OpenSSL::X509::Certificate ] :ssl_cert_object
# Same as the corresponding Client/Socket::SSL option.
# @option options [ String ] :ssl_cert_string
# Same as the corresponding Client/Socket::SSL option.
# @option options [ String ] :ssl_key
# Same as the corresponding Client/Socket::SSL option.
# @option options [ OpenSSL::PKey ] :ssl_key_object
# Same as the corresponding Client/Socket::SSL option.
# @option options [ String ] :ssl_key_pass_phrase
# Same as the corresponding Client/Socket::SSL option.
# @option options [ String ] :ssl_key_string
# Same as the corresponding Client/Socket::SSL option.
# @option options [ true, false ] :ssl_verify
# Same as the corresponding Client/Socket::SSL option.
# @option options [ true, false ] :ssl_verify_certificate
# Same as the corresponding Client/Socket::SSL option.
# @option options [ true, false ] :ssl_verify_hostname
# Same as the corresponding Client/Socket::SSL option.
#
# @return [ Mongo::Socket::SSL, Mongo::Socket::TCP ] The socket.
#
# @since 2.0.0
# @api private
def socket(socket_timeout, options = {})
if options[:ssl]
Socket::SSL.new(host, port, host_name, socket_timeout, Socket::PF_INET6, options)
else
Socket::TCP.new(host, port, socket_timeout, Socket::PF_INET6, options)
end
end
end
end
end
|