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:
Guido van Rossum 2007-05-21 23:13:11 +00:00
parent 88effc1251
commit 7d0a8264ff
5 changed files with 200 additions and 516 deletions

View File

@ -295,6 +295,22 @@ class IOBase:
"""
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):
@ -366,7 +382,6 @@ class SocketIO(RawIOBase):
"""Raw I/O implementation for stream sockets."""
# XXX More docs
# XXX Hook this up to socket.py
def __init__(self, sock, mode):
assert mode in ("r", "w", "rw")
@ -377,13 +392,32 @@ class SocketIO(RawIOBase):
def readinto(self, 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):
return self._sock.send(b)
def close(self):
if not self.closed:
RawIOBase.close()
self._sock.close()
RawIOBase.close(self)
def readable(self):
return "r" in self._mode
@ -450,20 +484,6 @@ class BufferedIOBase(IOBase):
b[:n] = data
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:
"""write(b: bytes) -> int. Write the given buffer to the IO stream.

View File

@ -54,7 +54,7 @@ try:
except ImportError:
pass
import os, sys
import os, sys, io
try:
from errno import EBADF
@ -66,14 +66,6 @@ __all__.extend(os._get_exports_list(_socket))
if _have_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
if sys.platform.lower().startswith("win"):
errorTab = {}
@ -95,6 +87,99 @@ if sys.platform.lower().startswith("win"):
__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=''):
"""Get fully qualified domain name from name.
@ -122,298 +207,6 @@ def getfqdn(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):
"""Connect to address (host, port) with an optional timeout.

View File

@ -14,7 +14,7 @@ import signal
PORT = 50007
HOST = 'localhost'
MSG = 'Michael Gilfix was here\n'
MSG = b'Michael Gilfix was here\n'
class SocketTCPTest(unittest.TestCase):
@ -542,16 +542,16 @@ class BasicTCPTest(SocketConnectedTest):
def testSendAll(self):
# Testing sendall() with a 2048 byte string over TCP
msg = ''
msg = b''
while 1:
read = self.cli_conn.recv(1024)
if not read:
break
msg += read
self.assertEqual(msg, 'f' * 2048)
self.assertEqual(msg, b'f' * 2048)
def _testSendAll(self):
big_chunk = 'f' * 2048
big_chunk = b'f' * 2048
self.serv_conn.sendall(big_chunk)
def testFromFd(self):
@ -612,7 +612,7 @@ class TCPCloserTest(ThreadedTCPSocketTest):
sd = self.cli
read, write, err = select.select([sd], [], [], 1.0)
self.assertEqual(read, [sd])
self.assertEqual(sd.recv(1), '')
self.assertEqual(sd.recv(1), b'')
def _testClose(self):
self.cli.connect((HOST, PORT))
@ -754,7 +754,7 @@ class FileObjectClassTestCase(SocketConnectedTest):
def testUnbufferedRead(self):
# Performing unbuffered file read test
buf = ''
buf = b''
while 1:
char = self.serv_file.read(1)
if not char:
@ -796,14 +796,14 @@ class UnbufferedFileObjectClassTestCase(FileObjectClassTestCase):
def testUnbufferedReadline(self):
# Read a line, create a new file object, read another line with it
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)
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):
self.cli_file.write("A. " + MSG)
self.cli_file.write("B. " + MSG)
self.cli_file.write(b"A. " + MSG)
self.cli_file.write(b"B. " + MSG)
self.cli_file.flush()
class LineBufferedFileObjectClassTestCase(FileObjectClassTestCase):
@ -818,6 +818,7 @@ class SmallBufferedFileObjectClassTestCase(FileObjectClassTestCase):
class NetworkConnectionTest(object):
"""Prove network connection."""
def clientSetUp(self):
self.cli = socket.create_connection((HOST, PORT))
self.serv_conn = self.cli
@ -827,6 +828,7 @@ class BasicTCPTest2(NetworkConnectionTest, BasicTCPTest):
"""
class NetworkConnectionNoServer(unittest.TestCase):
def testWithoutServer(self):
self.failUnlessRaises(socket.error, lambda: socket.create_connection((HOST, PORT)))
@ -895,43 +897,19 @@ class NetworkConnectionBehaviourTest(SocketTCPTest, ThreadableTest):
def testInsideTimeout(self):
conn, addr = self.serv.accept()
time.sleep(3)
conn.send("done!")
conn.send(b"done!")
testOutsideTimeout = testInsideTimeout
def _testInsideTimeout(self):
self.cli = sock = socket.create_connection((HOST, PORT))
data = sock.recv(5)
self.assertEqual(data, "done!")
self.assertEqual(data, b"done!")
def _testOutsideTimeout(self):
self.cli = sock = socket.create_connection((HOST, PORT), timeout=1)
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):
def testTCPTimeout(self):
@ -1055,7 +1033,7 @@ class BufferIOTest(SocketConnectedTest):
buf = b" "*1024
nbytes = self.cli_conn.recv_into(buf)
self.assertEqual(nbytes, len(MSG))
msg = str(buf[:len(MSG)])
msg = buf[:len(MSG)]
self.assertEqual(msg, MSG)
def _testRecvInto(self):
@ -1066,7 +1044,7 @@ class BufferIOTest(SocketConnectedTest):
buf = b" "*1024
nbytes, addr = self.cli_conn.recvfrom_into(buf)
self.assertEqual(nbytes, len(MSG))
msg = str(buf[:len(MSG)])
msg = buf[:len(MSG)]
self.assertEqual(msg, MSG)
def _testRecvFromInto(self):
@ -1085,7 +1063,6 @@ def test_main():
UnbufferedFileObjectClassTestCase,
LineBufferedFileObjectClassTestCase,
SmallBufferedFileObjectClassTestCase,
Urllib2FileobjectTest,
NetworkConnectionNoServer,
NetworkConnectionAttributesTest,
NetworkConnectionBehaviourTest,

View File

@ -1085,10 +1085,8 @@ class AbstractHTTPHandler(BaseHandler):
# to read(). This weird wrapping allows the returned object to
# 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
# XXX socket._fileobject is gone; use some class from io.py instead
fp = socket._fileobject(r, close=True)
resp = addinfourl(fp, r.msg, req.get_full_url())

View File

@ -19,15 +19,14 @@ Module interface:
a subclass of socket.error
- socket.herror: exception raised for gethostby* errors,
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.gethostbyaddr(IP address) --> (hostname, [alias, ...], [IP addr, ...])
- socket.gethostname() --> host name (string: 'spam' or 'spam.domain.com')
- socket.getprotobyname(protocolname) --> protocol number
- socket.getservbyname(servicename[, protocolname]) --> port number
- 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.ntohs(16 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\
gettimeout() -- return timeout or None\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_into(buffer[, nbytes[, flags]]) -- receive data (into a buffer)\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
#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
a Py prefix (or use CapitalizedWords). Later... */
@ -1551,7 +1553,7 @@ static PyObject *
sock_accept(PySocketSockObject *s)
{
sock_addr_t addrbuf;
SOCKET_T newfd;
SOCKET_T newfd = INVALID_SOCKET;
socklen_t addrlen;
PyObject *sock = NULL;
PyObject *addr = NULL;
@ -1562,12 +1564,6 @@ sock_accept(PySocketSockObject *s)
return NULL;
memset(&addrbuf, 0, addrlen);
#ifdef MS_WINDOWS
newfd = INVALID_SOCKET;
#else
newfd = -1;
#endif
if (!IS_SELECTABLE(s))
return select_error();
@ -1582,11 +1578,7 @@ sock_accept(PySocketSockObject *s)
return NULL;
}
#ifdef MS_WINDOWS
if (newfd == INVALID_SOCKET)
#else
if (newfd < 0)
#endif
return s->errorhandler();
/* Create the new object with unspecified family,
@ -1814,16 +1806,19 @@ sock_getsockopt(PySocketSockObject *s, PyObject *args)
"getsockopt buflen out of range");
return NULL;
}
buf = PyString_FromStringAndSize((char *)NULL, buflen);
buf = PyBytes_FromStringAndSize((char *)NULL, buflen);
if (buf == NULL)
return NULL;
res = getsockopt(s->sock_fd, level, optname,
(void *)PyString_AS_STRING(buf), &buflen);
(void *)PyBytes_AS_STRING(buf), &buflen);
if (res < 0) {
Py_DECREF(buf);
return s->errorhandler();
}
_PyString_Resize(&buf, buflen);
if (PyBytes_Resize(buf, buflen) < 0) {
Py_DECREF(buf);
return NULL;
}
return buf;
#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.");
#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
* 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. */
buf = PyString_FromStringAndSize((char *) 0, recvlen);
buf = PyBytes_FromStringAndSize((char *) 0, recvlen);
if (buf == NULL)
return NULL;
/* 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) {
/* An error occurred, release the string and return an
error. */
@ -2354,7 +2286,7 @@ sock_recv(PySocketSockObject *s, PyObject *args)
if (outlen != recvlen) {
/* We did not read as many bytes as we anticipated, resize the
string if possible and be succesful. */
if (_PyString_Resize(&buf, outlen) < 0)
if (PyBytes_Resize(buf, outlen) < 0)
/* Oopsy, not so succesful after all. */
return NULL;
}
@ -2513,11 +2445,11 @@ sock_recvfrom(PySocketSockObject *s, PyObject *args)
return NULL;
}
buf = PyString_FromStringAndSize((char *) 0, recvlen);
buf = PyBytes_FromStringAndSize((char *) 0, recvlen);
if (buf == NULL)
return NULL;
outlen = sock_recvfrom_guts(s, PyString_AS_STRING(buf),
outlen = sock_recvfrom_guts(s, PyBytes_AS_STRING(buf),
recvlen, flags, &addr);
if (outlen < 0) {
goto finally;
@ -2526,7 +2458,7 @@ sock_recvfrom(PySocketSockObject *s, PyObject *args)
if (outlen != recvlen) {
/* We did not read as many bytes as we anticipated, resize the
string if possible and be succesful. */
if (_PyString_Resize(&buf, outlen) < 0)
if (PyBytes_Resize(buf, outlen) < 0)
/* Oopsy, not so succesful after all. */
goto finally;
}
@ -2788,10 +2720,6 @@ static PyMethodDef sock_methods[] = {
getsockopt_doc},
{"listen", (PyCFunction)sock_listen, METH_O,
listen_doc},
#ifndef NO_DUP
{"makefile", (PyCFunction)sock_makefile, METH_VARARGS,
makefile_doc},
#endif
{"recv", (PyCFunction)sock_recv, METH_VARARGS,
recv_doc},
{"recv_into", (PyCFunction)sock_recv_into, METH_VARARGS | METH_KEYWORDS,
@ -2861,7 +2789,7 @@ sock_repr(PySocketSockObject *s)
#endif
PyOS_snprintf(
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,
s->sock_type,
s->sock_proto);
@ -2893,27 +2821,35 @@ static int
sock_initobj(PyObject *self, PyObject *args, PyObject *kwds)
{
PySocketSockObject *s = (PySocketSockObject *)self;
SOCKET_T fd;
PyObject *fdobj = NULL;
SOCKET_T fd = INVALID_SOCKET;
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,
"|iii:socket", keywords,
&family, &type, &proto))
"|iiiO:socket", keywords,
&family, &type, &proto, &fdobj))
return -1;
Py_BEGIN_ALLOW_THREADS
fd = socket(family, type, proto);
Py_END_ALLOW_THREADS
if (fdobj != NULL) {
fd = PyLong_AsLongLong(fdobj);
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)
#else
if (fd < 0)
#endif
{
set_error();
return -1;
if (fd == INVALID_SOCKET) {
set_error();
return -1;
}
}
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 */
#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 *
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. */
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\
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.");
@ -3644,7 +3547,7 @@ socket_inet_aton(PyObject *self, PyObject *args)
if (inet_aton != NULL) {
#endif
if (inet_aton(ip_addr, &buf))
return PyString_FromStringAndSize((char *)(&buf),
return PyBytes_FromStringAndSize((char *)(&buf),
sizeof(buf));
PyErr_SetString(socket_error,
@ -3673,8 +3576,8 @@ socket_inet_aton(PyObject *self, PyObject *args)
return NULL;
}
}
return PyString_FromStringAndSize((char *) &packed_addr,
sizeof(packed_addr));
return PyBytes_FromStringAndSize((char *) &packed_addr,
sizeof(packed_addr));
#ifdef USE_INET_ATON_WEAKLINK
}
@ -4077,10 +3980,6 @@ static PyMethodDef socket_methods[] = {
METH_VARARGS, getservbyport_doc},
{"getprotobyname", socket_getprotobyname,
METH_VARARGS, getprotobyname_doc},
#ifndef NO_DUP
{"fromfd", socket_fromfd,
METH_VARARGS, fromfd_doc},
#endif
#ifdef HAVE_SOCKETPAIR
{"socketpair", socket_socketpair,
METH_VARARGS, socketpair_doc},
@ -4229,14 +4128,11 @@ PySocketModule_APIObject PySocketModuleAPI =
/* Initialize the _socket module.
This module is actually called "_socket", and there's a wrapper
"socket.py" which implements some additional functionality. On some
platforms (e.g. Windows and OS/2), socket.py also implements a
wrapper for the socket type that provides missing functionality such
as makefile(), dup() and fromfd(). The import of "_socket" may fail
with an ImportError exception if os-specific initialization fails.
On Windows, this does WINSOCK initialization. When WINSOCK is
initialized succesfully, a call to WSACleanup() is scheduled to be
made at exit time.
"socket.py" which implements some additional functionality.
The import of "_socket" may fail with an ImportError exception if
os-specific initialization fails. 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,