diff options
author | Daiki Ueno <ueno@gnu.org> | 2021-02-16 14:27:14 +0000 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2021-02-16 14:27:14 +0000 |
commit | 49c955d26486ef939077e4e6d3f53ef1bd34d9df (patch) | |
tree | f8450d630bf95ca7293d0f11fa4e3efce29cd6a3 | |
parent | 8314ad75b4a99e8b1fa5242607e272e31fc83ec2 (diff) | |
parent | bfd453f39cb6126e561000a711264b2535eefc36 (diff) | |
download | gnutls-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.c | 4 | ||||
-rw-r--r-- | lib/system.h | 3 | ||||
-rw-r--r-- | lib/system/fastopen.c | 12 | ||||
-rw-r--r-- | lib/system/sockets.c | 42 |
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) { |