@@ -272,11 +272,11 @@ async def _connect_secure(cls, resolved_address, timeout, keep_alive, ssl):
272272 ) from error
273273 raise
274274
275- async def _handshake (self , resolved_address ):
275+ async def _handshake (self , resolved_address , deadline ):
276276 """
277277
278- :param s: Socket
279278 :param resolved_address:
279+ :param deadline: Deadline for handshake
280280
281281 :returns: (socket, version, client_handshake, server_response_data)
282282 """
@@ -296,47 +296,52 @@ async def _handshake(self, resolved_address):
296296 log .debug ("[#%04X] C: <HANDSHAKE> %s %s %s %s" , local_port ,
297297 * supported_versions )
298298
299- data = self .Bolt .MAGIC_PREAMBLE + self .Bolt .get_handshake ()
300- await self .sendall (data )
299+ request = self .Bolt .MAGIC_PREAMBLE + self .Bolt .get_handshake ()
301300
302301 # Handle the handshake response
303302 original_timeout = self .gettimeout ()
304- if original_timeout is not None :
305- self .settimeout (original_timeout + 1 )
303+ self .settimeout (deadline .to_timeout ())
306304 try :
307- data = await self .recv (4 )
305+ await self .sendall (request )
306+ response = await self .recv (4 )
308307 except OSError as exc :
309308 raise ServiceUnavailable (
310- "Failed to read any data from server {!r} "
311- "after connected" .format (resolved_address )) from exc
309+ f"Failed to read any data from server { resolved_address !r} "
310+ f"after connected (deadline { deadline } )"
311+ ) from exc
312312 finally :
313313 self .settimeout (original_timeout )
314- data_size = len (data )
314+ data_size = len (response )
315315 if data_size == 0 :
316316 # If no data is returned after a successful select
317317 # response, the server has closed the connection
318318 log .debug ("[#%04X] S: <CLOSE>" , local_port )
319319 await self .close ()
320320 raise ServiceUnavailable (
321- "Connection to {address} closed without handshake response" .format (
322- address = resolved_address ))
321+ f"Connection to { resolved_address } closed without handshake "
322+ "response"
323+ )
323324 if data_size != 4 :
324325 # Some garbled data has been received
325326 log .debug ("[#%04X] S: @*#!" , local_port )
326327 await self .close ()
327328 raise BoltProtocolError (
328- "Expected four byte Bolt handshake response from %r, received %r instead; check for incorrect port number" % (
329- resolved_address , data ), address = resolved_address )
330- elif data == b"HTTP" :
329+ "Expected four byte Bolt handshake response from "
330+ f"{ resolved_address !r} , received { response !r} instead; "
331+ "check for incorrect port number"
332+ , address = resolved_address
333+ )
334+ elif response == b"HTTP" :
331335 log .debug ("[#%04X] S: <CLOSE>" , local_port )
332336 await self .close ()
333337 raise ServiceUnavailable (
334- "Cannot to connect to Bolt service on {!r} "
335- "(looks like HTTP)" .format (resolved_address ))
336- agreed_version = data [- 1 ], data [- 2 ]
338+ f"Cannot to connect to Bolt service on { resolved_address !r} "
339+ "(looks like HTTP)"
340+ )
341+ agreed_version = response [- 1 ], response [- 2 ]
337342 log .debug ("[#%04X] S: <HANDSHAKE> 0x%06X%02X" , local_port ,
338343 agreed_version [1 ], agreed_version [0 ])
339- return self , agreed_version , handshake , data
344+ return self , agreed_version , handshake , response
340345
341346 @classmethod
342347 async def close_socket (cls , socket_ ):
@@ -356,8 +361,8 @@ async def close_socket(cls, socket_):
356361 pass
357362
358363 @classmethod
359- async def connect (cls , address , * , timeout , custom_resolver , ssl_context ,
360- keep_alive ):
364+ async def connect (cls , address , * , tcp_timeout , deadline ,
365+ custom_resolver , ssl_context , keep_alive ):
361366 """ Connect and perform a handshake and return a valid Connection object,
362367 assuming a protocol version can be agreed.
363368 """
@@ -371,12 +376,18 @@ async def connect(cls, address, *, timeout, custom_resolver, ssl_context,
371376 addressing .Address (address ), resolver = custom_resolver
372377 )
373378 async for resolved_address in resolved_addresses :
379+ deadline_timeout = deadline .to_timeout ()
380+ if (
381+ deadline_timeout is not None
382+ and deadline_timeout <= tcp_timeout
383+ ):
384+ tcp_timeout = deadline_timeout
374385 s = None
375386 try :
376387 s = await cls ._connect_secure (
377- resolved_address , timeout , keep_alive , ssl_context
388+ resolved_address , tcp_timeout , keep_alive , ssl_context
378389 )
379- return await s ._handshake (resolved_address )
390+ return await s ._handshake (resolved_address , deadline )
380391 except (BoltError , DriverError , OSError ) as error :
381392 try :
382393 local_port = s .getsockname ()[1 ]
@@ -560,11 +571,12 @@ def _secure(cls, s, host, ssl_context):
560571 return s
561572
562573 @classmethod
563- def _handshake (cls , s , resolved_address ):
574+ def _handshake (cls , s , resolved_address , deadline ):
564575 """
565576
566577 :param s: Socket
567578 :param resolved_address:
579+ :param deadline:
568580
569581 :returns: (socket, version, client_handshake, server_response_data)
570582 """
@@ -584,46 +596,52 @@ def _handshake(cls, s, resolved_address):
584596 log .debug ("[#%04X] C: <HANDSHAKE> %s %s %s %s" , local_port ,
585597 * supported_versions )
586598
587- data = cls .Bolt .MAGIC_PREAMBLE + cls .Bolt .get_handshake ()
588- s .sendall (data )
599+ request = cls .Bolt .MAGIC_PREAMBLE + cls .Bolt .get_handshake ()
589600
590601 # Handle the handshake response
591- ready_to_read = False
592- with selectors .DefaultSelector () as selector :
593- selector .register (s , selectors .EVENT_READ )
594- selector .select (1 )
602+ original_timeout = s .gettimeout ()
603+ s .settimeout (deadline .to_timeout ())
595604 try :
596- data = s .recv (4 )
605+ s .sendall (request )
606+ response = s .recv (4 )
597607 except OSError as exc :
598608 raise ServiceUnavailable (
599- "Failed to read any data from server {!r} "
600- "after connected" .format (resolved_address )) from exc
601- data_size = len (data )
609+ f"Failed to read any data from server { resolved_address !r} "
610+ f"after connected (deadline { deadline } )"
611+ ) from exc
612+ finally :
613+ s .settimeout (original_timeout )
614+ data_size = len (response )
602615 if data_size == 0 :
603616 # If no data is returned after a successful select
604617 # response, the server has closed the connection
605618 log .debug ("[#%04X] S: <CLOSE>" , local_port )
606619 cls .close_socket (s )
607620 raise ServiceUnavailable (
608- "Connection to {address} closed without handshake response" .format (
609- address = resolved_address ))
621+ f"Connection to { resolved_address } closed without handshake "
622+ "response"
623+ )
610624 if data_size != 4 :
611625 # Some garbled data has been received
612626 log .debug ("[#%04X] S: @*#!" , local_port )
613627 cls .close_socket (s )
614628 raise BoltProtocolError (
615- "Expected four byte Bolt handshake response from %r, received %r instead; check for incorrect port number" % (
616- resolved_address , data ), address = resolved_address )
617- elif data == b"HTTP" :
629+ "Expected four byte Bolt handshake response from "
630+ f"{ resolved_address !r} , received { response !r} instead; "
631+ "check for incorrect port number"
632+ , address = resolved_address
633+ )
634+ elif response == b"HTTP" :
618635 log .debug ("[#%04X] S: <CLOSE>" , local_port )
619636 cls .close_socket (s )
620637 raise ServiceUnavailable (
621- "Cannot to connect to Bolt service on {!r} "
622- "(looks like HTTP)" .format (resolved_address ))
623- agreed_version = data [- 1 ], data [- 2 ]
638+ f"Cannot to connect to Bolt service on { resolved_address !r} "
639+ "(looks like HTTP)"
640+ )
641+ agreed_version = response [- 1 ], response [- 2 ]
624642 log .debug ("[#%04X] S: <HANDSHAKE> 0x%06X%02X" , local_port ,
625643 agreed_version [1 ], agreed_version [0 ])
626- return cls (s ), agreed_version , handshake , data
644+ return cls (s ), agreed_version , handshake , response
627645
628646 @classmethod
629647 def close_socket (cls , socket_ ):
@@ -639,8 +657,8 @@ def close_socket(cls, socket_):
639657 pass
640658
641659 @classmethod
642- def connect (cls , address , * , timeout , custom_resolver , ssl_context ,
643- keep_alive ):
660+ def connect (cls , address , * , tcp_timeout , deadline , custom_resolver ,
661+ ssl_context , keep_alive ):
644662 """ Connect and perform a handshake and return a valid Connection object,
645663 assuming a protocol version can be agreed.
646664 """
@@ -653,12 +671,19 @@ def connect(cls, address, *, timeout, custom_resolver, ssl_context,
653671 addressing .Address (address ), resolver = custom_resolver
654672 )
655673 for resolved_address in resolved_addresses :
674+ deadline_timeout = deadline .to_timeout ()
675+ if (
676+ deadline_timeout is not None
677+ and deadline_timeout <= tcp_timeout
678+ ):
679+ tcp_timeout = deadline_timeout
656680 s = None
657681 try :
658- s = BoltSocket ._connect (resolved_address , timeout , keep_alive )
682+ s = BoltSocket ._connect (resolved_address , tcp_timeout ,
683+ keep_alive )
659684 s = BoltSocket ._secure (s , resolved_address ._host_name ,
660685 ssl_context )
661- return BoltSocket ._handshake (s , resolved_address )
686+ return BoltSocket ._handshake (s , resolved_address , deadline )
662687 except (BoltError , DriverError , OSError ) as error :
663688 try :
664689 local_port = s .getsockname ()[1 ]
0 commit comments