void OutputMessagePool::send(OutputMessage_ptr msg) { m_outputPoolLock.lock(); OutputMessage::OutputMessageState state = msg->getState(); m_outputPoolLock.unlock(); if(state == OutputMessage::STATE_ALLOCATED_NO_AUTOSEND) { #ifdef __DEBUG_NET_DETAIL__ std::cout << "Sending message - SINGLE" << std::endl; #endif if(msg->getConnection()) { if(!msg->getConnection()->send(msg)) { // Send only fails when connection is closing (or in error state) // This call will free the message msg->getProtocol()->onSendMessage(msg); } } else { #ifdef __DEBUG_NET__ std::cout << "Error: [OutputMessagePool::send] NULL connection." << std::endl; #endif } } else { #ifdef __DEBUG_NET__ std::cout << "Warning: [OutputMessagePool::send] State != STATE_ALLOCATED_NO_AUTOSEND" << std::endl; #endif } }
void Connection::internalSend(OutputMessage_ptr msg) { m_pendingWrite++; boost::asio::async_write(m_socket, boost::asio::buffer(msg->getOutputBuffer(), msg->getMessageLength()), boost::bind(&Connection::onWriteOperation, this, msg, boost::asio::placeholders::error)); }
OutputMessage_ptr OutputMessagePool::getOutputMessage(Protocol* protocol, bool autosend /*= true*/) { #ifdef __DEBUG_NET_DETAIL__ std::cout << "request output message - auto = " << autosend << std::endl; #endif if(m_shutdown) return OutputMessage_ptr(); OTSYS_THREAD_LOCK_CLASS lockClass(m_outputPoolLock); if(!protocol->getConnection()) return OutputMessage_ptr(); if(m_outputMessages.empty()) { OutputMessage* msg = new OutputMessage(); m_outputMessages.push_back(msg); #ifdef __TRACK_NETWORK__ m_allOutputMessages.push_back(msg); #endif } OutputMessage_ptr omsg; omsg.reset(m_outputMessages.back(), boost::bind(&OutputMessagePool::releaseMessage, this, _1)); m_outputMessages.pop_back(); configureOutputMessage(omsg, protocol, autosend); return omsg; }
bool Connection::send(OutputMessage_ptr msg) { LOGt("Connection::send()"); boost::recursive_mutex::scoped_lock lock(m_connectionLock); if(m_connectionState != CONNECTION_STATE_OPEN || m_writeError) { return false; } TRACK_MESSAGE(msg); if(!m_pendingWrite) { if(msg->getProtocol()) msg->getProtocol()->onSendMessage(msg); internalSend(msg); } else if(m_pendingWrite > 100 && server.configManager().getBool(ConfigManager::FORCE_CLOSE_SLOW_CONNECTION)) { LOGd("Forcing slow connection to disconnect!"); close(); } else { OutputMessagePool::getInstance()->autoSend(msg); } return true; }
void OutputMessagePool::send(OutputMessage_ptr msg) { OTSYS_THREAD_LOCK(m_outputPoolLock, ""); OutputMessage::OutputMessageState state = msg->getState(); OTSYS_THREAD_UNLOCK(m_outputPoolLock, ""); if(state == OutputMessage::STATE_ALLOCATED_NO_AUTOSEND) { #ifdef __DEBUG_NET_DETAIL__ std::cout << "Sending message - SINGLE" << std::endl; #endif if(msg->getConnection()) { if(!msg->getConnection()->send(msg) && msg->getProtocol()) msg->getProtocol()->onSendMessage(msg); } #ifdef __DEBUG_NET__ else std::cout << "Error: [OutputMessagePool::send] NULL connection." << std::endl; #endif } #ifdef __DEBUG_NET__ else std::cout << "Warning: [OutputMessagePool::send] State != STATE_ALLOCATED_NO_AUTOSEND" << std::endl; #endif }
OutputMessage_ptr OutputMessagePool::getOutputMessage(Protocol* protocol, bool autosend /*= true*/) { #ifdef __DEBUG_NET_DETAIL__ std::cout << "request output message - auto = " << autosend << std::endl; #endif if(!m_isOpen){ return OutputMessage_ptr(); } boost::recursive_mutex::scoped_lock lockClass(m_outputPoolLock); if(protocol->getConnection() == NULL){ return OutputMessage_ptr(); } if(m_outputMessages.empty()){ OutputMessage* msg = new OutputMessage(); m_outputMessages.push_back(msg); #ifdef __TRACK_NETWORK__ m_allOutputMessages.push_back(msg); #endif } OutputMessage_ptr outputmessage; outputmessage.reset(m_outputMessages.back(), boost::bind(&OutputMessagePool::releaseMessage, this, _1)); m_outputMessages.pop_back(); configureOutputMessage(outputmessage, protocol, autosend); return outputmessage; }
void ProtocolAdmin::adminCommandSendMail(const std::string& xmlData) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(!output) return; std::string name; TRACK_MESSAGE(output); if(Item* mailItem = Admin::createMail(xmlData, name)) { if(IOLoginData::getInstance()->playerMail(NULL, name, mailItem)) { addLogLine(LOGTYPE_EVENT, "sent mailbox to " + name); output->put<char>(AP_MSG_COMMAND_OK); } else { addLogLine(LOGTYPE_EVENT, "failed sending mailbox to " + name); output->put<char>(AP_MSG_COMMAND_FAILED); output->putString("could not send the box"); } } else { addLogLine(LOGTYPE_EVENT, "failed parsing mailbox"); output->put<char>(AP_MSG_COMMAND_FAILED); output->putString("could not parse the box"); } OutputMessagePool::getInstance()->send(output); }
void ProtocolAdmin::adminCommandKickPlayer(const std::string& name) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output) { TRACK_MESSAGE(output); Player* player = g_game.getPlayerByName(name); if(player) { player->kickPlayer(false); addLogLine(this, LOGTYPE_EVENT, 1, "kicked player " + name); output->AddByte(AP_MSG_COMMAND_OK); } else { addLogLine(this, LOGTYPE_WARNING, 1, "Could not kick player (not online): " + name); output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString("player is not online"); } OutputMessagePool::getInstance()->send(output); } }
bool Connection::send(OutputMessage_ptr msg) { m_connectionLock.lock(); if(m_closeState == CLOSE_STATE_CLOSING || m_writeError) { m_connectionLock.unlock(); return false; } msg->getProtocol()->onSendMessage(msg); if(m_pendingWrite == 0) { #ifdef __DEBUG_NET_DETAIL__ std::clog << "Connection::send " << msg->getMessageLength() << std::endl; #endif internalSend(msg); } else { #ifdef __DEBUG_NET__ std::clog << "Connection::send Adding to queue " << msg->getMessageLength() << std::endl; #endif m_outputQueue.push_back(msg); } m_connectionLock.unlock(); return true; }
OutputMessage_ptr OutputMessagePool::getOutputMessage(Protocol* protocol, bool autosend /*= true*/) { if (!m_isOpen) { return OutputMessage_ptr(); } std::lock_guard<std::recursive_mutex> lockClass(m_outputPoolLock); if (!protocol->getConnection()) { return OutputMessage_ptr(); } if (m_outputMessages.empty()) { OutputMessage* msg = new OutputMessage(); m_outputMessages.push_back(msg); } OutputMessage_ptr outputmessage; outputmessage.reset(m_outputMessages.back(), std::bind(&OutputMessagePool::releaseMessage, this, std::placeholders::_1)); m_outputMessages.pop_back(); configureOutputMessage(outputmessage, protocol, autosend); return outputmessage; }
void ProtocolSpectator::writeToOutputBuffer(const NetworkMessage& msg) { OutputMessage_ptr out = getOutputBuffer(msg.getLength()); if (out) { out->append(msg); } }
void ProtocolLogin::disconnectClient(uint8_t error, const char* message) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { output->AddByte(error); output->AddString(message); OutputMessagePool::getInstance()->send(output); } getConnection()->closeConnection(); }
void ProtocolOld::dispatchedDisconnectClient(const std::string& message) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { output->addByte(0x0A); output->addString(message); OutputMessagePool::getInstance()->send(output); } getConnection()->close(); }
void ProtocolLogin::disconnectClient(const std::string& message, uint16_t version) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { output->addByte(version >= 1076 ? 0x0B : 0x0A); output->addString(message); OutputMessagePool::getInstance()->send(output); } getConnection()->close(); }
void ProtocolAdmin::adminCommandPayHouses() { Houses::getInstance().payHouses(); addLogLine(this, LOGTYPE_EVENT, 1, "pay houses ok"); OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output){ TRACK_MESSAGE(output); output->AddByte(AP_MSG_COMMAND_OK); OutputMessagePool::getInstance()->send(output); } }
void ProtocolAdmin::adminCommandSaveServer(bool shallow) { g_game.saveServer(false, shallow); addLogLine(this, LOGTYPE_EVENT, 1, "save server ok"); OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output){ TRACK_MESSAGE(output); output->AddByte(AP_MSG_COMMAND_OK); OutputMessagePool::getInstance()->send(output); } }
void ProtocolAdmin::adminCommandOpenServer() { g_game.setGameState(GAME_STATE_NORMAL); addLogLine(this, LOGTYPE_EVENT, 1, "open server ok"); OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { output->AddByte(AP_MSG_COMMAND_OK); OutputMessagePool::getInstance()->send(output); } }
void ProtocolAdmin::adminCommandShutdownServer() { g_game.setGameState(GAME_STATE_SHUTDOWN); addLogLine(this, LOGTYPE_EVENT, 1, "start server shutdown"); OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output){ TRACK_MESSAGE(output); output->AddByte(AP_MSG_COMMAND_OK); OutputMessagePool::getInstance()->send(output); } }
void ProtocolAdmin::adminCommandRelationalSaveServer() { std::string old_type = g_config.getString(ConfigManager::MAP_STORAGE_TYPE); g_config.setString(ConfigManager::MAP_STORAGE_TYPE, "relational"); g_game.saveServer(false); g_config.setString(ConfigManager::MAP_STORAGE_TYPE, old_type); addLogLine(this, LOGTYPE_EVENT, 1, "relational save server ok"); OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output){ TRACK_MESSAGE(output); output->AddByte(AP_MSG_COMMAND_OK); OutputMessagePool::getInstance()->send(output); } }
void OutputMessagePool::send(OutputMessage_ptr msg) { m_outputPoolLock.lock(); OutputMessage::OutputMessageState state = msg->getState(); m_outputPoolLock.unlock(); if (state == OutputMessage::STATE_ALLOCATED_NO_AUTOSEND) { Connection_ptr connection = msg->getConnection(); if (connection && !connection->send(msg)) { // Send only fails when connection is closing (or in error state) // This call will free the message msg->getProtocol()->onSendMessage(msg); } } }
void Connection::onWriteOperation(OutputMessage_ptr msg, const boost::system::error_code& error) { #ifdef __DEBUG_NET_DETAIL__ std::clog << "onWriteOperation" << std::endl; #endif msg.reset(); m_connectionLock.lock(); if(!error) { if(m_pendingWrite > 0) { if(!m_outputQueue.empty()) { OutputMessage_ptr msg = m_outputQueue.front(); m_outputQueue.pop_front(); internalSend(msg); #ifdef __DEBUG_NET_DETAIL__ std::clog << "Connection::onWriteOperation send " << msg->getMessageLength() << std::endl; #endif } m_pendingWrite--; } else { std::clog << "Error: [Connection::onWriteOperation] Getting unexpected notification!" << std::endl; // Error. Pending operations counter is 0, but we are getting a // notification!! } } else { m_pendingWrite--; handleWriteError(error); } if(m_closeState == CLOSE_STATE_CLOSING) { if(!closingConnection()) m_connectionLock.lock(); return; } m_connectionLock.unlock(); }
void Connection::internalSend(const OutputMessage_ptr& msg) { protocol->onSendMessage(msg); try { writeTimer.expires_from_now(boost::posix_time::seconds(Connection::write_timeout)); writeTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr<Connection>(shared_from_this()), std::placeholders::_1)); boost::asio::async_write(socket, boost::asio::buffer(msg->getOutputBuffer(), msg->getLength()), std::bind(&Connection::onWriteOperation, shared_from_this(), std::placeholders::_1)); } catch (boost::system::system_error& e) { std::cout << "[Network error - Connection::internalSend] " << e.what() << std::endl; close(FORCE_CLOSE); } }
void Connection::onWriteOperation(OutputMessage_ptr msg, const boost::system::error_code& error) { #ifdef __DEBUG_NET_DETAIL__ std::cout << "onWriteOperation" << std::endl; #endif m_connectionLock.lock(); m_writeTimer.cancel(); TRACK_MESSAGE(msg); msg.reset(); if(error){ handleWriteError(error); } if(m_connectionState != CONNECTION_STATE_OPEN || m_writeError){ closeSocket(); closeConnection(); m_connectionLock.unlock(); return; } --m_pendingWrite; m_connectionLock.unlock(); }
void ProtocolAdmin::adminCommandPayHouses() { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { if (Houses::getInstance().payHouses()) { addLogLine(this, LOGTYPE_EVENT, 1, "pay houses ok"); output->AddByte(AP_MSG_COMMAND_OK); } else { addLogLine(this, LOGTYPE_WARNING, 1, "pay houses fail"); output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString(" "); } OutputMessagePool::getInstance()->send(output); } }
void ProtocolSpectator::disconnectSpectator(const std::string& message) { if (client) { client->removeSpectator(this); player = nullptr; client = nullptr; } OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { output->addByte(0x14); output->addString(message); OutputMessagePool::getInstance()->send(output); } disconnect(); }
void Connection::internalSend(OutputMessage_ptr msg) { try { ++m_pendingWrite; m_writeTimer.expires_from_now(boost::posix_time::seconds(Connection::write_timeout)); m_writeTimer.async_wait( boost::bind(&Connection::handleWriteTimeout, boost::weak_ptr<Connection>(shared_from_this()), boost::asio::placeholders::error)); boost::asio::async_write(getHandle(), boost::asio::buffer(msg->getOutputBuffer(), msg->getMessageLength()), boost::bind(&Connection::onWriteOperation, shared_from_this(), msg, boost::asio::placeholders::error)); } catch (boost::system::system_error& e) { if (m_logError) { LOG_MESSAGE("NETWORK", LOGTYPE_ERROR, 1, e.what()); m_logError = false; } } }
void Connection::internalSend(OutputMessage_ptr msg) { try { ++m_pendingWrite; m_writeTimer.expires_from_now(boost::posix_time::seconds(Connection::write_timeout)); m_writeTimer.async_wait( std::bind(&Connection::handleWriteTimeout, std::weak_ptr<Connection>(shared_from_this()), std::placeholders::_1)); boost::asio::async_write(getHandle(), boost::asio::buffer(msg->getOutputBuffer(), msg->getMessageLength()), std::bind(&Connection::onWriteOperation, shared_from_this(), msg, std::placeholders::_1)); } catch (boost::system::system_error& e) { if (m_logError) { std::cout << "[Network error - Connection::internalSend] " << e.what() << std::endl; m_logError = false; } } }
void ProtocolAdmin::adminCommandSetOwner(const std::string& param) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (output) { boost::char_separator<char> sep(", "); tokenizer cmdtokens(param, sep); tokenizer::iterator cmdit = cmdtokens.begin(); std::string _house, name; _house = parseParams(cmdit, cmdtokens.end()); name = parseParams(cmdit, cmdtokens.end()); trimString(_house); trimString(name); if (House* house = Houses::getInstance().getHouse(atoi(_house.c_str()))) { uint32_t _guid; if (IOLoginData::getInstance()->getGuidByName(_guid, name)) { house->setHouseOwner(_guid); addLogLine(this, LOGTYPE_EVENT, 1, "set " + name + " as new owner of house with id " + _house); output->AddByte(AP_MSG_COMMAND_OK); } else { addLogLine(this, LOGTYPE_WARNING, 1, "Could not find player with name: " + name); output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString("such player does not exists"); } } else { addLogLine(this, LOGTYPE_WARNING, 1, "Could not find house with id: " + _house); output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString("such house does not exists"); } OutputMessagePool::getInstance()->send(output); } }
void OutputMessagePool::configureOutputMessage(OutputMessage_ptr msg, Protocol* protocol, bool autosend) { TRACK_MESSAGE(msg); msg->Reset(); if(autosend) { msg->setState(OutputMessage::STATE_ALLOCATED); m_autoSendOutputMessages.push_back(msg); } else msg->setState(OutputMessage::STATE_ALLOCATED_NO_AUTOSEND); Connection_ptr connection = protocol->getConnection(); assert(connection != NULL); msg->setProtocol(protocol); protocol->addRef(); #ifdef __DEBUG_NET_DETAIL__ std::cout << "Adding reference to protocol - " << protocol << std::endl; #endif msg->setConnection(connection); connection->addRef(); #ifdef __DEBUG_NET_DETAIL__ std::cout << "Adding reference to connection - " << connection << std::endl; #endif msg->setFrame(m_frameTime); }
void ProtocolAdmin::adminCommandSendMail(const std::string& xmlData) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if(output){ TRACK_MESSAGE(output); std::string name; uint32_t depotId; Item* mailItem = createMail(xmlData, name, depotId); if(mailItem){ if(Mailbox::sendItemTo(name, depotId, mailItem)){ output->AddByte(AP_MSG_COMMAND_OK); } else{ output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString("Could not mail item"); } } else{ output->AddByte(AP_MSG_COMMAND_FAILED); output->AddString("Could not mail item"); } OutputMessagePool::getInstance()->send(output); } }