Skip to content

Client: Last SSL payload from server not being waited for breaks stuff #8

@HoneyryderChuck

Description

@HoneyryderChuck

As said in the other issue, I've managed to get my tests running with ruby-tls. However, from time to time (and quite often if I'm running them all at once) I'm getting errors, which seems to be due to the way the handshake is processed.

I've also implemented my client with ruby-tls, and I'm sure that the error is there (server with ruby-tls seems to work fine when ussing openssl as client). So, my client is only able to send requests after having an enabled ssl connection, which in my case means "handshake has been complete":

def initialize(...)
 ...
  @handshake_completed = false
  io_read_write until @handshake_completed
end
...
def handshake_cb(protocol)
  @handshake_completed = true
  puts "handshake completed: #{protocol.inspect}"
end

I get then two different logs, for when it succeeds and when it fails (gonna copy the relevant part only):

# it succeeds
client: handshake completed: :h2
client: encrypted: "\x16\x03\x03\x01\x06\x10...."
client: written 318 bytes
server: encrypted: "\x16\x03\x03\x00\xAA...."
client: frame was sent!
client: {:type=>:settings, :stream=>0, :payload=>[[:settings_max_concurrent_streams, 100]]}
client: frame was sent!
client: {:type=>:headers, :flags=>[:end_headers, :end_stream], :payload=>[["accept", "*/*"], [":scheme", "https"], [":method", "GET"], [":path", "/"]], :stream=>1}
client response (HTTP/2) (stream {1): is half closed
client: read 226 bytes
client: encrypted: "\x17\x03\x03\x00P\x00..."
....


# it fails
client: handshake completed: :h2
client: encrypted: "\x16\x03\x03\x01\x06..."
client: written 318 bytes
client: frame was sent!
client: {:type=>:settings, :stream=>0, :payload=>[[:settings_max_concurrent_streams, 100]]}
client: frame was sent!
client: {:type=>:headers, :flags=>[:end_headers, :end_stream], :payload=>[["accept", "*/*"], ["accept-encoding", "deflate"], [":scheme", "https"], [":method", "GET"], [":path", "/"]], :stream=>1}
client response (HTTP/2) (stream {1): is half closed
server: encrypted: "\x16\x03\x03\x00\xAA...."
client: read 226 bytes
client: shutdown

so, in both cases, what happens is: after the handshake has been completed, it sends some payload to the server (I assume this is the change cipher message from the spec?). But after, I proceed to start building buffering tls packets without processing the last ssl handshake message coming from the server, which is (probably) invalidating my already build TLS packets, and then boom, shutdown.

I think that the handshake should only be considered complete after those last tls messages, and then my assertion io_read_write until @handshake_completed could be considered valid. Either that or I need a different method/variable/callback to tell me if handshake is really over.

I've looked at the source code and I didn't find it. Is there a way to signal to usercode when the change-cipher dance is over?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions