mirror of
https://github.com/python/cpython.git
synced 2025-08-28 12:45:07 +00:00
Sockets facelift. APIs that could return binary data (e.g. aton() and
recv()) now return bytes, not str or str8. The socket.py code is redone; it now subclasses _socket.socket and instead of having its own _fileobject for makefile(), it uses io.SocketIO. Some stuff in io.py was moved around to make this work. (I really need to rethink my policy regarding readline() and read(-1) on raw files; and readline() on buffered files ought to use peeking(). Later.)
This commit is contained in:
parent
88effc1251
commit
7d0a8264ff
5 changed files with 200 additions and 516 deletions
54
Lib/io.py
54
Lib/io.py
|
@ -295,6 +295,22 @@ class IOBase:
|
||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
### Readline ###
|
||||||
|
|
||||||
|
def readline(self, sizehint: int = -1) -> bytes:
|
||||||
|
"""For backwards compatibility, a (slow) readline()."""
|
||||||
|
if sizehint is None:
|
||||||
|
sizehint = -1
|
||||||
|
res = b""
|
||||||
|
while sizehint < 0 or len(res) < sizehint:
|
||||||
|
b = self.read(1)
|
||||||
|
if not b:
|
||||||
|
break
|
||||||
|
res += b
|
||||||
|
if b == b"\n":
|
||||||
|
break
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
class RawIOBase(IOBase):
|
class RawIOBase(IOBase):
|
||||||
|
|
||||||
|
@ -366,7 +382,6 @@ class SocketIO(RawIOBase):
|
||||||
"""Raw I/O implementation for stream sockets."""
|
"""Raw I/O implementation for stream sockets."""
|
||||||
|
|
||||||
# XXX More docs
|
# XXX More docs
|
||||||
# XXX Hook this up to socket.py
|
|
||||||
|
|
||||||
def __init__(self, sock, mode):
|
def __init__(self, sock, mode):
|
||||||
assert mode in ("r", "w", "rw")
|
assert mode in ("r", "w", "rw")
|
||||||
|
@ -377,13 +392,32 @@ class SocketIO(RawIOBase):
|
||||||
def readinto(self, b):
|
def readinto(self, b):
|
||||||
return self._sock.recv_into(b)
|
return self._sock.recv_into(b)
|
||||||
|
|
||||||
|
def read(self, n: int = None) -> bytes:
|
||||||
|
"""read(n: int) -> bytes. Read and return up to n bytes.
|
||||||
|
|
||||||
|
Returns an empty bytes array on EOF, or None if the object is
|
||||||
|
set not to block and has no data to read.
|
||||||
|
"""
|
||||||
|
if n is None:
|
||||||
|
n = -1
|
||||||
|
if n >= 0:
|
||||||
|
return RawIOBase.read(self, n)
|
||||||
|
# Support reading until the end.
|
||||||
|
# XXX Why doesn't RawIOBase support this?
|
||||||
|
data = b""
|
||||||
|
while True:
|
||||||
|
more = RawIOBase.read(self, DEFAULT_BUFFER_SIZE)
|
||||||
|
if not more:
|
||||||
|
break
|
||||||
|
data += more
|
||||||
|
return data
|
||||||
|
|
||||||
def write(self, b):
|
def write(self, b):
|
||||||
return self._sock.send(b)
|
return self._sock.send(b)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if not self.closed:
|
if not self.closed:
|
||||||
RawIOBase.close()
|
RawIOBase.close(self)
|
||||||
self._sock.close()
|
|
||||||
|
|
||||||
def readable(self):
|
def readable(self):
|
||||||
return "r" in self._mode
|
return "r" in self._mode
|
||||||
|
@ -450,20 +484,6 @@ class BufferedIOBase(IOBase):
|
||||||
b[:n] = data
|
b[:n] = data
|
||||||
return n
|
return n
|
||||||
|
|
||||||
def readline(self, sizehint: int = -1) -> bytes:
|
|
||||||
"""For backwards compatibility, a (slow) readline()."""
|
|
||||||
if sizehint is None:
|
|
||||||
sizehint = -1
|
|
||||||
res = b""
|
|
||||||
while sizehint < 0 or len(res) < sizehint:
|
|
||||||
b = self.read(1)
|
|
||||||
if not b:
|
|
||||||
break
|
|
||||||
res += b
|
|
||||||
if b == b"\n":
|
|
||||||
break
|
|
||||||
return res
|
|
||||||
|
|
||||||
def write(self, b: bytes) -> int:
|
def write(self, b: bytes) -> int:
|
||||||
"""write(b: bytes) -> int. Write the given buffer to the IO stream.
|
"""write(b: bytes) -> int. Write the given buffer to the IO stream.
|
||||||
|
|
||||||
|
|
395
Lib/socket.py
395
Lib/socket.py
|
@ -54,7 +54,7 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
import os, sys
|
import os, sys, io
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from errno import EBADF
|
from errno import EBADF
|
||||||
|
@ -66,14 +66,6 @@ __all__.extend(os._get_exports_list(_socket))
|
||||||
if _have_ssl:
|
if _have_ssl:
|
||||||
__all__.extend(os._get_exports_list(_ssl))
|
__all__.extend(os._get_exports_list(_ssl))
|
||||||
|
|
||||||
_realsocket = socket
|
|
||||||
if _have_ssl:
|
|
||||||
_realssl = ssl
|
|
||||||
def ssl(sock, keyfile=None, certfile=None):
|
|
||||||
if hasattr(sock, "_sock"):
|
|
||||||
sock = sock._sock
|
|
||||||
return _realssl(sock, keyfile, certfile)
|
|
||||||
|
|
||||||
# WSA error codes
|
# WSA error codes
|
||||||
if sys.platform.lower().startswith("win"):
|
if sys.platform.lower().startswith("win"):
|
||||||
errorTab = {}
|
errorTab = {}
|
||||||
|
@ -95,6 +87,99 @@ if sys.platform.lower().startswith("win"):
|
||||||
__all__.append("errorTab")
|
__all__.append("errorTab")
|
||||||
|
|
||||||
|
|
||||||
|
_os_has_dup = hasattr(os, "dup")
|
||||||
|
if _os_has_dup:
|
||||||
|
def fromfd(fd, family=AF_INET, type=SOCK_STREAM, proto=0):
|
||||||
|
nfd = os.dup(fd)
|
||||||
|
return socket(family, type, proto, fileno=nfd)
|
||||||
|
|
||||||
|
|
||||||
|
class socket(_socket.socket):
|
||||||
|
|
||||||
|
"""A subclass of _socket.socket adding the makefile() method."""
|
||||||
|
|
||||||
|
__slots__ = ["__weakref__"]
|
||||||
|
if not _os_has_dup:
|
||||||
|
__slots__.append("_base")
|
||||||
|
|
||||||
|
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" % (self.__class__.__module__,
|
||||||
|
self.__class__.__name__,
|
||||||
|
s[7:])
|
||||||
|
return s
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
"""Wrap accept() to give the connection the right type."""
|
||||||
|
conn, addr = _socket.socket.accept(self)
|
||||||
|
fd = conn.fileno()
|
||||||
|
nfd = fd
|
||||||
|
if _os_has_dup:
|
||||||
|
nfd = os.dup(fd)
|
||||||
|
wrapper = socket(self.family, self.type, self.proto, fileno=nfd)
|
||||||
|
if fd == nfd:
|
||||||
|
wrapper._base = conn # Keep the base alive
|
||||||
|
else:
|
||||||
|
conn.close()
|
||||||
|
return wrapper, addr
|
||||||
|
|
||||||
|
if not _os_has_dup:
|
||||||
|
def close(self):
|
||||||
|
"""Wrap close() to close the _base as well."""
|
||||||
|
_socket.socket.close(self)
|
||||||
|
base = getattr(self, "_base", None)
|
||||||
|
if base is not None:
|
||||||
|
base.close()
|
||||||
|
|
||||||
|
def makefile(self, mode="r", buffering=None, *,
|
||||||
|
encoding=None, newline=None):
|
||||||
|
"""Return 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 = io.SocketIO(self, rawmode)
|
||||||
|
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()
|
||||||
|
self.mode = mode
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
def getfqdn(name=''):
|
def getfqdn(name=''):
|
||||||
"""Get fully qualified domain name from name.
|
"""Get fully qualified domain name from name.
|
||||||
|
@ -122,298 +207,6 @@ def getfqdn(name=''):
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
_socketmethods = (
|
|
||||||
'bind', 'connect', 'connect_ex', 'fileno', 'listen',
|
|
||||||
'getpeername', 'getsockname', 'getsockopt', 'setsockopt',
|
|
||||||
'sendall', 'setblocking',
|
|
||||||
'settimeout', 'gettimeout', 'shutdown')
|
|
||||||
|
|
||||||
if sys.platform == "riscos":
|
|
||||||
_socketmethods = _socketmethods + ('sleeptaskw',)
|
|
||||||
|
|
||||||
# All the method names that must be delegated to either the real socket
|
|
||||||
# object or the _closedsocket object.
|
|
||||||
_delegate_methods = ("recv", "recvfrom", "recv_into", "recvfrom_into",
|
|
||||||
"send", "sendto")
|
|
||||||
|
|
||||||
class _closedsocket(object):
|
|
||||||
__slots__ = []
|
|
||||||
def _dummy(*args):
|
|
||||||
raise error(EBADF, 'Bad file descriptor')
|
|
||||||
# All _delegate_methods must also be initialized here.
|
|
||||||
send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy
|
|
||||||
__getattr__ = _dummy
|
|
||||||
|
|
||||||
class _socketobject(object):
|
|
||||||
|
|
||||||
__doc__ = _realsocket.__doc__
|
|
||||||
|
|
||||||
__slots__ = ["_sock", "__weakref__"] + list(_delegate_methods)
|
|
||||||
|
|
||||||
def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
|
|
||||||
if _sock is None:
|
|
||||||
_sock = _realsocket(family, type, proto)
|
|
||||||
self._sock = _sock
|
|
||||||
for method in _delegate_methods:
|
|
||||||
setattr(self, method, getattr(_sock, method))
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
self._sock = _closedsocket()
|
|
||||||
dummy = self._sock._dummy
|
|
||||||
for method in _delegate_methods:
|
|
||||||
setattr(self, method, dummy)
|
|
||||||
close.__doc__ = _realsocket.close.__doc__
|
|
||||||
|
|
||||||
def accept(self):
|
|
||||||
sock, addr = self._sock.accept()
|
|
||||||
return _socketobject(_sock=sock), addr
|
|
||||||
accept.__doc__ = _realsocket.accept.__doc__
|
|
||||||
|
|
||||||
def dup(self):
|
|
||||||
"""dup() -> socket object
|
|
||||||
|
|
||||||
Return a new socket object connected to the same system resource."""
|
|
||||||
return _socketobject(_sock=self._sock)
|
|
||||||
|
|
||||||
def makefile(self, mode='r', bufsize=-1):
|
|
||||||
"""makefile([mode[, bufsize]]) -> file object
|
|
||||||
|
|
||||||
Return a regular file object corresponding to the socket. The mode
|
|
||||||
and bufsize arguments are as for the built-in open() function."""
|
|
||||||
return _fileobject(self._sock, mode, bufsize)
|
|
||||||
|
|
||||||
family = property(lambda self: self._sock.family, doc="the socket family")
|
|
||||||
type = property(lambda self: self._sock.type, doc="the socket type")
|
|
||||||
proto = property(lambda self: self._sock.proto, doc="the socket protocol")
|
|
||||||
|
|
||||||
_s = ("def %s(self, *args): return self._sock.%s(*args)\n\n"
|
|
||||||
"%s.__doc__ = _realsocket.%s.__doc__\n")
|
|
||||||
for _m in _socketmethods:
|
|
||||||
exec(_s % (_m, _m, _m, _m))
|
|
||||||
del _m, _s
|
|
||||||
|
|
||||||
socket = SocketType = _socketobject
|
|
||||||
|
|
||||||
class _fileobject(object):
|
|
||||||
"""Faux file object attached to a socket object."""
|
|
||||||
|
|
||||||
default_bufsize = 8192
|
|
||||||
name = "<socket>"
|
|
||||||
|
|
||||||
__slots__ = ["mode", "bufsize",
|
|
||||||
# "closed" is a property, see below
|
|
||||||
"_sock", "_rbufsize", "_wbufsize", "_rbuf", "_wbuf",
|
|
||||||
"_close"]
|
|
||||||
|
|
||||||
def __init__(self, sock, mode='rb', bufsize=-1, close=False):
|
|
||||||
self._sock = sock
|
|
||||||
self.mode = mode # Not actually used in this version
|
|
||||||
if bufsize < 0:
|
|
||||||
bufsize = self.default_bufsize
|
|
||||||
self.bufsize = bufsize
|
|
||||||
if bufsize == 0:
|
|
||||||
self._rbufsize = 1
|
|
||||||
elif bufsize == 1:
|
|
||||||
self._rbufsize = self.default_bufsize
|
|
||||||
else:
|
|
||||||
self._rbufsize = bufsize
|
|
||||||
self._wbufsize = bufsize
|
|
||||||
self._rbuf = "" # A string
|
|
||||||
self._wbuf = [] # A list of strings
|
|
||||||
self._close = close
|
|
||||||
|
|
||||||
def _getclosed(self):
|
|
||||||
return self._sock is None
|
|
||||||
closed = property(_getclosed, doc="True if the file is closed")
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
try:
|
|
||||||
if self._sock:
|
|
||||||
self.flush()
|
|
||||||
finally:
|
|
||||||
if self._close:
|
|
||||||
self._sock.close()
|
|
||||||
self._sock = None
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
try:
|
|
||||||
self.close()
|
|
||||||
except:
|
|
||||||
# close() may fail if __init__ didn't complete
|
|
||||||
pass
|
|
||||||
|
|
||||||
def flush(self):
|
|
||||||
if self._wbuf:
|
|
||||||
buffer = "".join(self._wbuf)
|
|
||||||
self._wbuf = []
|
|
||||||
self._sock.sendall(buffer)
|
|
||||||
|
|
||||||
def fileno(self):
|
|
||||||
return self._sock.fileno()
|
|
||||||
|
|
||||||
def write(self, data):
|
|
||||||
data = str(data) # XXX Should really reject non-string non-buffers
|
|
||||||
if not data:
|
|
||||||
return
|
|
||||||
self._wbuf.append(data)
|
|
||||||
if (self._wbufsize == 0 or
|
|
||||||
self._wbufsize == 1 and '\n' in data or
|
|
||||||
self._get_wbuf_len() >= self._wbufsize):
|
|
||||||
self.flush()
|
|
||||||
|
|
||||||
def writelines(self, list):
|
|
||||||
# XXX We could do better here for very long lists
|
|
||||||
# XXX Should really reject non-string non-buffers
|
|
||||||
self._wbuf.extend(filter(None, map(str, list)))
|
|
||||||
if (self._wbufsize <= 1 or
|
|
||||||
self._get_wbuf_len() >= self._wbufsize):
|
|
||||||
self.flush()
|
|
||||||
|
|
||||||
def _get_wbuf_len(self):
|
|
||||||
buf_len = 0
|
|
||||||
for x in self._wbuf:
|
|
||||||
buf_len += len(x)
|
|
||||||
return buf_len
|
|
||||||
|
|
||||||
def read(self, size=-1):
|
|
||||||
data = self._rbuf
|
|
||||||
if size < 0:
|
|
||||||
# Read until EOF
|
|
||||||
buffers = []
|
|
||||||
if data:
|
|
||||||
buffers.append(data)
|
|
||||||
self._rbuf = ""
|
|
||||||
if self._rbufsize <= 1:
|
|
||||||
recv_size = self.default_bufsize
|
|
||||||
else:
|
|
||||||
recv_size = self._rbufsize
|
|
||||||
while True:
|
|
||||||
data = self._sock.recv(recv_size)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
buffers.append(data)
|
|
||||||
return "".join(buffers)
|
|
||||||
else:
|
|
||||||
# Read until size bytes or EOF seen, whichever comes first
|
|
||||||
buf_len = len(data)
|
|
||||||
if buf_len >= size:
|
|
||||||
self._rbuf = data[size:]
|
|
||||||
return data[:size]
|
|
||||||
buffers = []
|
|
||||||
if data:
|
|
||||||
buffers.append(data)
|
|
||||||
self._rbuf = ""
|
|
||||||
while True:
|
|
||||||
left = size - buf_len
|
|
||||||
recv_size = max(self._rbufsize, left)
|
|
||||||
data = self._sock.recv(recv_size)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
buffers.append(data)
|
|
||||||
n = len(data)
|
|
||||||
if n >= left:
|
|
||||||
self._rbuf = data[left:]
|
|
||||||
buffers[-1] = data[:left]
|
|
||||||
break
|
|
||||||
buf_len += n
|
|
||||||
return "".join(buffers)
|
|
||||||
|
|
||||||
def readline(self, size=-1):
|
|
||||||
data = self._rbuf
|
|
||||||
if size < 0:
|
|
||||||
# Read until \n or EOF, whichever comes first
|
|
||||||
if self._rbufsize <= 1:
|
|
||||||
# Speed up unbuffered case
|
|
||||||
assert data == ""
|
|
||||||
buffers = []
|
|
||||||
recv = self._sock.recv
|
|
||||||
while data != "\n":
|
|
||||||
data = recv(1)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
buffers.append(data)
|
|
||||||
return "".join(buffers)
|
|
||||||
nl = data.find('\n')
|
|
||||||
if nl >= 0:
|
|
||||||
nl += 1
|
|
||||||
self._rbuf = data[nl:]
|
|
||||||
return data[:nl]
|
|
||||||
buffers = []
|
|
||||||
if data:
|
|
||||||
buffers.append(data)
|
|
||||||
self._rbuf = ""
|
|
||||||
while True:
|
|
||||||
data = self._sock.recv(self._rbufsize)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
buffers.append(data)
|
|
||||||
nl = data.find('\n')
|
|
||||||
if nl >= 0:
|
|
||||||
nl += 1
|
|
||||||
self._rbuf = data[nl:]
|
|
||||||
buffers[-1] = data[:nl]
|
|
||||||
break
|
|
||||||
return "".join(buffers)
|
|
||||||
else:
|
|
||||||
# Read until size bytes or \n or EOF seen, whichever comes first
|
|
||||||
nl = data.find('\n', 0, size)
|
|
||||||
if nl >= 0:
|
|
||||||
nl += 1
|
|
||||||
self._rbuf = data[nl:]
|
|
||||||
return data[:nl]
|
|
||||||
buf_len = len(data)
|
|
||||||
if buf_len >= size:
|
|
||||||
self._rbuf = data[size:]
|
|
||||||
return data[:size]
|
|
||||||
buffers = []
|
|
||||||
if data:
|
|
||||||
buffers.append(data)
|
|
||||||
self._rbuf = ""
|
|
||||||
while True:
|
|
||||||
data = self._sock.recv(self._rbufsize)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
buffers.append(data)
|
|
||||||
left = size - buf_len
|
|
||||||
nl = data.find('\n', 0, left)
|
|
||||||
if nl >= 0:
|
|
||||||
nl += 1
|
|
||||||
self._rbuf = data[nl:]
|
|
||||||
buffers[-1] = data[:nl]
|
|
||||||
break
|
|
||||||
n = len(data)
|
|
||||||
if n >= left:
|
|
||||||
self._rbuf = data[left:]
|
|
||||||
buffers[-1] = data[:left]
|
|
||||||
break
|
|
||||||
buf_len += n
|
|
||||||
return "".join(buffers)
|
|
||||||
|
|
||||||
def readlines(self, sizehint=0):
|
|
||||||
total = 0
|
|
||||||
list = []
|
|
||||||
while True:
|
|
||||||
line = self.readline()
|
|
||||||
if not line:
|
|
||||||
break
|
|
||||||
list.append(line)
|
|
||||||
total += len(line)
|
|
||||||
if sizehint and total >= sizehint:
|
|
||||||
break
|
|
||||||
return list
|
|
||||||
|
|
||||||
# Iterator protocols
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __next__(self):
|
|
||||||
line = self.readline()
|
|
||||||
if not line:
|
|
||||||
raise StopIteration
|
|
||||||
return line
|
|
||||||
|
|
||||||
|
|
||||||
def create_connection(address, timeout=None):
|
def create_connection(address, timeout=None):
|
||||||
"""Connect to address (host, port) with an optional timeout.
|
"""Connect to address (host, port) with an optional timeout.
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import signal
|
||||||
|
|
||||||
PORT = 50007
|
PORT = 50007
|
||||||
HOST = 'localhost'
|
HOST = 'localhost'
|
||||||
MSG = 'Michael Gilfix was here\n'
|
MSG = b'Michael Gilfix was here\n'
|
||||||
|
|
||||||
class SocketTCPTest(unittest.TestCase):
|
class SocketTCPTest(unittest.TestCase):
|
||||||
|
|
||||||
|
@ -542,16 +542,16 @@ class BasicTCPTest(SocketConnectedTest):
|
||||||
|
|
||||||
def testSendAll(self):
|
def testSendAll(self):
|
||||||
# Testing sendall() with a 2048 byte string over TCP
|
# Testing sendall() with a 2048 byte string over TCP
|
||||||
msg = ''
|
msg = b''
|
||||||
while 1:
|
while 1:
|
||||||
read = self.cli_conn.recv(1024)
|
read = self.cli_conn.recv(1024)
|
||||||
if not read:
|
if not read:
|
||||||
break
|
break
|
||||||
msg += read
|
msg += read
|
||||||
self.assertEqual(msg, 'f' * 2048)
|
self.assertEqual(msg, b'f' * 2048)
|
||||||
|
|
||||||
def _testSendAll(self):
|
def _testSendAll(self):
|
||||||
big_chunk = 'f' * 2048
|
big_chunk = b'f' * 2048
|
||||||
self.serv_conn.sendall(big_chunk)
|
self.serv_conn.sendall(big_chunk)
|
||||||
|
|
||||||
def testFromFd(self):
|
def testFromFd(self):
|
||||||
|
@ -612,7 +612,7 @@ class TCPCloserTest(ThreadedTCPSocketTest):
|
||||||
sd = self.cli
|
sd = self.cli
|
||||||
read, write, err = select.select([sd], [], [], 1.0)
|
read, write, err = select.select([sd], [], [], 1.0)
|
||||||
self.assertEqual(read, [sd])
|
self.assertEqual(read, [sd])
|
||||||
self.assertEqual(sd.recv(1), '')
|
self.assertEqual(sd.recv(1), b'')
|
||||||
|
|
||||||
def _testClose(self):
|
def _testClose(self):
|
||||||
self.cli.connect((HOST, PORT))
|
self.cli.connect((HOST, PORT))
|
||||||
|
@ -754,7 +754,7 @@ class FileObjectClassTestCase(SocketConnectedTest):
|
||||||
|
|
||||||
def testUnbufferedRead(self):
|
def testUnbufferedRead(self):
|
||||||
# Performing unbuffered file read test
|
# Performing unbuffered file read test
|
||||||
buf = ''
|
buf = b''
|
||||||
while 1:
|
while 1:
|
||||||
char = self.serv_file.read(1)
|
char = self.serv_file.read(1)
|
||||||
if not char:
|
if not char:
|
||||||
|
@ -796,14 +796,14 @@ class UnbufferedFileObjectClassTestCase(FileObjectClassTestCase):
|
||||||
def testUnbufferedReadline(self):
|
def testUnbufferedReadline(self):
|
||||||
# Read a line, create a new file object, read another line with it
|
# Read a line, create a new file object, read another line with it
|
||||||
line = self.serv_file.readline() # first line
|
line = self.serv_file.readline() # first line
|
||||||
self.assertEqual(line, "A. " + MSG) # first line
|
self.assertEqual(line, b"A. " + MSG) # first line
|
||||||
self.serv_file = self.cli_conn.makefile('rb', 0)
|
self.serv_file = self.cli_conn.makefile('rb', 0)
|
||||||
line = self.serv_file.readline() # second line
|
line = self.serv_file.readline() # second line
|
||||||
self.assertEqual(line, "B. " + MSG) # second line
|
self.assertEqual(line, b"B. " + MSG) # second line
|
||||||
|
|
||||||
def _testUnbufferedReadline(self):
|
def _testUnbufferedReadline(self):
|
||||||
self.cli_file.write("A. " + MSG)
|
self.cli_file.write(b"A. " + MSG)
|
||||||
self.cli_file.write("B. " + MSG)
|
self.cli_file.write(b"B. " + MSG)
|
||||||
self.cli_file.flush()
|
self.cli_file.flush()
|
||||||
|
|
||||||
class LineBufferedFileObjectClassTestCase(FileObjectClassTestCase):
|
class LineBufferedFileObjectClassTestCase(FileObjectClassTestCase):
|
||||||
|
@ -818,6 +818,7 @@ class SmallBufferedFileObjectClassTestCase(FileObjectClassTestCase):
|
||||||
|
|
||||||
class NetworkConnectionTest(object):
|
class NetworkConnectionTest(object):
|
||||||
"""Prove network connection."""
|
"""Prove network connection."""
|
||||||
|
|
||||||
def clientSetUp(self):
|
def clientSetUp(self):
|
||||||
self.cli = socket.create_connection((HOST, PORT))
|
self.cli = socket.create_connection((HOST, PORT))
|
||||||
self.serv_conn = self.cli
|
self.serv_conn = self.cli
|
||||||
|
@ -827,6 +828,7 @@ class BasicTCPTest2(NetworkConnectionTest, BasicTCPTest):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class NetworkConnectionNoServer(unittest.TestCase):
|
class NetworkConnectionNoServer(unittest.TestCase):
|
||||||
|
|
||||||
def testWithoutServer(self):
|
def testWithoutServer(self):
|
||||||
self.failUnlessRaises(socket.error, lambda: socket.create_connection((HOST, PORT)))
|
self.failUnlessRaises(socket.error, lambda: socket.create_connection((HOST, PORT)))
|
||||||
|
|
||||||
|
@ -895,43 +897,19 @@ class NetworkConnectionBehaviourTest(SocketTCPTest, ThreadableTest):
|
||||||
def testInsideTimeout(self):
|
def testInsideTimeout(self):
|
||||||
conn, addr = self.serv.accept()
|
conn, addr = self.serv.accept()
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
conn.send("done!")
|
conn.send(b"done!")
|
||||||
testOutsideTimeout = testInsideTimeout
|
testOutsideTimeout = testInsideTimeout
|
||||||
|
|
||||||
def _testInsideTimeout(self):
|
def _testInsideTimeout(self):
|
||||||
self.cli = sock = socket.create_connection((HOST, PORT))
|
self.cli = sock = socket.create_connection((HOST, PORT))
|
||||||
data = sock.recv(5)
|
data = sock.recv(5)
|
||||||
self.assertEqual(data, "done!")
|
self.assertEqual(data, b"done!")
|
||||||
|
|
||||||
def _testOutsideTimeout(self):
|
def _testOutsideTimeout(self):
|
||||||
self.cli = sock = socket.create_connection((HOST, PORT), timeout=1)
|
self.cli = sock = socket.create_connection((HOST, PORT), timeout=1)
|
||||||
self.failUnlessRaises(socket.timeout, lambda: sock.recv(5))
|
self.failUnlessRaises(socket.timeout, lambda: sock.recv(5))
|
||||||
|
|
||||||
|
|
||||||
class Urllib2FileobjectTest(unittest.TestCase):
|
|
||||||
|
|
||||||
# urllib2.HTTPHandler has "borrowed" socket._fileobject, and requires that
|
|
||||||
# it close the socket if the close c'tor argument is true
|
|
||||||
|
|
||||||
def testClose(self):
|
|
||||||
class MockSocket:
|
|
||||||
closed = False
|
|
||||||
def flush(self): pass
|
|
||||||
def close(self): self.closed = True
|
|
||||||
|
|
||||||
# must not close unless we request it: the original use of _fileobject
|
|
||||||
# by module socket requires that the underlying socket not be closed until
|
|
||||||
# the _socketobject that created the _fileobject is closed
|
|
||||||
s = MockSocket()
|
|
||||||
f = socket._fileobject(s)
|
|
||||||
f.close()
|
|
||||||
self.assert_(not s.closed)
|
|
||||||
|
|
||||||
s = MockSocket()
|
|
||||||
f = socket._fileobject(s, close=True)
|
|
||||||
f.close()
|
|
||||||
self.assert_(s.closed)
|
|
||||||
|
|
||||||
class TCPTimeoutTest(SocketTCPTest):
|
class TCPTimeoutTest(SocketTCPTest):
|
||||||
|
|
||||||
def testTCPTimeout(self):
|
def testTCPTimeout(self):
|
||||||
|
@ -1055,7 +1033,7 @@ class BufferIOTest(SocketConnectedTest):
|
||||||
buf = b" "*1024
|
buf = b" "*1024
|
||||||
nbytes = self.cli_conn.recv_into(buf)
|
nbytes = self.cli_conn.recv_into(buf)
|
||||||
self.assertEqual(nbytes, len(MSG))
|
self.assertEqual(nbytes, len(MSG))
|
||||||
msg = str(buf[:len(MSG)])
|
msg = buf[:len(MSG)]
|
||||||
self.assertEqual(msg, MSG)
|
self.assertEqual(msg, MSG)
|
||||||
|
|
||||||
def _testRecvInto(self):
|
def _testRecvInto(self):
|
||||||
|
@ -1066,7 +1044,7 @@ class BufferIOTest(SocketConnectedTest):
|
||||||
buf = b" "*1024
|
buf = b" "*1024
|
||||||
nbytes, addr = self.cli_conn.recvfrom_into(buf)
|
nbytes, addr = self.cli_conn.recvfrom_into(buf)
|
||||||
self.assertEqual(nbytes, len(MSG))
|
self.assertEqual(nbytes, len(MSG))
|
||||||
msg = str(buf[:len(MSG)])
|
msg = buf[:len(MSG)]
|
||||||
self.assertEqual(msg, MSG)
|
self.assertEqual(msg, MSG)
|
||||||
|
|
||||||
def _testRecvFromInto(self):
|
def _testRecvFromInto(self):
|
||||||
|
@ -1085,7 +1063,6 @@ def test_main():
|
||||||
UnbufferedFileObjectClassTestCase,
|
UnbufferedFileObjectClassTestCase,
|
||||||
LineBufferedFileObjectClassTestCase,
|
LineBufferedFileObjectClassTestCase,
|
||||||
SmallBufferedFileObjectClassTestCase,
|
SmallBufferedFileObjectClassTestCase,
|
||||||
Urllib2FileobjectTest,
|
|
||||||
NetworkConnectionNoServer,
|
NetworkConnectionNoServer,
|
||||||
NetworkConnectionAttributesTest,
|
NetworkConnectionAttributesTest,
|
||||||
NetworkConnectionBehaviourTest,
|
NetworkConnectionBehaviourTest,
|
||||||
|
|
|
@ -1085,10 +1085,8 @@ class AbstractHTTPHandler(BaseHandler):
|
||||||
# to read(). This weird wrapping allows the returned object to
|
# to read(). This weird wrapping allows the returned object to
|
||||||
# have readline() and readlines() methods.
|
# have readline() and readlines() methods.
|
||||||
|
|
||||||
# XXX It might be better to extract the read buffering code
|
|
||||||
# out of socket._fileobject() and into a base class.
|
|
||||||
|
|
||||||
r.recv = r.read
|
r.recv = r.read
|
||||||
|
# XXX socket._fileobject is gone; use some class from io.py instead
|
||||||
fp = socket._fileobject(r, close=True)
|
fp = socket._fileobject(r, close=True)
|
||||||
|
|
||||||
resp = addinfourl(fp, r.msg, req.get_full_url())
|
resp = addinfourl(fp, r.msg, req.get_full_url())
|
||||||
|
|
|
@ -19,15 +19,14 @@ Module interface:
|
||||||
a subclass of socket.error
|
a subclass of socket.error
|
||||||
- socket.herror: exception raised for gethostby* errors,
|
- socket.herror: exception raised for gethostby* errors,
|
||||||
a subclass of socket.error
|
a subclass of socket.error
|
||||||
- socket.fromfd(fd, family, type[, proto]) --> new socket object (created
|
|
||||||
from an existing file descriptor)
|
|
||||||
- socket.gethostbyname(hostname) --> host IP address (string: 'dd.dd.dd.dd')
|
- socket.gethostbyname(hostname) --> host IP address (string: 'dd.dd.dd.dd')
|
||||||
- socket.gethostbyaddr(IP address) --> (hostname, [alias, ...], [IP addr, ...])
|
- socket.gethostbyaddr(IP address) --> (hostname, [alias, ...], [IP addr, ...])
|
||||||
- socket.gethostname() --> host name (string: 'spam' or 'spam.domain.com')
|
- socket.gethostname() --> host name (string: 'spam' or 'spam.domain.com')
|
||||||
- socket.getprotobyname(protocolname) --> protocol number
|
- socket.getprotobyname(protocolname) --> protocol number
|
||||||
- socket.getservbyname(servicename[, protocolname]) --> port number
|
- socket.getservbyname(servicename[, protocolname]) --> port number
|
||||||
- socket.getservbyport(portnumber[, protocolname]) --> service name
|
- socket.getservbyport(portnumber[, protocolname]) --> service name
|
||||||
- socket.socket([family[, type [, proto]]]) --> new socket object
|
- socket.socket([family[, type [, proto, fileno]]]) --> new socket object
|
||||||
|
(fileno specifies a pre-existing socket file descriptor)
|
||||||
- socket.socketpair([family[, type [, proto]]]) --> (socket, socket)
|
- socket.socketpair([family[, type [, proto]]]) --> (socket, socket)
|
||||||
- socket.ntohs(16 bit value) --> new int object
|
- socket.ntohs(16 bit value) --> new int object
|
||||||
- socket.ntohl(32 bit value) --> new int object
|
- socket.ntohl(32 bit value) --> new int object
|
||||||
|
@ -102,7 +101,6 @@ getsockname() -- return local address\n\
|
||||||
getsockopt(level, optname[, buflen]) -- get socket options\n\
|
getsockopt(level, optname[, buflen]) -- get socket options\n\
|
||||||
gettimeout() -- return timeout or None\n\
|
gettimeout() -- return timeout or None\n\
|
||||||
listen(n) -- start listening for incoming connections\n\
|
listen(n) -- start listening for incoming connections\n\
|
||||||
makefile([mode, [bufsize]]) -- return a file object for the socket [*]\n\
|
|
||||||
recv(buflen[, flags]) -- receive data\n\
|
recv(buflen[, flags]) -- receive data\n\
|
||||||
recv_into(buffer[, nbytes[, flags]]) -- receive data (into a buffer)\n\
|
recv_into(buffer[, nbytes[, flags]]) -- receive data (into a buffer)\n\
|
||||||
recvfrom(buflen[, flags]) -- receive data and sender\'s address\n\
|
recvfrom(buflen[, flags]) -- receive data and sender\'s address\n\
|
||||||
|
@ -402,6 +400,10 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
|
||||||
#define NI_MAXSERV 32
|
#define NI_MAXSERV 32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef INVALID_SOCKET /* MS defines this */
|
||||||
|
#define INVALID_SOCKET (-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* XXX There's a problem here: *static* functions are not supposed to have
|
/* XXX There's a problem here: *static* functions are not supposed to have
|
||||||
a Py prefix (or use CapitalizedWords). Later... */
|
a Py prefix (or use CapitalizedWords). Later... */
|
||||||
|
|
||||||
|
@ -1551,7 +1553,7 @@ static PyObject *
|
||||||
sock_accept(PySocketSockObject *s)
|
sock_accept(PySocketSockObject *s)
|
||||||
{
|
{
|
||||||
sock_addr_t addrbuf;
|
sock_addr_t addrbuf;
|
||||||
SOCKET_T newfd;
|
SOCKET_T newfd = INVALID_SOCKET;
|
||||||
socklen_t addrlen;
|
socklen_t addrlen;
|
||||||
PyObject *sock = NULL;
|
PyObject *sock = NULL;
|
||||||
PyObject *addr = NULL;
|
PyObject *addr = NULL;
|
||||||
|
@ -1562,12 +1564,6 @@ sock_accept(PySocketSockObject *s)
|
||||||
return NULL;
|
return NULL;
|
||||||
memset(&addrbuf, 0, addrlen);
|
memset(&addrbuf, 0, addrlen);
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
newfd = INVALID_SOCKET;
|
|
||||||
#else
|
|
||||||
newfd = -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!IS_SELECTABLE(s))
|
if (!IS_SELECTABLE(s))
|
||||||
return select_error();
|
return select_error();
|
||||||
|
|
||||||
|
@ -1582,11 +1578,7 @@ sock_accept(PySocketSockObject *s)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
if (newfd == INVALID_SOCKET)
|
if (newfd == INVALID_SOCKET)
|
||||||
#else
|
|
||||||
if (newfd < 0)
|
|
||||||
#endif
|
|
||||||
return s->errorhandler();
|
return s->errorhandler();
|
||||||
|
|
||||||
/* Create the new object with unspecified family,
|
/* Create the new object with unspecified family,
|
||||||
|
@ -1814,16 +1806,19 @@ sock_getsockopt(PySocketSockObject *s, PyObject *args)
|
||||||
"getsockopt buflen out of range");
|
"getsockopt buflen out of range");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
buf = PyString_FromStringAndSize((char *)NULL, buflen);
|
buf = PyBytes_FromStringAndSize((char *)NULL, buflen);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
res = getsockopt(s->sock_fd, level, optname,
|
res = getsockopt(s->sock_fd, level, optname,
|
||||||
(void *)PyString_AS_STRING(buf), &buflen);
|
(void *)PyBytes_AS_STRING(buf), &buflen);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
Py_DECREF(buf);
|
Py_DECREF(buf);
|
||||||
return s->errorhandler();
|
return s->errorhandler();
|
||||||
}
|
}
|
||||||
_PyString_Resize(&buf, buflen);
|
if (PyBytes_Resize(buf, buflen) < 0) {
|
||||||
|
Py_DECREF(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return buf;
|
return buf;
|
||||||
#endif /* __BEOS__ */
|
#endif /* __BEOS__ */
|
||||||
}
|
}
|
||||||
|
@ -2173,69 +2168,6 @@ least 1; it specifies the number of unaccepted connection that the system\n\
|
||||||
will allow before refusing new connections.");
|
will allow before refusing new connections.");
|
||||||
|
|
||||||
|
|
||||||
#ifndef NO_DUP
|
|
||||||
/* s.makefile(mode) method.
|
|
||||||
Create a new open file object referring to a dupped version of
|
|
||||||
the socket's file descriptor. (The dup() call is necessary so
|
|
||||||
that the open file and socket objects may be closed independent
|
|
||||||
of each other.)
|
|
||||||
The mode argument specifies 'r' or 'w' passed to fdopen(). */
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
sock_makefile(PySocketSockObject *s, PyObject *args)
|
|
||||||
{
|
|
||||||
extern int fclose(FILE *);
|
|
||||||
char *mode = "r";
|
|
||||||
int bufsize = -1;
|
|
||||||
#ifdef MS_WIN32
|
|
||||||
Py_intptr_t fd;
|
|
||||||
#else
|
|
||||||
int fd;
|
|
||||||
#endif
|
|
||||||
FILE *fp;
|
|
||||||
PyObject *f;
|
|
||||||
#ifdef __VMS
|
|
||||||
char *mode_r = "r";
|
|
||||||
char *mode_w = "w";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "|si:makefile", &mode, &bufsize))
|
|
||||||
return NULL;
|
|
||||||
#ifdef __VMS
|
|
||||||
if (strcmp(mode,"rb") == 0) {
|
|
||||||
mode = mode_r;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (strcmp(mode,"wb") == 0) {
|
|
||||||
mode = mode_w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef MS_WIN32
|
|
||||||
if (((fd = _open_osfhandle(s->sock_fd, _O_BINARY)) < 0) ||
|
|
||||||
((fd = dup(fd)) < 0) || ((fp = fdopen(fd, mode)) == NULL))
|
|
||||||
#else
|
|
||||||
if ((fd = dup(s->sock_fd)) < 0 || (fp = fdopen(fd, mode)) == NULL)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (fd >= 0)
|
|
||||||
SOCKETCLOSE(fd);
|
|
||||||
return s->errorhandler();
|
|
||||||
}
|
|
||||||
f = PyFile_FromFile(fp, "<socket>", mode, fclose);
|
|
||||||
if (f != NULL)
|
|
||||||
PyFile_SetBufSize(f, bufsize);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(makefile_doc,
|
|
||||||
"makefile([mode[, buffersize]]) -> file object\n\
|
|
||||||
\n\
|
|
||||||
Return a regular file object corresponding to the socket.\n\
|
|
||||||
The mode and buffersize arguments are as for the built-in open() function.");
|
|
||||||
|
|
||||||
#endif /* NO_DUP */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the guts of the recv() and recv_into() methods, which reads into a
|
* This is the guts of the recv() and recv_into() methods, which reads into a
|
||||||
* char buffer. If you have any inc/dec ref to do to the objects that contain
|
* char buffer. If you have any inc/dec ref to do to the objects that contain
|
||||||
|
@ -2339,12 +2271,12 @@ sock_recv(PySocketSockObject *s, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate a new string. */
|
/* Allocate a new string. */
|
||||||
buf = PyString_FromStringAndSize((char *) 0, recvlen);
|
buf = PyBytes_FromStringAndSize((char *) 0, recvlen);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Call the guts */
|
/* Call the guts */
|
||||||
outlen = sock_recv_guts(s, PyString_AS_STRING(buf), recvlen, flags);
|
outlen = sock_recv_guts(s, PyBytes_AS_STRING(buf), recvlen, flags);
|
||||||
if (outlen < 0) {
|
if (outlen < 0) {
|
||||||
/* An error occurred, release the string and return an
|
/* An error occurred, release the string and return an
|
||||||
error. */
|
error. */
|
||||||
|
@ -2354,7 +2286,7 @@ sock_recv(PySocketSockObject *s, PyObject *args)
|
||||||
if (outlen != recvlen) {
|
if (outlen != recvlen) {
|
||||||
/* We did not read as many bytes as we anticipated, resize the
|
/* We did not read as many bytes as we anticipated, resize the
|
||||||
string if possible and be succesful. */
|
string if possible and be succesful. */
|
||||||
if (_PyString_Resize(&buf, outlen) < 0)
|
if (PyBytes_Resize(buf, outlen) < 0)
|
||||||
/* Oopsy, not so succesful after all. */
|
/* Oopsy, not so succesful after all. */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2513,11 +2445,11 @@ sock_recvfrom(PySocketSockObject *s, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = PyString_FromStringAndSize((char *) 0, recvlen);
|
buf = PyBytes_FromStringAndSize((char *) 0, recvlen);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
outlen = sock_recvfrom_guts(s, PyString_AS_STRING(buf),
|
outlen = sock_recvfrom_guts(s, PyBytes_AS_STRING(buf),
|
||||||
recvlen, flags, &addr);
|
recvlen, flags, &addr);
|
||||||
if (outlen < 0) {
|
if (outlen < 0) {
|
||||||
goto finally;
|
goto finally;
|
||||||
|
@ -2526,7 +2458,7 @@ sock_recvfrom(PySocketSockObject *s, PyObject *args)
|
||||||
if (outlen != recvlen) {
|
if (outlen != recvlen) {
|
||||||
/* We did not read as many bytes as we anticipated, resize the
|
/* We did not read as many bytes as we anticipated, resize the
|
||||||
string if possible and be succesful. */
|
string if possible and be succesful. */
|
||||||
if (_PyString_Resize(&buf, outlen) < 0)
|
if (PyBytes_Resize(buf, outlen) < 0)
|
||||||
/* Oopsy, not so succesful after all. */
|
/* Oopsy, not so succesful after all. */
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
@ -2788,10 +2720,6 @@ static PyMethodDef sock_methods[] = {
|
||||||
getsockopt_doc},
|
getsockopt_doc},
|
||||||
{"listen", (PyCFunction)sock_listen, METH_O,
|
{"listen", (PyCFunction)sock_listen, METH_O,
|
||||||
listen_doc},
|
listen_doc},
|
||||||
#ifndef NO_DUP
|
|
||||||
{"makefile", (PyCFunction)sock_makefile, METH_VARARGS,
|
|
||||||
makefile_doc},
|
|
||||||
#endif
|
|
||||||
{"recv", (PyCFunction)sock_recv, METH_VARARGS,
|
{"recv", (PyCFunction)sock_recv, METH_VARARGS,
|
||||||
recv_doc},
|
recv_doc},
|
||||||
{"recv_into", (PyCFunction)sock_recv_into, METH_VARARGS | METH_KEYWORDS,
|
{"recv_into", (PyCFunction)sock_recv_into, METH_VARARGS | METH_KEYWORDS,
|
||||||
|
@ -2861,7 +2789,7 @@ sock_repr(PySocketSockObject *s)
|
||||||
#endif
|
#endif
|
||||||
PyOS_snprintf(
|
PyOS_snprintf(
|
||||||
buf, sizeof(buf),
|
buf, sizeof(buf),
|
||||||
"<socket object, fd=%ld, family=%d, type=%d, protocol=%d>",
|
"<socket object, fd=%ld, family=%d, type=%d, proto=%d>",
|
||||||
(long)s->sock_fd, s->sock_family,
|
(long)s->sock_fd, s->sock_family,
|
||||||
s->sock_type,
|
s->sock_type,
|
||||||
s->sock_proto);
|
s->sock_proto);
|
||||||
|
@ -2893,27 +2821,35 @@ static int
|
||||||
sock_initobj(PyObject *self, PyObject *args, PyObject *kwds)
|
sock_initobj(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
PySocketSockObject *s = (PySocketSockObject *)self;
|
PySocketSockObject *s = (PySocketSockObject *)self;
|
||||||
SOCKET_T fd;
|
PyObject *fdobj = NULL;
|
||||||
|
SOCKET_T fd = INVALID_SOCKET;
|
||||||
int family = AF_INET, type = SOCK_STREAM, proto = 0;
|
int family = AF_INET, type = SOCK_STREAM, proto = 0;
|
||||||
static char *keywords[] = {"family", "type", "proto", 0};
|
static char *keywords[] = {"family", "type", "proto", "fileno", 0};
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds,
|
if (!PyArg_ParseTupleAndKeywords(args, kwds,
|
||||||
"|iii:socket", keywords,
|
"|iiiO:socket", keywords,
|
||||||
&family, &type, &proto))
|
&family, &type, &proto, &fdobj))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
if (fdobj != NULL) {
|
||||||
fd = socket(family, type, proto);
|
fd = PyLong_AsLongLong(fdobj);
|
||||||
Py_END_ALLOW_THREADS
|
if (fd == (SOCKET_T)(-1) && PyErr_Occurred())
|
||||||
|
return -1;
|
||||||
|
if (fd == INVALID_SOCKET) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"can't use invalid socket value");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
fd = socket(family, type, proto);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
if (fd == INVALID_SOCKET) {
|
||||||
if (fd == INVALID_SOCKET)
|
set_error();
|
||||||
#else
|
return -1;
|
||||||
if (fd < 0)
|
}
|
||||||
#endif
|
|
||||||
{
|
|
||||||
set_error();
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
init_sockobject(s, fd, family, type, proto);
|
init_sockobject(s, fd, family, type, proto);
|
||||||
|
|
||||||
|
@ -3462,39 +3398,6 @@ AF_UNIX if defined on the platform; otherwise, the default is AF_INET.");
|
||||||
#endif /* HAVE_SOCKETPAIR */
|
#endif /* HAVE_SOCKETPAIR */
|
||||||
|
|
||||||
|
|
||||||
#ifndef NO_DUP
|
|
||||||
/* Create a socket object from a numeric file description.
|
|
||||||
Useful e.g. if stdin is a socket.
|
|
||||||
Additional arguments as for socket(). */
|
|
||||||
|
|
||||||
/*ARGSUSED*/
|
|
||||||
static PyObject *
|
|
||||||
socket_fromfd(PyObject *self, PyObject *args)
|
|
||||||
{
|
|
||||||
PySocketSockObject *s;
|
|
||||||
SOCKET_T fd;
|
|
||||||
int family, type, proto = 0;
|
|
||||||
if (!PyArg_ParseTuple(args, "iii|i:fromfd",
|
|
||||||
&fd, &family, &type, &proto))
|
|
||||||
return NULL;
|
|
||||||
/* Dup the fd so it and the socket can be closed independently */
|
|
||||||
fd = dup(fd);
|
|
||||||
if (fd < 0)
|
|
||||||
return set_error();
|
|
||||||
s = new_sockobject(fd, family, type, proto);
|
|
||||||
return (PyObject *) s;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(fromfd_doc,
|
|
||||||
"fromfd(fd, family, type[, proto]) -> socket object\n\
|
|
||||||
\n\
|
|
||||||
Create a socket object from a duplicate of the given\n\
|
|
||||||
file descriptor.\n\
|
|
||||||
The remaining arguments are the same as for socket().");
|
|
||||||
|
|
||||||
#endif /* NO_DUP */
|
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
socket_ntohs(PyObject *self, PyObject *args)
|
socket_ntohs(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -3613,7 +3516,7 @@ Convert a 32-bit integer from host to network byte order.");
|
||||||
/* socket.inet_aton() and socket.inet_ntoa() functions. */
|
/* socket.inet_aton() and socket.inet_ntoa() functions. */
|
||||||
|
|
||||||
PyDoc_STRVAR(inet_aton_doc,
|
PyDoc_STRVAR(inet_aton_doc,
|
||||||
"inet_aton(string) -> packed 32-bit IP representation\n\
|
"inet_aton(string) -> bytes giving packed 32-bit IP representation\n\
|
||||||
\n\
|
\n\
|
||||||
Convert an IP address in string format (123.45.67.89) to the 32-bit packed\n\
|
Convert an IP address in string format (123.45.67.89) to the 32-bit packed\n\
|
||||||
binary format used in low-level network functions.");
|
binary format used in low-level network functions.");
|
||||||
|
@ -3644,7 +3547,7 @@ socket_inet_aton(PyObject *self, PyObject *args)
|
||||||
if (inet_aton != NULL) {
|
if (inet_aton != NULL) {
|
||||||
#endif
|
#endif
|
||||||
if (inet_aton(ip_addr, &buf))
|
if (inet_aton(ip_addr, &buf))
|
||||||
return PyString_FromStringAndSize((char *)(&buf),
|
return PyBytes_FromStringAndSize((char *)(&buf),
|
||||||
sizeof(buf));
|
sizeof(buf));
|
||||||
|
|
||||||
PyErr_SetString(socket_error,
|
PyErr_SetString(socket_error,
|
||||||
|
@ -3673,8 +3576,8 @@ socket_inet_aton(PyObject *self, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PyString_FromStringAndSize((char *) &packed_addr,
|
return PyBytes_FromStringAndSize((char *) &packed_addr,
|
||||||
sizeof(packed_addr));
|
sizeof(packed_addr));
|
||||||
|
|
||||||
#ifdef USE_INET_ATON_WEAKLINK
|
#ifdef USE_INET_ATON_WEAKLINK
|
||||||
}
|
}
|
||||||
|
@ -4077,10 +3980,6 @@ static PyMethodDef socket_methods[] = {
|
||||||
METH_VARARGS, getservbyport_doc},
|
METH_VARARGS, getservbyport_doc},
|
||||||
{"getprotobyname", socket_getprotobyname,
|
{"getprotobyname", socket_getprotobyname,
|
||||||
METH_VARARGS, getprotobyname_doc},
|
METH_VARARGS, getprotobyname_doc},
|
||||||
#ifndef NO_DUP
|
|
||||||
{"fromfd", socket_fromfd,
|
|
||||||
METH_VARARGS, fromfd_doc},
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SOCKETPAIR
|
#ifdef HAVE_SOCKETPAIR
|
||||||
{"socketpair", socket_socketpair,
|
{"socketpair", socket_socketpair,
|
||||||
METH_VARARGS, socketpair_doc},
|
METH_VARARGS, socketpair_doc},
|
||||||
|
@ -4229,14 +4128,11 @@ PySocketModule_APIObject PySocketModuleAPI =
|
||||||
/* Initialize the _socket module.
|
/* Initialize the _socket module.
|
||||||
|
|
||||||
This module is actually called "_socket", and there's a wrapper
|
This module is actually called "_socket", and there's a wrapper
|
||||||
"socket.py" which implements some additional functionality. On some
|
"socket.py" which implements some additional functionality.
|
||||||
platforms (e.g. Windows and OS/2), socket.py also implements a
|
The import of "_socket" may fail with an ImportError exception if
|
||||||
wrapper for the socket type that provides missing functionality such
|
os-specific initialization fails. On Windows, this does WINSOCK
|
||||||
as makefile(), dup() and fromfd(). The import of "_socket" may fail
|
initialization. When WINSOCK is initialized succesfully, a call to
|
||||||
with an ImportError exception if os-specific initialization fails.
|
WSACleanup() is scheduled to be made at exit time.
|
||||||
On Windows, this does WINSOCK initialization. When WINSOCK is
|
|
||||||
initialized succesfully, a call to WSACleanup() is scheduled to be
|
|
||||||
made at exit time.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PyDoc_STRVAR(socket_doc,
|
PyDoc_STRVAR(socket_doc,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue