Beispiel #1
0
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
}
Beispiel #3
0
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();
    }
}
Beispiel #4
0
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
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
        }
    }
}
Beispiel #7
0
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;
}
Beispiel #8
0
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();
		}
	}
}
Beispiel #9
0
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
}
Beispiel #10
0
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);
	}
}
Beispiel #11
0
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();
}