All pastes #992129 Raw Edit

Untitled

public text v1 · immutable
#992129 ·published 2008-04-21 16:57 UTC
rendered paste body
#ifndef __LISTER_SOCKET_NWIN32_H__
#define __LISTER_SOCKET_NWIN32_H__

#include "Common.h"
#include "Log.h"
#include "SocketManager.h"
template<class T>
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("<Listen socket> 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("<Listen socket %u> Couldn't set option SO_REUSEADDR", 
					  m_SocketHandle);
				  break;
			  }

			  u_long arg = 1;
			  if(ioctlsocket(m_SocketHandle, FIONBIO, &arg) == SOCKET_ERROR)
			  {
				  sLog.outError("<Listen socket %u> 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("<Listen socket %u> 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("<Listen socket %u> Couldn't associate a local address with a socket", 
					  m_SocketHandle);
				  break;
			  }

			  if (listen(m_SocketHandle, 1024) == SOCKET_ERROR)
			  {
				  sLog.outError("<Listen socket %u> 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("<Listen socket %u> Listening started...", m_SocketHandle);
		  else
		  {
			  sLog.outError("<Listen socket %u> 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("<Listen socket %u> 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("<Listen socket %u> Couldn't add EV_READ | EV_PERSIST event on creating", 
			  GetSocket());
	  }

	  void OnRemoveSocket()
	  {
		  if(event_del(&m_ev_read) == -1)
			  sLog.outError("<Listen socket %u> 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("<Listen socket %u> Couldn't accept connection. Some error. Skipped.", 
				  m_SocketHandle);
			  return;
		  }
		  sLog.outString("<Listen socket %u> Accepted new connection. Socket %u", 
			  m_SocketHandle, client_sock);
		  T* pSocket = new T(client_sock);
		  pSocket->Accept(&ClientAddress);
	  }

	void StopListening()
	{
		sLog.outBasic("<Listen socket %u> Listen socket closed", m_SocketHandle);
		sSocketManager.RemoveSocket(this);
		::closesocket(m_SocketHandle);
		m_bSocketCreated = false;
	}

private:
	bool m_bSocketCreated;
};
#endif//__LISTER_SOCKET_NWIN32_H__