TLS1.3 requires handling "spurious reads"

With TLS1.3 the socket can indicate data is available even when there is no application data. This commit ignores a 0-byte read when no data is required. Long-term, handling short reads/writes in TCP mode need to be handled completely differently, but that is a story for another day.

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-01-31 17:25:16 +01:00
parent b8329ce206
commit 228aa71967
6 changed files with 21 additions and 13 deletions

View file

@ -36,7 +36,7 @@ typedef struct ddsi_tran_qos * ddsi_tran_qos_t;
/* Function pointer types */ /* Function pointer types */
typedef ssize_t (*ddsi_tran_read_fn_t) (ddsi_tran_conn_t, unsigned char *, size_t, nn_locator_t *); typedef ssize_t (*ddsi_tran_read_fn_t) (ddsi_tran_conn_t, unsigned char *, size_t, bool, nn_locator_t *);
typedef ssize_t (*ddsi_tran_write_fn_t) (ddsi_tran_conn_t, const nn_locator_t *, size_t, const os_iovec_t *, uint32_t); typedef ssize_t (*ddsi_tran_write_fn_t) (ddsi_tran_conn_t, const nn_locator_t *, size_t, const os_iovec_t *, uint32_t);
typedef int (*ddsi_tran_locator_fn_t) (ddsi_tran_base_t, nn_locator_t *); typedef int (*ddsi_tran_locator_fn_t) (ddsi_tran_base_t, nn_locator_t *);
typedef bool (*ddsi_tran_supports_fn_t) (int32_t); typedef bool (*ddsi_tran_supports_fn_t) (int32_t);
@ -220,8 +220,8 @@ inline int ddsi_conn_locator (ddsi_tran_conn_t conn, nn_locator_t * loc) {
inline ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const os_iovec_t *iov, uint32_t flags) { inline ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const os_iovec_t *iov, uint32_t flags) {
return conn->m_closed ? -1 : (conn->m_write_fn) (conn, dst, niov, iov, flags); return conn->m_closed ? -1 : (conn->m_write_fn) (conn, dst, niov, iov, flags);
} }
inline ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc) { inline ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc) {
return conn->m_closed ? -1 : conn->m_read_fn (conn, buf, len, srcloc); return conn->m_closed ? -1 : conn->m_read_fn (conn, buf, len, allow_spurious, srcloc);
} }
bool ddsi_conn_peer_locator (ddsi_tran_conn_t conn, nn_locator_t * loc); bool ddsi_conn_peer_locator (ddsi_tran_conn_t conn, nn_locator_t * loc);
void ddsi_conn_disable_multiplexing (ddsi_tran_conn_t conn); void ddsi_conn_disable_multiplexing (ddsi_tran_conn_t conn);

View file

@ -63,7 +63,7 @@ static char *ddsi_raweth_to_string (ddsi_tran_factory_t tran, char *dst, size_t
return dst; return dst;
} }
static ssize_t ddsi_raweth_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc) static ssize_t ddsi_raweth_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc)
{ {
int err; int err;
ssize_t ret; ssize_t ret;
@ -71,6 +71,7 @@ static ssize_t ddsi_raweth_conn_read (ddsi_tran_conn_t conn, unsigned char * buf
struct sockaddr_ll src; struct sockaddr_ll src;
struct iovec msg_iov; struct iovec msg_iov;
socklen_t srclen = (socklen_t) sizeof (src); socklen_t srclen = (socklen_t) sizeof (src);
(void) allow_spurious;
msg_iov.iov_base = (void*) buf; msg_iov.iov_base = (void*) buf;
msg_iov.iov_len = len; msg_iov.iov_len = len;

View file

@ -395,7 +395,7 @@ static int err_is_AGAIN_or_WOULDBLOCK (int err)
return 0; return 0;
} }
static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc) static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc)
{ {
ddsi_tcp_conn_t tcp = (ddsi_tcp_conn_t) conn; ddsi_tcp_conn_t tcp = (ddsi_tcp_conn_t) conn;
ssize_t (*rd) (ddsi_tcp_conn_t, void *, size_t, int * err) = ddsi_tcp_conn_read_plain; ssize_t (*rd) (ddsi_tcp_conn_t, void *, size_t, int * err) = ddsi_tcp_conn_read_plain;
@ -436,10 +436,10 @@ static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s
{ {
if (err_is_AGAIN_or_WOULDBLOCK (err)) if (err_is_AGAIN_or_WOULDBLOCK (err))
{ {
if (ddsi_tcp_select (tcp->m_sock, true, pos) == false) if (allow_spurious && pos == 0)
{ return 0;
else if (ddsi_tcp_select (tcp->m_sock, true, pos) == false)
break; break;
}
} }
else else
{ {

View file

@ -31,7 +31,7 @@ extern inline int ddsi_tran_locator (ddsi_tran_base_t base, nn_locator_t * loc);
extern inline int ddsi_listener_locator (ddsi_tran_listener_t listener, nn_locator_t * loc); extern inline int ddsi_listener_locator (ddsi_tran_listener_t listener, nn_locator_t * loc);
extern inline int ddsi_listener_listen (ddsi_tran_listener_t listener); extern inline int ddsi_listener_listen (ddsi_tran_listener_t listener);
extern inline ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listener); extern inline ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listener);
extern inline ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc); extern inline ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc);
extern inline ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const os_iovec_t *iov, uint32_t flags); extern inline ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const os_iovec_t *iov, uint32_t flags);
void ddsi_factory_add (ddsi_tran_factory_t factory) void ddsi_factory_add (ddsi_tran_factory_t factory)

View file

@ -48,7 +48,7 @@ static struct ddsi_udp_config ddsi_udp_config_g;
static struct ddsi_tran_factory ddsi_udp_factory_g; static struct ddsi_tran_factory ddsi_udp_factory_g;
static os_atomic_uint32_t ddsi_udp_init_g = OS_ATOMIC_UINT32_INIT(0); static os_atomic_uint32_t ddsi_udp_init_g = OS_ATOMIC_UINT32_INIT(0);
static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc) static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, bool allow_spurious, nn_locator_t *srcloc)
{ {
int err; int err;
ssize_t ret; ssize_t ret;
@ -56,6 +56,7 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s
os_sockaddr_storage src; os_sockaddr_storage src;
os_iovec_t msg_iov; os_iovec_t msg_iov;
socklen_t srclen = (socklen_t) sizeof (src); socklen_t srclen = (socklen_t) sizeof (src);
(void) allow_spurious;
msg_iov.iov_base = (void*) buf; msg_iov.iov_base = (void*) buf;
msg_iov.iov_len = (os_iov_len_t)len; /* Windows uses unsigned, POSIX (except Linux) int */ msg_iov.iov_len = (os_iov_len_t)len; /* Windows uses unsigned, POSIX (except Linux) int */

View file

@ -2970,7 +2970,13 @@ static bool do_packet
/* Read in DDSI header plus MSG_LEN sub message that follows it */ /* Read in DDSI header plus MSG_LEN sub message that follows it */
sz = ddsi_conn_read (conn, buff, stream_hdr_size, &srcloc); sz = ddsi_conn_read (conn, buff, stream_hdr_size, true, &srcloc);
if (sz == 0)
{
/* Spurious read -- which at this point is still ok */
nn_rmsg_commit (rmsg);
return true;
}
/* Read in remainder of packet */ /* Read in remainder of packet */
@ -2998,7 +3004,7 @@ static bool do_packet
} }
else else
{ {
sz = ddsi_conn_read (conn, buff + stream_hdr_size, ml->length - stream_hdr_size, NULL); sz = ddsi_conn_read (conn, buff + stream_hdr_size, ml->length - stream_hdr_size, false, NULL);
if (sz > 0) if (sz > 0)
{ {
sz = (ssize_t) ml->length; sz = (ssize_t) ml->length;
@ -3010,7 +3016,7 @@ static bool do_packet
{ {
/* Get next packet */ /* Get next packet */
sz = ddsi_conn_read (conn, buff, buff_len, &srcloc); sz = ddsi_conn_read (conn, buff, buff_len, true, &srcloc);
} }
if (sz > 0 && !gv.deaf) if (sz > 0 && !gv.deaf)