summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2015-01-05 15:08:28 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2015-01-05 16:30:42 +0100
commit43082a67c7514d65301d157fb567a133138a85ab (patch)
tree8d626158f3f880c73ee9a129969cebcc3f174011 /lib
parent7be51ddf6b861247e36f9a981739170a168fa712 (diff)
downloadgnutls-43082a67c7514d65301d157fb567a133138a85ab.tar.gz
in DTLS don't use writev() when multiple packets which exceed MTU are queued
That change requires the system_write() to be registered unconditionally, even when writev() is available. Resolves: https://savannah.gnu.org/support/?108715
Diffstat (limited to 'lib')
-rw-r--r--lib/gnutls_buffers.c22
-rw-r--r--lib/gnutls_state.c3
-rw-r--r--lib/system.c11
-rw-r--r--lib/system.h3
4 files changed, 27 insertions, 12 deletions
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index 24e52b1b96..ef2ad236b3 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -460,14 +460,30 @@ _gnutls_writev_emu(gnutls_session_t session, gnutls_transport_ptr_t fd,
static ssize_t
_gnutls_writev(gnutls_session_t session, const giovec_t * giovec,
- int giovec_cnt)
+ unsigned giovec_cnt)
{
int i;
+ bool is_dtls = IS_DTLS(session);
+ bool no_writev = 0;
gnutls_transport_ptr_t fd = session->internals.transport_send_ptr;
reset_errno(session);
- if (session->internals.push_func != NULL)
+ /* In DTLS we use writev() only when the total sum is less than
+ * the MTU. */
+
+ if (is_dtls && giovec_cnt > 1) {
+ unsigned sum = 0, j;
+ for (j = 0; j < giovec_cnt; j++) {
+ sum += giovec[j].iov_len;
+ }
+
+ if (sum > session->internals.dtls.mtu) {
+ no_writev = 1;
+ }
+ }
+
+ if (session->internals.push_func != NULL || no_writev != 0)
i = _gnutls_writev_emu(session, fd, giovec, giovec_cnt);
else
i = session->internals.vec_push_func(fd, giovec,
@@ -477,7 +493,7 @@ _gnutls_writev(gnutls_session_t session, const giovec_t * giovec,
int err = get_errno(session);
_gnutls_debug_log("errno: %d\n", err);
- return errno_to_gerr(err, IS_DTLS(session));
+ return errno_to_gerr(err, is_dtls);
}
return i;
}
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
index 623e9cfd5e..c964822bcb 100644
--- a/lib/gnutls_state.c
+++ b/lib/gnutls_state.c
@@ -376,9 +376,8 @@ int gnutls_init(gnutls_session_t * session, unsigned int flags)
#ifdef HAVE_WRITEV
gnutls_transport_set_vec_push_function(*session, system_writev);
-#else
- gnutls_transport_set_push_function(*session, system_write);
#endif
+ gnutls_transport_set_push_function(*session, system_write);
(*session)->internals.pull_timeout_func = system_recv_timeout;
(*session)->internals.pull_func = system_read;
(*session)->internals.errno_func = system_errno;
diff --git a/lib/system.c b/lib/system.c
index d866e19aa3..9504cfe8c6 100644
--- a/lib/system.c
+++ b/lib/system.c
@@ -60,6 +60,12 @@ static HMODULE Crypt32_dll;
/* System specific function wrappers.
*/
+ssize_t
+system_write(gnutls_transport_ptr ptr, const void *data, size_t data_size)
+{
+ return send(GNUTLS_POINTER_TO_INT(ptr), data, data_size, 0);
+}
+
#ifdef _WIN32
/* Do not use the gnulib functions for sending and receiving data.
* Using them makes gnutls only working with gnulib applications.
@@ -94,11 +100,6 @@ int system_errno(gnutls_transport_ptr p)
return ret;
}
-ssize_t
-system_write(gnutls_transport_ptr ptr, const void *data, size_t data_size)
-{
- return send(GNUTLS_POINTER_TO_INT(ptr), data, data_size, 0);
-}
#else /* POSIX */
int system_errno(gnutls_transport_ptr_t ptr)
{
diff --git a/lib/system.h b/lib/system.h
index d94b1564ee..f9b067538c 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -42,10 +42,9 @@
int system_errno(gnutls_transport_ptr_t);
int system_recv_timeout(gnutls_transport_ptr_t ptr, unsigned int ms);
-#ifdef _WIN32
ssize_t system_write(gnutls_transport_ptr_t ptr, const void *data,
size_t data_size);
-#else
+#ifndef _WIN32
#define HAVE_WRITEV
ssize_t system_writev(gnutls_transport_ptr_t ptr, const giovec_t * iovec,
int iovec_cnt);