//////////////////////////////////////////////////////////////////////// // OpenTibia - an opensource roleplaying game //////////////////////////////////////////////////////////////////////// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . //////////////////////////////////////////////////////////////////////// #ifndef __CONNECTION__ #define __CONNECTION__ #include "otsystem.h" #include "networkmessage.h" class Connection; class Protocol; class OutputMessage; typedef boost::shared_ptrOutputMessage_ptr; class ServiceBase; typedef boost::shared_ptr Service_ptr; class ServicePort; typedef boost::shared_ptr ServicePort_ptr; #ifdef __DEBUG_NET__ #define PRINT_ASIO_ERROR(desc) \ std::cout << "[Error - " << __FUNCTION__ << "]: " << desc << " - Value: " << \ error.value() << " Message: " << error.message() << std::endl; #else #define PRINT_ASIO_ERROR(desc) #endif struct LoginBlock { int32_t lastLogin, lastProtocol, loginsAmount; }; struct ConnectBlock { uint32_t count; uint64_t startTime, blockTime; }; class ConnectionManager { public: virtual ~ConnectionManager() {OTSYS_THREAD_LOCKVARRELEASE(m_connectionManagerLock);} static ConnectionManager* getInstance() { static ConnectionManager instance; return &instance; } Connection* createConnection(boost::asio::ip::tcp::socket* socket, boost::asio::io_service& io_service, ServicePort_ptr servicer); void releaseConnection(Connection* connection); bool isDisabled(uint32_t clientIp, int32_t protocolId); void addAttempt(uint32_t clientIp, int32_t protocolId, bool success); bool acceptConnection(uint32_t clientIp); void closeAll(); protected: ConnectionManager() {OTSYS_THREAD_LOCKVARINIT(m_connectionManagerLock);} typedef std::map IpLoginMap; IpLoginMap ipLoginMap; typedef std::map IpConnectMap; IpConnectMap ipConnectMap; std::list m_connections; OTSYS_THREAD_LOCKVAR m_connectionManagerLock; }; class Connection : boost::noncopyable { public: #ifdef __ENABLE_SERVER_DIAGNOSTIC__ static uint32_t connectionCount; #endif enum { CLOSE_STATE_NONE = 0, CLOSE_STATE_REQUESTED = 1, CLOSE_STATE_CLOSING = 2 }; private: Connection(boost::asio::ip::tcp::socket* socket, boost::asio::io_service& io_service, ServicePort_ptr servicer): m_timer(io_service), m_socket(socket), m_io_service(io_service), m_port(servicer) { m_protocol = NULL; m_closeState = CLOSE_STATE_NONE; m_refCount = m_pendingWrite = m_pendingRead = 0; m_receivedFirst = m_socketClosed = m_writeError = m_readError = false; OTSYS_THREAD_LOCKVARINIT(m_connectionLock); #ifdef __ENABLE_SERVER_DIAGNOSTIC__ connectionCount++; #endif } friend class ConnectionManager; public: virtual ~Connection() { OTSYS_THREAD_LOCKVARRELEASE(m_connectionLock); #ifdef __ENABLE_SERVER_DIAGNOSTIC__ connectionCount--; #endif } boost::asio::ip::tcp::socket& getHandle() {return *m_socket;} uint32_t getIP() const; void handle(Protocol* protocol); void accept(); void close(); bool send(OutputMessage_ptr msg); int32_t addRef() {return ++m_refCount;} int32_t unRef() {return --m_refCount;} private: void internalSend(OutputMessage_ptr msg); void closeConnection(); void releaseConnection(); void deleteConnection(); void parseHeader(const boost::system::error_code& error); void parsePacket(const boost::system::error_code& error); bool write(); void onWrite(OutputMessage_ptr msg, const boost::system::error_code& error); void onStop(); void handleTimeout(const boost::system::error_code& error); void handleReadError(const boost::system::error_code& error); void handleWriteError(const boost::system::error_code& error); NetworkMessage m_msg; Protocol* m_protocol; boost::asio::deadline_timer m_timer; boost::asio::ip::tcp::socket* m_socket; boost::asio::io_service& m_io_service; ServicePort_ptr m_port; static bool m_logError; bool m_receivedFirst, m_socketClosed, m_writeError, m_readError; int32_t m_pendingWrite, m_pendingRead; uint32_t m_closeState, m_refCount; OTSYS_THREAD_LOCKVAR m_connectionLock; }; #endif