#ifndef __LISTER_SOCKET_NWIN32_H__ #define __LISTER_SOCKET_NWIN32_H__ #include "Common.h" #include "Log.h" #include "SocketManager.h" template class ListenSocket: public SocketBase { public: ListenSocket(const char* szListenAddress, int unPort): m_bSocketCreated(false) { do { if((m_SocketHandle = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR) { sLog.outError(" Couldn't create socket"); break; } int on = 1; if (setsockopt(m_SocketHandle, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on)) == SOCKET_ERROR) { sLog.outError(" Couldn't set option SO_REUSEADDR", m_SocketHandle); break; } u_long arg = 1; if(ioctlsocket(m_SocketHandle, FIONBIO, &arg) == SOCKET_ERROR) { sLog.outError(" Couldn't set nonblocking mode", m_SocketHandle); break; } sockaddr_in address; if(!strcmp(szListenAddress, "0.0.0.0")) address.sin_addr.s_addr = htonl(INADDR_ANY); else { hostent* h = gethostbyname(szListenAddress); if(!h) { sLog.outError(" Couldn't retrieve host information corresponding " "to a host name from a host database", m_SocketHandle); break; } memcpy(&address.sin_addr, h->h_addr_list[0], sizeof(in_addr)); } address.sin_family = AF_INET; address.sin_port = ntohs(unPort); if (bind(m_SocketHandle, (const sockaddr*)&address, sizeof(sockaddr_in)) == SOCKET_ERROR) { sLog.outError(" Couldn't associate a local address with a socket", m_SocketHandle); break; } if (listen(m_SocketHandle, 1024) == SOCKET_ERROR) { sLog.outError(" Couldn't place a socket in a state in which it" " is listening for an incoming connection", m_SocketHandle); break; } m_bSocketCreated = true; } while(false); if (m_bSocketCreated && sSocketManager.AddSocket(this)) sLog.outString(" Listening started...", m_SocketHandle); else { sLog.outError(" Creating failed", m_SocketHandle); StopListening(); } } void Disconnect(bool bAbort = false) { StopListening(); } bool IsConnected() { return IsListenPortOpened(); } bool IsListenPortOpened() { return m_bSocketCreated;} void ScheduleReading() { #ifdef WIN32 timeval tv = {0, 50000}; #else timeval tv = {5, 0}; #endif if(event_add(&m_ev_read, &tv) == -1) sLog.outError(" Couldn't reschedule reading by timeout. Error [%u].", GetSocket(), errno); } void OnWriteEvent() {} void OnTimeoutEvent() { ScheduleReading(); } void OnAddSocket() { event_set(&m_ev_read, (int)GetSocket(), EV_READ | EV_PERSIST, io_handle, (SocketBase*)this); event_base_set(sSocketManager.GetEventBase(), &m_ev_read); #ifdef WIN32 timeval tv = {0, 50000}; #else timeval tv = {5, 0}; #endif if(event_add(&m_ev_read, &tv) == -1) sLog.outError(" Couldn't add EV_READ | EV_PERSIST event on creating", GetSocket()); } void OnRemoveSocket() { if(event_del(&m_ev_read) == -1) sLog.outError(" Couldn't delete READ event on exit", GetSocket()); } void OnReadEvent() { ScheduleReading(); struct sockaddr_in ClientAddress; socklen_t addrlen = sizeof(ClientAddress); SOCKET client_sock = INVALID_SOCKET; if ((client_sock = accept(m_SocketHandle, (sockaddr*)&ClientAddress, &addrlen)) == INVALID_SOCKET) { sLog.outError(" Couldn't accept connection. Some error. Skipped.", m_SocketHandle); return; } sLog.outString(" Accepted new connection. Socket %u", m_SocketHandle, client_sock); T* pSocket = new T(client_sock); pSocket->Accept(&ClientAddress); } void StopListening() { sLog.outBasic(" Listen socket closed", m_SocketHandle); sSocketManager.RemoveSocket(this); ::closesocket(m_SocketHandle); m_bSocketCreated = false; } private: bool m_bSocketCreated; }; #endif//__LISTER_SOCKET_NWIN32_H__