public static ERequestResult HandleRequest(CGameStateController gs, CPlayer player) { if (gs.PlayerState[player] != EPlayerState.UNITIALIZED) { return(ERequestResult.PLAYER_INCONSISTENT_STATE); } MAccountLoginPacket packet = MyMarshal.GetStructure <MAccountLoginPacket>(player.RecvPacket); MAccountFile?nAccFile; AccountCRUD.EErrorMsg accErr = AccountCRUD.TryRead(packet.AccName, out nAccFile); if (accErr == AccountCRUD.EErrorMsg.NO_ERROR) { MLoginSuccessfulPacket answer = PacketHelper.GetEmptyValid <MLoginSuccessfulPacket>(MLoginSuccessfulPacket.Opcode); MAccountFile accFile = nAccFile.Value; answer.AccName = accFile.Info.LoginInfo.AccName; answer.Cargo = accFile.Cargo; answer.CargoCoin = accFile.CargoCoin; for (int i = 0; i < GameBasics.MAXL_ACC_MOB; i++) { unsafe { answer.SelChar.Coin[i] = accFile.MobCore[i].Coin; answer.SelChar.Equip[i] = accFile.MobCore[i].Equip; answer.SelChar.Exp[i] = accFile.MobCore[i].Exp; answer.SelChar.Guild[i] = accFile.MobCore[i].Guild; answer.SelChar.Name[i] = accFile.MobCore[i].Name; answer.SelChar.Score[i] = accFile.MobCore[i].BaseScore; answer.SelChar.SPosX[i] = accFile.MobCore[i].StellarGemPosition.X; answer.SelChar.SPosY[i] = accFile.MobCore[i].StellarGemPosition.Y; } } player.SendPacket(MyMarshal.GetBytes(answer)); } else if (accErr == AccountCRUD.EErrorMsg.ACC_NOT_FOUND) { MTextMessagePacket answer = PacketHelper.GetEmptyValid <MTextMessagePacket>(MTextMessagePacket.Opcode); answer.Message = "Esta conta não foi encontrada."; player.SendPacket(MyMarshal.GetBytes(answer)); } else { return(ERequestResult.UNKNOWN); } return(ERequestResult.NO_ERROR); }
/// <summary> /// Process the newly connected client. /// </summary> /// <param name="client">The newly connected client.</param> private async void ProcessClient_Channel1(TcpClient client) { using (client) using (NetworkStream stream = client.GetStream()) { pServer GameServer = new pServer(stream); CCompoundBuffer packet = GameServer.RecvPacket; try { // Iterate processing incoming GameServer packets until he disconnects. while (GameServer.State != EServerStatus.CLOSED) { int readCount = 0; try { readCount = await stream.ReadAsync(packet.RawBuffer, 0, BaseDef.MAXL_PACKET); } catch (Exception e) { break; } if (readCount != 4 && (readCount < 12 || readCount > BaseDef.MAXL_PACKET)) // Invalid game packet. { // gameController.DisconnectPlayer(GameServer); break; } else // Possible valid game packet chunk. { unsafe { packet.Offset = 0; fixed(byte *PinnedPacketChunk = &packet.RawBuffer[packet.Offset]) { // Check for the init code. if (*(uint *)&PinnedPacketChunk[packet.Offset] == BaseDef.INIT_CODE) { packet.Offset = 4; // If a valid index can't be assigned to the GameServer, disconnect him if (!gameController.TryInsertPlayer(GameServer)) { GameServer.SendPacket(MTextMessagePacket.Create("O servidor está lotado. Tente novamente mais tarde.")); // gameController.DisconnectPlayer(GameServer); continue; } // If all the received chunk resumes to the INIT_CODE, read the next packet. if (readCount == 4) { continue; } } // Process all possible packets that were possibly sent together. while (packet.Offset < readCount && GameServer.State != EServerStatus.CLOSED) { // Check if the game packet size is bigger than the remaining received chunk. if (packet.ReadNextUShort(0) > readCount - packet.Offset || packet.ReadNextUShort(0) < 12) { throw new Exception("Pacote recebido inválido.O pacote de leitura é maior que o restante do pacote."); //continue; } // Tries to decrypt the packet. if (!PacketSecurity.Decrypt(packet)) { throw new Exception($"Não é possível descriptografar um pacote recebido de {client.Client.RemoteEndPoint}."); } // W2Log.Write(String.Format("Em processamento recv packet {{0x{0:X}/{1}}} a partir de {2}.", packet.ReadNextUShort(4), packet.ReadNextUShort(0), client.Client.RemoteEndPoint), ELogType.NETWORK); // Process the incoming packet. DBResult requestResult = gameController.ProcessPlayerRequest(GameServer); // Treat the processing packet return. switch (requestResult) { //case DBResult.PACKET_NOT_HANDLED: //{ // W2Log.Write(String.Format("Recv packet {{0x{0:X}/{1}}} de {2} não foi processado.", // packet.ReadNextUShort(4), packet.ReadNextUShort(0), client.Client.RemoteEndPoint), ELogType.NETWORK); // byte[] rawPacket = new byte[packet.ReadNextUShort(0)]; // for (int i = 0; i < rawPacket.Length; i++) // rawPacket[i] = PinnedPacketChunk[i + packet.Offset]; // File.WriteAllBytes($@"..\..\{packet.ReadNextUShort(4)}.bin", // rawPacket); // break; //} case DBResult.CHECKSUM_FAIL: { W2Log.Write($"Recibo de pacote de { client.Client.RemoteEndPoint} tem soma de verificação inválida.", ELogType.CRITICAL_ERROR); //gameController.DisconnectPlayer(GameServer); break; } case DBResult.PLAYER_INCONSISTENT_STATE: { W2Log.Write($"Um GameServer foi desconectado devido ao DBResult inconsistente.", ELogType.CRITICAL_ERROR); //gameController.DisconnectPlayer(GameServer); break; } case DBResult.WAIT: { break; } } // Correct the offset to process the next packet in the received chunk. PlayersCount.Text = gameController.PlayerCount.ToString(); GameServer.RecvPacket.Offset += packet.ReadNextUShort(0); } } } } } } catch (Exception ex) { W2Log.Write($"Uma exceção não tratada aconteceu processando o GameServer {GameServer.Index}. MSG: {ex.Message}", ELogType.CRITICAL_ERROR); } finally { // gameController.DisconnectPlayer(GameServer); } } }
/// <summary> /// Process the newly connected client. /// </summary> /// <param name="client">The newly connected client.</param> private async void ProcessClient_Channel1(TcpClient client) { using (client) using (NetworkStream stream = client.GetStream()) { CPlayer player = new CPlayer(stream); CCompoundBuffer packet = player.RecvPacket; try { // Iterate processing incoming player packets until he disconnects. while (player.State != EPlayerState.CLOSED) { int readCount = await stream.ReadAsync(packet.RawBuffer, 0, NetworkBasics.MAXL_PACKET); if (readCount != 4 && (readCount < 12 || readCount > NetworkBasics.MAXL_PACKET)) // Invalid game packet. { gameController.DisconnectPlayer(player); break; } else // Possible valid game packet chunk. { unsafe { packet.Offset = 0; fixed(byte *PinnedPacketChunk = &packet.RawBuffer[packet.Offset]) { // Check for the init code. if (*(uint *)&PinnedPacketChunk[packet.Offset] == NetworkBasics.INIT_CODE) { packet.Offset = 4; // If a valid index can't be assigned to the player, disconnect him if (!gameController.TryInsertPlayer(player)) { player.SendPacket(MTextMessagePacket.Create("O servidor está lotado. Tente novamente mais tarde.")); gameController.DisconnectPlayer(player); continue; } // If all the received chunk resumes to the INIT_CODE, read the next packet. if (readCount == 4) { continue; } } // Process all possible packets that were possibly sent together. while (packet.Offset < readCount && player.State != EPlayerState.CLOSED) { // Check if the game packet size is bigger than the remaining received chunk. if (packet.ReadNextUShort(0) > readCount - packet.Offset || packet.ReadNextUShort(0) < 12) { throw new Exception("Invalid received packet. Reading packet is bigger than the remaining chunk."); } // Tries to decrypt the packet. if (!PacketSecurity.Decrypt(packet)) { throw new Exception($"Can't decrypt a packet received from {client.Client.RemoteEndPoint}."); } W2Log.Write(String.Format("Processing recv packet {{0x{0:X}/{1}}} from {2}.", packet.ReadNextUShort(4), packet.ReadNextUShort(0), client.Client.RemoteEndPoint), ELogType.NETWORK); // Process the incoming packet. EPlayerRequestResult requestResult = gameController.ProcessPlayerRequest(player); // Treat the processing packet return. switch (requestResult) { case EPlayerRequestResult.PACKET_NOT_HANDLED: { W2Log.Write(String.Format("Recv packet {{0x{0:X}/{1}}} from {2} didn't was processed.", packet.ReadNextUShort(4), packet.ReadNextUShort(0), client.Client.RemoteEndPoint), ELogType.NETWORK); byte[] rawPacket = new byte[packet.ReadNextUShort(0)]; for (int i = 0; i < rawPacket.Length; i++) { rawPacket[i] = PinnedPacketChunk[i + packet.Offset]; } File.WriteAllBytes($@"..\..\Dumped Packets\Inner Packets\{packet.ReadNextUShort(4)}.bin", rawPacket); break; } case EPlayerRequestResult.CHECKSUM_FAIL: { W2Log.Write($"Recv packet from {client.Client.RemoteEndPoint} have invalid checksum.", ELogType.CRITICAL_ERROR); gameController.DisconnectPlayer(player); break; } case EPlayerRequestResult.PLAYER_INCONSISTENT_STATE: { W2Log.Write($"A player was disconnected due to inconsistent PlayerState.", ELogType.CRITICAL_ERROR); gameController.DisconnectPlayer(player); break; } } // Correct the offset to process the next packet in the received chunk. player.RecvPacket.Offset += packet.ReadNextUShort(0); } } } } } } catch (Exception ex) { W2Log.Write($"An unhandled exception happened processing the player {player.Index}. MSG: {ex.Message}", ELogType.CRITICAL_ERROR); } finally { gameController.DisconnectPlayer(player); } } }
private EPlayerRequestResult CGameStateController_OnProcessPacket(CGameStateController gs, CPlayer player) { switch (player.RecvPacket.ReadNextUShort(4)) { case MAccountLoginPacket.Opcode: { if (player.State != EPlayerState.WAITING_TO_LOGIN) { return(EPlayerRequestResult.PLAYER_INCONSISTENT_STATE); } MAccountLoginPacket packet = W2Marshal.GetStructure <MAccountLoginPacket>(player.RecvPacket); MAccountFile? nAccFile; AccountCRUD.EResult accErr = AccountCRUD.TryRead(packet.AccName, out nAccFile); if (accErr != AccountCRUD.EResult.NO_ERROR) { // if account doesn't exist... if (accErr == AccountCRUD.EResult.ACC_NOT_FOUND) { // create a new account file MAccountFile newAccFile = W2Marshal.CreateEmpty <MAccountFile>(); // set the username & password newAccFile.Info.LoginInfo.AccName = packet.AccName; newAccFile.Info.LoginInfo.Password = packet.Password; AccountCRUD.EResult createAccErr = AccountCRUD.TrySaveAccount(ref newAccFile); if (createAccErr == AccountCRUD.EResult.NO_ERROR) { accErr = AccountCRUD.TryRead(packet.AccName, out nAccFile); if (accErr != AccountCRUD.EResult.NO_ERROR) { return(EPlayerRequestResult.UNKNOWN); } } else if (createAccErr == AccountCRUD.EResult.ACC_NOT_SAVED) { MTextMessagePacket createFailedAnswer = W2Marshal.GetEmptyValid <MTextMessagePacket>(MTextMessagePacket.Opcode); createFailedAnswer.Message = "Não foi possível criar a conta."; player.SendPacket(createFailedAnswer); return(EPlayerRequestResult.NO_ERROR); } else if (createAccErr == AccountCRUD.EResult.UNKNOWN) { return(EPlayerRequestResult.UNKNOWN); } } else { return(EPlayerRequestResult.UNKNOWN); } } MLoginSuccessfulPacket answer = W2Marshal.GetEmptyValid <MLoginSuccessfulPacket>(MLoginSuccessfulPacket.Opcode); MAccountFile accFile = nAccFile.Value; answer.AccName = accFile.Info.LoginInfo.AccName; answer.Cargo = accFile.Cargo; answer.CargoCoin = accFile.CargoCoin; for (int i = 0; i < GameBasics.MAXL_ACC_MOB; i++) { unsafe { answer.SelChar.Coin[i] = accFile.MobCore[i].Coin; answer.SelChar.Equip[i] = accFile.MobCore[i].Equip; answer.SelChar.Exp[i] = accFile.MobCore[i].Exp; answer.SelChar.Guild[i] = accFile.MobCore[i].Guild; answer.SelChar.Name[i] = accFile.MobCore[i].Name; answer.SelChar.Score[i] = accFile.MobCore[i].BaseScore; answer.SelChar.SPosX[i] = accFile.MobCore[i].StellarGemPosition.X; answer.SelChar.SPosY[i] = accFile.MobCore[i].StellarGemPosition.Y; } } player.SendPacket(answer); player.State = EPlayerState.SEL_CHAR; return(EPlayerRequestResult.NO_ERROR); } default: return(EPlayerRequestResult.PACKET_NOT_HANDLED); } }
private EPlayerRequestResult CGameStateController_OnProcessPacket(CGameStateController gs, CPlayer player) { switch (player.RecvPacket.ReadNextUShort(4)) { case MAccountLoginPacket.Opcode: { if (player.State != EPlayerState.WAITING_TO_LOGIN) { return(EPlayerRequestResult.PLAYER_INCONSISTENT_STATE); } MAccountLoginPacket packet = W2Marshal.GetStructure <MAccountLoginPacket>(player.RecvPacket); MAccountFile? nAccFile; AccountCRUD.EResult accErr = AccountCRUD.TryRead(packet.AccName, out nAccFile); if (accErr == AccountCRUD.EResult.NO_ERROR) { MLoginSuccessfulPacket answer = W2Marshal.GetEmptyValid <MLoginSuccessfulPacket>(MLoginSuccessfulPacket.Opcode); MAccountFile accFile = nAccFile.Value; answer.AccName = accFile.Info.LoginInfo.AccName; answer.Cargo = accFile.Cargo; answer.CargoCoin = accFile.CargoCoin; for (int i = 0; i < GameBasics.MAXL_ACC_MOB; i++) { unsafe { answer.SelChar.Coin[i] = accFile.MobCore[i].Coin; answer.SelChar.Equip[i] = accFile.MobCore[i].Equip; answer.SelChar.Exp[i] = accFile.MobCore[i].Exp; answer.SelChar.Guild[i] = accFile.MobCore[i].Guild; answer.SelChar.Name[i] = accFile.MobCore[i].Name; answer.SelChar.Score[i] = accFile.MobCore[i].BaseScore; answer.SelChar.SPosX[i] = accFile.MobCore[i].StellarGemPosition.X; answer.SelChar.SPosY[i] = accFile.MobCore[i].StellarGemPosition.Y; } } player.SendPacket(answer); player.State = EPlayerState.SEL_CHAR; } else if (accErr == AccountCRUD.EResult.ACC_NOT_FOUND) { MTextMessagePacket answer = W2Marshal.GetEmptyValid <MTextMessagePacket>(MTextMessagePacket.Opcode); answer.Message = "Esta conta não foi encontrada."; player.SendPacket(answer); } else { return(EPlayerRequestResult.UNKNOWN); } return(EPlayerRequestResult.NO_ERROR); } default: return(EPlayerRequestResult.PACKET_NOT_HANDLED); } }