From 30810318020c2c40ad9c04e4c95d445dbbe157c3 Mon Sep 17 00:00:00 2001 From: Attila Molnar Date: Wed, 4 Mar 2015 20:05:00 +0100 Subject: Add writev() wrapper for Windows --- win/inspircd_win32wrapper.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'win') diff --git a/win/inspircd_win32wrapper.h b/win/inspircd_win32wrapper.h index a19bdf857..361724a2f 100644 --- a/win/inspircd_win32wrapper.h +++ b/win/inspircd_win32wrapper.h @@ -218,3 +218,20 @@ private: // Same value as EXIT_STATUS_FORK (EXIT_STATUS_FORK is unused on Windows) #define EXIT_STATUS_SERVICE 4 + +// Windows WSABUF with POSIX field names +struct WindowsIOVec +{ + // POSIX iovec has iov_base then iov_len, WSABUF in Windows has the fields in reverse order + u_long iov_len; // Number of bytes to transfer + char FAR* iov_base; // Starting address +}; + +inline ssize_t writev(int fd, const WindowsIOVec* iov, int count) +{ + DWORD sent; + int ret = WSASend(fd, reinterpret_cast(const_cast(iov)), count, &sent, 0, NULL, NULL); + if (ret == 0) + return sent; + return -1; +} -- cgit v1.2.3 From e0e1becc2f9129203966e69b2919582c11ab86f7 Mon Sep 17 00:00:00 2001 From: Attila Molnar Date: Wed, 4 Mar 2015 20:18:37 +0100 Subject: Add SocketEngine::WriteV() --- include/socketengine.h | 35 +++++++++++++++++++++++++++++++++++ src/inspsocket.cpp | 10 +--------- src/socketengine.cpp | 27 +++++++++++++++++++++++++++ win/inspircd_win32wrapper.h | 7 +++++++ 4 files changed, 70 insertions(+), 9 deletions(-) (limited to 'win') diff --git a/include/socketengine.h b/include/socketengine.h index 895457b89..f30289913 100644 --- a/include/socketengine.h +++ b/include/socketengine.h @@ -29,6 +29,14 @@ #include "socket.h" #include "base.h" +#ifndef _WIN32 +#include +#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. diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp index ee5287e5f..db005b1a1 100644 --- a/src/inspsocket.cpp +++ b/src/inspsocket.cpp @@ -25,14 +25,6 @@ #include "inspircd.h" #include "iohook.h" -#ifndef DISABLE_WRITEV -#include -#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) diff --git a/src/socketengine.cpp b/src/socketengine.cpp index 1c91ccdea..eadfc73d3 100644 --- a/src/socketengine.cpp +++ b/src/socketengine.cpp @@ -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(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(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); diff --git a/win/inspircd_win32wrapper.h b/win/inspircd_win32wrapper.h index 361724a2f..013d4d154 100644 --- a/win/inspircd_win32wrapper.h +++ b/win/inspircd_win32wrapper.h @@ -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 { -- cgit v1.2.3 From 08ea4d3e2a6f438d80a56ba5961f7afa6dddcd42 Mon Sep 17 00:00:00 2001 From: Attila Molnar Date: Wed, 4 Mar 2015 20:21:45 +0100 Subject: Remove DISABLE_WRITEV and StreamSocket code for platforms lacking writev() support --- src/inspsocket.cpp | 39 +-------------------------------------- win/inspircd_win32wrapper.h | 2 -- 2 files changed, 1 insertion(+), 40 deletions(-) (limited to 'win') diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp index db005b1a1..c9f8252f0 100644 --- a/src/inspsocket.cpp +++ b/src/inspsocket.cpp @@ -217,9 +217,7 @@ void StreamSocket::DoWrite() return; } -#ifndef DISABLE_WRITEV if (GetIOHook()) -#endif { int rv = -1; try @@ -246,7 +244,7 @@ void StreamSocket::DoWrite() } std::string& front = sendq.front(); int itemlen = front.length(); - if (GetIOHook()) + { rv = GetIOHook()->OnStreamSocketWrite(this, front); if (rv > 0) @@ -270,39 +268,6 @@ void StreamSocket::DoWrite() return; } } -#ifdef DISABLE_WRITEV - else - { - rv = SocketEngine::Send(this, front.data(), itemlen, 0); - if (rv == 0) - { - SetError("Connection closed"); - return; - } - else if (rv < 0) - { - if (errno == EINTR || SocketEngine::IgnoreError()) - SocketEngine::ChangeEventMask(this, FD_WANT_FAST_WRITE | FD_WRITE_WILL_BLOCK); - else - SetError(SocketEngine::LastError()); - return; - } - else if (rv < itemlen) - { - SocketEngine::ChangeEventMask(this, FD_WANT_FAST_WRITE | FD_WRITE_WILL_BLOCK); - front.erase(0, rv); - sendq_len -= rv; - return; - } - else - { - sendq_len -= itemlen; - sendq.pop_front(); - if (sendq.empty()) - SocketEngine::ChangeEventMask(this, FD_WANT_EDGE_WRITE); - } - } -#endif } } catch (CoreException& modexcept) @@ -311,7 +276,6 @@ void StreamSocket::DoWrite() modexcept.GetSource().c_str(), modexcept.GetReason().c_str()); } } -#ifndef DISABLE_WRITEV else { // don't even try if we are known to be blocking @@ -404,7 +368,6 @@ void StreamSocket::DoWrite() SocketEngine::ChangeEventMask(this, eventChange); } } -#endif } void StreamSocket::WriteData(const std::string &data) diff --git a/win/inspircd_win32wrapper.h b/win/inspircd_win32wrapper.h index 013d4d154..2218d9300 100644 --- a/win/inspircd_win32wrapper.h +++ b/win/inspircd_win32wrapper.h @@ -199,8 +199,6 @@ CoreExport void closedir(DIR * handle); void * ::operator new(size_t iSize); void ::operator delete(void * ptr); -#define DISABLE_WRITEV - #include class CWin32Exception : public std::exception -- cgit v1.2.3