]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Add SocketEngine::WriteV()
authorAttila Molnar <attilamolnar@hush.com>
Wed, 4 Mar 2015 19:18:37 +0000 (20:18 +0100)
committerAttila Molnar <attilamolnar@hush.com>
Wed, 4 Mar 2015 19:18:37 +0000 (20:18 +0100)
include/socketengine.h
src/inspsocket.cpp
src/socketengine.cpp
win/inspircd_win32wrapper.h

index 895457b89191034666b11ba9bcc89dce367c4882..f30289913b8b929008c08281e02c57cc12759e11 100644 (file)
 #include "socket.h"
 #include "base.h"
 
+#ifndef _WIN32
+#include <sys/uio.h>
+#endif
+
+#ifndef IOV_MAX
+#define IOV_MAX 1024
+#endif
+
 /** Types of event an EventHandler may receive.
  * EVENT_READ is a readable file descriptor,
  * and EVENT_WRITE is a writeable file descriptor.
@@ -306,6 +314,12 @@ class CoreExport SocketEngine
        }
 
 public:
+#ifndef _WIN32
+       typedef iovec IOVector;
+#else
+       typedef WindowsIOVec IOVector;
+#endif
+
        /** Constructor.
         * The constructor transparently initializes
         * the socket engine which the ircd is using.
@@ -434,6 +448,27 @@ public:
         */
        static int Send(EventHandler* fd, const void *buf, size_t len, int flags);
 
+       /** Abstraction for vector write function writev().
+        * This function should emulate its namesake system call exactly.
+        * @param fd EventHandler to send data with
+        * @param iov Array of IOVectors containing the buffers to send and their lengths in the platform's
+        * native format.
+        * @param count Number of elements in iov.
+        * @return This method should return exactly the same values as the system call it emulates.
+        */
+       static int WriteV(EventHandler* fd, const IOVector* iov, int count);
+
+#ifdef _WIN32
+       /** Abstraction for vector write function writev() that accepts a POSIX format iovec.
+        * This function should emulate its namesake system call exactly.
+        * @param fd EventHandler to send data with
+        * @param iov Array of iovecs containing the buffers to send and their lengths in POSIX format.
+        * @param count Number of elements in iov.
+        * @return This method should return exactly the same values as the system call it emulates.
+        */
+       static int WriteV(EventHandler* fd, const iovec* iov, int count);
+#endif
+
        /** Abstraction for BSD sockets recv(2).
         * This function should emulate its namesake system call exactly.
         * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
index ee5287e5f33888e0cd24b46f0ce68979cf2d33f9..db005b1a128f2552433af1a9dd1bdc10ceb24210 100644 (file)
 #include "inspircd.h"
 #include "iohook.h"
 
-#ifndef DISABLE_WRITEV
-#include <sys/uio.h>
-#endif
-
-#ifndef IOV_MAX
-#define IOV_MAX 1024
-#endif
-
 BufferedSocket::BufferedSocket()
 {
        Timeout = NULL;
@@ -348,7 +340,7 @@ void StreamSocket::DoWrite()
                                        iovecs[i].iov_len = sendq[i].length();
                                        rv_max += sendq[i].length();
                                }
-                               rv = writev(fd, iovecs, bufcount);
+                               rv = SocketEngine::WriteV(this, iovecs, bufcount);
                        }
 
                        if (rv == (int)sendq_len)
index 1c91ccdea0c37f52d6cb5d1ac2c8469bd79004aa..eadfc73d3e7b1bebdfb28afdc3304180d095d814 100644 (file)
@@ -224,6 +224,33 @@ int SocketEngine::SendTo(EventHandler* fd, const void *buf, size_t len, int flag
        return nbSent;
 }
 
+int SocketEngine::WriteV(EventHandler* fd, const IOVector* iovec, int count)
+{
+       int sent = writev(fd->GetFd(), iovec, count);
+       if (sent > 0)
+               stats.Update(0, sent);
+       return sent;
+}
+
+#ifdef _WIN32
+int SocketEngine::WriteV(EventHandler* fd, const iovec* iovec, int count)
+{
+       // On Windows the fields in iovec are not in the order required by the Winsock API; IOVector has
+       // the fields in the correct order.
+       // Create temporary IOVectors from the iovecs and pass them to the WriteV() method that accepts the
+       // platform's native struct.
+       IOVector wiovec[128];
+       count = std::min(count, static_cast<int>(sizeof(wiovec) / sizeof(IOVector)));
+
+       for (int i = 0; i < count; i++)
+       {
+               wiovec[i].iov_len = iovec[i].iov_len;
+               wiovec[i].iov_base = reinterpret_cast<char*>(iovec[i].iov_base);
+       }
+       return WriteV(fd, wiovec, count);
+}
+#endif
+
 int SocketEngine::Connect(EventHandler* fd, const sockaddr *serv_addr, socklen_t addrlen)
 {
        int ret = connect(fd->GetFd(), serv_addr, addrlen);
index 361724a2faa2ff76d82a0c1c1efc5f46d89f803a..013d4d1546317b1fc93bab8e5468c212fb1d7283 100644 (file)
@@ -219,6 +219,13 @@ private:
 // Same value as EXIT_STATUS_FORK (EXIT_STATUS_FORK is unused on Windows)
 #define EXIT_STATUS_SERVICE 4
 
+// POSIX iovec
+struct iovec
+{
+       void* iov_base; // Starting address
+       size_t iov_len; // Number of bytes to transfer
+};
+
 // Windows WSABUF with POSIX field names
 struct WindowsIOVec
 {