mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +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
				
			
		
							
								
								
									
										106
									
								
								Lib/socket.py
									
										
									
									
									
								
							
							
						
						
									
										106
									
								
								Lib/socket.py
									
										
									
									
									
								
							|  | @ -21,7 +21,6 @@ | ||||||
| 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 @@ | ||||||
| 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 @@ def fromfd(fd, family=AF_INET, type=SOCK_STREAM, proto=0): | ||||||
|         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,16 +101,17 @@ def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None): | ||||||
|             _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__, | ||||||
|                               s[7:]) |                                 (self._closed and " [closed] ") or "", | ||||||
|  |                                 s[7:]) | ||||||
|         return s |         return s | ||||||
| 
 | 
 | ||||||
|     def accept(self): |     def accept(self): | ||||||
|  | @ -216,9 +148,8 @@ def makefile(self, mode="r", buffering=None, *, | ||||||
|             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 @@ def makefile(self, mode="r", buffering=None, *, | ||||||
|         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 @@ def fileno(self): | ||||||
|     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
	
	 Guido van Rossum
						Guido van Rossum