]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/socketengine_iocp.cpp
publish "JSON-RPC" interface
[user/henk/code/inspircd.git] / src / socketengine_iocp.cpp
index 1ec70d2893a4afd3ce36819b8a533a86b1266681..89fd8717f8057271c12c8686e6c303f54df9231e 100644 (file)
@@ -32,7 +32,7 @@ IOCPEngine::~IOCPEngine()
 
 bool IOCPEngine::AddFd(EventHandler* eh)
 {
-       int fake_fd = GenerateFd();
+       int fake_fd = GenerateFd(eh->GetFd());
        int is_accept = 0;
        int opt_len = sizeof(int);
        if(fake_fd < 0)
@@ -46,8 +46,9 @@ bool IOCPEngine::AddFd(EventHandler* eh)
        eh->m_writeEvent = 0;
        eh->m_acceptEvent = 0;
 
+       unsigned long completion_key = (ULONG_PTR)eh->m_internalFd;
        /* assign the socket to the completion port */
-       if(!CreateIoCompletionPort((HANDLE)eh->GetFd(), m_completionPort, (ULONG_PTR)eh->m_internalFd, 0))
+       if(!CreateIoCompletionPort((HANDLE)eh->GetFd(), m_completionPort, completion_key, 0))
                return false;
 
        /* set up binding, increase set size */
@@ -97,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);
@@ -124,16 +130,18 @@ void IOCPEngine::WantWrite(EventHandler* eh)
        /* Post event - write begin */
        if(!eh->m_writeEvent)
        {
+               ULONG_PTR completion_key = (ULONG_PTR)eh->m_internalFd;
                Overlapped * ov = new Overlapped(SOCKET_IO_EVENT_WRITE_READY, 0);
                eh->m_writeEvent = (void*)ov;
-               PostQueuedCompletionStatus(m_completionPort, 0, (ULONG_PTR)eh->m_internalFd, &ov->m_overlap);
+               PostQueuedCompletionStatus(m_completionPort, 0, completion_key, &ov->m_overlap);
        }
 }
 
 bool IOCPEngine::PostCompletionEvent(EventHandler * eh, SocketIOEvent type, int param)
 {
        Overlapped * ov = new Overlapped(type, param);
-       return PostQueuedCompletionStatus(m_completionPort, 0, (ULONG_PTR)eh->m_internalFd, &ov->m_overlap);
+       ULONG_PTR completion_key = (ULONG_PTR)eh->m_internalFd;
+       return PostQueuedCompletionStatus(m_completionPort, 0, completion_key, &ov->m_overlap);
 }
 
 void IOCPEngine::PostReadEvent(EventHandler * eh)
@@ -163,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);
@@ -206,11 +219,11 @@ int IOCPEngine::DispatchEvents()
        LPOVERLAPPED overlap;
        Overlapped * ov;
        EventHandler * eh;
-       int intfd;
+       ULONG_PTR intfd;
        int ret;
        unsigned long bytes_recv;
 
-       while(GetQueuedCompletionStatus(m_completionPort, &len, (PULONG_PTR)&intfd, &overlap, 100))
+       while(GetQueuedCompletionStatus(m_completionPort, &len, &intfd, &overlap, 1000))
        {
                // woot, we got an event on a socket :P
                eh = ref[intfd];
@@ -227,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;
@@ -321,6 +349,13 @@ int __getsockname(SOCKET s, sockaddr * name, int * namelen, void * acceptevent)
        return 0;
 }
 
+int __recvfrom(SOCKET s, char * buf, int len, int flags, struct sockaddr * from, int * fromlen, udp_overlap * ov)
+{
+       memcpy(buf, ov->udp_buffer, ov->udp_len);
+       memcpy(from, ov->udp_sockaddr, *fromlen);
+       return ov->udp_len;
+}
+
 EventHandler * IOCPEngine::GetRef(int fd)
 {
        map<int, EventHandler*>::iterator itr = m_binding.find(fd);