5757
5858
5959def _init_timeout (timeout = CONNECTION_TIMEOUT ):
60- return time .time () + timeout
60+ return time .monotonic () + timeout
6161
6262def _check_timeout (t ):
63- return time .time () > t
63+ return time .monotonic () > t
6464
6565#
6666#
@@ -73,6 +73,11 @@ def arbitrary_address(family):
7373 if family == 'AF_INET' :
7474 return ('localhost' , 0 )
7575 elif family == 'AF_UNIX' :
76+ # Prefer abstract sockets if possible to avoid problems with the address
77+ # size. When coding portable applications, some implementations have
78+ # sun_path as short as 92 bytes in the sockaddr_un struct.
79+ if util .abstract_sockets_supported :
80+ return f"\0 listener-{ os .getpid ()} -{ next (_mmap_counter )} "
7681 return tempfile .mktemp (prefix = 'listener-' , dir = util .get_temp_dir ())
7782 elif family == 'AF_PIPE' :
7883 return tempfile .mktemp (prefix = r'\\.\pipe\pyc-%d-%d-' %
@@ -102,7 +107,7 @@ def address_type(address):
102107 return 'AF_INET'
103108 elif type (address ) is str and address .startswith ('\\ \\ ' ):
104109 return 'AF_PIPE'
105- elif type (address ) is str :
110+ elif type (address ) is str or util . is_abstract_socket_namespace ( address ) :
106111 return 'AF_UNIX'
107112 else :
108113 raise ValueError ('address type of %r unrecognized' % address )
@@ -389,23 +394,33 @@ def _recv(self, size, read=_read):
389394
390395 def _send_bytes (self , buf ):
391396 n = len (buf )
392- # For wire compatibility with 3.2 and lower
393- header = struct .pack ("!i" , n )
394- if n > 16384 :
395- # The payload is large so Nagle's algorithm won't be triggered
396- # and we'd better avoid the cost of concatenation.
397+ if n > 0x7fffffff :
398+ pre_header = struct .pack ("!i" , - 1 )
399+ header = struct .pack ("!Q" , n )
400+ self ._send (pre_header )
397401 self ._send (header )
398402 self ._send (buf )
399403 else :
400- # Issue #20540: concatenate before sending, to avoid delays due
401- # to Nagle's algorithm on a TCP socket.
402- # Also note we want to avoid sending a 0-length buffer separately,
403- # to avoid "broken pipe" errors if the other end closed the pipe.
404- self ._send (header + buf )
404+ # For wire compatibility with 3.7 and lower
405+ header = struct .pack ("!i" , n )
406+ if n > 16384 :
407+ # The payload is large so Nagle's algorithm won't be triggered
408+ # and we'd better avoid the cost of concatenation.
409+ self ._send (header )
410+ self ._send (buf )
411+ else :
412+ # Issue #20540: concatenate before sending, to avoid delays due
413+ # to Nagle's algorithm on a TCP socket.
414+ # Also note we want to avoid sending a 0-length buffer separately,
415+ # to avoid "broken pipe" errors if the other end closed the pipe.
416+ self ._send (header + buf )
405417
406418 def _recv_bytes (self , maxsize = None ):
407419 buf = self ._recv (4 )
408420 size , = struct .unpack ("!i" , buf .getvalue ())
421+ if size == - 1 :
422+ buf = self ._recv (8 )
423+ size , = struct .unpack ("!Q" , buf .getvalue ())
409424 if maxsize is not None and size > maxsize :
410425 return None
411426 return self ._recv (size )
@@ -465,8 +480,13 @@ def close(self):
465480 self ._listener = None
466481 listener .close ()
467482
468- address = property (lambda self : self ._listener ._address )
469- last_accepted = property (lambda self : self ._listener ._last_accepted )
483+ @property
484+ def address (self ):
485+ return self ._listener ._address
486+
487+ @property
488+ def last_accepted (self ):
489+ return self ._listener ._last_accepted
470490
471491 def __enter__ (self ):
472492 return self
@@ -582,7 +602,8 @@ def __init__(self, address, family, backlog=1):
582602 self ._family = family
583603 self ._last_accepted = None
584604
585- if family == 'AF_UNIX' :
605+ if family == 'AF_UNIX' and not util .is_abstract_socket_namespace (address ):
606+ # Linux abstract socket namespaces do not need to be explicitly unlinked
586607 self ._unlink = util .Finalize (
587608 self , os .unlink , args = (address ,), exitpriority = 0
588609 )
@@ -715,7 +736,9 @@ def PipeClient(address):
715736
716737def deliver_challenge (connection , authkey ):
717738 import hmac
718- assert isinstance (authkey , bytes )
739+ if not isinstance (authkey , bytes ):
740+ raise ValueError (
741+ "Authkey must be bytes, not {0!s}" .format (type (authkey )))
719742 message = os .urandom (MESSAGE_LENGTH )
720743 connection .send_bytes (CHALLENGE + message )
721744 digest = hmac .new (authkey , message , 'md5' ).digest ()
@@ -728,7 +751,9 @@ def deliver_challenge(connection, authkey):
728751
729752def answer_challenge (connection , authkey ):
730753 import hmac
731- assert isinstance (authkey , bytes )
754+ if not isinstance (authkey , bytes ):
755+ raise ValueError (
756+ "Authkey must be bytes, not {0!s}" .format (type (authkey )))
732757 message = connection .recv_bytes (256 ) # reject large message
733758 assert message [:len (CHALLENGE )] == CHALLENGE , 'message = %r' % message
734759 message = message [len (CHALLENGE ):]
@@ -780,8 +805,7 @@ def XmlClient(*args, **kwds):
780805# Wait
781806#
782807
783- # XXX RustPython TODO: implement all the functions in this block
784- if sys .platform == 'win32' and False :
808+ if sys .platform == 'win32' :
785809
786810 def _exhaustive_wait (handles , timeout ):
787811 # Return ALL handles which are currently signalled. (Only
@@ -906,15 +930,15 @@ def wait(object_list, timeout=None):
906930 selector .register (obj , selectors .EVENT_READ )
907931
908932 if timeout is not None :
909- deadline = time .time () + timeout
933+ deadline = time .monotonic () + timeout
910934
911935 while True :
912936 ready = selector .select (timeout )
913937 if ready :
914938 return [key .fileobj for (key , events ) in ready ]
915939 else :
916940 if timeout is not None :
917- timeout = deadline - time .time ()
941+ timeout = deadline - time .monotonic ()
918942 if timeout < 0 :
919943 return ready
920944
0 commit comments