mirror of
https://github.com/python/cpython.git
synced 2025-09-19 07:00:59 +00:00
Patch 1439 by Bill Janssen. I think this will work.
Tested on Windows by Christian Heimes. I changed the code slightly, renaming decref_socketios() to _decref_socketios(), and moving it closer to the close() method that it calls. Hopefully Bill can now submit his SSL port to 3.0.
This commit is contained in:
parent
e69a08ea93
commit
86bc33cb7c
1 changed files with 21 additions and 85 deletions
102
Lib/socket.py
102
Lib/socket.py
|
@ -21,7 +21,6 @@ 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
|
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_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)
|
inet_ntoa() -- convert 32-bit packed format IP to string (123.45.67.89)
|
||||||
ssl() -- secure socket layer support (only available if configured)
|
|
||||||
socket.getdefaulttimeout() -- get the default timeout value
|
socket.getdefaulttimeout() -- get the default timeout value
|
||||||
socket.setdefaulttimeout() -- set the default timeout value
|
socket.setdefaulttimeout() -- set the default timeout value
|
||||||
create_connection() -- connects to an address, with an optional timeout
|
create_connection() -- connects to an address, with an optional timeout
|
||||||
|
@ -46,36 +45,6 @@ the setsockopt() and getsockopt() methods.
|
||||||
import _socket
|
import _socket
|
||||||
from _socket import *
|
from _socket import *
|
||||||
|
|
||||||
try:
|
|
||||||
import _ssl
|
|
||||||
import ssl as _realssl
|
|
||||||
except ImportError:
|
|
||||||
# no SSL support
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
def ssl(sock, keyfile=None, certfile=None):
|
|
||||||
# we do an internal import here because the ssl
|
|
||||||
# module imports the socket module
|
|
||||||
warnings.warn("socket.ssl() is deprecated. Use ssl.wrap_socket() instead.",
|
|
||||||
DeprecationWarning, stacklevel=2)
|
|
||||||
return _realssl.sslwrap_simple(sock, keyfile, certfile)
|
|
||||||
|
|
||||||
# we need to import the same constants we used to...
|
|
||||||
from _ssl import SSLError as sslerror
|
|
||||||
from _ssl import \
|
|
||||||
RAND_add, \
|
|
||||||
RAND_egd, \
|
|
||||||
RAND_status, \
|
|
||||||
SSL_ERROR_ZERO_RETURN, \
|
|
||||||
SSL_ERROR_WANT_READ, \
|
|
||||||
SSL_ERROR_WANT_WRITE, \
|
|
||||||
SSL_ERROR_WANT_X509_LOOKUP, \
|
|
||||||
SSL_ERROR_SYSCALL, \
|
|
||||||
SSL_ERROR_SSL, \
|
|
||||||
SSL_ERROR_WANT_CONNECT, \
|
|
||||||
SSL_ERROR_EOF, \
|
|
||||||
SSL_ERROR_INVALID_ERROR_CODE
|
|
||||||
|
|
||||||
import os, sys, io
|
import os, sys, io
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -119,49 +88,11 @@ if _can_dup_socket:
|
||||||
nfd = os.dup(fd)
|
nfd = os.dup(fd)
|
||||||
return socket(family, type, proto, fileno=nfd)
|
return socket(family, type, proto, fileno=nfd)
|
||||||
|
|
||||||
class SocketCloser:
|
|
||||||
|
|
||||||
"""Helper to manage socket close() logic for makefile().
|
|
||||||
|
|
||||||
The OS socket should not be closed until the socket and all
|
|
||||||
of its makefile-children are closed. If the refcount is zero
|
|
||||||
when socket.close() is called, this is easy: Just close the
|
|
||||||
socket. If the refcount is non-zero when socket.close() is
|
|
||||||
called, then the real close should not occur until the last
|
|
||||||
makefile-child is closed.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, sock):
|
|
||||||
self._sock = sock
|
|
||||||
self._makefile_refs = 0
|
|
||||||
# Test whether the socket is open.
|
|
||||||
try:
|
|
||||||
sock.fileno()
|
|
||||||
self._socket_open = True
|
|
||||||
except error:
|
|
||||||
self._socket_open = False
|
|
||||||
|
|
||||||
def socket_close(self):
|
|
||||||
self._socket_open = False
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
def makefile_open(self):
|
|
||||||
self._makefile_refs += 1
|
|
||||||
|
|
||||||
def makefile_close(self):
|
|
||||||
self._makefile_refs -= 1
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
if not (self._socket_open or self._makefile_refs):
|
|
||||||
self._sock._real_close()
|
|
||||||
|
|
||||||
|
|
||||||
class socket(_socket.socket):
|
class socket(_socket.socket):
|
||||||
|
|
||||||
"""A subclass of _socket.socket adding the makefile() method."""
|
"""A subclass of _socket.socket adding the makefile() method."""
|
||||||
|
|
||||||
__slots__ = ["__weakref__", "_closer"]
|
__slots__ = ["__weakref__", "_io_refs", "_closed"]
|
||||||
if not _can_dup_socket:
|
if not _can_dup_socket:
|
||||||
__slots__.append("_base")
|
__slots__.append("_base")
|
||||||
|
|
||||||
|
@ -170,15 +101,16 @@ class socket(_socket.socket):
|
||||||
_socket.socket.__init__(self, family, type, proto)
|
_socket.socket.__init__(self, family, type, proto)
|
||||||
else:
|
else:
|
||||||
_socket.socket.__init__(self, family, type, proto, fileno)
|
_socket.socket.__init__(self, family, type, proto, fileno)
|
||||||
# Defer creating a SocketCloser until makefile() is actually called.
|
self._io_refs = 0
|
||||||
self._closer = None
|
self._closed = False
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
"""Wrap __repr__() to reveal the real class name."""
|
"""Wrap __repr__() to reveal the real class name."""
|
||||||
s = _socket.socket.__repr__(self)
|
s = _socket.socket.__repr__(self)
|
||||||
if s.startswith("<socket object"):
|
if s.startswith("<socket object"):
|
||||||
s = "<%s.%s%s" % (self.__class__.__module__,
|
s = "<%s.%s%s%s" % (self.__class__.__module__,
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
|
(self._closed and " [closed] ") or "",
|
||||||
s[7:])
|
s[7:])
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
@ -216,9 +148,8 @@ class socket(_socket.socket):
|
||||||
rawmode += "r"
|
rawmode += "r"
|
||||||
if writing:
|
if writing:
|
||||||
rawmode += "w"
|
rawmode += "w"
|
||||||
if self._closer is None:
|
raw = SocketIO(self, rawmode)
|
||||||
self._closer = SocketCloser(self)
|
self._io_refs += 1
|
||||||
raw = SocketIO(self, rawmode, self._closer)
|
|
||||||
if buffering is None:
|
if buffering is None:
|
||||||
buffering = -1
|
buffering = -1
|
||||||
if buffering < 0:
|
if buffering < 0:
|
||||||
|
@ -245,11 +176,16 @@ class socket(_socket.socket):
|
||||||
text.mode = mode
|
text.mode = mode
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
def _decref_socketios(self):
|
||||||
|
if self._io_refs > 0:
|
||||||
|
self._io_refs -= 1
|
||||||
|
if self._closed:
|
||||||
|
self.close()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self._closer is None:
|
self._closed = True
|
||||||
|
if self._io_refs < 1:
|
||||||
self._real_close()
|
self._real_close()
|
||||||
else:
|
|
||||||
self._closer.socket_close()
|
|
||||||
|
|
||||||
# _real_close calls close on the _socket.socket base class.
|
# _real_close calls close on the _socket.socket base class.
|
||||||
|
|
||||||
|
@ -275,16 +211,14 @@ class SocketIO(io.RawIOBase):
|
||||||
|
|
||||||
# XXX More docs
|
# XXX More docs
|
||||||
|
|
||||||
def __init__(self, sock, mode, closer):
|
def __init__(self, sock, mode):
|
||||||
if mode not in ("r", "w", "rw"):
|
if mode not in ("r", "w", "rw"):
|
||||||
raise ValueError("invalid mode: %r" % mode)
|
raise ValueError("invalid mode: %r" % mode)
|
||||||
io.RawIOBase.__init__(self)
|
io.RawIOBase.__init__(self)
|
||||||
self._sock = sock
|
self._sock = sock
|
||||||
self._mode = mode
|
self._mode = mode
|
||||||
self._closer = closer
|
|
||||||
self._reading = "r" in mode
|
self._reading = "r" in mode
|
||||||
self._writing = "w" in mode
|
self._writing = "w" in mode
|
||||||
closer.makefile_open()
|
|
||||||
|
|
||||||
def readinto(self, b):
|
def readinto(self, b):
|
||||||
self._checkClosed()
|
self._checkClosed()
|
||||||
|
@ -308,9 +242,11 @@ class SocketIO(io.RawIOBase):
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.closed:
|
if self.closed:
|
||||||
return
|
return
|
||||||
self._closer.makefile_close()
|
|
||||||
io.RawIOBase.close(self)
|
io.RawIOBase.close(self)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self._sock._decref_socketios()
|
||||||
|
|
||||||
|
|
||||||
def getfqdn(name=''):
|
def getfqdn(name=''):
|
||||||
"""Get fully qualified domain name from name.
|
"""Get fully qualified domain name from name.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue