| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1604,8 +1604,25 @@ the sockets in non-blocking mode and use an event loop). | |||
| 1604 | 1604 | Notes on non-blocking sockets | |
| 1605 | 1605 | ----------------------------- | |
| 1606 | 1606 | ||
| 1607 | - When working with non-blocking sockets, there are several things you need | ||
| 1608 | - to be aware of: | ||
| 1607 | + SSL sockets behave slightly different than regular sockets in | ||
| 1608 | + non-blocking mode. When working with non-blocking sockets, there are | ||
| 1609 | + thus several things you need to be aware of: | ||
| 1610 | + | ||
| 1611 | + - Most :class:`SSLSocket` methods will raise either | ||
| 1612 | + :exc:`SSLWantWriteError` or :exc:`SSLWantReadError` instead of | ||
| 1613 | + :exc:`BlockingIOError` if an I/O operation would | ||
| 1614 | + block. :exc:`SSLWantReadError` will be raised if a read operation on | ||
| 1615 | + the underlying socket is necessary, and :exc:`SSLWantWriteError` for | ||
| 1616 | + a write operation on the underlying socket. Note that attempts to | ||
| 1617 | + *write* to an SSL socket may require *reading* from the underlying | ||
| 1618 | + socket first, and attempts to *read* from the SSL socket may require | ||
| 1619 | + a prior *write* to the underlying socket. | ||
| 1620 | + | ||
| 1621 | + .. versionchanged:: 3.5 | ||
| 1622 | + | ||
| 1623 | + In earlier Python versions, the :meth:`!SSLSocket.send` method | ||
| 1624 | + returned zero instead of raising :exc:`SSLWantWriteError` or | ||
| 1625 | + :exc:`SSLWantReadError`. | ||
| 1609 | 1626 | ||
| 1610 | 1627 | - Calling :func:`~select.select` tells you that the OS-level socket can be | |
| 1611 | 1628 | read from (or written to), but it does not imply that there is sufficient | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -664,17 +664,7 @@ def send(self, data, flags=0): | |||
| 664 | 664 | raise ValueError( | |
| 665 | 665 | "non-zero flags not allowed in calls to send() on %s" % | |
| 666 | 666 | self.__class__) | |
| 667 | - try: | ||
| 668 | - v = self._sslobj.write(data) | ||
| 669 | - except SSLError as x: | ||
| 670 | - if x.args[0] == SSL_ERROR_WANT_READ: | ||
| 671 | - return 0 | ||
| 672 | - elif x.args[0] == SSL_ERROR_WANT_WRITE: | ||
| 673 | - return 0 | ||
| 674 | - else: | ||
| 675 | - raise | ||
| 676 | - else: | ||
| 677 | - return v | ||
| 667 | + return self._sslobj.write(data) | ||
| 678 | 668 | else: | |
| 679 | 669 | return socket.send(self, data, flags) | |
| 680 | 670 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2547,6 +2547,36 @@ def _recvfrom_into(): | |||
| 2547 | 2547 | s.write(b"over\n") | |
| 2548 | 2548 | s.close() | |
| 2549 | 2549 | ||
| 2550 | + def test_nonblocking_send(self): | ||
| 2551 | + server = ThreadedEchoServer(CERTFILE, | ||
| 2552 | + certreqs=ssl.CERT_NONE, | ||
| 2553 | + ssl_version=ssl.PROTOCOL_TLSv1, | ||
| 2554 | + cacerts=CERTFILE, | ||
| 2555 | + chatty=True, | ||
| 2556 | + connectionchatty=False) | ||
| 2557 | + with server: | ||
| 2558 | + s = ssl.wrap_socket(socket.socket(), | ||
| 2559 | + server_side=False, | ||
| 2560 | + certfile=CERTFILE, | ||
| 2561 | + ca_certs=CERTFILE, | ||
| 2562 | + cert_reqs=ssl.CERT_NONE, | ||
| 2563 | + ssl_version=ssl.PROTOCOL_TLSv1) | ||
| 2564 | + s.connect((HOST, server.port)) | ||
| 2565 | + s.setblocking(False) | ||
| 2566 | + | ||
| 2567 | + # If we keep sending data, at some point the buffers | ||
| 2568 | + # will be full and the call will block | ||
| 2569 | + buf = bytearray(8192) | ||
| 2570 | + def fill_buffer(): | ||
| 2571 | + while True: | ||
| 2572 | + s.send(buf) | ||
| 2573 | + self.assertRaises((ssl.SSLWantWriteError, | ||
| 2574 | + ssl.SSLWantReadError), fill_buffer) | ||
| 2575 | + | ||
| 2576 | + # Now read all the output and discard it | ||
| 2577 | + s.setblocking(True) | ||
| 2578 | + s.close() | ||
| 2579 | + | ||
| 2550 | 2580 | def test_handshake_timeout(self): | |
| 2551 | 2581 | # Issue #5103: SSL handshake must respect the socket timeout | |
| 2552 | 2582 | server = socket.socket(socket.AF_INET) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -60,6 +60,10 @@ Core and Builtins | |||
| 60 | 60 | Library | |
| 61 | 61 | ------- | |
| 62 | 62 | ||
| 63 | + - Issue #20951: SSLSocket.send() now raises either SSLWantReadError or | ||
| 64 | + SSLWantWriteError on a non-blocking socket if the operation would block. | ||
| 65 | + Previously, it would return 0. Patch by Nikolaus Rath. | ||
| 66 | + | ||
| 63 | 67 | - Issue #13248: removed previously deprecated asyncore.dispatcher __getattr__ | |
| 64 | 68 | cheap inheritance hack. | |
| 65 | 69 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments