From 30a17a7034a5afce1094479628408a0903c62e17 Mon Sep 17 00:00:00 2001 From: brain Date: Sun, 20 May 2007 13:58:30 +0000 Subject: Remove asserts and convert to unix line endings git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@7064 e03df62e-2008-0410-955e-edbf42e46eb7 --- include/socketengine_iocp.h | 218 +++++++++--------- src/socketengine_iocp.cpp | 542 ++++++++++++++++++++++---------------------- 2 files changed, 380 insertions(+), 380 deletions(-) diff --git a/include/socketengine_iocp.h b/include/socketengine_iocp.h index 1b4db096b..70c342c77 100644 --- a/include/socketengine_iocp.h +++ b/include/socketengine_iocp.h @@ -9,83 +9,83 @@ * the file COPYING for details. * * --------------------------------------------------- - */ - -#ifndef __SOCKETENGINE_IOCP__ -#define __SOCKETENGINE_IOCP__ - -#define READ_BUFFER_SIZE 500 -#define USING_IOCP 1 - -#include "inspircd_config.h" -#include "inspircd_win32wrapper.h" + */ + +#ifndef __SOCKETENGINE_IOCP__ +#define __SOCKETENGINE_IOCP__ + +#define READ_BUFFER_SIZE 500 +#define USING_IOCP 1 + +#include "inspircd_config.h" +#include "inspircd_win32wrapper.h" #include "globals.h" #include "inspircd.h" -#include "socketengine.h" - -enum SocketIOEvent -{ - SOCKET_IO_EVENT_READ_READY = 0, - SOCKET_IO_EVENT_WRITE_READY = 1, - SOCKET_IO_EVENT_ACCEPT = 2, - SOCKET_IO_EVENT_ERROR = 3, - NUM_SOCKET_IO_EVENTS = 4, -}; - -class Overlapped -{ -public: - OVERLAPPED m_overlap; - SocketIOEvent m_event; - int m_params; - Overlapped(SocketIOEvent ev, int params) : m_event(ev), m_params(params) - { - memset(&m_overlap, 0, sizeof(OVERLAPPED)); - } -}; - -struct accept_overlap -{ - int socket; - char buf[1024]; -}; - -class IOCPEngine : public SocketEngine -{ - /** Creates a "fake" file descriptor for use with an IOCP socket. - * @return -1 if there are no free slots, and an integer if it finds one. - */ - __inline int GenerateFd() - { - register int i = 0; - for(; i < MAX_DESCRIPTORS; ++i) - if(ref[i] == 0) - return i; - return -1; - } - - /** Global I/O completion port that sockets attach to. - */ - HANDLE m_completionPort; - - /** This is kinda shitty... :/ for getting an address from a real fd. - */ - map m_binding; - -public: - /** Creates an IOCP Socket Engine - * @param Instance The creator of this object - */ - IOCPEngine(InspIRCd * Instance); - - /** Deletes an IOCP socket engine and all the attached sockets - */ - ~IOCPEngine(); - - /** Adds an event handler to the completion port, and sets up initial events. - * @param eh EventHandler to add - * @return True if success, false if no room - */ +#include "socketengine.h" + +enum SocketIOEvent +{ + SOCKET_IO_EVENT_READ_READY = 0, + SOCKET_IO_EVENT_WRITE_READY = 1, + SOCKET_IO_EVENT_ACCEPT = 2, + SOCKET_IO_EVENT_ERROR = 3, + NUM_SOCKET_IO_EVENTS = 4, +}; + +class Overlapped +{ +public: + OVERLAPPED m_overlap; + SocketIOEvent m_event; + int m_params; + Overlapped(SocketIOEvent ev, int params) : m_event(ev), m_params(params) + { + memset(&m_overlap, 0, sizeof(OVERLAPPED)); + } +}; + +struct accept_overlap +{ + int socket; + char buf[1024]; +}; + +class IOCPEngine : public SocketEngine +{ + /** Creates a "fake" file descriptor for use with an IOCP socket. + * @return -1 if there are no free slots, and an integer if it finds one. + */ + __inline int GenerateFd() + { + register int i = 0; + for(; i < MAX_DESCRIPTORS; ++i) + if(ref[i] == 0) + return i; + return -1; + } + + /** Global I/O completion port that sockets attach to. + */ + HANDLE m_completionPort; + + /** This is kinda shitty... :/ for getting an address from a real fd. + */ + map m_binding; + +public: + /** Creates an IOCP Socket Engine + * @param Instance The creator of this object + */ + IOCPEngine(InspIRCd * Instance); + + /** Deletes an IOCP socket engine and all the attached sockets + */ + ~IOCPEngine(); + + /** Adds an event handler to the completion port, and sets up initial events. + * @param eh EventHandler to add + * @return True if success, false if no room + */ bool AddFd(EventHandler* eh); /** Gets the maximum number of file descriptors that this engine can handle. @@ -124,52 +124,52 @@ public: /** Queues a Write event on the specified event handler. * @param eh EventHandler that needs data sent on */ - void WantWrite(EventHandler* eh); - - /** Posts a completion event on the specified socket. - * @param eh EventHandler for message - * @param type Event Type - * @param param Event Parameter - * @return True if added, false if not - */ - bool PostCompletionEvent(EventHandler * eh, SocketIOEvent type, int param); - - /** Posts a read event on the specified socket - * @param eh EventHandler (socket) - */ - void PostReadEvent(EventHandler * eh); - - /** Posts an accept event on the specified socket - * @param eh EventHandler (socket) - */ - void PostAcceptEvent(EventHandler * eh); - + void WantWrite(EventHandler* eh); + + /** Posts a completion event on the specified socket. + * @param eh EventHandler for message + * @param type Event Type + * @param param Event Parameter + * @return True if added, false if not + */ + bool PostCompletionEvent(EventHandler * eh, SocketIOEvent type, int param); + + /** Posts a read event on the specified socket + * @param eh EventHandler (socket) + */ + void PostReadEvent(EventHandler * eh); + + /** Posts an accept event on the specified socket + * @param eh EventHandler (socket) + */ + void PostAcceptEvent(EventHandler * eh); + /** Returns the EventHandler attached to a specific fd. * If the fd isnt in the socketengine, returns NULL. * @param fd The event handler to look for * @return A pointer to the event handler, or NULL */ - EventHandler* GetRef(int fd); - + EventHandler* GetRef(int fd); + /** Returns true if a file descriptor exists in * the socket engine's list. * @param fd The event handler to look for * @return True if this fd has an event handler */ - bool HasFd(int fd); - + bool HasFd(int fd); + /** Returns the EventHandler attached to a specific fd. * If the fd isnt in the socketengine, returns NULL. * @param fd The event handler to look for * @return A pointer to the event handler, or NULL */ - EventHandler* GetIntRef(int fd); -}; - -//typedef void(*OpHandler)(EventHandler) -/** Event Handler Array - */ - + EventHandler* GetIntRef(int fd); +}; + +//typedef void(*OpHandler)(EventHandler) +/** Event Handler Array + */ + /** Creates a SocketEngine */ class SocketEngineFactory @@ -178,6 +178,6 @@ public: /** Create a new instance of SocketEngine based on IOCPEngine */ SocketEngine* Create(InspIRCd* Instance) { return new IOCPEngine(Instance); } -}; - -#endif +}; + +#endif diff --git a/src/socketengine_iocp.cpp b/src/socketengine_iocp.cpp index 947b518b6..9070f4d49 100644 --- a/src/socketengine_iocp.cpp +++ b/src/socketengine_iocp.cpp @@ -9,276 +9,276 @@ * the file COPYING for details. * * --------------------------------------------------- - */ - -#include "socketengine_iocp.h" -#include -#include - -IOCPEngine::IOCPEngine(InspIRCd * Instance) : SocketEngine(Instance) -{ - // Create completion port - m_completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)0, 0); - - // Null variables out. - CurrentSetSize = 0; - EngineHandle = 0; - memset(ref, 0, sizeof(EventHandler*) * MAX_DESCRIPTORS); -} - -IOCPEngine::~IOCPEngine() -{ - CloseHandle(m_completionPort); -}; - -bool IOCPEngine::AddFd(EventHandler* eh) -{ - int fake_fd = GenerateFd(); - int is_accept = 0; - int opt_len = sizeof(int); - if(fake_fd < 0) - return false; - - // are we a listen socket? - getsockopt(eh->GetFd(), SOL_SOCKET, SO_ACCEPTCONN, (char*)&is_accept, &opt_len); - - // set up the read event so the socket can actually receive data :P - eh->m_internalFd = fake_fd; - eh->m_writeEvent = 0; - eh->m_acceptEvent = 0; - - // assign the socket to the completion port - if(!CreateIoCompletionPort((HANDLE)eh->GetFd(), m_completionPort, (ULONG_PTR)eh->m_internalFd, 0)) - return false; - - // set up binding, increase set size - ref[fake_fd] = eh; - ++CurrentSetSize; - - // setup initial events - if(is_accept) - PostAcceptEvent(eh); - else - PostReadEvent(eh); - - // log message - ServerInstance->Log(DEBUG, "New fake fd: %u, real fd: %u, address 0x%p", fake_fd, eh->GetFd(), eh); - - // post a write event if there is data to be written - if(eh->Writeable()) - WantWrite(eh); - - // we're all good =) - m_binding.insert( map::value_type( eh->GetFd(), eh ) ); - return true; -} - -bool IOCPEngine::DelFd(EventHandler* eh, bool force /* = false */) -{ - int fake_fd = eh->m_internalFd; - int fd = eh->GetFd(); - - if(ref[fake_fd] == 0) - return false; - - ServerInstance->Log(DEBUG, "Removing fake fd %u, real fd %u, address 0x%p", fake_fd, eh->GetFd(), eh); - - // Cancel pending i/o operations. - assert(CancelIo((HANDLE)fd) == TRUE); - - // Free the buffer, and delete the event. - if(eh->m_readEvent != 0) - delete ((Overlapped*)eh->m_readEvent); - - if(eh->m_writeEvent != 0) - delete ((Overlapped*)eh->m_writeEvent); - - if(eh->m_acceptEvent != 0) - { - delete ((accept_overlap*)((Overlapped*)eh->m_acceptEvent)->m_params); - delete ((Overlapped*)eh->m_acceptEvent); - } - - // Clear binding - ref[fake_fd] = 0; - m_binding.erase(eh->GetFd()); - - // decrement set size - --CurrentSetSize; - - // success - return true; -} - -void IOCPEngine::WantWrite(EventHandler* eh) -{ - // Post event - write begin - if(!eh->m_writeEvent) - { - 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); - } -} - -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); -} - -void IOCPEngine::PostReadEvent(EventHandler * eh) -{ - Overlapped * ov = new Overlapped(SOCKET_IO_EVENT_READ_READY, 0); - DWORD flags = 0; - DWORD r_length = 0; - WSABUF buf; - - // by passing a null buffer pointer, we can have this working in the same way as epoll.. - // its slower, but it saves modifying all network code. - buf.buf = 0; - buf.len = 0; - - // determine socket type. - DWORD sock_type; - int sock_len = sizeof(DWORD); - if(getsockopt(eh->GetFd(), SOL_SOCKET, SO_TYPE, (char*)&sock_type, &sock_len) == -1) - { - // wtfhax? - PostCompletionEvent(eh, SOCKET_IO_EVENT_ERROR, 0); - delete ov; - return; - } - switch(sock_type) - { - case SOCK_DGRAM: // UDP Socket - { - if(WSARecvFrom(eh->GetFd(), &buf, 1, &r_length, &flags, 0, 0, &ov->m_overlap, 0)) - { - int err = WSAGetLastError(); - if(WSAGetLastError() != WSA_IO_PENDING) - { - delete ov; - PostCompletionEvent(eh, SOCKET_IO_EVENT_ERROR, 0); - return; - } - } - }break; - - case SOCK_STREAM: // TCP Socket - { - if(WSARecv(eh->GetFd(), &buf, 1, &r_length, &flags, &ov->m_overlap, 0) == SOCKET_ERROR) - { - if(WSAGetLastError() != WSA_IO_PENDING) - { - delete ov; - PostCompletionEvent(eh, SOCKET_IO_EVENT_ERROR, 0); - return; - } - } - }break; - - default: - { - printf("unknwon socket type: %u\n", sock_type); - assert(false); - }break; - } - eh->m_readEvent = (void*)ov; -} - -int IOCPEngine::DispatchEvents() -{ - DWORD len; - LPOVERLAPPED overlap; - Overlapped * ov; - EventHandler * eh; - int intfd; - int ret; - unsigned long bytes_recv; - - while(GetQueuedCompletionStatus(m_completionPort, &len, (PULONG_PTR)&intfd, &overlap, 100)) - { - // woot, we got an event on a socket :P - eh = ref[intfd]; - ov = CONTAINING_RECORD(overlap, Overlapped, m_overlap); - if(eh == 0) continue; - switch(ov->m_event) - { - case SOCKET_IO_EVENT_WRITE_READY: - { - eh->m_writeEvent = 0; - eh->HandleEvent(EVENT_WRITE, 0); - }break; - - case SOCKET_IO_EVENT_READ_READY: - { - 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); - } - else - { - eh->HandleEvent(EVENT_READ, 0); - PostReadEvent(eh); - } - }break; - - case SOCKET_IO_EVENT_ACCEPT: - { - /* this is kinda messy.. :/ */ - eh->HandleEvent(EVENT_READ, ov->m_params); - delete ((accept_overlap*)ov->m_params); - eh->m_acceptEvent = 0; - PostAcceptEvent(eh); - }break; - - case SOCKET_IO_EVENT_ERROR: - { - eh->HandleEvent(EVENT_ERROR, ov->m_params); - }break; - } - - delete ov; - } - - return 0; -} - -void IOCPEngine::PostAcceptEvent(EventHandler * eh) -{ - int fd = WSASocket(AF_INET, SOCK_STREAM, 0, 0, 0, WSA_FLAG_OVERLAPPED); - int len = sizeof(sockaddr_in) + 16; - DWORD dwBytes; - accept_overlap * ao = new accept_overlap; - memset(ao->buf, 0, 1024); - ao->socket = fd; - - Overlapped * ov = new Overlapped(SOCKET_IO_EVENT_ACCEPT, (int)ao); - eh->m_acceptEvent = (void*)ov; - - if(AcceptEx(eh->GetFd(), fd, ao->buf, 0, len, len, &dwBytes, &ov->m_overlap) == FALSE) - { - int err = WSAGetLastError(); - if(err != WSA_IO_PENDING) - { - printf("PostAcceptEvent err: %d\n", err); - } - } -} - - -std::string IOCPEngine::GetName() -{ - return "iocp"; -} - -int __accept_socket(SOCKET s, sockaddr * addr, int * addrlen, void * acceptevent) -{ - Overlapped * ovl = (Overlapped*)acceptevent; + */ + +#include "socketengine_iocp.h" +#include + +IOCPEngine::IOCPEngine(InspIRCd * Instance) : SocketEngine(Instance) +{ + // Create completion port + m_completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)0, 0); + + // Null variables out. + CurrentSetSize = 0; + EngineHandle = 0; + memset(ref, 0, sizeof(EventHandler*) * MAX_DESCRIPTORS); +} + +IOCPEngine::~IOCPEngine() +{ + CloseHandle(m_completionPort); +} + +bool IOCPEngine::AddFd(EventHandler* eh) +{ + int fake_fd = GenerateFd(); + int is_accept = 0; + int opt_len = sizeof(int); + if(fake_fd < 0) + return false; + + // are we a listen socket? + getsockopt(eh->GetFd(), SOL_SOCKET, SO_ACCEPTCONN, (char*)&is_accept, &opt_len); + + // set up the read event so the socket can actually receive data :P + eh->m_internalFd = fake_fd; + eh->m_writeEvent = 0; + eh->m_acceptEvent = 0; + + // assign the socket to the completion port + if(!CreateIoCompletionPort((HANDLE)eh->GetFd(), m_completionPort, (ULONG_PTR)eh->m_internalFd, 0)) + return false; + + // set up binding, increase set size + ref[fake_fd] = eh; + ++CurrentSetSize; + + // setup initial events + if(is_accept) + PostAcceptEvent(eh); + else + PostReadEvent(eh); + + // log message + ServerInstance->Log(DEBUG, "New fake fd: %u, real fd: %u, address 0x%p", fake_fd, eh->GetFd(), eh); + + // post a write event if there is data to be written + if(eh->Writeable()) + WantWrite(eh); + + // we're all good =) + m_binding.insert( map::value_type( eh->GetFd(), eh ) ); + return true; +} + +bool IOCPEngine::DelFd(EventHandler* eh, bool force /* = false */) +{ + int fake_fd = eh->m_internalFd; + int fd = eh->GetFd(); + + if(ref[fake_fd] == 0) + return false; + + ServerInstance->Log(DEBUG, "Removing fake fd %u, real fd %u, address 0x%p", fake_fd, eh->GetFd(), eh); + + // Cancel pending i/o operations. + if (CancelIo((HANDLE)fd) == FALSE) + return false; + + // Free the buffer, and delete the event. + if(eh->m_readEvent != 0) + delete ((Overlapped*)eh->m_readEvent); + + if(eh->m_writeEvent != 0) + delete ((Overlapped*)eh->m_writeEvent); + + if(eh->m_acceptEvent != 0) + { + delete ((accept_overlap*)((Overlapped*)eh->m_acceptEvent)->m_params); + delete ((Overlapped*)eh->m_acceptEvent); + } + + // Clear binding + ref[fake_fd] = 0; + m_binding.erase(eh->GetFd()); + + // decrement set size + --CurrentSetSize; + + // success + return true; +} + +void IOCPEngine::WantWrite(EventHandler* eh) +{ + // Post event - write begin + if(!eh->m_writeEvent) + { + 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); + } +} + +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); +} + +void IOCPEngine::PostReadEvent(EventHandler * eh) +{ + Overlapped * ov = new Overlapped(SOCKET_IO_EVENT_READ_READY, 0); + DWORD flags = 0; + DWORD r_length = 0; + WSABUF buf; + + // by passing a null buffer pointer, we can have this working in the same way as epoll.. + // its slower, but it saves modifying all network code. + buf.buf = 0; + buf.len = 0; + + // determine socket type. + DWORD sock_type; + int sock_len = sizeof(DWORD); + if(getsockopt(eh->GetFd(), SOL_SOCKET, SO_TYPE, (char*)&sock_type, &sock_len) == -1) + { + // wtfhax? + PostCompletionEvent(eh, SOCKET_IO_EVENT_ERROR, 0); + delete ov; + return; + } + switch(sock_type) + { + case SOCK_DGRAM: // UDP Socket + { + if(WSARecvFrom(eh->GetFd(), &buf, 1, &r_length, &flags, 0, 0, &ov->m_overlap, 0)) + { + int err = WSAGetLastError(); + if(WSAGetLastError() != WSA_IO_PENDING) + { + delete ov; + PostCompletionEvent(eh, SOCKET_IO_EVENT_ERROR, 0); + return; + } + } + }break; + + case SOCK_STREAM: // TCP Socket + { + if(WSARecv(eh->GetFd(), &buf, 1, &r_length, &flags, &ov->m_overlap, 0) == SOCKET_ERROR) + { + if(WSAGetLastError() != WSA_IO_PENDING) + { + delete ov; + PostCompletionEvent(eh, SOCKET_IO_EVENT_ERROR, 0); + return; + } + } + }break; + + default: + { + printf("unknwon socket type: %u\n", sock_type); + return; + }break; + } + eh->m_readEvent = (void*)ov; +} + +int IOCPEngine::DispatchEvents() +{ + DWORD len; + LPOVERLAPPED overlap; + Overlapped * ov; + EventHandler * eh; + int intfd; + int ret; + unsigned long bytes_recv; + + while(GetQueuedCompletionStatus(m_completionPort, &len, (PULONG_PTR)&intfd, &overlap, 100)) + { + // woot, we got an event on a socket :P + eh = ref[intfd]; + ov = CONTAINING_RECORD(overlap, Overlapped, m_overlap); + if(eh == 0) continue; + switch(ov->m_event) + { + case SOCKET_IO_EVENT_WRITE_READY: + { + eh->m_writeEvent = 0; + eh->HandleEvent(EVENT_WRITE, 0); + }break; + + case SOCKET_IO_EVENT_READ_READY: + { + 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); + } + else + { + eh->HandleEvent(EVENT_READ, 0); + PostReadEvent(eh); + } + }break; + + case SOCKET_IO_EVENT_ACCEPT: + { + /* this is kinda messy.. :/ */ + eh->HandleEvent(EVENT_READ, ov->m_params); + delete ((accept_overlap*)ov->m_params); + eh->m_acceptEvent = 0; + PostAcceptEvent(eh); + }break; + + case SOCKET_IO_EVENT_ERROR: + { + eh->HandleEvent(EVENT_ERROR, ov->m_params); + }break; + } + + delete ov; + } + + return 0; +} + +void IOCPEngine::PostAcceptEvent(EventHandler * eh) +{ + int fd = WSASocket(AF_INET, SOCK_STREAM, 0, 0, 0, WSA_FLAG_OVERLAPPED); + int len = sizeof(sockaddr_in) + 16; + DWORD dwBytes; + accept_overlap * ao = new accept_overlap; + memset(ao->buf, 0, 1024); + ao->socket = fd; + + Overlapped * ov = new Overlapped(SOCKET_IO_EVENT_ACCEPT, (int)ao); + eh->m_acceptEvent = (void*)ov; + + if(AcceptEx(eh->GetFd(), fd, ao->buf, 0, len, len, &dwBytes, &ov->m_overlap) == FALSE) + { + int err = WSAGetLastError(); + if(err != WSA_IO_PENDING) + { + printf("PostAcceptEvent err: %d\n", err); + } + } +} + + +std::string IOCPEngine::GetName() +{ + return "iocp"; +} + +int __accept_socket(SOCKET s, sockaddr * addr, int * addrlen, void * acceptevent) +{ + Overlapped * ovl = (Overlapped*)acceptevent; accept_overlap * ov = (accept_overlap*)ovl->m_params; sockaddr_in * server_address = (sockaddr_in*)&ov->buf[10]; @@ -292,7 +292,7 @@ int __accept_socket(SOCKET s, sockaddr * addr, int * addrlen, void * acceptevent int __getsockname(SOCKET s, sockaddr * name, int * namelen, void * acceptevent) { - Overlapped * ovl = (Overlapped*)acceptevent; + Overlapped * ovl = (Overlapped*)acceptevent; accept_overlap * ov = (accept_overlap*)ovl->m_params; sockaddr_in * server_address = (sockaddr_in*)&ov->buf[10]; -- cgit v1.2.3