This patch splits common part out to avoid copy-paste from the
- bufferevent_openssl.c
- bufferevent_mbedtls.c
It uses VFS/bufferevent-like approach, i.e. structure of callbacks.
windows has intptr_t instead of regular int.
Also tt_fd_op() had been introduced, since we cannot use tt_int_op() for
comparing fd, since it is not always int.
From nmathewson/Libevent#83 by @fancycode:
There are a few code paths where the passed SSL object is not released in error cases, even if BEV_OPT_CLOSE_ON_FREE is passed as option while for others it is released. That way it's impossible for the caller to know it he has to free it on errors himself or not.
Line numbers are from "bufferevent_openssl.c" in 911abf3:
L1414 ("underlying == NULL" passed)
L1416 (bio could not be created)
L1446 (different fd passed)
L1325 (both underlying and fd passed)
L1328 (out-of-memory)
L1333 ("bufferevent_init_common_" failed)
In all error cases after the "bufferevent_ops_openssl" has been assigned, the option is evaluated on "bufferevent_free" (L1399) and the SSL object released (L1226).
Fixes: nmathewson/Libevent#83
If reconnecting the via BEV_CTRL_SET_FD, bufferevent_openssl.c expects
OpenSSL to reuse the configuration state in the SSL object but retain
connection state. This corresponds to the SSL_clear API.
The code currently only calls SSL_set_connect_state or
SSL_set_accept_state. Due to a quirk in OpenSSL, doing this causes the
handshake to implicitly SSL_clear the next time it is entered. However,
this, in the intervening time, leaves the SSL object in an odd state as
the connection state has not been dropped yet. This behavior also does
not appear to be documented by OpenSSL.
Instead, call SSL_clear explicitly:
https://www.openssl.org/docs/manmaster/man3/SSL_clear.html
The main problems was due to when bufferevent_openssl has underlying (i.e.
created with bufferevent_openssl_filter_new()) some events was
disabled/suspended, while with openssl, READ can require WRITE and vice-versa
hence this issues.
The BEV_CTRL_GET_FD hunk to fix http subsystem, since it depends from what
bufferevent_getfd() returns.
Fixes: #428
Fixes: ssl/bufferevent_filter_write_after_connect
Fixes: http/https_filter_chunk_out
Fixes: da52933550fd4736aa1c213b6de497e2ffc31e34 ("be_openssl: don't call
do_write() directly from outbuf_cb")
For example if you trying to issue multiple requests over the same
evhttp_conneciton, and if connection already closed (IOW it should be
re-connected), than you will get into trouble since it will got wrong
openssl state. This patch addresses this issue by restoring state to
initial if SETFD called with -1 fd.
So move all of the declarations to the top of the offending function.
This patch includes both of issues (Fixes:), from @jeking3 and
@pprindeville
Fixes: #418Fixes: nmathewson/Libevent#136
OpenSSL doesn't document the behaviour of these functions when given a
NULL BIO, and it happens to return zero at the moment. But don't depend
on that.
Closes: #406 (cherry-picked)
Otherwise we can trigger incorrect callback, the simplest way to trigger this
is using http regression tests -- https_chunk_out, since all it do is:
evhttp_send_reply_end()
evbuffer_add()
do_write()
evhttp_write_buffer()
evcon->cb = cb
And indeed this is what happens:
(gdb) bt
#0 do_write (bev_ssl=0x738a90, atmost=16384) at bufferevent_openssl.c:717
#1 0x00000000004b69f7 in consider_writing (bev_ssl=0x738a90) at bufferevent_openssl.c:875
#2 0x00000000004b7386 in be_openssl_outbuf_cb (buf=0x7387b0, cbinfo=0x7fffffffd590, arg=0x738a90) at bufferevent_openssl.c:1147
#3 0x0000000000490100 in evbuffer_run_callbacks (buffer=0x7387b0, running_deferred=0) at buffer.c:508
#4 0x00000000004901e5 in evbuffer_invoke_callbacks_ (buffer=0x7387b0) at buffer.c:529
#5 0x0000000000493a30 in evbuffer_add (buf=0x7387b0, data_in=0x4ecfb2, datlen=5) at buffer.c:1803
#6 0x00000000004be2e3 in evhttp_send_reply_end (req=0x7371a0) at http.c:2794
#7 0x000000000045c407 in http_chunked_trickle_cb (fd=-1, events=1, arg=0x75aaf0) at regress_http.c:402
...
(gdb) p bev.writecb
$4 = (bufferevent_data_cb) 0x4ba17e <evhttp_write_cb>
$5 = (void *) 0x7379b0
(gdb) p (struct evhttp_connection *)bev.cbarg
$6 = (struct evhttp_connection *) 0x7379b0
(gdb) p $6->cb
$7 = (void (*)(struct evhttp_connection *, void *)) 0x0
And be_sock don't do like this anyway.
Fixes: https_chunk_out
By using bufferevent_enable() there will be no event for READ *or* WRITE if
they are not enabled before, and this patch reduces difference for
be_sock_enable/be_openssl_enable (handshake)
Using the following examples you can get changes between be_openssl and
be_sock:
$ function diff_addr()
{
eval diff -u $(printf "<(strip_addr %s) " "$@")
}
$ function strip_addr()
{
sed 's/0x[a-zA-Z0-9]*/0xFFFF/g' "$@"
}
$ EVENT_DEBUG_LOGGING_ALL= regress --verbose --no-fork +http/https_connection_retry 2> /tmp/https-retry.log >&2
$ EVENT_DEBUG_LOGGING_ALL= regress --verbose --no-fork +http/connection_retry 2> /tmp/http-retry.log >&2
$ diff_addr /tmp/http-retry.log /tmp/https-retry.log
This will split cases when we need to extract fd (cases when we have fd==-1
passed to set_open_callbacks()), and cases when we mustn't have to do this --
SET_FD via be_openssl_ctrl().
This patch is a cleanup and a bug fix, it drops ```fd_is_set``` flag, and
replace it with some checks to event_initialized(), and now we will not call
event_assign() on already added event, plus we will delete event when we really
have to (this patch fixes the case when server is down, IOW before this patch
we will not call event_del() because ```fd_is_set``` was reset to 0) and this
will fix some issues with retries in http layer for ssl.
Reported-in: #258
Fixes: regress ssl/bufferevent_socketpair_timeout
Fixes: regress ssl/bufferevent_socketpair_timeout_freed_fd
Since the bufferevents' events are now EV_FINALIZE (name pending),
they won't deadlock. To clean up properly, though, we must use the
finalization feature.
This patch also split bufferevent deallocation into an "unlink" step
that happens fast, and a "destruct" step that happens after
finalization.
More work is needed: there needs to be a way to specify a finalizer
for the bufferevent's argument itself. Also, this finalizer business
makes lots of the reference counting we were doing unnecessary.
Also, more testing is needed.