mirror of
https://github.com/python/cpython.git
synced 2025-01-04 15:44:23 +08:00
f78e02b798
svn+ssh://pythondev@svn.python.org/python/trunk ........ r63562 | martin.v.loewis | 2008-05-23 17:06:50 +0200 (Fri, 23 May 2008) | 2 lines Patch #1722225: Support QNX 6. ........ r63570 | trent.nelson | 2008-05-23 22:33:14 +0200 (Fri, 23 May 2008) | 1 line Introduce a user macro named $(externalsDir), which should point to the root directory of where all the external sources should live. Developers can change this value if their external sources live elsewhere. The default of '..\..' matches the current status quo. ........ r63728 | gregory.p.smith | 2008-05-26 23:16:34 +0200 (Mon, 26 May 2008) | 4 lines Fix issue2589: there was a potential integer overflow leading to memory corruption on esoteric platforms and incorrect behavior on normal platforms. ........ r63734 | gregory.p.smith | 2008-05-27 00:07:28 +0200 (Tue, 27 May 2008) | 3 lines Fix issue2588: Do not execute str[size-1] = '\0' when a 0 size is passed in. (The assert won't prevent this in non-debug builds). ........ r63784 | raymond.hettinger | 2008-05-29 10:38:23 +0200 (Thu, 29 May 2008) | 1 line Fix two typos. ........ r63788 | facundo.batista | 2008-05-29 18:39:26 +0200 (Thu, 29 May 2008) | 6 lines Fixed the semantic of timeout for socket.create_connection and all the upper level libraries that use it, including urllib2. Added and fixed some tests, and changed docs correspondingly. Thanks to John J Lee for the patch and the pusing, :) ........ r63802 | mark.dickinson | 2008-05-30 04:46:53 +0200 (Fri, 30 May 2008) | 2 lines Fix typo in testSum ........ r63817 | raymond.hettinger | 2008-05-30 20:20:50 +0200 (Fri, 30 May 2008) | 8 lines * Mark intermedidate computes values (hi, lo, yr) as volatile. * Expand comments. * Swap variable names in the sum_exact code so that x and y are consistently chosen as the larger and smaller magnitude values respectively. ........ r63827 | raymond.hettinger | 2008-05-31 05:24:31 +0200 (Sat, 31 May 2008) | 1 line Implement heapq in terms of less-than (to match list.sort()). ........ r63839 | gerhard.haering | 2008-05-31 23:33:27 +0200 (Sat, 31 May 2008) | 2 lines Fixed rowcount for SELECT statements. They're -1 now (again), for better DB-API 2.0 compliance. ........ r63887 | gregory.p.smith | 2008-06-02 06:05:52 +0200 (Mon, 02 Jun 2008) | 4 lines Fix issue 2782: be less strict about the format string type in strftime. Accept unicode and anything else ParseTuple "s#" can deal with. This matches the time.strftime behavior. ........ r63975 | neal.norwitz | 2008-06-06 06:47:01 +0200 (Fri, 06 Jun 2008) | 3 lines Aldo Cortesi confirmed this is still needed for OpenBSD 4.2 and 4.3. (I didn't regen configure, since I don't have a working autoconf.) ........ r63998 | raymond.hettinger | 2008-06-06 23:47:51 +0200 (Fri, 06 Jun 2008) | 1 line Issue 3501: Make heapq support both __le__ and __lt__. ........
299 lines
9.4 KiB
Python
299 lines
9.4 KiB
Python
# 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 [*]
|
|
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() -- mape 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
|
|
|
|
[*] 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.
|
|
"""
|
|
|
|
import _socket
|
|
from _socket import *
|
|
|
|
import os, sys, io
|
|
|
|
try:
|
|
from errno import EBADF
|
|
except ImportError:
|
|
EBADF = 9
|
|
|
|
__all__ = ["getfqdn"]
|
|
__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):
|
|
_socket.socket.__init__(self, family, type, proto, fileno)
|
|
self._io_refs = 0
|
|
self._closed = False
|
|
|
|
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__,
|
|
(self._closed and " [closed] ") or "",
|
|
s[7:])
|
|
return s
|
|
|
|
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()
|
|
return socket(self.family, self.type, self.proto, fileno=fd), addr
|
|
|
|
def makefile(self, mode="r", buffering=None, *,
|
|
encoding=None, newline=None):
|
|
"""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?)
|
|
"""
|
|
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")
|
|
raw.name = self.fileno()
|
|
raw.mode = mode
|
|
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:
|
|
buffer.name = self.fileno()
|
|
buffer.mode = mode
|
|
return buffer
|
|
text = io.TextIOWrapper(buffer, encoding, newline)
|
|
text.name = self.fileno()
|
|
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):
|
|
_socket.socket.close(self)
|
|
|
|
def close(self):
|
|
self._closed = True
|
|
if self._io_refs <= 0:
|
|
self._real_close()
|
|
|
|
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)
|
|
|
|
|
|
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.
|
|
"""
|
|
|
|
# XXX More docs
|
|
|
|
def __init__(self, sock, mode):
|
|
if mode not in ("r", "w", "rw"):
|
|
raise ValueError("invalid mode: %r" % mode)
|
|
io.RawIOBase.__init__(self)
|
|
self._sock = sock
|
|
self._mode = mode
|
|
self._reading = "r" in mode
|
|
self._writing = "w" in mode
|
|
|
|
def readinto(self, b):
|
|
self._checkClosed()
|
|
self._checkReadable()
|
|
return self._sock.recv_into(b)
|
|
|
|
def write(self, b):
|
|
self._checkClosed()
|
|
self._checkWritable()
|
|
return self._sock.send(b)
|
|
|
|
def readable(self):
|
|
return self._reading and not self.closed
|
|
|
|
def writable(self):
|
|
return self._writing and not self.closed
|
|
|
|
def fileno(self):
|
|
return self._sock.fileno()
|
|
|
|
def close(self):
|
|
if self.closed:
|
|
return
|
|
io.RawIOBase.close(self)
|
|
|
|
def __del__(self):
|
|
self._sock._decref_socketios()
|
|
|
|
|
|
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
|
|
|
|
|
|
_GLOBAL_DEFAULT_TIMEOUT = object()
|
|
|
|
def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT):
|
|
"""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.
|
|
"""
|
|
|
|
msg = "getaddrinfo returns an empty list"
|
|
host, port = address
|
|
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)
|
|
sock.connect(sa)
|
|
return sock
|
|
|
|
except error as err:
|
|
msg = err
|
|
if sock is not None:
|
|
sock.close()
|
|
|
|
raise error(msg)
|