void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg)
{
if (g_game.getGameState() == GAME_STATE_SHUTDOWN) {
disconnect();
return;
}
OperatingSystem_t operatingSystem = static_cast<OperatingSystem_t>(msg.get<uint16_t>());
version = msg.get<uint16_t>();
msg.skipBytes(7); // U32 client version, U8 client type, U16 dat revision
if (!Protocol::RSA_decrypt(msg)) {
disconnect();
return;
}
uint32_t key[4];
key[0] = msg.get<uint32_t>();
key[1] = msg.get<uint32_t>();
key[2] = msg.get<uint32_t>();
key[3] = msg.get<uint32_t>();
enableXTEAEncryption();
setXTEAKey(key);
if (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) {
NetworkMessage opcodeMessage;
opcodeMessage.addByte(0x32);
opcodeMessage.addByte(0x00);
opcodeMessage.add<uint16_t>(0x00);
writeToOutputBuffer(opcodeMessage);
}
msg.skipBytes(1); // gamemaster flag
std::string sessionKey = msg.getString();
auto sessionArgs = explodeString(sessionKey, "\n", 4);
if (sessionArgs.size() != 4) {
disconnect();
return;
}
std::string& accountName = sessionArgs[0];
std::string& password = sessionArgs[1];
std::string& token = sessionArgs[2];
uint32_t tokenTime = strtoul(sessionArgs[3].c_str(), NULL, 10);
if (accountName.empty()) {
disconnectClient("You must enter your account name.");
return;
}
std::string characterName = msg.getString();
uint32_t timeStamp = msg.get<uint32_t>();
uint8_t randNumber = msg.getByte();
if (challengeTimestamp != timeStamp || challengeRandom != randNumber) {
disconnect();
return;
}
if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) {
std::ostringstream ss;
ss << "Only clients with protocol " << CLIENT_VERSION_STR << " allowed!";
disconnectClient(ss.str());
return;
}
if (g_game.getGameState() == GAME_STATE_STARTUP) {
disconnectClient("Gameworld is starting up. Please wait.");
return;
}
if (g_game.getGameState() == GAME_STATE_MAINTAIN) {
disconnectClient("Gameworld is under maintenance. Please re-connect in a while.");
return;
}
BanInfo banInfo;
if (IOBan::isIpBanned(getIP(), banInfo)) {
if (banInfo.reason.empty()) {
banInfo.reason = "(none)";
}
std::ostringstream ss;
ss << "Your IP has been banned until " << formatDateShort(banInfo.expiresAt) << " by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason;
disconnectClient(ss.str());
return;
}
uint32_t accountId = IOLoginData::gameworldAuthentication(accountName, password, characterName, token, tokenTime);
if (accountId == 0) {
disconnectClient("Account name or password is not correct.");
return;
}
g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::login, getThis(), characterName, accountId, operatingSystem)));
}