summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2021-02-16 14:27:14 +0000
committerDaiki Ueno <ueno@gnu.org>2021-02-16 14:27:14 +0000
commit49c955d26486ef939077e4e6d3f53ef1bd34d9df (patch)
treef8450d630bf95ca7293d0f11fa4e3efce29cd6a3
parent8314ad75b4a99e8b1fa5242607e272e31fc83ec2 (diff)
parentbfd453f39cb6126e561000a711264b2535eefc36 (diff)
downloadgnutls-49c955d26486ef939077e4e6d3f53ef1bd34d9df.tar.gz
Merge branch 'w32_sendmsg' into 'master'
Sockets: implement sendmsg()-like function on Win32 See merge request gnutls/gnutls!1377
-rw-r--r--lib/state.c4
-rw-r--r--lib/system.h3
-rw-r--r--lib/system/fastopen.c12
-rw-r--r--lib/system/sockets.c42
4 files changed, 46 insertions, 15 deletions
diff --git a/lib/state.c b/lib/state.c
index 9f306faf70..9da3a340e0 100644
--- a/lib/state.c
+++ b/lib/state.c
@@ -588,16 +588,12 @@ int gnutls_init(gnutls_session_t * session, unsigned int flags)
#endif
handshake_internal_state_clear1(*session);
-#ifdef HAVE_WRITEV
#ifdef MSG_NOSIGNAL
if (flags & GNUTLS_NO_SIGNAL)
gnutls_transport_set_vec_push_function(*session, system_writev_nosignal);
else
#endif
gnutls_transport_set_vec_push_function(*session, system_writev);
-#else
- gnutls_transport_set_push_function(*session, system_write);
-#endif
(*session)->internals.pull_timeout_func = gnutls_system_recv_timeout;
(*session)->internals.pull_func = system_read;
(*session)->internals.errno_func = system_errno;
diff --git a/lib/system.h b/lib/system.h
index b7b964fe11..1e8ca7d070 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -52,10 +52,8 @@ extern CertEnumCRLsInStoreFunc pCertEnumCRLsInStore;
int system_errno(gnutls_transport_ptr_t);
-#ifdef _WIN32
ssize_t system_write(gnutls_transport_ptr_t ptr, const void *data,
size_t data_size);
-#else
#define HAVE_WRITEV
ssize_t system_writev(gnutls_transport_ptr_t ptr, const giovec_t * iovec,
int iovec_cnt);
@@ -65,7 +63,6 @@ ssize_t system_writev_tfo(gnutls_session_t ptr, const giovec_t * iovec,
int iovec_cnt);
ssize_t system_writev_nosignal_tfo(gnutls_session_t ptr, const giovec_t * iovec,
int iovec_cnt);
-#endif
ssize_t system_read(gnutls_transport_ptr_t ptr, void *data,
size_t data_size);
diff --git a/lib/system/fastopen.c b/lib/system/fastopen.c
index bf1ee0929f..55ab292127 100644
--- a/lib/system/fastopen.c
+++ b/lib/system/fastopen.c
@@ -55,7 +55,7 @@
#ifdef _WIN32
static ssize_t
-tfo_send(gnutls_transport_ptr_t ptr, const void *buf, size_t len)
+tfo_writev(gnutls_transport_ptr_t ptr, const giovec_t * iovec, int iovec_cnt)
{
tfo_st *p = ptr;
int fd = p->fd;
@@ -63,7 +63,8 @@ tfo_send(gnutls_transport_ptr_t ptr, const void *buf, size_t len)
if (unlikely(p->connect_addrlen != 0)) {
int ret;
- ret = connect(fd, (struct sockaddr*)&p->connect_addr, p->connect_addrlen);
+ ret = connect(fd, (struct sockaddr*)&p->connect_addr,
+ p->connect_addrlen);
if (ret == -1 && (errno == EINPROGRESS)) {
gnutls_assert();
errno = EAGAIN;
@@ -77,7 +78,7 @@ tfo_send(gnutls_transport_ptr_t ptr, const void *buf, size_t len)
return ret;
}
- return send(fd, buf, len, 0);
+ return system_writev(GNUTLS_INT_TO_POINTER(fd), iovec, iovec_cnt);
}
#else /* sendmsg */
static ssize_t
@@ -239,11 +240,6 @@ gnutls_transport_set_fastopen(gnutls_session_t session,
session->internals.tfo.flags |= MSG_NOSIGNAL;
#endif
-#ifdef _WIN32
- gnutls_transport_set_vec_push_function(session, NULL);
- gnutls_transport_set_push_function(session, tfo_send);
-#else
gnutls_transport_set_vec_push_function(session, tfo_writev);
-#endif
}
diff --git a/lib/system/sockets.c b/lib/system/sockets.c
index a9c1c43985..5990d2dfa6 100644
--- a/lib/system/sockets.c
+++ b/lib/system/sockets.c
@@ -79,6 +79,48 @@ system_write(gnutls_transport_ptr ptr, const void *data, size_t data_size)
{
return send(GNUTLS_POINTER_TO_INT(ptr), data, data_size, 0);
}
+
+ssize_t
+system_writev(gnutls_transport_ptr_t ptr, const giovec_t * iovec,
+ int iovec_cnt)
+{
+ WSABUF bufs[iovec_cnt];
+ DWORD bytes_sent;
+ int to_send_cnt = 0;
+ size_t to_send_bytes = 0;
+
+ while (to_send_cnt < iovec_cnt && to_send_bytes < SSIZE_MAX) {
+ bufs[to_send_cnt].buf = iovec[to_send_cnt].iov_base;
+
+ if (to_send_bytes + iovec[to_send_cnt].iov_len > SSIZE_MAX) {
+ /* Return value limit: successful result value cannot
+ * exceed SSIZE_MAX */
+ size_t space_left = (size_t)SSIZE_MAX - to_send_bytes;
+ bufs[to_send_cnt].len = (unsigned long)
+ (space_left > ULONG_MAX ?
+ ULONG_MAX : space_left);
+ to_send_cnt++;
+ break;
+ }
+ if (iovec[to_send_cnt].iov_len > ULONG_MAX) {
+ /* WSASend() limitation */
+ bufs[to_send_cnt].len = ULONG_MAX;
+ to_send_cnt++;
+ break;
+ }
+ bufs[to_send_cnt].len =
+ (unsigned long) iovec[to_send_cnt].iov_len;
+ to_send_bytes += iovec[to_send_cnt].iov_len;
+ to_send_cnt++;
+ }
+
+ if (WSASend(GNUTLS_POINTER_TO_INT(ptr), bufs, to_send_cnt, &bytes_sent,
+ 0, NULL, NULL) != 0)
+ return -1;
+
+ return (ssize_t)bytes_sent;
+}
+
#else /* POSIX */
int system_errno(gnutls_transport_ptr_t ptr)
{