diff options
-rw-r--r-- | include/socketengine_iocp.h | 21 | ||||
-rw-r--r-- | src/dns.cpp | 10 | ||||
-rw-r--r-- | src/socketengine_iocp.cpp | 43 |
3 files changed, 62 insertions, 12 deletions
diff --git a/include/socketengine_iocp.h b/include/socketengine_iocp.h index 615c44fd7..5de7af03f 100644 --- a/include/socketengine_iocp.h +++ b/include/socketengine_iocp.h @@ -14,7 +14,7 @@ #ifndef __SOCKETENGINE_IOCP__ #define __SOCKETENGINE_IOCP__ -#define READ_BUFFER_SIZE 500 +#define READ_BUFFER_SIZE 600 #define USING_IOCP 1 #include "inspircd_config.h" @@ -37,7 +37,11 @@ class Overlapped public: OVERLAPPED m_overlap; SocketIOEvent m_event; - int m_params; +#ifdef WIN64 + unsigned __int64 m_params; +#else + unsigned long m_params; +#endif Overlapped(SocketIOEvent ev, int params) : m_event(ev), m_params(params) { @@ -45,6 +49,14 @@ class Overlapped } }; +struct udp_overlap +{ + unsigned char udp_buffer[600]; + unsigned long udp_len; + sockaddr udp_sockaddr[2]; + unsigned long udp_sockaddr_len; +}; + struct accept_overlap { int socket; @@ -173,6 +185,11 @@ public: * @return A pointer to the event handler, or NULL */ EventHandler* GetIntRef(int fd); + + /** Holds the preallocated buffer passed to WSARecvFrom
+ * function. Yes, I know, it's a dirty hack.
+ */
+ udp_overlap * udp_ov;
}; //typedef void(*OpHandler)(EventHandler) diff --git a/src/dns.cpp b/src/dns.cpp index 99b156bf1..2d8fdeb65 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -29,6 +29,7 @@ looks like this, walks like this or tastes like this. #include <arpa/inet.h> #else #include "inspircd_win32wrapper.h" +#include "inspircd_se_config.h" #endif #include "dns.h" @@ -623,8 +624,15 @@ DNSResult DNS::GetResult() #endif const char* ipaddr_from; unsigned short int port_from = 0; - +#ifdef USING_IOCP + /** Dirty hack for IOCP UDP sockets **/ + udp_overlap * ov = ((IOCPEngine*)ServerInstance->SE)->udp_ov; + memcpy(buffer, ov->udp_buffer, ov->udp_len); + memcpy(from, ov->udp_sockaddr, ov->udp_sockaddr_len); + int length = ov->udp_len; +#else int length = recvfrom(this->GetFd(),(char*)buffer,sizeof(DNSHeader),0,from,&x); +#endif /* Did we get the whole header? */ if (length < 12) diff --git a/src/socketengine_iocp.cpp b/src/socketengine_iocp.cpp index 82462f8b9..8144c8be2 100644 --- a/src/socketengine_iocp.cpp +++ b/src/socketengine_iocp.cpp @@ -98,7 +98,12 @@ bool IOCPEngine::DelFd(EventHandler* eh, bool force /* = false */) /* Free the buffer, and delete the event. */ if(eh->m_readEvent != 0) + { + if(((Overlapped*)eh->m_readEvent)->m_params != 0) + delete ((udp_overlap*)((Overlapped*)eh->m_readEvent)->m_params); + delete ((Overlapped*)eh->m_readEvent); + } if(eh->m_writeEvent != 0) delete ((Overlapped*)eh->m_writeEvent); @@ -166,10 +171,15 @@ void IOCPEngine::PostReadEvent(EventHandler * eh) { case SOCK_DGRAM: /* UDP Socket */ { - if(WSARecvFrom(eh->GetFd(), &buf, 1, &r_length, &flags, 0, 0, &ov->m_overlap, 0)) + udp_overlap * uv = new udp_overlap; + uv->udp_sockaddr_len = sizeof(sockaddr); + buf.buf = (char*)uv->udp_buffer; + buf.len = sizeof(uv->udp_buffer); + ov->m_params = (unsigned long)uv; + if(WSARecvFrom(eh->GetFd(), &buf, 1, &uv->udp_len, &flags, uv->udp_sockaddr, (LPINT)&uv->udp_sockaddr_len, &ov->m_overlap, 0)) { int err = WSAGetLastError(); - if(WSAGetLastError() != WSA_IO_PENDING) + if(err != WSA_IO_PENDING) { delete ov; PostCompletionEvent(eh, SOCKET_IO_EVENT_ERROR, 0); @@ -230,17 +240,32 @@ int IOCPEngine::DispatchEvents() case SOCKET_IO_EVENT_READ_READY: { - ret = ioctlsocket(eh->GetFd(), FIONREAD, &bytes_recv); - eh->m_readEvent = 0; - if(ret != 0 || bytes_recv == 0) + if(ov->m_params) { - /* end of file */ - PostCompletionEvent(eh, SOCKET_IO_EVENT_ERROR, EIO); /* Old macdonald had an error, EIEIO. */ + // if we had params, it means we are a udp socket with a udp_overlap pointer in this long. + udp_overlap * uv = (udp_overlap*)ov->m_params; + uv->udp_len = len; + this->udp_ov = uv; + eh->m_readEvent = 0; + eh->HandleEvent(EVENT_READ, 0); + this->udp_ov = 0; + delete uv; + PostReadEvent(eh); } else { - eh->HandleEvent(EVENT_READ, 0); - PostReadEvent(eh); + ret = ioctlsocket(eh->GetFd(), FIONREAD, &bytes_recv); + eh->m_readEvent = 0; + if(ret != 0 || bytes_recv == 0) + { + /* end of file */ + PostCompletionEvent(eh, SOCKET_IO_EVENT_ERROR, EIO); /* Old macdonald had an error, EIEIO. */ + } + else + { + eh->HandleEvent(EVENT_READ, 0); + PostReadEvent(eh); + } } } break; |