summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-10-12 01:13:51 +0000
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-10-12 01:13:51 +0000
commit170820cc8d09064742b6c2d3d716abac457cd880 (patch)
tree50a83f1ae4244b5f0859bf5b4cbfba5737f20db6
parente4a590c7926b4b9454093f88b2d4d1616b717df2 (diff)
Define DISABLE_WRITEV and use the IOHook single-copy method for Windows send()
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11848 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--src/inspsocket.cpp108
-rw-r--r--win/inspircd_win32wrapper.cpp24
-rw-r--r--win/inspircd_win32wrapper.h9
3 files changed, 77 insertions, 64 deletions
diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp
index c63748eab..d98fa1b61 100644
--- a/src/inspsocket.cpp
+++ b/src/inspsocket.cpp
@@ -15,8 +15,12 @@
#include "socket.h"
#include "inspstring.h"
#include "socketengine.h"
-#ifndef WINDOWS
+
+#ifndef DISABLE_WRITEV
#include <sys/uio.h>
+#ifndef IOV_MAX
+#define IOV_MAX 1024
+#endif
#endif
BufferedSocket::BufferedSocket()
@@ -225,52 +229,90 @@ void StreamSocket::DoWrite()
return;
}
+#ifndef DISABLE_WRITEV
if (IOHook)
+#endif
{
int rv = -1;
try
{
- if (sendq.size() > 1 && sendq[0].length() < 1024)
- {
- // Avoid multiple repeated SSL encryption invocations
- // This adds a single copy of the queue, but avoids
- // much more overhead in terms of system calls invoked
- // by the IOHook.
- //
- // The length limit of 1024 is to prevent merging strings
- // more than once when writes begin to block.
- std::string tmp;
- tmp.reserve(sendq_len);
- for(unsigned int i=0; i < sendq.size(); i++)
- tmp.append(sendq[i]);
- sendq.clear();
- sendq.push_back(tmp);
- }
while (!sendq.empty())
{
- std::string& front = sendq.front();
- int itemlen = front.length();
- rv = IOHook->OnStreamSocketWrite(this, front);
- if (rv > 0)
+ if (sendq.size() > 1 && sendq[0].length() < 1024)
{
- // consumed the entire string, and is ready for more
- sendq_len -= itemlen;
- sendq.pop_front();
+ // Avoid multiple repeated SSL encryption invocations
+ // This adds a single copy of the queue, but avoids
+ // much more overhead in terms of system calls invoked
+ // by the IOHook.
+ //
+ // The length limit of 1024 is to prevent merging strings
+ // more than once when writes begin to block.
+ std::string tmp;
+ tmp.reserve(sendq_len);
+ for(unsigned int i=0; i < sendq.size(); i++)
+ tmp.append(sendq[i]);
+ sendq.clear();
+ sendq.push_back(tmp);
}
- else if (rv == 0)
+ std::string& front = sendq.front();
+ int itemlen = front.length();
+ if (IOHook)
{
- // socket has blocked. Stop trying to send data.
- // IOHook has requested unblock notification from the socketengine
+ rv = IOHook->OnStreamSocketWrite(this, front);
+ if (rv > 0)
+ {
+ // consumed the entire string, and is ready for more
+ sendq_len -= itemlen;
+ sendq.pop_front();
+ }
+ else if (rv == 0)
+ {
+ // socket has blocked. Stop trying to send data.
+ // IOHook has requested unblock notification from the socketengine
- // Since it is possible that a partial write took place, adjust sendq_len
- sendq_len = sendq_len - itemlen + front.length();
- return;
+ // Since it is possible that a partial write took place, adjust sendq_len
+ sendq_len = sendq_len - itemlen + front.length();
+ return;
+ }
+ else
+ {
+ SetError("Write Error"); // will not overwrite a better error message
+ return;
+ }
}
+#ifdef DISABLE_WRITEV
else
{
- SetError("Write Error"); // will not overwrite a better error message
- return;
+ rv = ServerInstance->SE->Send(this, front.data(), itemlen, 0);
+ if (rv == 0)
+ {
+ SetError("Connection closed");
+ return;
+ }
+ else if (rv < 0)
+ {
+ if (errno == EAGAIN || errno == EINTR)
+ ServerInstance->SE->ChangeEventMask(this, FD_WANT_FAST_WRITE | FD_WRITE_WILL_BLOCK);
+ else
+ SetError(strerror(errno));
+ return;
+ }
+ else if (rv < itemlen)
+ {
+ ServerInstance->SE->ChangeEventMask(this, FD_WANT_FAST_WRITE | FD_WRITE_WILL_BLOCK);
+ front = front.substr(itemlen - rv);
+ sendq_len -= rv;
+ return;
+ }
+ else
+ {
+ sendq_len -= itemlen;
+ sendq.pop_front();
+ if (sendq.empty())
+ ServerInstance->SE->ChangeEventMask(this, FD_WANT_EDGE_WRITE);
+ }
}
+#endif
}
}
catch (CoreException& modexcept)
@@ -279,6 +321,7 @@ void StreamSocket::DoWrite()
modexcept.GetSource(), modexcept.GetReason());
}
}
+#ifndef DISABLE_WRITEV
else
{
// don't even try if we are known to be blocking
@@ -368,6 +411,7 @@ void StreamSocket::DoWrite()
ServerInstance->SE->ChangeEventMask(this, eventChange);
}
}
+#endif
}
void StreamSocket::WriteData(const std::string &data)
diff --git a/win/inspircd_win32wrapper.cpp b/win/inspircd_win32wrapper.cpp
index eb73378f2..1309e6064 100644
--- a/win/inspircd_win32wrapper.cpp
+++ b/win/inspircd_win32wrapper.cpp
@@ -147,30 +147,6 @@ const char * dlerror()
return errormessage;
}
-ssize_t writev(int fd, const struct iovec* iov, int iovcnt)
-{
- ssize_t ret;
- size_t tot = 0;
- int i;
- char *buf, *p;
-
- for(i = 0; i < iovcnt; ++i)
- tot += iov[i].iov_len;
- buf = (char*)malloc(tot);
- if (tot != 0 && buf == NULL) {
- errno = ENOMEM;
- return -1;
- }
- p = buf;
- for (i = 0; i < iovcnt; ++i) {
- memcpy (p, iov[i].iov_base, iov[i].iov_len);
- p += iov[i].iov_len;
- }
- ret = send((SOCKET)fd, buf, tot, 0);
- free (buf);
- return ret;
-}
-
#define TRED FOREGROUND_RED | FOREGROUND_INTENSITY
#define TGREEN FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define TYELLOW FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
diff --git a/win/inspircd_win32wrapper.h b/win/inspircd_win32wrapper.h
index 4b9ce80ec..740436d93 100644
--- a/win/inspircd_win32wrapper.h
+++ b/win/inspircd_win32wrapper.h
@@ -229,14 +229,7 @@ class ServerConfig;
/* Look up the nameserver in use from the registry on windows */
CoreExport std::string FindNameServerWin();
-/* no uio.h on win, but win has alternatives in io.h rest is wrapped here */
-#define IOV_MAX 1024
-struct iovec
-{
- size_t iov_len;
- void* iov_base;
-};
-CoreExport ssize_t writev(int fd, const struct iovec* iov, int iovcnt);
+#define DISABLE_WRITEV
/* Clear a windows console */
CoreExport void ClearConsole();