github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/third_party/stdlib/socket.py (about)

     1  # Wrapper module for _socket, providing some additional facilities
     2  # implemented in Python.
     3  
     4  """\
     5  This module provides socket operations and some related functions.
     6  On Unix, it supports IP (Internet Protocol) and Unix domain sockets.
     7  On other systems, it only supports IP. Functions specific for a
     8  socket are available as methods of the socket object.
     9  
    10  Functions:
    11  
    12  socket() -- create a new socket object
    13  socketpair() -- create a pair of new socket objects [*]
    14  fromfd() -- create a socket object from an open file descriptor [*]
    15  gethostname() -- return the current hostname
    16  gethostbyname() -- map a hostname to its IP number
    17  gethostbyaddr() -- map an IP number or hostname to DNS info
    18  getservbyname() -- map a service name and a protocol name to a port number
    19  getprotobyname() -- map a protocol name (e.g. 'tcp') to a number
    20  ntohs(), ntohl() -- convert 16, 32 bit int from network to host byte order
    21  htons(), htonl() -- convert 16, 32 bit int from host to network byte order
    22  inet_aton() -- convert IP addr string (123.45.67.89) to 32-bit packed format
    23  inet_ntoa() -- convert 32-bit packed format IP to string (123.45.67.89)
    24  ssl() -- secure socket layer support (only available if configured)
    25  socket.getdefaulttimeout() -- get the default timeout value
    26  socket.setdefaulttimeout() -- set the default timeout value
    27  create_connection() -- connects to an address, with an optional timeout and
    28                         optional source address.
    29  
    30   [*] not available on all platforms!
    31  
    32  Special objects:
    33  
    34  SocketType -- type object for socket objects
    35  error -- exception raised for I/O errors
    36  has_ipv6 -- boolean value indicating if IPv6 is supported
    37  
    38  Integer constants:
    39  
    40  AF_INET, AF_UNIX -- socket domains (first argument to socket() call)
    41  SOCK_STREAM, SOCK_DGRAM, SOCK_RAW -- socket types (second argument)
    42  
    43  Many other constants may be defined; these may be used in calls to
    44  the setsockopt() and getsockopt() methods.
    45  """
    46  
    47  import _socket
    48  #from _socket import *
    49  for _k, _v in _socket.__dict__.iteritems():
    50    if not _k.startswith('_'):
    51      globals()[_k] = _v
    52  from functools import partial
    53  from types import MethodType
    54  
    55  #try:
    56  #    import _ssl
    57  #except ImportError:
    58  #    # no SSL support
    59  #    pass
    60  #else:
    61  #    def ssl(sock, keyfile=None, certfile=None):
    62  #        # we do an internal import here because the ssl
    63  #        # module imports the socket module
    64  #        import ssl as _realssl
    65  #        warnings.warn("socket.ssl() is deprecated.  Use ssl.wrap_socket() instead.",
    66  #                      DeprecationWarning, stacklevel=2)
    67  #        return _realssl.sslwrap_simple(sock, keyfile, certfile)
    68  #
    69  #    # we need to import the same constants we used to...
    70  #    from _ssl import SSLError as sslerror
    71  #    from _ssl import \
    72  #         RAND_add, \
    73  #         RAND_status, \
    74  #         SSL_ERROR_ZERO_RETURN, \
    75  #         SSL_ERROR_WANT_READ, \
    76  #         SSL_ERROR_WANT_WRITE, \
    77  #         SSL_ERROR_WANT_X509_LOOKUP, \
    78  #         SSL_ERROR_SYSCALL, \
    79  #         SSL_ERROR_SSL, \
    80  #         SSL_ERROR_WANT_CONNECT, \
    81  #         SSL_ERROR_EOF, \
    82  #         SSL_ERROR_INVALID_ERROR_CODE
    83  #    try:
    84  #        from _ssl import RAND_egd
    85  #    except ImportError:
    86  #        # LibreSSL does not provide RAND_egd
    87  #        pass
    88  
    89  import os, sys, warnings
    90  
    91  try:
    92      from cStringIO import StringIO
    93  except ImportError:
    94      from StringIO import StringIO
    95  
    96  try:
    97      import errno
    98  except ImportError:
    99      errno = None
   100  EBADF = getattr(errno, 'EBADF', 9)
   101  EINTR = getattr(errno, 'EINTR', 4)
   102  
   103  __all__ = ["getfqdn", "create_connection"]
   104  __all__.extend(dir(_socket))
   105  #__all__.extend(os._get_exports_list(_socket))
   106  
   107  
   108  _realsocket = socket
   109  
   110  # WSA error codes
   111  #if sys.platform.lower().startswith("win"):
   112  #    errorTab = {}
   113  #    errorTab[10004] = "The operation was interrupted."
   114  #    errorTab[10009] = "A bad file handle was passed."
   115  #    errorTab[10013] = "Permission denied."
   116  #    errorTab[10014] = "A fault occurred on the network??" # WSAEFAULT
   117  #    errorTab[10022] = "An invalid operation was attempted."
   118  #    errorTab[10035] = "The socket operation would block"
   119  #    errorTab[10036] = "A blocking operation is already in progress."
   120  #    errorTab[10048] = "The network address is in use."
   121  #    errorTab[10054] = "The connection has been reset."
   122  #    errorTab[10058] = "The network has been shut down."
   123  #    errorTab[10060] = "The operation timed out."
   124  #    errorTab[10061] = "Connection refused."
   125  #    errorTab[10063] = "The name is too long."
   126  #    errorTab[10064] = "The host is down."
   127  #    errorTab[10065] = "The host is unreachable."
   128  #    __all__.append("errorTab")
   129  
   130  
   131  
   132  def getfqdn(name=''):
   133      """Get fully qualified domain name from name.
   134  
   135      An empty argument is interpreted as meaning the local host.
   136  
   137      First the hostname returned by gethostbyaddr() is checked, then
   138      possibly existing aliases. In case no FQDN is available, hostname
   139      from gethostname() is returned.
   140      """
   141      name = name.strip()
   142      if not name or name == '0.0.0.0':
   143          name = gethostname()
   144      try:
   145          hostname, aliases, ipaddrs = gethostbyaddr(name)
   146      except error:
   147          pass
   148      else:
   149          aliases.insert(0, hostname)
   150          for name in aliases:
   151              if '.' in name:
   152                  break
   153          else:
   154              name = hostname
   155      return name
   156  
   157  
   158  _socketmethods = (
   159      'bind', 'connect', 'connect_ex', 'fileno', 'listen',
   160      'getpeername', 'getsockname', 'getsockopt', 'setsockopt',
   161      'sendall', 'setblocking',
   162      'settimeout', 'gettimeout', 'shutdown')
   163  
   164  #if os.name == "nt":
   165  #    _socketmethods = _socketmethods + ('ioctl',)
   166  #
   167  #if sys.platform == "riscos":
   168  #    _socketmethods = _socketmethods + ('sleeptaskw',)
   169  
   170  # All the method names that must be delegated to either the real socket
   171  # object or the _closedsocket object.
   172  _delegate_methods = ("recv", "recvfrom", "recv_into", "recvfrom_into",
   173                       "send", "sendto")
   174  
   175  class _closedsocket(object):
   176      __slots__ = []
   177      def _dummy(*args):
   178          raise error(EBADF, 'Bad file descriptor')
   179      # All _delegate_methods must also be initialized here.
   180      send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy
   181      __getattr__ = _dummy
   182  
   183  # Wrapper around platform socket objects. This implements
   184  # a platform-independent dup() functionality. The
   185  # implementation currently relies on reference counting
   186  # to close the underlying socket object.
   187  class _socketobject(object):
   188  
   189      #__doc__ = _realsocket.__doc__
   190  
   191      __slots__ = ["_sock", "__weakref__"] + list(_delegate_methods)
   192  
   193      def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
   194          if _sock is None:
   195              _sock = _realsocket(family, type, proto)
   196          self._sock = _sock
   197          for method in _delegate_methods:
   198              setattr(self, method, getattr(_sock, method))
   199  
   200      def close(self, _closedsocket=_closedsocket,
   201                _delegate_methods=_delegate_methods, setattr=setattr):
   202          # This function should not reference any globals. See issue #808164.
   203          self._sock = _closedsocket()
   204          dummy = self._sock._dummy
   205          for method in _delegate_methods:
   206              setattr(self, method, dummy)
   207      #close.__doc__ = _realsocket.close.__doc__
   208  
   209      def accept(self):
   210          sock, addr = self._sock.accept()
   211          return _socketobject(_sock=sock), addr
   212      #accept.__doc__ = _realsocket.accept.__doc__
   213  
   214      def dup(self):
   215          """dup() -> socket object
   216  
   217          Return a new socket object connected to the same system resource."""
   218          return _socketobject(_sock=self._sock)
   219  
   220      def makefile(self, mode='r', bufsize=-1):
   221          """makefile([mode[, bufsize]]) -> file object
   222  
   223          Return a regular file object corresponding to the socket.  The mode
   224          and bufsize arguments are as for the built-in open() function."""
   225          return _fileobject(self._sock, mode, bufsize)
   226  
   227      family = property(lambda self: self._sock.family, doc="the socket family")
   228      type = property(lambda self: self._sock.type, doc="the socket type")
   229      proto = property(lambda self: self._sock.proto, doc="the socket protocol")
   230  
   231  def meth(name,self,*args):
   232      return getattr(self._sock,name)(*args)
   233  
   234  for _m in _socketmethods:
   235      p = partial(meth,_m)
   236      p.__name__ = _m
   237      #p.__doc__ = getattr(_realsocket,_m).__doc__
   238      m = MethodType(p,None,_socketobject)
   239      setattr(_socketobject,_m,m)
   240  
   241  socket = SocketType = _socketobject
   242  
   243  class _fileobject(object):
   244      """Faux file object attached to a socket object."""
   245  
   246      default_bufsize = 8192
   247      name = "<socket>"
   248  
   249      __slots__ = ["mode", "bufsize", "softspace",
   250                   # "closed" is a property, see below
   251                   "_sock", "_rbufsize", "_wbufsize", "_rbuf", "_wbuf", "_wbuf_len",
   252                   "_close"]
   253  
   254      def __init__(self, sock, mode='rb', bufsize=-1, close=False):
   255          self._sock = sock
   256          self.mode = mode # Not actually used in this version
   257          if bufsize < 0:
   258              bufsize = self.default_bufsize
   259          self.bufsize = bufsize
   260          self.softspace = False
   261          # _rbufsize is the suggested recv buffer size.  It is *strictly*
   262          # obeyed within readline() for recv calls.  If it is larger than
   263          # default_bufsize it will be used for recv calls within read().
   264          if bufsize == 0:
   265              self._rbufsize = 1
   266          elif bufsize == 1:
   267              self._rbufsize = self.default_bufsize
   268          else:
   269              self._rbufsize = bufsize
   270          self._wbufsize = bufsize
   271          # We use StringIO for the read buffer to avoid holding a list
   272          # of variously sized string objects which have been known to
   273          # fragment the heap due to how they are malloc()ed and often
   274          # realloc()ed down much smaller than their original allocation.
   275          self._rbuf = StringIO()
   276          self._wbuf = [] # A list of strings
   277          self._wbuf_len = 0
   278          self._close = close
   279  
   280      def _getclosed(self):
   281          return self._sock is None
   282      closed = property(_getclosed, doc="True if the file is closed")
   283  
   284      def close(self):
   285          try:
   286              if self._sock:
   287                  self.flush()
   288          finally:
   289              if self._close:
   290                  self._sock.close()
   291              self._sock = None
   292  
   293      def __del__(self):
   294          try:
   295              self.close()
   296          except:
   297              # close() may fail if __init__ didn't complete
   298              pass
   299  
   300      def flush(self):
   301          if self._wbuf:
   302              data = "".join(self._wbuf)
   303              self._wbuf = []
   304              self._wbuf_len = 0
   305              buffer_size = max(self._rbufsize, self.default_bufsize)
   306              data_size = len(data)
   307              write_offset = 0
   308              view = data #memoryview(data)
   309              try:
   310                  while write_offset < data_size:
   311                      self._sock.sendall(view[write_offset:write_offset+buffer_size])
   312                      write_offset += buffer_size
   313              finally:
   314                  if write_offset < data_size:
   315                      remainder = data[write_offset:]
   316                      del view, data  # explicit free
   317                      self._wbuf.append(remainder)
   318                      self._wbuf_len = len(remainder)
   319  
   320      def fileno(self):
   321          return self._sock.fileno()
   322  
   323      def write(self, data):
   324          data = str(data) # XXX Should really reject non-string non-buffers
   325          if not data:
   326              return
   327          self._wbuf.append(data)
   328          self._wbuf_len += len(data)
   329          if (self._wbufsize == 0 or
   330              (self._wbufsize == 1 and '\n' in data) or
   331              (self._wbufsize > 1 and self._wbuf_len >= self._wbufsize)):
   332              self.flush()
   333  
   334      def writelines(self, list):
   335          # XXX We could do better here for very long lists
   336          # XXX Should really reject non-string non-buffers
   337          lines = filter(None, map(str, list))
   338          self._wbuf_len += sum(map(len, lines))
   339          self._wbuf.extend(lines)
   340          if (self._wbufsize <= 1 or
   341              self._wbuf_len >= self._wbufsize):
   342              self.flush()
   343  
   344      def read(self, size=-1):
   345          # Use max, disallow tiny reads in a loop as they are very inefficient.
   346          # We never leave read() with any leftover data from a new recv() call
   347          # in our internal buffer.
   348          rbufsize = max(self._rbufsize, self.default_bufsize)
   349          # Our use of StringIO rather than lists of string objects returned by
   350          # recv() minimizes memory usage and fragmentation that occurs when
   351          # rbufsize is large compared to the typical return value of recv().
   352          buf = self._rbuf
   353          buf.seek(0, 2)  # seek end
   354          if size < 0:
   355              # Read until EOF
   356              self._rbuf = StringIO()  # reset _rbuf.  we consume it via buf.
   357              while True:
   358                  try:
   359                      data = self._sock.recv(rbufsize)
   360                  except error, e:
   361                      if e.args[0] == EINTR:
   362                          continue
   363                      raise
   364                  if not data:
   365                      break
   366                  buf.write(data)
   367              return buf.getvalue()
   368          else:
   369              # Read until size bytes or EOF seen, whichever comes first
   370              buf_len = buf.tell()
   371              if buf_len >= size:
   372                  # Already have size bytes in our buffer?  Extract and return.
   373                  buf.seek(0)
   374                  rv = buf.read(size)
   375                  self._rbuf = StringIO()
   376                  self._rbuf.write(buf.read())
   377                  return rv
   378  
   379              self._rbuf = StringIO()  # reset _rbuf.  we consume it via buf.
   380              while True:
   381                  left = size - buf_len
   382                  # recv() will malloc the amount of memory given as its
   383                  # parameter even though it often returns much less data
   384                  # than that.  The returned data string is short lived
   385                  # as we copy it into a StringIO and free it.  This avoids
   386                  # fragmentation issues on many platforms.
   387                  try:
   388                      data = self._sock.recv(left)
   389                  except error, e:
   390                      if e.args[0] == EINTR:
   391                          continue
   392                      raise
   393                  if not data:
   394                      break
   395                  n = len(data)
   396                  if n == size and not buf_len:
   397                      # Shortcut.  Avoid buffer data copies when:
   398                      # - We have no data in our buffer.
   399                      # AND
   400                      # - Our call to recv returned exactly the
   401                      #   number of bytes we were asked to read.
   402                      return data
   403                  if n == left:
   404                      buf.write(data)
   405                      del data  # explicit free
   406                      break
   407                  assert n <= left, "recv(%d) returned %d bytes" % (left, n)
   408                  buf.write(data)
   409                  buf_len += n
   410                  del data  # explicit free
   411                  #assert buf_len == buf.tell()
   412              return buf.getvalue()
   413  
   414      def readline(self, size=-1):
   415          buf = self._rbuf
   416          buf.seek(0, 2)  # seek end
   417          if buf.tell() > 0:
   418              # check if we already have it in our buffer
   419              buf.seek(0)
   420              bline = buf.readline(size)
   421              if bline.endswith('\n') or len(bline) == size:
   422                  self._rbuf = StringIO()
   423                  self._rbuf.write(buf.read())
   424                  return bline
   425              del bline
   426          if size < 0:
   427              # Read until \n or EOF, whichever comes first
   428              if self._rbufsize <= 1:
   429                  # Speed up unbuffered case
   430                  buf.seek(0)
   431                  buffers = [buf.read()]
   432                  self._rbuf = StringIO()  # reset _rbuf.  we consume it via buf.
   433                  data = None
   434                  recv = self._sock.recv
   435                  while True:
   436                      try:
   437                          while data != "\n":
   438                              data = recv(1)
   439                              if not data:
   440                                  break
   441                              buffers.append(data)
   442                      except error, e:
   443                          # The try..except to catch EINTR was moved outside the
   444                          # recv loop to avoid the per byte overhead.
   445                          if e.args[0] == EINTR:
   446                              continue
   447                          raise
   448                      break
   449                  return "".join(buffers)
   450  
   451              buf.seek(0, 2)  # seek end
   452              self._rbuf = StringIO()  # reset _rbuf.  we consume it via buf.
   453              while True:
   454                  try:
   455                      data = self._sock.recv(self._rbufsize)
   456                  except error, e:
   457                      if e.args[0] == EINTR:
   458                          continue
   459                      raise
   460                  if not data:
   461                      break
   462                  nl = data.find('\n')
   463                  if nl >= 0:
   464                      nl += 1
   465                      buf.write(data[:nl])
   466                      self._rbuf.write(data[nl:])
   467                      del data
   468                      break
   469                  buf.write(data)
   470              return buf.getvalue()
   471          else:
   472              # Read until size bytes or \n or EOF seen, whichever comes first
   473              buf.seek(0, 2)  # seek end
   474              buf_len = buf.tell()
   475              if buf_len >= size:
   476                  buf.seek(0)
   477                  rv = buf.read(size)
   478                  self._rbuf = StringIO()
   479                  self._rbuf.write(buf.read())
   480                  return rv
   481              self._rbuf = StringIO()  # reset _rbuf.  we consume it via buf.
   482              while True:
   483                  try:
   484                      data = self._sock.recv(self._rbufsize)
   485                  except error, e:
   486                      if e.args[0] == EINTR:
   487                          continue
   488                      raise
   489                  if not data:
   490                      break
   491                  left = size - buf_len
   492                  # did we just receive a newline?
   493                  nl = data.find('\n', 0, left)
   494                  if nl >= 0:
   495                      nl += 1
   496                      # save the excess data to _rbuf
   497                      self._rbuf.write(data[nl:])
   498                      if buf_len:
   499                          buf.write(data[:nl])
   500                          break
   501                      else:
   502                          # Shortcut.  Avoid data copy through buf when returning
   503                          # a substring of our first recv().
   504                          return data[:nl]
   505                  n = len(data)
   506                  if n == size and not buf_len:
   507                      # Shortcut.  Avoid data copy through buf when
   508                      # returning exactly all of our first recv().
   509                      return data
   510                  if n >= left:
   511                      buf.write(data[:left])
   512                      self._rbuf.write(data[left:])
   513                      break
   514                  buf.write(data)
   515                  buf_len += n
   516                  #assert buf_len == buf.tell()
   517              return buf.getvalue()
   518  
   519      def readlines(self, sizehint=0):
   520          total = 0
   521          list = []
   522          while True:
   523              line = self.readline()
   524              if not line:
   525                  break
   526              list.append(line)
   527              total += len(line)
   528              if sizehint and total >= sizehint:
   529                  break
   530          return list
   531  
   532      # Iterator protocols
   533  
   534      def __iter__(self):
   535          return self
   536  
   537      def next(self):
   538          line = self.readline()
   539          if not line:
   540              raise StopIteration
   541          return line
   542  
   543  _GLOBAL_DEFAULT_TIMEOUT = object()
   544  
   545  def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
   546                        source_address=None):
   547      """Connect to *address* and return the socket object.
   548  
   549      Convenience function.  Connect to *address* (a 2-tuple ``(host,
   550      port)``) and return the socket object.  Passing the optional
   551      *timeout* parameter will set the timeout on the socket instance
   552      before attempting to connect.  If no *timeout* is supplied, the
   553      global default timeout setting returned by :func:`getdefaulttimeout`
   554      is used.  If *source_address* is set it must be a tuple of (host, port)
   555      for the socket to bind as a source address before making the connection.
   556      A host of '' or port 0 tells the OS to use the default.
   557      """
   558  
   559      host, port = address
   560      err = None
   561      for res in getaddrinfo(host, port, 0, SOCK_STREAM):
   562          af, socktype, proto, canonname, sa = res
   563          sock = None
   564          try:
   565              sock = socket(af, socktype, proto)
   566              if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
   567                  sock.settimeout(timeout)
   568              if source_address:
   569                  sock.bind(source_address)
   570              sock.connect(sa)
   571              return sock
   572  
   573          except error as _:
   574              err = _
   575              if sock is not None:
   576                  sock.close()
   577  
   578      if err is not None:
   579          raise err
   580      else:
   581          raise error("getaddrinfo returns an empty list")