-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
ussl: Fix polling of SSL sockets #9871
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
If it will only copy the work done in #5840, then it would be better to merge #5840 itself. The reason I didn't merge that PR yet is because I don't fully understand that logic. Maybe you can implement it in a simpler way?
Let's leave that out for now. |
I think you really just need this: damz@1166b86 The library tells you if it needs to read next or to write next. That is the only direction you are interested in for the next poll operation. Which operation you reenter after that doesn't matter, as both read and write paths reenter the handshake/renegotiation process. |
That is definitely simpler than #5840. Did you have any test cases that show that your patch does indeed work? |
2dc0921
to
b4b9c8b
Compare
Codecov Report
@@ Coverage Diff @@
## master #9871 +/- ##
==========================================
- Coverage 98.33% 98.27% -0.07%
==========================================
Files 154 153 -1
Lines 20511 20526 +15
==========================================
+ Hits 20170 20171 +1
- Misses 341 355 +14
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
A new boolean argument `dtls` is added to `ussl.wrap_socket()`, if true the library assumes that the underlying socket is a datagram socket (i.e. UDP or similar). Implement our own timer callbacks as the out of the box implementation relies on `gettimeofday()`. To fully support asyncio for DTLS socket, we will need to return a readable or writable event in `poll(MP_STREAM_POLL, ...)` if `_mbedtls_timing_get_delay(self) >= 1`. This is left for future work so as not to interfere with micropython#9871.
A new boolean argument `dtls` is added to `ussl.wrap_socket()`, if true the library assumes that the underlying socket is a datagram socket (i.e. UDP or similar). Implement our own timer callbacks as the out of the box implementation relies on `gettimeofday()`. To fully support asyncio for DTLS socket, we will need to return a readable or writable event in `poll(MP_STREAM_POLL, ...)` if `_mbedtls_timing_get_delay(self) >= 1`. This is left for future work so as not to interfere with micropython#9871.
A new boolean argument `dtls` is added to `ussl.wrap_socket()`, if true the library assumes that the underlying socket is a datagram socket (i.e. UDP or similar). Implement our own timer callbacks as the out of the box implementation relies on `gettimeofday()`. To fully support asyncio for DTLS socket, we will need to return a readable or writable event in `poll(MP_STREAM_POLL, ...)` if `_mbedtls_timing_get_delay(self) >= 1`. This is left for future work so as not to interfere with micropython#9871.
A new boolean argument `dtls` is added to `ussl.wrap_socket()`, if true the library assumes that the underlying socket is a datagram socket (i.e. UDP or similar). Implement our own timer callbacks as the out of the box implementation relies on `gettimeofday()`. To fully support asyncio for DTLS socket, we will need to return a readable or writable event in `poll(MP_STREAM_POLL, ...)` if `_mbedtls_timing_get_delay(self) >= 1`. This is left for future work so as not to interfere with micropython#9871.
A new boolean argument `dtls` is added to `ussl.wrap_socket()`, if true the library assumes that the underlying socket is a datagram socket (i.e. UDP or similar). Implement our own timer callbacks as the out of the box implementation relies on `gettimeofday()`. To fully support asyncio for DTLS socket, we will need to return a readable or writable event in `poll(MP_STREAM_POLL, ...)` if `_mbedtls_timing_get_delay(self) >= 1`. This is left for future work so as not to interfere with micropython#9871.
A new boolean argument `dtls` is added to `ussl.wrap_socket()`, if true the library assumes that the underlying socket is a datagram socket (i.e. UDP or similar). Implement our own timer callbacks as the out of the box implementation relies on `gettimeofday()`. To fully support asyncio for DTLS socket, we will need to return a readable or writable event in `poll(MP_STREAM_POLL, ...)` if `_mbedtls_timing_get_delay(self) >= 1`. This is left for future work so as not to interfere with micropython#9871.
Code size report:
|
Code size report:
|
Code size report:
|
Code size report:
|
Code size report:
|
A new boolean argument `dtls` is added to `ussl.wrap_socket()`, if true the library assumes that the underlying socket is a datagram socket (i.e. UDP or similar). Implement our own timer callbacks as the out of the box implementation relies on `gettimeofday()`. To fully support asyncio for DTLS socket, we will need to return a readable or writable event in `poll(MP_STREAM_POLL, ...)` if `_mbedtls_timing_get_delay(self) >= 1`. This is left for future work so as not to interfere with micropython#9871.
@dpgeorge I updated the code as you requested, and based on further experience with running this code over the last few weeks at Ribbit Network. There is now a full unit test that runs in unix/coverage. |
Code size report:
|
As recommended by @Carglglz I reused the certificate/key pair already used in |
During the initial handshake or subsequent renegotiation, the protocol might need to read in order to write (or conversely to write in order to read). It might be blocked from doing so by the state of the underlying socket (i.e. there is no data to read, or there is no space to write). The library indicates this condition by returning one of the errors `MBEDTLS_ERR_SSL_WANT_READ` or `MBEDTLS_ERR_SSL_WANT_WRITE`. When that happens, we need to enforce that the next poll operation only considers the direction that the library indicated. In addition, mbedtls does its own read buffering that we need to take into account while polling, and we need to save the last error between read()/write() and ioctl().
Code size report:
|
Thank you very much for the work on this, it's a nice clean change with a good test. |
A new boolean argument `dtls` is added to `ussl.wrap_socket()`, if true the library assumes that the underlying socket is a datagram socket (i.e. UDP or similar). Implement our own timer callbacks as the out of the box implementation relies on `gettimeofday()`. To fully support asyncio for DTLS socket, we will need to return a readable or writable event in `poll(MP_STREAM_POLL, ...)` if `_mbedtls_timing_get_delay(self) >= 1`. This is left for future work so as not to interfere with micropython#9871.
What does this PR solve?
There are three issues in the current implementation
ioctl(MP_STREAM_POLL)
for SSL sockets:mbedtls_ssl_check_pending
) which needs to be considered when checking forMP_STREAM_POLL_RD
;read()
orwrite()
needs to be stored so that we don't block on polling (e.g. we should not wait to read data on an SSL socket that is in error).How does this PR solve the problem?
ioctl(MP_STREAM_POLL)
;