Fix: Rework SSL poll event handling to avoid infinite loops
The downstream connection callback must only be invoked when the event
that SSL requests for the connection to make progress has actually
occured. Otherwise, the downstream callback might do nothing but
re-queue an unrelated event (e.g. in user_net_io_want_write), and the
event loop comes around instantly while making no progress. Track the
SSL-requested events separately and deliver the required downstream
event when they fire.
Sample strace:
epoll_wait(0, {{EPOLLIN, {u32=96, u64=96}}}, 91, 10000) = 1
: net_ssl_callback in state tls_st_need_write calls cb NET_EVENT_WRITE
: User writes data, OpenSSL tries to write data
write(96, <snip>..., 170) = -1 EAGAIN (Resource temporarily unavailable)
: handle_openssl_error requests NET_EVENT_WRITE
epoll_ctl(0, EPOLL_CTL_MOD, 96, {EPOLLOUT, {u32=96, u64=96}}) = 0
: User callback then requests NET_EVENT_READ|NET_EVENT_WRITE
epoll_ctl(0, EPOLL_CTL_MOD, 96, {EPOLLIN|EPOLLOUT, {u32=96, u64=96}}) =
: Data available for *reading*
epoll_wait(0, {{EPOLLIN, {u32=96, u64=96}}}, 91, 10000) = 1
: net_ssl_callback in state tls_st_need_write calls cb NET_EVENT_WRITE
: again...
This commit is contained in:
committed by
Jan Vidar Krey
parent
9f78a2e85f
commit
0426cb523a
@@ -32,8 +32,6 @@ enum ssl_state
|
||||
tls_st_accepting,
|
||||
tls_st_connecting,
|
||||
tls_st_connected,
|
||||
tls_st_need_read, /* special case of connected */
|
||||
tls_st_need_write, /* special case of connected */
|
||||
tls_st_disconnecting,
|
||||
};
|
||||
|
||||
@@ -90,6 +88,15 @@ extern ssize_t net_con_ssl_connect(struct net_connection*);
|
||||
extern ssize_t net_ssl_send(struct net_connection* con, const void* buf, size_t len);
|
||||
extern ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len);
|
||||
|
||||
/**
|
||||
* Update the event mask. Additional events may be requested depending on the
|
||||
* needs of the TLS layer.
|
||||
*
|
||||
* @param con Connection handle.
|
||||
* @param events Event mask (NET_EVENT_*)
|
||||
*/
|
||||
extern void net_ssl_update(struct net_connection* con, int events);
|
||||
|
||||
extern void net_ssl_shutdown(struct net_connection* con);
|
||||
extern void net_ssl_destroy(struct net_connection* con);
|
||||
extern void net_ssl_callback(struct net_connection* con, int events);
|
||||
|
||||
Reference in New Issue
Block a user