#ifndef TCPSERVER_H_ #define TCPSERVER_H_ #include "types.h" #include "mutex.h" #include #include #define TCPServer_ErrorBufferSize 1024 //this is the non-connection type specific server. class BaseTCPServer { public: BaseTCPServer(uint16 iPort = 0); virtual ~BaseTCPServer(); bool Open(uint16 iPort = 0, char* errbuf = 0); // opens the port void Close(); // closes the port bool IsOpen(); inline uint16 GetPort() { return pPort; } inline uint32 GetNextID() { return NextID++; } protected: static ThreadReturnType TCPServerLoop(void* tmp); //factory method: virtual void CreateNewConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) = 0; virtual void Process(); bool RunLoop(); Mutex MLoopRunning; void StopLoopAndWait(); void ListenNewConnections(); uint32 NextID; Mutex MRunLoop; bool pRunLoop; Mutex MSock; SOCKET sock; uint16 pPort; }; template class TCPServer : public BaseTCPServer { protected: typedef typename std::vector vstore; typedef typename std::vector::iterator vitr; public: TCPServer(uint16 iPort = 0) : BaseTCPServer(iPort) { } virtual ~TCPServer() { StopLoopAndWait(); //im not sure what the right thing to do here is... //we are freeing a connection which somebody likely has a pointer to.. //but, we really shouldent ever get called anyhow.. vitr cur, end; cur = m_list.begin(); end = m_list.end(); for(; cur != end; ++cur) { delete *cur; } } T * NewQueuePop() { T * ret = nullptr; MNewQueue.lock(); if(!m_NewQueue.empty()) { ret = m_NewQueue.front(); m_NewQueue.pop(); } MNewQueue.unlock(); return ret; } protected: virtual void Process() { BaseTCPServer::Process(); vitr cur; cur = m_list.begin(); while(cur != m_list.end()) { T *data = *cur; if (data->IsFree() && (!data->CheckNetActive())) { #if EQN_DEBUG >= 4 std::cout << "TCPConnection Connection deleted." << std::endl; #endif delete data; cur = m_list.erase(cur); } else { if (!data->Process()) data->Disconnect(); ++cur; } } } void AddConnection(T *con) { m_list.push_back(con); MNewQueue.lock(); m_NewQueue.push(con); MNewQueue.unlock(); } //queue of new connections, for the app to pull from Mutex MNewQueue; std::queue m_NewQueue; vstore m_list; }; #endif /*TCPSERVER_H_*/