]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Sockets: implement sendmsg()-like functions on Win32
authorEvgeny Grin <k2k@narod.ru>
Sun, 10 Jan 2021 18:36:18 +0000 (21:36 +0300)
committerEvgeny Grin <k2k@narod.ru>
Tue, 16 Feb 2021 11:58:03 +0000 (14:58 +0300)
Use WSASend() to send several buffer per one sys-call.
Unified send()/recv() support for POSIX/Win32.

Signed-off-by: Evgeny Grin <k2k@narod.ru>
lib/state.c
lib/system.h
lib/system/fastopen.c
lib/system/sockets.c

index fcf6183fa4305c2fdc3130936c447fa3a0b42182..4ad46cb4e094b47ede9791f28db52a8c92ca05cb 100644 (file)
@@ -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;
index b7b964fe119deb9eec8b53f3e29050dd6a907806..1e8ca7d070a7ceba02eec4d8b604f3ba28638cc9 100644 (file)
@@ -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);
 
index bf1ee0929f45051f38ecfc41a179a34c1e53e965..55ab2921276fb0bda6a3dbe4fd3b910a711b4875 100644 (file)
@@ -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
 }
 
index a9c1c4398541fb133f26ed6d6b5e14507b21b345..5990d2dfa6d27b27cfc8e97ad3854b31b02494e9 100644 (file)
@@ -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)
 {