123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454 |
- # Wrapper module for _socket, providing some additional facilities
- # implemented in Python.
- """\
- This module provides socket operations and some related functions.
- On Unix, it supports IP (Internet Protocol) and Unix domain sockets.
- On other systems, it only supports IP. Functions specific for a
- socket are available as methods of the socket object.
- Functions:
- socket() -- create a new socket object
- socketpair() -- create a pair of new socket objects [*]
- fromfd() -- create a socket object from an open file descriptor [*]
- fromshare() -- create a socket object from data received from socket.share() [*]
- gethostname() -- return the current hostname
- gethostbyname() -- map a hostname to its IP number
- gethostbyaddr() -- map an IP number or hostname to DNS info
- getservbyname() -- map a service name and a protocol name to a port number
- getprotobyname() -- map a protocol name (e.g. 'tcp') to a number
- ntohs(), ntohl() -- convert 16, 32 bit int from network to host byte order
- htons(), htonl() -- convert 16, 32 bit int from host to network byte order
- inet_aton() -- convert IP addr string (123.45.67.89) to 32-bit packed format
- inet_ntoa() -- convert 32-bit packed format IP to string (123.45.67.89)
- socket.getdefaulttimeout() -- get the default timeout value
- socket.setdefaulttimeout() -- set the default timeout value
- create_connection() -- connects to an address, with an optional timeout and
- optional source address.
- [*] not available on all platforms!
- Special objects:
- SocketType -- type object for socket objects
- error -- exception raised for I/O errors
- has_ipv6 -- boolean value indicating if IPv6 is supported
- Integer constants:
- AF_INET, AF_UNIX -- socket domains (first argument to socket() call)
- SOCK_STREAM, SOCK_DGRAM, SOCK_RAW -- socket types (second argument)
- Many other constants may be defined; these may be used in calls to
- the setsockopt() and getsockopt() methods.
- """
- from __future__ import unicode_literals
- from __future__ import print_function
- from __future__ import division
- from __future__ import absolute_import
- from future.builtins import super
- import _socket
- from _socket import *
- import os, sys, io
- try:
- import errno
- except ImportError:
- errno = None
- EBADF = getattr(errno, 'EBADF', 9)
- EAGAIN = getattr(errno, 'EAGAIN', 11)
- EWOULDBLOCK = getattr(errno, 'EWOULDBLOCK', 11)
- __all__ = ["getfqdn", "create_connection"]
- __all__.extend(os._get_exports_list(_socket))
- _realsocket = socket
- # WSA error codes
- if sys.platform.lower().startswith("win"):
- errorTab = {}
- errorTab[10004] = "The operation was interrupted."
- errorTab[10009] = "A bad file handle was passed."
- errorTab[10013] = "Permission denied."
- errorTab[10014] = "A fault occurred on the network??" # WSAEFAULT
- errorTab[10022] = "An invalid operation was attempted."
- errorTab[10035] = "The socket operation would block"
- errorTab[10036] = "A blocking operation is already in progress."
- errorTab[10048] = "The network address is in use."
- errorTab[10054] = "The connection has been reset."
- errorTab[10058] = "The network has been shut down."
- errorTab[10060] = "The operation timed out."
- errorTab[10061] = "Connection refused."
- errorTab[10063] = "The name is too long."
- errorTab[10064] = "The host is down."
- errorTab[10065] = "The host is unreachable."
- __all__.append("errorTab")
- class socket(_socket.socket):
- """A subclass of _socket.socket adding the makefile() method."""
- __slots__ = ["__weakref__", "_io_refs", "_closed"]
- def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None):
- if fileno is None:
- _socket.socket.__init__(self, family, type, proto)
- else:
- _socket.socket.__init__(self, family, type, proto, fileno)
- self._io_refs = 0
- self._closed = False
- def __enter__(self):
- return self
- def __exit__(self, *args):
- if not self._closed:
- self.close()
- def __repr__(self):
- """Wrap __repr__() to reveal the real class name."""
- s = _socket.socket.__repr__(self)
- if s.startswith("<socket object"):
- s = "<%s.%s%s%s" % (self.__class__.__module__,
- self.__class__.__name__,
- getattr(self, '_closed', False) and " [closed] " or "",
- s[7:])
- return s
- def __getstate__(self):
- raise TypeError("Cannot serialize socket object")
- def dup(self):
- """dup() -> socket object
- Return a new socket object connected to the same system resource.
- """
- fd = dup(self.fileno())
- sock = self.__class__(self.family, self.type, self.proto, fileno=fd)
- sock.settimeout(self.gettimeout())
- return sock
- def accept(self):
- """accept() -> (socket object, address info)
- Wait for an incoming connection. Return a new socket
- representing the connection, and the address of the client.
- For IP sockets, the address info is a pair (hostaddr, port).
- """
- fd, addr = self._accept()
- sock = socket(self.family, self.type, self.proto, fileno=fd)
- # Issue #7995: if no default timeout is set and the listening
- # socket had a (non-zero) timeout, force the new socket in blocking
- # mode to override platform-specific socket flags inheritance.
- if getdefaulttimeout() is None and self.gettimeout():
- sock.setblocking(True)
- return sock, addr
- def makefile(self, mode="r", buffering=None, **_3to2kwargs):
- """makefile(...) -> an I/O stream connected to the socket
- The arguments are as for io.open() after the filename,
- except the only mode characters supported are 'r', 'w' and 'b'.
- The semantics are similar too. (XXX refactor to share code?)
- """
- if 'newline' in _3to2kwargs: newline = _3to2kwargs['newline']; del _3to2kwargs['newline']
- else: newline = None
- if 'errors' in _3to2kwargs: errors = _3to2kwargs['errors']; del _3to2kwargs['errors']
- else: errors = None
- if 'encoding' in _3to2kwargs: encoding = _3to2kwargs['encoding']; del _3to2kwargs['encoding']
- else: encoding = None
- for c in mode:
- if c not in ("r", "w", "b"):
- raise ValueError("invalid mode %r (only r, w, b allowed)")
- writing = "w" in mode
- reading = "r" in mode or not writing
- assert reading or writing
- binary = "b" in mode
- rawmode = ""
- if reading:
- rawmode += "r"
- if writing:
- rawmode += "w"
- raw = SocketIO(self, rawmode)
- self._io_refs += 1
- if buffering is None:
- buffering = -1
- if buffering < 0:
- buffering = io.DEFAULT_BUFFER_SIZE
- if buffering == 0:
- if not binary:
- raise ValueError("unbuffered streams must be binary")
- return raw
- if reading and writing:
- buffer = io.BufferedRWPair(raw, raw, buffering)
- elif reading:
- buffer = io.BufferedReader(raw, buffering)
- else:
- assert writing
- buffer = io.BufferedWriter(raw, buffering)
- if binary:
- return buffer
- text = io.TextIOWrapper(buffer, encoding, errors, newline)
- text.mode = mode
- return text
- def _decref_socketios(self):
- if self._io_refs > 0:
- self._io_refs -= 1
- if self._closed:
- self.close()
- def _real_close(self, _ss=_socket.socket):
- # This function should not reference any globals. See issue #808164.
- _ss.close(self)
- def close(self):
- # This function should not reference any globals. See issue #808164.
- self._closed = True
- if self._io_refs <= 0:
- self._real_close()
- def detach(self):
- """detach() -> file descriptor
- Close the socket object without closing the underlying file descriptor.
- The object cannot be used after this call, but the file descriptor
- can be reused for other purposes. The file descriptor is returned.
- """
- self._closed = True
- return super().detach()
- def fromfd(fd, family, type, proto=0):
- """ fromfd(fd, family, type[, proto]) -> socket object
- Create a socket object from a duplicate of the given file
- descriptor. The remaining arguments are the same as for socket().
- """
- nfd = dup(fd)
- return socket(family, type, proto, nfd)
- if hasattr(_socket.socket, "share"):
- def fromshare(info):
- """ fromshare(info) -> socket object
- Create a socket object from a the bytes object returned by
- socket.share(pid).
- """
- return socket(0, 0, 0, info)
- if hasattr(_socket, "socketpair"):
- def socketpair(family=None, type=SOCK_STREAM, proto=0):
- """socketpair([family[, type[, proto]]]) -> (socket object, socket object)
- Create a pair of socket objects from the sockets returned by the platform
- socketpair() function.
- The arguments are the same as for socket() except the default family is
- AF_UNIX if defined on the platform; otherwise, the default is AF_INET.
- """
- if family is None:
- try:
- family = AF_UNIX
- except NameError:
- family = AF_INET
- a, b = _socket.socketpair(family, type, proto)
- a = socket(family, type, proto, a.detach())
- b = socket(family, type, proto, b.detach())
- return a, b
- _blocking_errnos = set([EAGAIN, EWOULDBLOCK])
- class SocketIO(io.RawIOBase):
- """Raw I/O implementation for stream sockets.
- This class supports the makefile() method on sockets. It provides
- the raw I/O interface on top of a socket object.
- """
- # One might wonder why not let FileIO do the job instead. There are two
- # main reasons why FileIO is not adapted:
- # - it wouldn't work under Windows (where you can't used read() and
- # write() on a socket handle)
- # - it wouldn't work with socket timeouts (FileIO would ignore the
- # timeout and consider the socket non-blocking)
- # XXX More docs
- def __init__(self, sock, mode):
- if mode not in ("r", "w", "rw", "rb", "wb", "rwb"):
- raise ValueError("invalid mode: %r" % mode)
- io.RawIOBase.__init__(self)
- self._sock = sock
- if "b" not in mode:
- mode += "b"
- self._mode = mode
- self._reading = "r" in mode
- self._writing = "w" in mode
- self._timeout_occurred = False
- def readinto(self, b):
- """Read up to len(b) bytes into the writable buffer *b* and return
- the number of bytes read. If the socket is non-blocking and no bytes
- are available, None is returned.
- If *b* is non-empty, a 0 return value indicates that the connection
- was shutdown at the other end.
- """
- self._checkClosed()
- self._checkReadable()
- if self._timeout_occurred:
- raise IOError("cannot read from timed out object")
- while True:
- try:
- return self._sock.recv_into(b)
- except timeout:
- self._timeout_occurred = True
- raise
- # except InterruptedError:
- # continue
- except error as e:
- if e.args[0] in _blocking_errnos:
- return None
- raise
- def write(self, b):
- """Write the given bytes or bytearray object *b* to the socket
- and return the number of bytes written. This can be less than
- len(b) if not all data could be written. If the socket is
- non-blocking and no bytes could be written None is returned.
- """
- self._checkClosed()
- self._checkWritable()
- try:
- return self._sock.send(b)
- except error as e:
- # XXX what about EINTR?
- if e.args[0] in _blocking_errnos:
- return None
- raise
- def readable(self):
- """True if the SocketIO is open for reading.
- """
- if self.closed:
- raise ValueError("I/O operation on closed socket.")
- return self._reading
- def writable(self):
- """True if the SocketIO is open for writing.
- """
- if self.closed:
- raise ValueError("I/O operation on closed socket.")
- return self._writing
- def seekable(self):
- """True if the SocketIO is open for seeking.
- """
- if self.closed:
- raise ValueError("I/O operation on closed socket.")
- return super().seekable()
- def fileno(self):
- """Return the file descriptor of the underlying socket.
- """
- self._checkClosed()
- return self._sock.fileno()
- @property
- def name(self):
- if not self.closed:
- return self.fileno()
- else:
- return -1
- @property
- def mode(self):
- return self._mode
- def close(self):
- """Close the SocketIO object. This doesn't close the underlying
- socket, except if all references to it have disappeared.
- """
- if self.closed:
- return
- io.RawIOBase.close(self)
- self._sock._decref_socketios()
- self._sock = None
- def getfqdn(name=''):
- """Get fully qualified domain name from name.
- An empty argument is interpreted as meaning the local host.
- First the hostname returned by gethostbyaddr() is checked, then
- possibly existing aliases. In case no FQDN is available, hostname
- from gethostname() is returned.
- """
- name = name.strip()
- if not name or name == '0.0.0.0':
- name = gethostname()
- try:
- hostname, aliases, ipaddrs = gethostbyaddr(name)
- except error:
- pass
- else:
- aliases.insert(0, hostname)
- for name in aliases:
- if '.' in name:
- break
- else:
- name = hostname
- return name
- # Re-use the same sentinel as in the Python stdlib socket module:
- from socket import _GLOBAL_DEFAULT_TIMEOUT
- # Was: _GLOBAL_DEFAULT_TIMEOUT = object()
- def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
- source_address=None):
- """Connect to *address* and return the socket object.
- Convenience function. Connect to *address* (a 2-tuple ``(host,
- port)``) and return the socket object. Passing the optional
- *timeout* parameter will set the timeout on the socket instance
- before attempting to connect. If no *timeout* is supplied, the
- global default timeout setting returned by :func:`getdefaulttimeout`
- is used. If *source_address* is set it must be a tuple of (host, port)
- for the socket to bind as a source address before making the connection.
- An host of '' or port 0 tells the OS to use the default.
- """
- host, port = address
- err = None
- for res in getaddrinfo(host, port, 0, SOCK_STREAM):
- af, socktype, proto, canonname, sa = res
- sock = None
- try:
- sock = socket(af, socktype, proto)
- if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
- sock.settimeout(timeout)
- if source_address:
- sock.bind(source_address)
- sock.connect(sa)
- return sock
- except error as _:
- err = _
- if sock is not None:
- sock.close()
- if err is not None:
- raise err
- else:
- raise error("getaddrinfo returns an empty list")
|