glyph: looks like it also doesn't handle pipelining HTTP requests - possibly related
terrycojones joined the channel
glyph
vdog: Pipelined HTTP requests are explicitly disabled.
vdog: do you have that poc yet?
vdog
glyph: Using openssl s_client won't work, due to the primitave way it handles user input, so I have to write C code
ugh
glyph
vdog: feel free to take your existing crummy C example and just attach it to a ticket :). You can always clean it up later
vdog
it's a 10 file C project
not suited for a bug report
glyph
ah. gotcha.
I should note that in that header file, even the definition references DTLS - this is not a TLS feature :)
vdog
glyph: I didn't write it
jcline joined the channel
glyph: Ugh... also doesn't happen with my BIO based C example
glyph
vdog: Can you make it happen with an SSLSocket-based C example?
runciter joined the channel
runciter: welcome back!
vdog
glyph: I don't have one
runciter
glyph: :)
glyph
vdog: Oh. So your other C example is just "way more complex" not "not using BIOs"?
vdog
my other C example is not an example, its a big program
I'm trying to avoid all the crap of establishing a socket
runciter
can you extract the ssl heartbeat/write bits?
vdog
so I grabbed the example openssl code, but it uses BIOs
extract the bits?
I could give you a wireshark trace
runciter
vdog: oh sorry i mean the C code that writes immediately after sending a heartbeat
glyph
vdog: How are you getting the data into Twisted?
vdog
let me see if the BIO is setting TCP_NODELAY
I have a C program that opens an SSL connection
its a big program
runciter
vdog: is it something where you can't share its source code?
if it isn't, send it my way
that's really confusingly worded - what i mean is, if its license lets you share its source, i don't mind if it's a big program
i can help produce an SSCCE
glyph
vdog: the big C program is also speaking HTTPS, though, correct?
vdog
glyph: yes
I found new example code, im going to try it out
glyph
vdog: It's possible that the heartbeat is a red herring, and the problem is just the HTTP response layer
vdog: The removal of pipelining and the addition of HTTP/2 resulted in a lot of hacky flow-control stuff people were doing in earlier versions of Twisted, which was always wrong, but sort of worked by accident, suddenly just being a hang
vdog: and the behavior you see is that twisted apparently freezes?
vdog
right, twisted appears to not read any data after the heartbeat
but it does respond to the heartbeat
efphe has quit
runciter
vdog: so what i'm seeing is that the heartbeat causes an exception
this does not appear to depend on the version of libssl
vdog: are you up to filing a ticket?
vdog
hrm, it only occurs in this weird situation
heartbeats, in general, don't cause that
runciter: do you think this is in the python layer?
runciter
vdog: it appears to be an interaction between TLSMemoryBIOProtocol and HTTPChannel
vdog
I see
runciter
vdog: that is, the exception i'm getting
i can't reproduce the hang
vdog
are you doing a wireshark trace?
runciter
yep
vdog
runciter: are you getting the heartbeat and application record in the same packet?
runciter
yep
vdog
but twisted still processes the http request?
runciter
vdog: twisted blows up with an exception
vdog
but can you keep twisted running and have another socket connect?
runciter
oh, sure
the exception is that the HTTPChannel no longer has an associated socket
because twisted sees the socket as closed, so it calls TLSMemoryBIOProtocol's connectionLost, which tries to flush received data out of BIO and upwards into the wrapped protocol, so it calls the wrapped protocol's dataReceived, which eventually hits HTTPChannel.requestReceived, which wants to call getHost, but the socket is gone
i'm going to do a terrible hack
vdog
runciter: I see, yes my example program reacts the same. I think I know the problem
runciter
vdog: oh so it doesn't hang?
because all this means is that a given connection didn't go as planned
vdog
runciter: my example program causes the crash as well, but my big piece of code acts differently
let me dig for a bit
runciter
the rest of the event loop is OK
vdog: hacking out the offending getHost call against the transport in HTTPChannel.reqeuestReceived lets twisted receive part3
but it closes the connection on the client
vdog
I think the problem with the example program is that the receive fails, the program exits, and the socket is killed
vdog: we want to print the error that SSL_read encountered on line 269
vdog
there, that makes them client/server deadlock
runciter: ok, I don't think it matters, but sure
this is a server side problem, I am almost certain
runciter
vdog: when you write C, you *always* need to check error conditions
vdog: ok, so one thing is you are using non-blocking sockets in your C code but you have no select(2) or poll(2) calls
vdog: consequently part 3 (line 269) fails with SSL_ERROR_WANT_READ
vdog
i thought this was blocking
runciter
and your program fails
vdog
i just copy pasted this
runciter
ok
vdog
this should be blocking..
runciter
vdog: it appears to be - i made a bad assumption
vdog: sorry, it's been a little while, but i believe the man page of SSL_get_error is helpful here
vdog
I'm working on it
runciter
Any TLS/SSL I/O function can lead to either of SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE. In particular, SSL_read() or SSL_peek() may want to write
data and SSL_write() may want to read data.
vdog
but, wireshark shows the packet being delivered
for me
runciter
wireshark also shows that the client sends an RST
vdog
did you use the new code?
runciter
no, but you didn't fix the problem of not handling the error condition from SSL_read in the new code
vdog
it doesn't matter
runciter
it does matter
vdog
calling SSL_read will not compel the server to send bytes
runciter
yes, it will
vdog
no, it won't
runciter
if there's a new handshake that needs to occur
vdog
the handshake is complete
once SSL_write completes, the data is sent, that is the contract
after that, it is up to the server to make a response hit the wire
sure, error checking on read is what you do in the real world, but it won't make the server put a response on the wire
at least not in this situation
runciter
so the difference is that you retry the read while the return code is less than 0?
vdog
yeah
it keeps the program from dying, which caused the RST packet
which is how you would handle most of the errors that come out of SSL_read anyways
except that you wait on epoll or whateverr
runciter
vdog: ok, so a couple of things
vdog: one thing is that it's only correct to retry the read if you got an SSL_ERROR_WANT_READ/_WRITE; it happens that this is what SSL_read returns, so it's the correct thing to do