void ProtocolManager::parsePacket(NetworkMessage& msg) { if(g_game.getGameState() == GAMESTATE_SHUTDOWN) { getConnection()->close(); return; } uint8_t recvbyte = msg.get<char>(); OutputMessage_ptr output = getOutputBuffer(); if(!output) return; TRACK_MESSAGE(output); switch(m_state) { case NO_LOGGED_IN: { if((time(NULL) - m_startTime) > 30000) { //login timeout getConnection()->close(); addLogLine(LOGTYPE_WARNING, "Login timeout"); return; } if(m_loginTries > 3) { output->put<char>(MP_MSG_ERROR); output->putString("Too many login attempts"); getConnection()->send(output); getConnection()->close(); addLogLine(LOGTYPE_WARNING, "Too many login attempts"); return; } if(recvbyte != MP_MSG_LOGIN) { output->put<char>(MP_MSG_ERROR); output->putString("You are not logged in"); getConnection()->send(output); getConnection()->close(); addLogLine(LOGTYPE_WARNING, "Wrong command while not logged in"); return; } break; } case LOGGED_IN: break; default: { getConnection()->close(); addLogLine(LOGTYPE_ERROR, "No valid connection state"); return; } } m_lastCommand = time(NULL); switch(recvbyte) { case MP_MSG_LOGIN: { if(m_state == NO_LOGGED_IN) { std::string pass = msg.getString(), word = g_config.getString(ConfigManager::MANAGER_PASSWORD); _encrypt(word, false); if(pass == word) { if(!Manager::getInstance()->loginConnection(this)) { output->put<char>(MP_MSG_FAILURE); output->putString("Unknown connection"); getConnection()->send(output); getConnection()->close(); addLogLine(LOGTYPE_ERROR, "Login failed due to unknown connection"); return; } else { m_state = LOGGED_IN; output->put<char>(MP_MSG_USERS); addLogLine(LOGTYPE_EVENT, "Logged in, sending users"); std::map<uint32_t, std::string> users; for(AutoList<Player>::iterator it = Player::autoList.begin(); it != Player::autoList.end(); ++it) { if(!it->second->isRemoved()) users[it->first] = it->second->getName(); } output->put<uint16_t>(users.size()); for(std::map<uint32_t, std::string>::iterator it = users.begin(); it != users.end(); ++it) { output->put<uint32_t>(it->first); output->putString(it->second); } } } else { output->put<char>(MP_MSG_FAILURE); output->putString("Wrong password"); m_loginTries++; addLogLine(LOGTYPE_EVENT, "Login failed due to wrong password (" + pass + ")"); } } else { output->put<char>(MP_MSG_FAILURE); output->putString("Cannot login right now!"); addLogLine(LOGTYPE_ERROR, "Wrong state at login"); } break; } case MP_MSG_LOGOUT: { output->put<char>(MP_MSG_BYE); output->putString("Bye, bye!"); getConnection()->send(output); getConnection()->close(); addLogLine(LOGTYPE_EVENT, "Logout"); return; } case MP_MSG_KEEP_ALIVE: break; case MP_MSG_PING: output->put<char>(MP_MSG_PONG); break; case MP_MSG_LUA: { std::string script = msg.getString(); if(!Manager::getInstance()->execute(script)) { output->put<char>(MP_MSG_FAILURE); output->putString("Unable to reserve enviroment for Lua script"); addLogLine(LOGTYPE_ERROR, "Unable to reserve enviroment for Lua script"); } else { output->put<char>(MP_MSG_SUCCESS); addLogLine(LOGTYPE_EVENT, "Executed Lua script"); } break; } case MP_MSG_USER_INFO: { uint32_t playerId = msg.get<uint32_t>(); if(Player* player = g_game.getPlayerByID(playerId)) { output->put<char>(MP_MSG_USER_DATA); output->put<uint32_t>(playerId); output->put<uint32_t>(player->getGroupId()); output->put<uint32_t>(player->getVocationId()); output->put<uint32_t>(player->getLevel()); output->put<uint32_t>(player->getMagicLevel()); // TODO? } else { output->put<char>(MP_MSG_FAILURE); output->putString("Player not found"); } } case MP_MSG_CHAT_REQUEST: { output->put<char>(MP_MSG_CHAT_LIST); ChannelList list = g_chat.getPublicChannels(); output->put<uint16_t>(list.size()); for(ChannelList::const_iterator it = list.begin(); it != list.end(); ++it) { output->put<uint16_t>((*it)->getId()); output->putString((*it)->getName()); output->put<uint16_t>((*it)->getFlags()); output->put<uint16_t>((*it)->getUsers().size()); } break; } case MP_MSG_CHAT_OPEN: { ChatChannel* channel = NULL; uint16_t channelId = msg.get<uint16_t>(); if((channel = g_chat.getChannelById(channelId)) && g_chat.isPublicChannel(channelId)) { m_channels |= (uint32_t)channelId; output->put<char>(MP_MSG_CHAT_USERS); UsersMap users = channel->getUsers(); output->put<uint16_t>(users.size()); for(UsersMap::const_iterator it = users.begin(); it != users.end(); ++it) output->put<uint32_t>(it->first); } else { output->put<char>(MP_MSG_FAILURE); output->putString("Invalid channel"); } break; } case MP_MSG_CHAT_CLOSE: { uint16_t channelId = msg.get<uint16_t>(); if(g_chat.getChannelById(channelId) && g_chat.isPublicChannel(channelId)) { m_channels &= ~(uint32_t)channelId; output->put<char>(MP_MSG_SUCCESS); } else { output->put<char>(MP_MSG_FAILURE); output->putString("Invalid channel"); } break; } case MP_MSG_CHAT_TALK: { std::string name = msg.getString(); uint16_t channelId = msg.get<uint16_t>(); SpeakClasses type = (SpeakClasses)msg.get<char>(); std::string message = msg.getString(); ChatChannel* channel = NULL; if((channel = g_chat.getChannelById(channelId)) && g_chat.isPublicChannel(channelId)) { if(!channel->talk(name, type, message)) { output->put<char>(MP_MSG_FAILURE); output->putString("Could not talk to channel"); } else output->put<char>(MP_MSG_SUCCESS); } else { output->put<char>(MP_MSG_FAILURE); output->putString("Invalid channel"); } break; } default: { output->put<char>(MP_MSG_ERROR); output->putString("Unknown command"); addLogLine(LOGTYPE_WARNING, "Unknown command"); break; } } }