|
52 | 52 |
|
53 | 53 | import socket |
54 | 54 | import sys |
55 | | -import threading |
56 | 55 | import time |
57 | 56 | from warnings import warn as _warn |
58 | 57 |
|
@@ -176,99 +175,51 @@ class SSLFileobjectStreamWriter(SSLFileobjectMixin, StreamWriter): |
176 | 175 | """SSL file object attached to a socket object.""" |
177 | 176 |
|
178 | 177 |
|
179 | | -class SSLConnectionProxyMeta: |
180 | | - """Metaclass for generating a bunch of proxy methods.""" |
181 | | - |
182 | | - def __new__(mcl, name, bases, nmspc): |
183 | | - """Attach a list of proxy methods to a new class.""" |
184 | | - proxy_methods = ( |
185 | | - 'get_context', |
186 | | - 'pending', |
187 | | - 'send', |
188 | | - 'write', |
189 | | - 'recv', |
190 | | - 'read', |
191 | | - 'renegotiate', |
192 | | - 'bind', |
193 | | - 'listen', |
194 | | - 'connect', |
195 | | - 'accept', |
196 | | - 'setblocking', |
197 | | - 'fileno', |
198 | | - 'close', |
199 | | - 'get_cipher_list', |
200 | | - 'getpeername', |
201 | | - 'getsockname', |
202 | | - 'getsockopt', |
203 | | - 'setsockopt', |
204 | | - 'makefile', |
205 | | - 'get_app_data', |
206 | | - 'set_app_data', |
207 | | - 'state_string', |
208 | | - 'sock_shutdown', |
209 | | - 'get_peer_certificate', |
210 | | - 'want_read', |
211 | | - 'want_write', |
212 | | - 'set_connect_state', |
213 | | - 'set_accept_state', |
214 | | - 'connect_ex', |
215 | | - 'sendall', |
216 | | - 'settimeout', |
217 | | - 'gettimeout', |
218 | | - 'shutdown', |
219 | | - ) |
220 | | - proxy_methods_no_args = ('shutdown',) |
221 | | - |
222 | | - proxy_props = ('family',) |
223 | | - |
224 | | - def lock_decorator(method): |
225 | | - """Create a proxy method for a new class.""" |
226 | | - |
227 | | - def proxy_wrapper(self, *args): |
228 | | - self._lock.acquire() |
229 | | - try: |
230 | | - new_args = ( |
231 | | - args[:] if method not in proxy_methods_no_args else [] |
232 | | - ) |
233 | | - return getattr(self._ssl_conn, method)(*new_args) |
234 | | - finally: |
235 | | - self._lock.release() |
236 | | - |
237 | | - return proxy_wrapper |
238 | | - |
239 | | - for m in proxy_methods: |
240 | | - nmspc[m] = lock_decorator(m) |
241 | | - nmspc[m].__name__ = m |
242 | | - |
243 | | - def make_property(property_): |
244 | | - """Create a proxy method for a new class.""" |
245 | | - |
246 | | - def proxy_prop_wrapper(self): |
247 | | - return getattr(self._ssl_conn, property_) |
| 178 | +class SSLConnection(SSL.Connection): |
| 179 | + """ |
| 180 | + A compatibility wrapper around :py:class:`OpenSSL.SSL.Connection`. |
248 | 181 |
|
249 | | - proxy_prop_wrapper.__name__ = property_ |
250 | | - return property(proxy_prop_wrapper) |
| 182 | + This class exists primarily to ensure the standard Python socket method |
| 183 | + :py:meth:`.shutdown()` is available for interface compatibility. |
| 184 | + """ |
251 | 185 |
|
252 | | - for p in proxy_props: |
253 | | - nmspc[p] = make_property(p) |
| 186 | + def makefile(self, *args, **kwargs): |
| 187 | + """ |
| 188 | + Raise :exc:`NotImplementedError` for ``makefile()`` interface. |
254 | 189 |
|
255 | | - # Doesn't work via super() for some reason. |
256 | | - # Falling back to type() instead: |
257 | | - return type(name, bases, nmspc) |
| 190 | + PyOpenSSL's :py:class:`~OpenSSL.SSL.Connection` marks |
| 191 | + :py:meth:`~OpenSSL.SSL.Connection.makefile` as not implemented. |
| 192 | + This method exists only for interface compatibility with |
| 193 | + Python sockets. |
| 194 | + """ |
| 195 | + # Replicate the parent's behavior to avoid calling a method |
| 196 | + # that is known to be unimplemented. |
| 197 | + raise NotImplementedError( |
| 198 | + "PyOpenSSL's Connection class does not support the makefile() interface", |
| 199 | + ) |
258 | 200 |
|
| 201 | + def shutdown(self, how=None): |
| 202 | + """Shutdown the SSL connection. |
259 | 203 |
|
260 | | -class SSLConnection(metaclass=SSLConnectionProxyMeta): |
261 | | - r"""A thread-safe wrapper for an ``SSL.Connection``. |
| 204 | + :param how: Ignored. PyOpenSSL's |
| 205 | + :py:meth:`~OpenSSL.SSL.Connection.shutdown` |
| 206 | + method does not accept any arguments. |
| 207 | + Present here for interface compatibility with Python |
| 208 | + :py:meth:`~socket.socket.shutdown` that |
| 209 | + :py:class:`ssl.SSLSocket` wrapper exposes. |
| 210 | + :type how: object |
| 211 | + """ |
| 212 | + return super().shutdown() |
262 | 213 |
|
263 | | - :param tuple args: the arguments to create the wrapped \ |
264 | | - :py:class:`SSL.Connection(*args) \ |
265 | | - <pyopenssl:OpenSSL.SSL.Connection>` |
266 | | - """ |
| 214 | + def sock_shutdown(self, how=None): |
| 215 | + """Shutdown the SSL connection. |
267 | 216 |
|
268 | | - def __init__(self, *args): |
269 | | - """Initialize SSLConnection instance.""" |
270 | | - self._ssl_conn = SSL.Connection(*args) |
271 | | - self._lock = threading.RLock() |
| 217 | + This method is provided for interface compatibility and delegates |
| 218 | + directly to the standard shutdown() method. |
| 219 | + """ |
| 220 | + # We call self.shutdown(how) to use the method where we added |
| 221 | + # the compatibility logic (handling 'how=None' for the parent). |
| 222 | + return self.shutdown(how) |
272 | 223 |
|
273 | 224 |
|
274 | 225 | class pyOpenSSLAdapter(Adapter): |
|
0 commit comments