summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2007-11-16 01:24:05 (GMT)
committerGuido van Rossum <guido@python.org>2007-11-16 01:24:05 (GMT)
commit39eb8fa0dbbcd6568fceb7ca59220aa3281e0cc4 (patch)
tree5fa187d82123d1055401cb9ae8a4dcd16928bfde /Lib
parentdd9e3b8736fae1f730d027d5383a2b17c661ce82 (diff)
downloadcpython-39eb8fa0dbbcd6568fceb7ca59220aa3281e0cc4.zip
cpython-39eb8fa0dbbcd6568fceb7ca59220aa3281e0cc4.tar.gz
cpython-39eb8fa0dbbcd6568fceb7ca59220aa3281e0cc4.tar.bz2
This is roughly socket2.diff from issue 1378, with a few changes applied
to ssl.py (no need to test whether we can dup any more). Regular sockets no longer have a _base, but we still have explicit reference counting of socket objects for the benefit of makefile(); using duplicate sockets won't work for SSLSocket.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/socket.py71
-rw-r--r--Lib/ssl.py21
-rw-r--r--Lib/test/test_socket.py9
3 files changed, 45 insertions, 56 deletions
diff --git a/Lib/socket.py b/Lib/socket.py
index 6a9a381..62eb82d 100644
--- a/Lib/socket.py
+++ b/Lib/socket.py
@@ -79,28 +79,14 @@ if sys.platform.lower().startswith("win"):
__all__.append("errorTab")
-# True if os.dup() can duplicate socket descriptors.
-# (On Windows at least, os.dup only works on files)
-_can_dup_socket = hasattr(_socket.socket, "dup")
-
-if _can_dup_socket:
- 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__", "_io_refs", "_closed"]
- if not _can_dup_socket:
- __slots__.append("_base")
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)
+ _socket.socket.__init__(self, family, type, proto, fileno)
self._io_refs = 0
self._closed = False
@@ -114,23 +100,29 @@ class socket(_socket.socket):
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):
- """Wrap accept() to give the connection the right type."""
- conn, addr = _socket.socket.accept(self)
- fd = conn.fileno()
- nfd = fd
- if _can_dup_socket:
- 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
+ """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):
- """Return an I/O stream connected to the socket.
+ """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'.
@@ -184,21 +176,18 @@ class socket(_socket.socket):
def close(self):
self._closed = True
- if self._io_refs < 1:
- self._real_close()
+ if self._io_refs <= 0:
+ _socket.socket.close(self)
- # _real_close calls close on the _socket.socket base class.
- if not _can_dup_socket:
- def _real_close(self):
- _socket.socket.close(self)
- base = getattr(self, "_base", None)
- if base is not None:
- self._base = None
- base.close()
- else:
- def _real_close(self):
- _socket.socket.close(self)
+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):
diff --git a/Lib/ssl.py b/Lib/ssl.py
index c2cfa31..9d63d12 100644
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -78,8 +78,8 @@ from _ssl import (
from socket import socket, AF_INET, SOCK_STREAM, error
from socket import getnameinfo as _getnameinfo
from socket import error as socket_error
+from socket import dup as _dup
import base64 # for DER-to-PEM translation
-_can_dup_socket = hasattr(socket, "dup")
class SSLSocket(socket):
@@ -99,20 +99,11 @@ class SSLSocket(socket):
if sock is not None:
# copied this code from socket.accept()
fd = sock.fileno()
- nfd = fd
- if _can_dup_socket:
- nfd = os.dup(fd)
- try:
- socket.__init__(self, family=sock.family, type=sock.type,
- proto=sock.proto, fileno=nfd)
- except:
- if nfd != fd:
- os.close(nfd)
- else:
- if fd != nfd:
- sock.close()
- sock = None
-
+ nfd = _dup(fd)
+ socket.__init__(self, family=sock.family, type=sock.type,
+ proto=sock.proto, fileno=nfd)
+ sock.close()
+ sock = None
elif fileno is not None:
socket.__init__(self, fileno=fileno)
else:
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index 82eb6e7..c01d998 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -575,6 +575,15 @@ class BasicTCPTest(SocketConnectedTest):
def _testFromFd(self):
self.serv_conn.send(MSG)
+ def testDup(self):
+ # Testing dup()
+ sock = self.cli_conn.dup()
+ msg = sock.recv(1024)
+ self.assertEqual(msg, MSG)
+
+ def _testDup(self):
+ self.serv_conn.send(MSG)
+
def testShutdown(self):
# Testing shutdown()
msg = self.cli_conn.recv(1024)