Skip to content

ssl: support SSLSocket#connect and #accept with timeout - #1098

Merged
rhenium merged 4 commits into
ruby:masterfrom
rhenium:ky/ssl-handshake-timeout
Oct 11, 2026
Merged

rhenium merged 4 commits into
ruby:masterfrom
rhenium:ky/ssl-handshake-timeout

Conversation

@rhenium

@rhenium rhenium commented Aug 27, 2026 •

Copy link
Copy Markdown
Member

Add a keyword argument timeout to specify the total time allowed for the TLS handshake to complete. Inspired by Addrinfo#connect(timeout:) and TCPSocket.open(connect_timeout:).

Applies on top of #1105

@rhenium
rhenium force-pushed the ky/ssl-handshake-timeout branch from 76bc4f0 to 2cf80fe Compare September 2, 2026 12:48
@ioquatix

ioquatix commented Sep 2, 2026

Copy link
Copy Markdown
Member

Do you default to IO#timeout where appropriate? wait_readable and wait_writable will use the default.

@rhenium
rhenium force-pushed the ky/ssl-handshake-timeout branch from 2cf80fe to 1efb173 Compare October 10, 2026 09:36
Let the extension provide only the essential part to call the OpenSSL
API: SSLSocket#ssl_connect, #ssl_accept, #ssl_read, and #ssl_write.

Implement the public methods in ssl.rb:
SSLSocket#connect, #accept, #sysread, and #syswrite, along with
their #*_nonblock variants.

This greatly simplifies code and prepares for the upcoming patches to
add proper timeout support and closed-stream state tracking, which do
not need to be in the extension.
Currently String.new(capacity: len) causes Hash allocations for the
keyword arguments, which is undesirable in this hot path.

This workaround should be reverted once it is no longer necessary.
Subtract elapsed time from the timeout before retrying
IO#wait_{read,writ}able.

Currently, each call to IO#wait_{read,writ}able (or rb_io_wait() before
the previous patch) uses the full default timeout. This makes
SSLSocket#timeout= ineffective when a peer splits a TLS record into
many small TCP segments and sends them slowly.

Buffered methods such as #gets still apply timeout separately to each
primitive blocking operation, but this appears to match the behavior of
core IO methods.
@rhenium
rhenium force-pushed the ky/ssl-handshake-timeout branch from 1efb173 to 09f15f0 Compare October 11, 2026 05:48
Add a keyword argument timeout to specify the total time allowed for
the TLS handshake to complete. Inspired by Addrinfo#connect(timeout:)
and TCPSocket.open(connect_timeout:).
@rhenium
rhenium force-pushed the ky/ssl-handshake-timeout branch from 09f15f0 to 3896e94 Compare October 11, 2026 06:16
@rhenium

rhenium commented Oct 11, 2026

Copy link
Copy Markdown
Member Author

Yes, the new method signature is def connect(timeout: self.timeout).

@rhenium
rhenium merged commit e679f1d into ruby:master Oct 11, 2026
43 of 48 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants