OTSYS_THREAD_RETURN Dispatcher::dispatcherThread(void* p) { #if defined __EXCEPTION_TRACER__ ExceptionHandler dispatcherExceptionHandler; dispatcherExceptionHandler.InstallHandler(); #endif srand((uint32_t)OTSYS_TIME()); OutputMessagePool* outputPool = NULL; while(Dispatcher::m_threadState != Dispatcher::STATE_TERMINATED) { Task* task = NULL; // check if there are tasks waiting OTSYS_THREAD_LOCK(getDispatcher().m_taskLock, ""); if(getDispatcher().m_taskList.empty()) //if the list is empty wait for signal OTSYS_THREAD_WAITSIGNAL(getDispatcher().m_taskSignal, getDispatcher().m_taskLock); if(!getDispatcher().m_taskList.empty() && Dispatcher::m_threadState != Dispatcher::STATE_TERMINATED) { // take the first task task = getDispatcher().m_taskList.front(); getDispatcher().m_taskList.pop_front(); } OTSYS_THREAD_UNLOCK(getDispatcher().m_taskLock, ""); // finally execute the task... if(!task) continue; if(!task->hasExpired()) { if((outputPool = OutputMessagePool::getInstance())) outputPool->startExecutionFrame(); (*task)(); if(outputPool) outputPool->sendAll(); g_game.clearSpectatorCache(); } delete task; } #if defined __EXCEPTION_TRACER__ dispatcherExceptionHandler.RemoveHandler(); #endif #if not defined(WIN32) return NULL; #endif }
void Dispatcher::dispatcherThread(void* p) { Dispatcher* dispatcher = (Dispatcher*)p; #if defined __EXCEPTION_TRACER__ ExceptionHandler dispatcherExceptionHandler; dispatcherExceptionHandler.InstallHandler(); #endif srand((uint32_t)OTSYS_TIME()); OutputMessagePool* outputPool = NULL; boost::unique_lock<boost::mutex> taskLockUnique(dispatcher->m_taskLock, boost::defer_lock); while(Dispatcher::m_threadState != Dispatcher::STATE_TERMINATED) { Task* task = NULL; // check if there are tasks waiting taskLockUnique.lock(); if(dispatcher->m_taskList.empty()) //if the list is empty wait for signal dispatcher->m_taskSignal.wait(taskLockUnique); if(!dispatcher->m_taskList.empty() && Dispatcher::m_threadState != Dispatcher::STATE_TERMINATED) { // take the first task task = dispatcher->m_taskList.front(); dispatcher->m_taskList.pop_front(); } taskLockUnique.unlock(); // finally execute the task... if(!task) continue; if(!task->hasExpired()) { if((outputPool = OutputMessagePool::getInstance())) outputPool->startExecutionFrame(); (*task)(); if(outputPool) outputPool->sendAll(); g_game.clearSpectatorCache(); } delete task; } #if defined __EXCEPTION_TRACER__ dispatcherExceptionHandler.RemoveHandler(); #endif }
void Dispatcher::flush() { while (!m_taskList.empty()) { Task* task = m_taskList.front(); m_taskList.pop_front(); (*task)(); delete task; OutputMessagePool* outputPool = OutputMessagePool::getInstance(); if (outputPool) { outputPool->sendAll(); } g_game.clearSpectatorCache(); } }
void Dispatcher::flush() { Task* task = NULL; while(!m_taskList.empty()){ task = m_taskList.front(); m_taskList.pop_front(); (*task)(); delete task; OutputMessagePool* outputPool = OutputMessagePool::getInstance(); if(outputPool) outputPool->sendAll(); g_game.clearSpectatorCache(); } #ifdef __DEBUG_SCHEDULER__ std::cout << "Flushing Dispatcher" << std::endl; #endif }
bool Connection::send(OutputMessage_ptr msg) { m_connectionLock.lock(); if (m_connectionState != CONNECTION_STATE_OPEN || m_writeError) { m_connectionLock.unlock(); return false; } if (m_pendingWrite == 0) { msg->getProtocol()->onSendMessage(msg); internalSend(msg); } else { OutputMessagePool* outputPool = OutputMessagePool::getInstance(); outputPool->addToAutoSend(msg); } m_connectionLock.unlock(); return true; }
void Dispatcher::dispatcherThread() { OutputMessagePool* outputPool = OutputMessagePool::getInstance(); // NOTE: second argument defer_lock is to prevent from immediate locking std::unique_lock<std::mutex> taskLockUnique(m_taskLock, std::defer_lock); while (m_threadState != STATE_TERMINATED) { Task* task = nullptr; // check if there are tasks waiting taskLockUnique.lock(); if (m_taskList.empty()) { //if the list is empty wait for signal m_taskSignal.wait(taskLockUnique); } if (!m_taskList.empty() && (m_threadState != STATE_TERMINATED)) { // take the first task task = m_taskList.front(); m_taskList.pop_front(); } taskLockUnique.unlock(); // finally execute the task... if (task) { if (!task->hasExpired()) { outputPool->startExecutionFrame(); (*task)(); outputPool->sendAll(); g_game.clearSpectatorCache(); } delete task; } } }
bool Connection::send(OutputMessage_ptr msg) { #ifdef __DEBUG_NET_DETAIL__ std::cout << "Connection::send init" << std::endl; #endif m_connectionLock.lock(); if(m_connectionState != CONNECTION_STATE_OPEN || m_writeError){ m_connectionLock.unlock(); return false; } if(m_pendingWrite == 0){ msg->getProtocol()->onSendMessage(msg); TRACK_MESSAGE(msg); #ifdef __DEBUG_NET_DETAIL__ std::cout << "Connection::send " << msg->getMessageLength() << std::endl; #endif internalSend(msg); } else{ #ifdef __DEBUG_NET__ std::cout << "Connection::send Adding to queue " << msg->getMessageLength() << std::endl; #endif TRACK_MESSAGE(msg); OutputMessagePool* outputPool = OutputMessagePool::getInstance(); outputPool->addToAutoSend(msg); } m_connectionLock.unlock(); return true; }
void Dispatcher::dispatcherThread() { OutputMessagePool* outputPool = OutputMessagePool::getInstance(); // NOTE: second argument defer_lock is to prevent from immediate locking std::unique_lock<std::mutex> taskLockUnique(taskLock, std::defer_lock); while (getState() != THREAD_STATE_TERMINATED) { // check if there are tasks waiting taskLockUnique.lock(); if (taskList.empty()) { //if the list is empty wait for signal taskSignal.wait(taskLockUnique); } if (!taskList.empty()) { // take the first task Task* task = taskList.front(); taskList.pop_front(); taskLockUnique.unlock(); if (!task->hasExpired()) { // execute it outputPool->startExecutionFrame(); (*task)(); outputPool->sendAll(); g_game.map.clearSpectatorCache(); } delete task; } else { taskLockUnique.unlock(); } } }
void Dispatcher::dispatcherThread(void* p) { #if defined __EXCEPTION_TRACER__ ExceptionHandler dispatcherExceptionHandler; dispatcherExceptionHandler.InstallHandler(); #endif srand((unsigned int)OTSYS_TIME()); #ifdef __DEBUG_SCHEDULER__ std::cout << "Starting Dispatcher" << std::endl; #endif OutputMessagePool* outputPool; // NOTE: second argument defer_lock is to prevent from immediate locking boost::unique_lock<boost::mutex> taskLockUnique(getDispatcher().m_taskLock, boost::defer_lock); while(Dispatcher::m_threadState != Dispatcher::STATE_TERMINATED){ Task* task = NULL; // check if there are tasks waiting taskLockUnique.lock();//getDispatcher().m_taskLock.lock(); if(getDispatcher().m_taskList.empty()){ //if the list is empty wait for signal #ifdef __DEBUG_SCHEDULER__ std::cout << "Dispatcher: Waiting for task" << std::endl; #endif getDispatcher().m_taskSignal.wait(taskLockUnique); } #ifdef __DEBUG_SCHEDULER__ std::cout << "Dispatcher: Signalled" << std::endl; #endif if(!getDispatcher().m_taskList.empty() && (Dispatcher::m_threadState != Dispatcher::STATE_TERMINATED)){ // take the first task task = getDispatcher().m_taskList.front(); getDispatcher().m_taskList.pop_front(); } taskLockUnique.unlock(); // finally execute the task... if(task){ OutputMessagePool::getInstance()->startExecutionFrame(); (*task)(); delete task; outputPool = OutputMessagePool::getInstance(); if(outputPool){ outputPool->sendAll(); } g_game.clearSpectatorCache(); #ifdef __DEBUG_SCHEDULER__ std::cout << "Dispatcher: Executing task" << std::endl; #endif } } #if defined __EXCEPTION_TRACER__ dispatcherExceptionHandler.RemoveHandler(); #endif }
void ProtocolAdmin::parsePacket(NetworkMessage& msg) { if (g_game.getGameState() == GAME_STATE_SHUTDOWN) { getConnection()->closeConnection(); return; } uint8_t recvbyte = msg.GetByte(); OutputMessagePool* outputPool = OutputMessagePool::getInstance(); OutputMessage_ptr output = outputPool->getOutputMessage(this, false); if (!output) { return; } switch (m_state) { case ENCRYPTION_NO_SET: { if (g_adminConfig->requireEncryption()) { if ((time(NULL) - m_startTime) > 30000) { getConnection()->closeConnection(); addLogLine(this, LOGTYPE_WARNING, 1, "encryption timeout"); return; } if (recvbyte != AP_MSG_ENCRYPTION && recvbyte != AP_MSG_KEY_EXCHANGE) { output->AddByte(AP_MSG_ERROR); output->AddString("encryption needed"); outputPool->send(output); getConnection()->closeConnection(); addLogLine(this, LOGTYPE_WARNING, 1, "wrong command while ENCRYPTION_NO_SET"); return; } break; } else { m_state = NO_LOGGED_IN; } } case NO_LOGGED_IN: { if (g_adminConfig->requireLogin()) { if ((time(NULL) - m_startTime) > 30000) { //login timeout getConnection()->closeConnection(); addLogLine(this, LOGTYPE_WARNING, 1, "login timeout"); return; } if (m_loginTries > 3) { output->AddByte(AP_MSG_ERROR); output->AddString("too many login tries"); outputPool->send(output); getConnection()->closeConnection(); addLogLine(this, LOGTYPE_WARNING, 1, "too many login tries"); return; } if (recvbyte != AP_MSG_LOGIN) { output->AddByte(AP_MSG_ERROR); output->AddString("you are not logged in"); outputPool->send(output); getConnection()->closeConnection(); addLogLine(this, LOGTYPE_WARNING, 1, "wrong command while NO_LOGGED_IN"); return; } break; } else { m_state = LOGGED_IN; } } case LOGGED_IN: { //can execute commands break; } default: { getConnection()->closeConnection(); return; } } m_lastCommand = time(NULL); switch (recvbyte) { case AP_MSG_LOGIN: { if (m_state == NO_LOGGED_IN && g_adminConfig->requireLogin()) { std::string password = msg.GetString(); if (g_adminConfig->passwordMatch(password)) { m_state = LOGGED_IN; output->AddByte(AP_MSG_LOGIN_OK); addLogLine(this, LOGTYPE_EVENT, 1, "login ok"); } else { m_loginTries++; output->AddByte(AP_MSG_LOGIN_FAILED); output->AddString("wrong password"); addLogLine(this, LOGTYPE_WARNING, 1, "login failed.(" + password + ")"); } } else { output->AddByte(AP_MSG_LOGIN_FAILED); output->AddString("can not login"); addLogLine(this, LOGTYPE_WARNING, 1, "wrong state at login"); } break; } case AP_MSG_ENCRYPTION: { if (m_state == ENCRYPTION_NO_SET && g_adminConfig->requireEncryption()) { uint8_t keyType = msg.GetByte(); if (keyType == ENCRYPTION_RSA1024XTEA) { RSA* rsa = g_adminConfig->getRSAKey(ENCRYPTION_RSA1024XTEA); if (!rsa) { output->AddByte(AP_MSG_ENCRYPTION_FAILED); addLogLine(this, LOGTYPE_WARNING, 1, "no valid server key type"); break; } if (RSA_decrypt(rsa, msg)) { m_state = NO_LOGGED_IN; uint32_t k[4]; k[0] = msg.GetU32(); k[1] = msg.GetU32(); k[2] = msg.GetU32(); k[3] = msg.GetU32(); //use for in/out the new key we have enableXTEAEncryption(); setXTEAKey(k); output->AddByte(AP_MSG_ENCRYPTION_OK); addLogLine(this, LOGTYPE_EVENT, 1, "encryption ok"); } else { output->AddByte(AP_MSG_ENCRYPTION_FAILED); output->AddString("wrong encrypted packet"); addLogLine(this, LOGTYPE_WARNING, 1, "wrong encrypted packet"); } } else { output->AddByte(AP_MSG_ENCRYPTION_FAILED); output->AddString("no valid key type"); addLogLine(this, LOGTYPE_WARNING, 1, "no valid client key type"); } } else { output->AddByte(AP_MSG_ENCRYPTION_FAILED); output->AddString("can not set encryption"); addLogLine(this, LOGTYPE_EVENT, 1, "can not set encryption"); } break; } case AP_MSG_KEY_EXCHANGE: { if (m_state == ENCRYPTION_NO_SET && g_adminConfig->requireEncryption()) { uint8_t keyType = msg.GetByte(); if (keyType == ENCRYPTION_RSA1024XTEA) { RSA* rsa = g_adminConfig->getRSAKey(ENCRYPTION_RSA1024XTEA); if (!rsa) { output->AddByte(AP_MSG_KEY_EXCHANGE_FAILED); addLogLine(this, LOGTYPE_WARNING, 1, "no valid server key type"); break; } output->AddByte(AP_MSG_KEY_EXCHANGE_OK); output->AddByte(ENCRYPTION_RSA1024XTEA); char RSAPublicKey[128]; rsa->getPublicKey(RSAPublicKey); output->AddBytes(RSAPublicKey, 128); } else { output->AddByte(AP_MSG_KEY_EXCHANGE_FAILED); addLogLine(this, LOGTYPE_WARNING, 1, "no valid client key type"); } } else { output->AddByte(AP_MSG_KEY_EXCHANGE_FAILED); output->AddString("can not get public key"); addLogLine(this, LOGTYPE_WARNING, 1, "can not get public key"); } break; } case AP_MSG_COMMAND: { if (m_state != LOGGED_IN) { addLogLine(this, LOGTYPE_ERROR, 1, "recvbyte == AP_MSG_COMMAND && m_state != LOGGED_IN !!!"); // We should never reach this point break; } uint8_t command = msg.GetByte(); switch (command) { case CMD_BROADCAST: { const std::string message = msg.GetString(); addLogLine(this, LOGTYPE_EVENT, 1, "broadcast: " + message); g_dispatcher.addTask(createTask(boost::bind(&Game::broadcastMessage, &g_game, message, MSG_STATUS_WARNING))); output->AddByte(AP_MSG_COMMAND_OK); break; } case CMD_CLOSE_SERVER: { g_dispatcher.addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandCloseServer, this))); break; } case CMD_PAY_HOUSES: { g_dispatcher.addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandPayHouses, this))); break; } case CMD_OPEN_SERVER: { g_dispatcher.addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandOpenServer, this))); break; } case CMD_SHUTDOWN_SERVER: { g_dispatcher.addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandShutdownServer, this))); getConnection()->closeConnection(); return; } case CMD_KICK: { const std::string name = msg.GetString(); g_dispatcher.addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandKickPlayer, this, name))); break; } case CMD_SETOWNER: { const std::string param = msg.GetString(); g_dispatcher.addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandSetOwner, this, param))); break; } default: { output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString("not known server command"); addLogLine(this, LOGTYPE_WARNING, 1, "not known server command"); break; } } break; } case AP_MSG_PING: { output->AddByte(AP_MSG_PING_OK); break; } default: { output->AddByte(AP_MSG_ERROR); output->AddString("not known command byte"); addLogLine(this, LOGTYPE_WARNING, 1, "not known command byte"); break; } } if (output->getMessageLength() > 0) { outputPool->send(output); } }
void Dispatcher::dispatcherThread(void* p) { Dispatcher* dispatcher = static_cast<Dispatcher*>(p); ExceptionHandler dispatcherExceptionHandler; dispatcherExceptionHandler.InstallHandler(); #ifdef __DEBUG_SCHEDULER__ std::cout << "Starting Dispatcher" << std::endl; #endif OutputMessagePool* outputPool; // NOTE: second argument defer_lock is to prevent from immediate locking boost::unique_lock<boost::mutex> taskLockUnique(dispatcher->m_taskLock, boost::defer_lock); while (dispatcher->m_threadState != STATE_TERMINATED) { Task* task = NULL; // check if there are tasks waiting taskLockUnique.lock(); if (dispatcher->m_taskList.empty()) { //if the list is empty wait for signal #ifdef __DEBUG_SCHEDULER__ std::cout << "Dispatcher: Waiting for task" << std::endl; #endif dispatcher->m_taskSignal.wait(taskLockUnique); } #ifdef __DEBUG_SCHEDULER__ std::cout << "Dispatcher: Signalled" << std::endl; #endif if (!dispatcher->m_taskList.empty() && (dispatcher->m_threadState != STATE_TERMINATED)) { // take the first task task = dispatcher->m_taskList.front(); dispatcher->m_taskList.pop_front(); } taskLockUnique.unlock(); // finally execute the task... if (task) { if (!task->hasExpired()) { OutputMessagePool::getInstance()->startExecutionFrame(); (*task)(); outputPool = OutputMessagePool::getInstance(); if (outputPool) { outputPool->sendAll(); } g_game.clearSpectatorCache(); } delete task; #ifdef __DEBUG_SCHEDULER__ std::cout << "Dispatcher: Executing task" << std::endl; #endif } } dispatcherExceptionHandler.RemoveHandler(); }