@@ -180,42 +180,44 @@ def inspect
180180 # @return [ Mongo::Socket::SSL | Mongo::Socket::TCP | Mongo::Socket::Unix ]
181181 # The socket.
182182 #
183- # @raise [ Exception ] If network connection failed.
183+ # @raise [ Mongo::Error ] If network connection failed.
184184 #
185185 # @since 2.0.0
186186 def socket ( socket_timeout , ssl_options = { } , options = { } )
187- if seed . downcase =~ Unix ::MATCH
188- specific_address = Unix . new ( seed . downcase )
189- return specific_address . socket ( socket_timeout , ssl_options , options )
190- end
187+ map_exceptions do
188+ if seed . downcase =~ Unix ::MATCH
189+ specific_address = Unix . new ( seed . downcase )
190+ return specific_address . socket ( socket_timeout , ssl_options , options )
191+ end
192+
193+ options = {
194+ connect_timeout : Server ::CONNECT_TIMEOUT ,
195+ } . update ( options )
191196
192- options = {
193- connect_timeout : Server ::CONNECT_TIMEOUT ,
194- } . update ( options )
195-
196- # When the driver connects to "localhost", it only attempts IPv4
197- # connections. When the driver connects to other hosts, it will
198- # attempt both IPv4 and IPv6 connections.
199- family = ( host == LOCALHOST ) ? ::Socket ::AF_INET : ::Socket ::AF_UNSPEC
200- error = nil
201- # Sometimes Socket#getaddrinfo returns the same info more than once
202- # (multiple identical items in the returned array). It does not make
203- # sense to try to connect to the same address more than once, thus
204- # eliminate duplicates here.
205- infos = ::Socket . getaddrinfo ( host , nil , family , ::Socket ::SOCK_STREAM )
206- results = infos . map do |info |
207- [ info [ 4 ] , info [ 3 ] ]
208- end . uniq
209- results . each do |family , address_str |
210- begin
211- specific_address = FAMILY_MAP [ family ] . new ( address_str , port , host )
212- socket = specific_address . socket ( socket_timeout , ssl_options , options )
213- return socket
214- rescue IOError , SystemCallError , Error ::SocketTimeoutError , Error ::SocketError => e
215- error = e
197+ # When the driver connects to "localhost", it only attempts IPv4
198+ # connections. When the driver connects to other hosts, it will
199+ # attempt both IPv4 and IPv6 connections.
200+ family = ( host == LOCALHOST ) ? ::Socket ::AF_INET : ::Socket ::AF_UNSPEC
201+ error = nil
202+ # Sometimes Socket#getaddrinfo returns the same info more than once
203+ # (multiple identical items in the returned array). It does not make
204+ # sense to try to connect to the same address more than once, thus
205+ # eliminate duplicates here.
206+ infos = ::Socket . getaddrinfo ( host , nil , family , ::Socket ::SOCK_STREAM )
207+ results = infos . map do |info |
208+ [ info [ 4 ] , info [ 3 ] ]
209+ end . uniq
210+ results . each do |family , address_str |
211+ begin
212+ specific_address = FAMILY_MAP [ family ] . new ( address_str , port , host )
213+ socket = specific_address . socket ( socket_timeout , ssl_options , options )
214+ return socket
215+ rescue IOError , SystemCallError , Error ::SocketTimeoutError , Error ::SocketError => e
216+ error = e
217+ end
216218 end
219+ raise error
217220 end
218- raise error
219221 end
220222
221223 # Get the address as a string.
@@ -248,5 +250,17 @@ def parse_host_port
248250 else IPv4 . parse ( address )
249251 end
250252 end
253+
254+ def map_exceptions
255+ begin
256+ yield
257+ rescue Errno ::ETIMEDOUT => e
258+ raise Error ::SocketTimeoutError , "#{ e . class } : #{ e } (for #{ self } )"
259+ rescue IOError , SystemCallError => e
260+ raise Error ::SocketError , "#{ e . class } : #{ e } (for #{ self } )"
261+ rescue OpenSSL ::SSL ::SSLError => e
262+ raise Error ::SocketError , "#{ e . class } : #{ e } (for #{ self } ) (#{ SSL_ERROR } )"
263+ end
264+ end
251265 end
252266end
0 commit comments