/// <summary> /// A cityserver requested a decryptionkey for a client! /// </summary> public static void HandleKeyFetch(ref LoginListener Listener, PacketStream P, CityServerClient Client) { string AccountName = P.ReadString(); byte[] EncKey = new byte[1]; foreach (LoginClient Cl in Listener.Clients) { if (Cl.Username == AccountName) { EncKey = Cl.EncKey; if (Cl.CurrentlyActiveSim.CreatedThisSession) { //TODO: Update the DB to reflect the city that // this sim resides in. Database.UpdateCityForCharacter(Cl.CurrentlyActiveSim.Name, Client.ServerInfo.Name); } } } PacketStream OutPacket = new PacketStream(0x01, 0x00); OutPacket.WriteByte((byte)0x01); OutPacket.WriteByte((byte)(EncKey.Length + 2)); OutPacket.WriteByte((byte)EncKey.Length); OutPacket.Write(EncKey, 0, EncKey.Length); Client.Send(OutPacket.ToArray()); //For now, assume client has already disconnected and doesn't need to be disconnected manually. Listener.TransferringClients.Remove(Client); }
public static void HandleCharacterCreate(PacketStream P, ref LoginClient Client, ref CityServerListener CServerListener) { byte PacketLength = (byte)P.ReadByte(); //Length of the unencrypted data, excluding the header (ID, length, unencrypted length). byte UnencryptedLength = (byte)P.ReadByte(); P.DecryptPacket(Client.EncKey, Client.CryptoService, UnencryptedLength); Logger.LogDebug("Received CharacterCreate!"); string AccountName = P.ReadString(); Sim Char = new Sim(P.ReadString()); Char.Timestamp = P.ReadString(); Char.Name = P.ReadString(); Char.Sex = P.ReadString(); Char.CreatedThisSession = true; Client.CurrentlyActiveSim = Char; switch (Character.CreateCharacter(Char)) { case CharacterCreationStatus.NameAlreadyExisted: //TODO: Send packet. break; case CharacterCreationStatus.ExceededCharacterLimit: //TODO: Send packet. break; } }
/// <summary> /// A cityserver logged in! /// </summary> public static void HandleCityServerLogin(PacketStream P, ref CityServerClient Client) { byte PacketLength = (byte)P.ReadByte(); string Name = P.ReadString(); string Description = P.ReadString(); ulong Thumbnail = P.ReadUInt64(); string IP = P.ReadString(); int Port = P.ReadInt32(); CityServerInfo Info = new CityServerInfo(Name, Description, Thumbnail, IP, Port); Client.ServerInfo = Info; }
/// <summary> /// A cityserver logged in! /// </summary> public static void HandleCityServerLogin(PacketStream P, ref CityServerClient Client) { byte PacketLength = (byte)P.ReadByte(); Logger.LogDebug("CityServer logged in!"); string Name = P.ReadString(); string Description = P.ReadString(); ulong Thumbnail = P.ReadUInt64(); Guid GUID = new Guid(); string UUID = GUID.ToString(); ulong Map = P.ReadUInt64(); string IP = P.ReadString(); int Port = P.ReadInt32(); CityInfo Info = new CityInfo(Name, Description, Thumbnail, UUID, Map, IP, Port); Client.ServerInfo = Info; }
/// <summary> /// Called by LoginClient instances /// when they've received some new data /// (a new packet). Should not be called /// from anywhere else. /// </summary> /// <param name="P"></param> public void OnReceivedData(PacketStream P, LoginClient Client) { OnReceiveEvent(P, Client); }
public void OnReceivedData(IAsyncResult AR) { //base.OnReceivedData(AR); //Not needed for this application! try { Socket Sock = (Socket)AR.AsyncState; int NumBytesRead = Sock.EndReceive(AR); if (NumBytesRead > 0) { byte[] TmpBuf = new byte[NumBytesRead]; Buffer.BlockCopy(m_RecvBuffer, 0, TmpBuf, 0, NumBytesRead); //The packet is given an ID of 0x00 because its ID is currently unknown. PacketStream TempPacket = new PacketStream(0x00, NumBytesRead, TmpBuf); byte ID = TempPacket.PeekByte(0); int PacketLength = 0; bool FoundMatchingID = false; /*foreach (KeyValuePair<byte, int> Pair in m_PacketIDs) { if (ID == Pair.Key) { Console.WriteLine("Found matching Packet ID!"); FoundMatchingID = true; PacketLength = Pair.Value; break; } }*/ FoundMatchingID = FindMatchingPacketID(ID); if (FoundMatchingID) { PacketLength = m_PacketIDs[ID]; Logger.LogInfo("Found matching PacketID!\r\n\r\n"); if (NumBytesRead == PacketLength) { Logger.LogInfo("Got packet - exact length!\r\n\r\n"); m_RecvBuffer = new byte[11024]; m_Listener.OnReceivedData(new PacketStream(ID, PacketLength, TempPacket.ToArray()), this); } else if (NumBytesRead < PacketLength) { m_TempPacket = new PacketStream(ID, PacketLength); byte[] TmpBuffer = new byte[NumBytesRead]; //Store the number of bytes that were read in the temporary buffer. Logger.LogInfo("Got data, but not a full packet - stored " + NumBytesRead.ToString() + "bytes!\r\n\r\n"); Buffer.BlockCopy(m_RecvBuffer, 0, TmpBuffer, 0, NumBytesRead); m_TempPacket.WriteBytes(TmpBuffer); //And reset the buffers! m_RecvBuffer = new byte[11024]; TmpBuffer = null; } else if (PacketLength == 0) { Logger.LogInfo("Received variable length packet!\r\n"); if (NumBytesRead > 2) { PacketLength = TempPacket.PeekByte(1); if (NumBytesRead == PacketLength) { Logger.LogInfo("Received exact number of bytes for packet!\r\n"); m_RecvBuffer = new byte[11024]; m_TempPacket = null; m_Listener.OnReceivedData(new PacketStream(ID, PacketLength, TempPacket.ToArray()), this); } else if (NumBytesRead < PacketLength) { Logger.LogInfo("Didn't receive entire packet - stored: " + PacketLength + " bytes!\r\n"); TempPacket.SetLength(PacketLength); m_TempPacket = TempPacket; m_RecvBuffer = new byte[11024]; } else if (NumBytesRead > PacketLength) { Logger.LogInfo("Received more bytes than needed for packet. Excess: " + (NumBytesRead - PacketLength) + "\r\n"); byte[] TmpBuffer = new byte[NumBytesRead - PacketLength]; Buffer.BlockCopy(TempPacket.ToArray(), 0, TmpBuffer, 0, TmpBuffer.Length); m_TempPacket = new PacketStream(TmpBuffer[0], NumBytesRead - PacketLength, TmpBuffer); byte[] PacketBuffer = new byte[PacketLength]; Buffer.BlockCopy(TempPacket.ToArray(), 0, PacketBuffer, 0, PacketBuffer.Length); m_RecvBuffer = new byte[11024]; m_Listener.OnReceivedData(new PacketStream(ID, PacketLength, PacketBuffer), this); } } } } else { if (m_TempPacket != null) { if (m_TempPacket.Length < m_TempPacket.BufferLength) { //Received the exact number of bytes needed to complete the stored packet. if ((m_TempPacket.BufferLength + NumBytesRead) == m_TempPacket.Length) { byte[] TmpBuffer = new byte[NumBytesRead]; Buffer.BlockCopy(m_RecvBuffer, 0, TmpBuffer, 0, NumBytesRead); m_RecvBuffer = new byte[11024]; TmpBuffer = null; } //Received more than the number of bytes needed to complete the packet! else if ((m_TempPacket.BufferLength + NumBytesRead) > m_TempPacket.Length) { int Target = (int)((m_TempPacket.BufferLength + NumBytesRead) - m_TempPacket.Length); byte[] TmpBuffer = new byte[Target]; Buffer.BlockCopy(m_RecvBuffer, 0, TmpBuffer, 0, Target); m_TempPacket.WriteBytes(TmpBuffer); //Now we have a full packet, so call the received event! m_Listener.OnReceivedData(new PacketStream(m_TempPacket.PacketID, (int)m_TempPacket.Length, m_TempPacket.ToArray()), this); //Copy the remaining bytes in the receiving buffer. TmpBuffer = new byte[NumBytesRead - Target]; Buffer.BlockCopy(m_RecvBuffer, Target, TmpBuffer, 0, (NumBytesRead - Target)); //Give the temporary packet an ID of 0x00 since we don't know its ID yet. TempPacket = new PacketStream(0x00, NumBytesRead - Target, TmpBuffer); ID = TempPacket.PeekByte(0); //This SHOULD be an existing ID, but let's sanity-check it... if (FindMatchingPacketID(ID)) { m_TempPacket = new PacketStream(ID, m_PacketIDs[ID], TempPacket.ToArray()); //Congratulations, you just received another packet! if (m_TempPacket.Length == m_TempPacket.BufferLength) { m_Listener.OnReceivedData(new PacketStream(m_TempPacket.PacketID, (int)m_TempPacket.Length, m_TempPacket.ToArray()), this); //No more data to store on this read, so reset everything... m_TempPacket = null; TmpBuffer = null; m_RecvBuffer = new byte[11024]; } } else { //Houston, we have a problem (this should never occur)! } } } } } } else { //Client disconnected! //For now, assume that client initiated a transfer. m_Listener.TransferClient(this); } m_Socket.BeginReceive(m_RecvBuffer, 0, m_RecvBuffer.Length, SocketFlags.None, new AsyncCallback(OnReceivedData), m_Socket); } catch (SocketException) { Disconnect(); } }
/// <summary> /// Handles incoming packets from a CityServer. /// </summary> private void m_CServerListener_OnReceiveEvent(PacketStream P, ref CityServerClient Client) { byte ID = (byte)P.ReadByte(); switch (ID) { case 0x00: CityServerPacketHandlers.HandleCityServerLogin(P, ref Client); break; case 0x01: CityServerPacketHandlers.HandleKeyFetch(ref NetworkFacade.ClientListener, P, Client); break; case 0x02: CityServerPacketHandlers.HandlePulse(P, ref Client); break; } }
public void OnReceivedData(IAsyncResult AR) { //base.OnReceivedData(AR); //Not needed for this application! try { int NumBytesRead = m_Socket.EndReceive(AR); Logger.LogInfo("Received: " + NumBytesRead.ToString() + " bytes!\r\n\r\n"); //The packet is given an ID of 0x00 because its ID is currently unknown. PacketStream TempPacket = new PacketStream(0x00, NumBytesRead, CreateABuffer(NumBytesRead, m_RecvBuffer)); byte ID = TempPacket.PeekByte(0); int PacketLength = 0; bool FoundMatchingID = false; FoundMatchingID = FindMatchingPacketID(ID); if (FoundMatchingID) { PacketLength = m_PacketIDs[ID]; Logger.LogInfo("Found matching PacketID!\r\n\r\n"); if (NumBytesRead == PacketLength) { Logger.LogInfo("Got packet - exact length!\r\n\r\n"); m_Listener.OnReceivedData(new PacketStream(ID, PacketLength, TempPacket.ToArray()), this); m_RecvBuffer = new byte[11024]; } else if (NumBytesRead < PacketLength) { m_TempPacket = new PacketStream(ID, PacketLength); byte[] TmpBuffer = new byte[NumBytesRead]; //Store the number of bytes that were read in the temporary buffer. Logger.LogInfo("Got data, but not a full packet - stored " + NumBytesRead.ToString() + "bytes!\r\n\r\n"); Buffer.BlockCopy(m_RecvBuffer, 0, TmpBuffer, 0, NumBytesRead); m_TempPacket.WriteBytes(TmpBuffer); //And reset the buffers! m_RecvBuffer = new byte[11024]; TmpBuffer = null; } else if (PacketLength == 0) { } } else { if (m_TempPacket != null) { if (m_TempPacket.Length < m_TempPacket.BufferLength) { //Received the exact number of bytes needed to complete the stored packet. if ((m_TempPacket.BufferLength + NumBytesRead) == m_TempPacket.Length) { byte[] TmpBuffer = new byte[NumBytesRead]; Buffer.BlockCopy(m_RecvBuffer, 0, TmpBuffer, 0, NumBytesRead); m_RecvBuffer = new byte[11024]; TmpBuffer = null; } //Received more than the number of bytes needed to complete the packet! else if ((m_TempPacket.BufferLength + NumBytesRead) > m_TempPacket.Length) { int Target = (int)((m_TempPacket.BufferLength + NumBytesRead) - m_TempPacket.Length); byte[] TmpBuffer = new byte[Target]; Buffer.BlockCopy(m_RecvBuffer, 0, TmpBuffer, 0, Target); m_TempPacket.WriteBytes(TmpBuffer); //Now we have a full packet, so call the received event! m_Listener.OnReceivedData(new PacketStream(m_TempPacket.PacketID, (int)m_TempPacket.Length, m_TempPacket.ToArray()), this); //Copy the remaining bytes in the receiving buffer. TmpBuffer = new byte[NumBytesRead - Target]; Buffer.BlockCopy(m_RecvBuffer, Target, TmpBuffer, 0, (NumBytesRead - Target)); //Give the temporary packet an ID of 0x00 since we don't know its ID yet. TempPacket = new PacketStream(0x00, NumBytesRead - Target, TmpBuffer); ID = TempPacket.PeekByte(0); //This SHOULD be an existing ID, but let's sanity-check it... if (FindMatchingPacketID(ID)) { m_TempPacket = new PacketStream(ID, m_PacketIDs[ID], TempPacket.ToArray()); //Congratulations, you just received another packet! if (m_TempPacket.Length == m_TempPacket.BufferLength) { m_Listener.OnReceivedData(new PacketStream(m_TempPacket.PacketID, (int)m_TempPacket.Length, m_TempPacket.ToArray()), this); //No more data to store on this read, so reset everything... m_TempPacket = null; TmpBuffer = null; m_RecvBuffer = new byte[11024]; } } else { //Houston, we have a problem (this should never occur)! } } } } } m_Socket.BeginReceive(m_RecvBuffer, 0, m_RecvBuffer.Length, SocketFlags.None, new AsyncCallback(OnReceivedData), m_Socket); } catch (SocketException) { Disconnect(); } }
public void OnReceivedData(IAsyncResult AR) { //base.OnReceivedData(AR); //Not needed for this application! try { if (Thread.CurrentThread.IsThreadPoolThread) { Logger.LogDebug("Current thread is threadpool thread."); } else if (Thread.CurrentThread.IsBackground) { Logger.LogDebug("Current thread is background thread."); } Socket Sock = (Socket)AR.AsyncState; int NumBytesRead = Sock.EndReceive(AR); if (NumBytesRead > 0) { byte[] TmpBuf = new byte[NumBytesRead]; Buffer.BlockCopy(m_RecvBuffer, 0, TmpBuf, 0, NumBytesRead); //The packet is given an ID of 0x00 because its ID is currently unknown. PacketStream TempPacket = new PacketStream(0x00, NumBytesRead, TmpBuf); byte ID = TempPacket.PeekByte(0); int PacketLength = 0; bool FoundMatchingID = false; FoundMatchingID = FindMatchingPacketID(ID); if (FoundMatchingID) { PacketLength = m_PacketIDs[ID]; Logger.LogInfo("Found matching PacketID!\r\n\r\n"); if (NumBytesRead == PacketLength) { Logger.LogInfo("Got packet - exact length!\r\n\r\n"); m_RecvBuffer = new byte[11024]; m_Listener.OnReceivedData(new PacketStream(ID, PacketLength, TempPacket.ToArray()), this); } else if (NumBytesRead < PacketLength) { m_TempPacket = new PacketStream(ID, PacketLength); byte[] TmpBuffer = new byte[NumBytesRead]; //Store the number of bytes that were read in the temporary buffer. Logger.LogInfo("Got data, but not a full packet - stored " + NumBytesRead.ToString() + "bytes!\r\n\r\n"); Buffer.BlockCopy(m_RecvBuffer, 0, TmpBuffer, 0, NumBytesRead); m_TempPacket.WriteBytes(TmpBuffer); //And reset the buffers! m_RecvBuffer = new byte[11024]; TmpBuffer = null; } else if (PacketLength == 0) { Logger.LogInfo("Received variable length packet!\r\n"); if (NumBytesRead > 2) { PacketLength = TempPacket.PeekByte(1); if (NumBytesRead == PacketLength) { Logger.LogInfo("Received exact number of bytes for packet!\r\n"); m_RecvBuffer = new byte[11024]; m_TempPacket = null; m_Listener.OnReceivedData(new PacketStream(ID, PacketLength, TempPacket.ToArray()), this); } else if (NumBytesRead < PacketLength) { Logger.LogInfo("Didn't receive entire packet - stored: " + PacketLength + " bytes!\r\n"); TempPacket.SetLength(PacketLength); m_TempPacket = TempPacket; m_RecvBuffer = new byte[11024]; } else if (NumBytesRead > PacketLength) { Logger.LogInfo("Received more bytes than needed for packet. Excess: " + (NumBytesRead - PacketLength) + "\r\n"); byte[] TmpBuffer = new byte[NumBytesRead - PacketLength]; Buffer.BlockCopy(TempPacket.ToArray(), 0, TmpBuffer, 0, TmpBuffer.Length); m_TempPacket = new PacketStream(TmpBuffer[0], NumBytesRead - PacketLength, TmpBuffer); byte[] PacketBuffer = new byte[PacketLength]; Buffer.BlockCopy(TempPacket.ToArray(), 0, PacketBuffer, 0, PacketBuffer.Length); m_RecvBuffer = new byte[11024]; m_Listener.OnReceivedData(new PacketStream(ID, PacketLength, PacketBuffer), this); } } } } else { if (m_TempPacket != null) { if (m_TempPacket.Length < m_TempPacket.BufferLength) { //Received the exact number of bytes needed to complete the stored packet. if ((m_TempPacket.BufferLength + NumBytesRead) == m_TempPacket.Length) { byte[] TmpBuffer = new byte[NumBytesRead]; Buffer.BlockCopy(m_RecvBuffer, 0, TmpBuffer, 0, NumBytesRead); m_RecvBuffer = new byte[11024]; TmpBuffer = null; } //Received more than the number of bytes needed to complete the packet! else if ((m_TempPacket.BufferLength + NumBytesRead) > m_TempPacket.Length) { int Target = (int)((m_TempPacket.BufferLength + NumBytesRead) - m_TempPacket.Length); byte[] TmpBuffer = new byte[Target]; Buffer.BlockCopy(m_RecvBuffer, 0, TmpBuffer, 0, Target); m_TempPacket.WriteBytes(TmpBuffer); //Now we have a full packet, so call the received event! m_Listener.OnReceivedData(new PacketStream(m_TempPacket.PacketID, (int)m_TempPacket.Length, m_TempPacket.ToArray()), this); //Copy the remaining bytes in the receiving buffer. TmpBuffer = new byte[NumBytesRead - Target]; Buffer.BlockCopy(m_RecvBuffer, Target, TmpBuffer, 0, (NumBytesRead - Target)); //Give the temporary packet an ID of 0x00 since we don't know its ID yet. TempPacket = new PacketStream(0x00, NumBytesRead - Target, TmpBuffer); ID = TempPacket.PeekByte(0); //This SHOULD be an existing ID, but let's sanity-check it... if (FindMatchingPacketID(ID)) { m_TempPacket = new PacketStream(ID, m_PacketIDs[ID], TempPacket.ToArray()); //Congratulations, you just received another packet! if (m_TempPacket.Length == m_TempPacket.BufferLength) { m_Listener.OnReceivedData(new PacketStream(m_TempPacket.PacketID, (int)m_TempPacket.Length, m_TempPacket.ToArray()), this); //No more data to store on this read, so reset everything... m_TempPacket = null; TmpBuffer = null; m_RecvBuffer = new byte[11024]; } } else { //Houston, we have a problem (this should never occur)! } } } } } } else { //Client disconnected! //TODO: Figure out if this client was successfully authenticated before transferring. m_Listener.TransferClient(this); } m_Socket.BeginReceive(m_RecvBuffer, 0, m_RecvBuffer.Length, SocketFlags.None, new AsyncCallback(OnReceivedData), m_Socket); } catch (SocketException) { Disconnect(); } }
public static void HandleCityInfoRequest(PacketStream P, LoginClient Client) { byte PacketLength = (byte)P.ReadByte(); //Length of the unencrypted data, excluding the header (ID, length, unencrypted length). byte UnencryptedLength = (byte)P.ReadByte(); P.DecryptPacket(Client.EncKey, Client.CryptoService, UnencryptedLength); //This packet only contains a dummy byte, don't bother reading it. PacketStream Packet = new PacketStream(0x06, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter PacketWriter = new BinaryWriter(PacketData); PacketWriter.Write((byte)NetworkFacade.CServerListener.CityServers.Count); foreach (CityServerClient City in NetworkFacade.CServerListener.CityServers) { PacketWriter.Write(City.ServerInfo.Name); PacketWriter.Write(City.ServerInfo.Description); PacketWriter.Write(City.ServerInfo.IP); PacketWriter.Write(City.ServerInfo.Port); PacketWriter.Write((byte)City.ServerInfo.Status); PacketWriter.Write(City.ServerInfo.Thumbnail); PacketWriter.Write(City.ServerInfo.UUID); PacketWriter.Flush(); } Packet.Write(PacketData.ToArray(), 0, PacketData.ToArray().Length); PacketWriter.Close(); Client.SendEncrypted(0x06, Packet.ToArray()); }
public static void HandleCharacterInfoRequest(ref LoginClient Client, PacketStream P) { ushort PacketLength = (ushort)P.ReadUShort(); //Length of the unencrypted data, excluding the header (ID, length, unencrypted length). ushort UnencryptedLength = (ushort)P.ReadUShort(); P.DecryptPacket(Client.EncKey, Client.CryptoService, UnencryptedLength); Logger.LogDebug("Received CharacterInfoRequest!"); DateTime Timestamp = DateTime.Parse(P.ReadASCII()); //Database.CheckCharacterTimestamp(Client.Username, Client, TimeStamp); Character[] Characters = new Character[]{}; using (var db = DataAccess.Get()) { Characters = db.Characters.GetForAccount(Client.AccountID).ToArray(); } if (Characters != null) { PacketStream Packet = new PacketStream(0x05, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter PacketWriter = new BinaryWriter(PacketData); /** * Whats the point of checking a timestamp here? It saves a few bytes on a packet * sent once per user session. Premature optimization. */ PacketWriter.Write((byte)Characters.Length); foreach(Character avatar in Characters){ PacketWriter.Write(avatar.CharacterID); PacketWriter.Write(avatar.GUID.ToString()); PacketWriter.Write(avatar.LastCached); PacketWriter.Write(avatar.Name); PacketWriter.Write(avatar.Sex); } Packet.Write(PacketData.ToArray(), 0, (int)PacketData.Length); PacketWriter.Close(); Client.SendEncrypted(0x05, Packet.ToArray()); } else //No characters existed for the account. { PacketStream Packet = new PacketStream(0x05, 0); Packet.WriteByte(0x00); //0 characters. Client.SendEncrypted(0x05, Packet.ToArray()); } }
public static void HandleCharacterCreate(ref LoginClient Client, PacketStream P) { ushort PacketLength = (ushort)P.ReadUShort(); //Length of the unencrypted data, excluding the header (ID, length, unencrypted length). ushort UnencryptedLength = (ushort)P.ReadUShort(); P.DecryptPacket(Client.EncKey, Client.CryptoService, UnencryptedLength); Logger.LogDebug("Received CharacterCreate!"); string AccountName = P.ReadString(); //GUID generation should always be done on the server side //You cant trust the client side, it may have been hacked Sim Char = new Sim(Guid.NewGuid()); Char.Timestamp = P.ReadString(); Char.Name = P.ReadString(); Char.Sex = P.ReadString(); Char.CreatedThisSession = true; Client.CurrentlyActiveSim = Char; using (var db = DataAccess.Get()) { var characterModel = new Character(); characterModel.Name = Char.Name; characterModel.Sex = Char.Sex; characterModel.LastCached = Char.Timestamp; characterModel.GUID = Char.GUID; var status = db.Characters.CreateCharacter(characterModel); switch (status) { case CharacterCreationStatus.NameAlreadyExisted: //TODO: Send packet. break; case CharacterCreationStatus.ExceededCharacterLimit: //TODO: Send packet. break; } } }
public static void Handle(PacketStream stream, LoginClient session) { byte ID = (byte)stream.ReadByte(); if (m_Handlers.ContainsKey(ID)) { m_Handlers[ID].Handler(ref session, stream); } }
/** * Actual packet handlers */ public static void HandleLoginRequest(ref LoginClient Client, PacketStream P) { Logger.LogInfo("Received LoginRequest!\r\n"); ushort PacketLength = (ushort)P.ReadUShort(); byte AccountStrLength = (byte)P.ReadByte(); byte[] AccountNameBuf = new byte[AccountStrLength]; P.Read(AccountNameBuf, 0, AccountStrLength); string AccountName = Encoding.ASCII.GetString(AccountNameBuf); Logger.LogInfo("Accountname: " + AccountName + "\r\n"); byte HashLength = (byte)P.ReadByte(); byte[] HashBuf = new byte[HashLength]; P.Read(HashBuf, 0, HashLength); Client.Hash = HashBuf; byte KeyLength = (byte)P.ReadByte(); Client.EncKey = new byte[KeyLength]; P.Read(Client.EncKey, 0, KeyLength); byte Version1 = (byte)P.ReadByte(); byte Version2 = (byte)P.ReadByte(); byte Version3 = (byte)P.ReadByte(); byte Version4 = (byte)P.ReadByte(); Logger.LogInfo("Done reading LoginRequest, checking account...\r\n"); using (var db = DataAccess.Get()) { var account = db.Accounts.GetByUsername(AccountName); if (account == null) { PacketStream OutPacket = new PacketStream(0x02, 2); OutPacket.WriteHeader(); OutPacket.WriteByte(0x01); Client.Send(OutPacket); Logger.LogInfo("Bad accountname - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } if (account.IsCorrectPassword(AccountName, HashBuf)) { //0x01 = InitLoginNotify PacketStream OutPacket = new PacketStream(0x01, 1); OutPacket.WriteHeader(); Client.Username = AccountName; //This is neccessary to encrypt packets. //TODO: Put something else here //Client.Password = Account.GetPassword(AccountName); Client.Send(OutPacket.ToArray()); Logger.LogInfo("Sent InitLoginNotify!\r\n"); } } }
public static void HandlePulse(PacketStream P, ref CityServerClient Client) { if(Client.ServerInfo != null) Client.ServerInfo.Online = true; Client.LastPulseReceived = DateTime.Now; }
/// <summary> /// Callback mehod for CheckCharacterTimestamp. /// This queries for the existence of a particular account /// in the DB and retrieves the character IDs associated with it. /// </summary> private static void EndCheckCharacterID(IAsyncResult AR) { DatabaseAsyncObject AsyncObject = AR.AsyncState as DatabaseAsyncObject; bool FoundAccountName = false; int NumCharacters = 0; int CharacterID1 = 0; int CharacterID2 = 0; int CharacterID3 = 0; using (MySqlDataReader Reader = AsyncObject.MySQLCmd.EndExecuteReader(AR)) { while (Reader.Read()) { if (((string)Reader[0]).ToUpper() == AsyncObject.AccountName.ToUpper()) { FoundAccountName = true; NumCharacters = (int)Reader[1]; if (NumCharacters == 0) break; else if (NumCharacters == 1) CharacterID1 = (int)Reader[2]; else if (NumCharacters == 2) { CharacterID1 = (int)Reader[2]; CharacterID2 = (int)Reader[3]; } else if (NumCharacters == 3) { CharacterID1 = (int)Reader[2]; CharacterID2 = (int)Reader[3]; CharacterID3 = (int)Reader[4]; } if (FoundAccountName == true) break; } } } if (FoundAccountName) { if (NumCharacters > 0) { MySqlCommand Command = new MySqlCommand("SELECT CharacterID, LastCached, Name, Sex FROM Character"); AsyncObject.NumCharacters = NumCharacters; AsyncObject.CharacterID1 = CharacterID1; AsyncObject.CharacterID2 = CharacterID2; AsyncObject.CharacterID3 = CharacterID3; Command.Connection = m_Connection; EndCheckCharacterTimestamp(Command.BeginExecuteReader(System.Data.CommandBehavior.Default)); } else { PacketStream Packet = new PacketStream(0x05, 0); Packet.WriteByte(0x00); //0 characters. AsyncObject.Client.SendEncrypted(0x05, Packet.ToArray()); } } }
public static void HandleCityInfoRequest(ref LoginClient Client, PacketStream P) { ushort PacketLength = (ushort)P.ReadUShort(); //Length of the unencrypted data, excluding the header (ID, length, unencrypted length). ushort UnencryptedLength = (ushort)P.ReadUShort(); P.DecryptPacket(Client.EncKey, Client.CryptoService, UnencryptedLength); //This packet only contains a dummy byte, don't bother reading it. PacketStream Packet = new PacketStream(0x06, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter PacketWriter = new BinaryWriter(PacketData); PacketWriter.Write((byte)NetworkFacade.CServerListener.CityServers.Count); foreach (CityServerClient City in NetworkFacade.CServerListener.CityServers) { PacketWriter.Write((string)City.ServerInfo.Name); PacketWriter.Write((string)City.ServerInfo.Description); PacketWriter.Write((string)City.ServerInfo.IP); PacketWriter.Write((int)City.ServerInfo.Port); //Hack (?) to ensure status is written correctly. switch (City.ServerInfo.Status) { case CityInfoStatus.Ok: PacketWriter.Write((byte)1); break; case CityInfoStatus.Busy: PacketWriter.Write((byte)2); break; case CityInfoStatus.Full: PacketWriter.Write((byte)3); break; case CityInfoStatus.Reserved: PacketWriter.Write((byte)4); break; } PacketWriter.Write((ulong)City.ServerInfo.Thumbnail); PacketWriter.Write((string)City.ServerInfo.UUID); PacketWriter.Write((ulong)City.ServerInfo.Map); PacketWriter.Flush(); } Packet.Write(PacketData.ToArray(), 0, PacketData.ToArray().Length); PacketWriter.Close(); Client.SendEncrypted(0x06, Packet.ToArray()); }
public static void HandleLoginRequest(PacketStream P, ref LoginClient Client) { Logger.LogInfo("Received LoginRequest!\r\n"); byte PacketLength = (byte)P.ReadByte(); byte AccountStrLength = (byte)P.ReadByte(); byte[] AccountNameBuf = new byte[AccountStrLength]; P.Read(AccountNameBuf, 0, AccountStrLength); string AccountName = Encoding.ASCII.GetString(AccountNameBuf); Logger.LogInfo("Accountname: " + AccountName + "\r\n"); byte HashLength = (byte)P.ReadByte(); byte[] HashBuf = new byte[HashLength]; P.Read(HashBuf, 0, HashLength); Client.Hash = HashBuf; byte KeyLength = (byte)P.ReadByte(); Client.EncKey = new byte[KeyLength]; P.Read(Client.EncKey, 0, KeyLength); byte Version1 = (byte)P.ReadByte(); byte Version2 = (byte)P.ReadByte(); byte Version3 = (byte)P.ReadByte(); byte Version4 = (byte)P.ReadByte(); Logger.LogInfo("Done reading LoginRequest, checking account...\r\n"); //Database.CheckAccount(AccountName, Client, HashBuf); if (Account.DoesAccountExist(AccountName) && Account.IsCorrectPassword(AccountName, HashBuf)) { //0x01 = InitLoginNotify PacketStream OutPacket = new PacketStream(0x01, 2); OutPacket.WriteByte(0x01); OutPacket.WriteByte(0x01); Client.Username = AccountName; //This is neccessary to encrypt packets. Client.Password = Account.GetPassword(AccountName); Client.Send(OutPacket.ToArray()); Logger.LogInfo("Sent InitLoginNotify!\r\n"); } else { PacketStream OutPacket = new PacketStream(0x02, 2); P.WriteByte(0x02); P.WriteByte(0x01); Client.Send(P.ToArray()); Logger.LogInfo("Bad accountname - sent SLoginFailResponse!\r\n"); Client.Disconnect(); } }
/// <summary> /// Client requested information about its characters. /// </summary> public static void HandleCharacterInfoRequest(NetworkClient Client, ProcessedPacket P) { Logger.LogInfo("Received CharacterInfoRequest!"); DateTime Timestamp = DateTime.Parse(P.ReadPascalString()); //Database.CheckCharacterTimestamp(Client.Username, Client, TimeStamp); Character[] Characters = new Character[] { }; using (var db = DataAccess.Get()) { var account = db.Accounts.GetByUsername(Client.ClientEncryptor.Username); Characters = db.Characters.GetForAccount((int)account.AccountID).ToArray(); } if (Characters != null) { PacketStream Packet = new PacketStream((byte)PacketType.CHARACTER_LIST, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter PacketWriter = new BinaryWriter(PacketData); int NumChars = 0; foreach (Character avatar in Characters) { //Zero means same, less than zero means T1 is earlier than T2, more than zero means T1 is later. if (DateTime.Compare(Timestamp, DateTime.Parse(avatar.LastCached)) < 0) { NumChars++; PacketWriter.Write((int)avatar.CharacterID); PacketWriter.Write(avatar.GUID.ToString()); PacketWriter.Write(avatar.LastCached); PacketWriter.Write(avatar.Name); PacketWriter.Write(avatar.Sex); PacketWriter.Write(avatar.Description); PacketWriter.Write((ulong)avatar.HeadOutfitID); PacketWriter.Write((ulong)avatar.BodyOutfitID); PacketWriter.Write((byte)avatar.AppearanceType); PacketWriter.Write((string)avatar.CityName); PacketWriter.Write((ulong)avatar.CityThumb); PacketWriter.Write((string)avatar.City); PacketWriter.Write((ulong)avatar.CityMap); PacketWriter.Write((string)avatar.CityIp); PacketWriter.Write((int)avatar.CityPort); } } Packet.WriteByte((byte)NumChars); Packet.Write(PacketData.ToArray(), 0, (int)PacketData.Length); PacketWriter.Close(); Client.SendEncrypted(0x05, Packet.ToArray()); } else //No characters existed for the account. { PacketStream Packet = new PacketStream(0x05, 0); Packet.WriteByte(0x00); //0 characters. Client.SendEncrypted((byte)PacketType.CHARACTER_LIST, Packet.ToArray()); } }
public static void HandleCharacterInfoRequest(PacketStream P, LoginClient Client) { byte PacketLength = (byte)P.ReadByte(); //Length of the unencrypted data, excluding the header (ID, length, unencrypted length). byte UnencryptedLength = (byte)P.ReadByte(); P.DecryptPacket(Client.EncKey, Client.CryptoService, UnencryptedLength); Logger.LogDebug("Received CharacterInfoRequest!"); byte Length = (byte)P.ReadByte(); byte[] StrBuf = new byte[Length]; P.Read(StrBuf, 0, Length - 1); DateTime Timestamp = DateTime.Parse(Encoding.ASCII.GetString(StrBuf)); //Database.CheckCharacterTimestamp(Client.Username, Client, TimeStamp); Character[] Characters = Character.GetCharacters(Client.Username); if (Characters != null) { PacketStream Packet = new PacketStream(0x05, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter PacketWriter = new BinaryWriter(PacketData); //The timestamp for all characters should be equal, so just check the first character. if (Timestamp < DateTime.Parse(Characters[0].LastCached) || Timestamp > DateTime.Parse(Characters[0].LastCached)) { //Write the characterdata into a temporary buffer. if (Characters.Length == 1) { PacketWriter.Write(Characters[0].CharacterID); PacketWriter.Write(Characters[0].GUID); PacketWriter.Write(Characters[0].LastCached); PacketWriter.Write(Characters[0].Name); PacketWriter.Write(Characters[0].Sex); PacketWriter.Flush(); } else if (Characters.Length == 2) { PacketWriter.Write(Characters[0].CharacterID); PacketWriter.Write(Characters[0].GUID); PacketWriter.Write(Characters[0].LastCached); PacketWriter.Write(Characters[0].Name); PacketWriter.Write(Characters[0].Sex); PacketWriter.Write(Characters[1].CharacterID); PacketWriter.Write(Characters[1].GUID); PacketWriter.Write(Characters[1].LastCached); PacketWriter.Write(Characters[1].Name); PacketWriter.Write(Characters[1].Sex); PacketWriter.Flush(); } else if (Characters.Length == 3) { PacketWriter.Write(Characters[0].CharacterID); PacketWriter.Write(Characters[0].GUID); PacketWriter.Write(Characters[0].LastCached); PacketWriter.Write(Characters[0].Name); PacketWriter.Write(Characters[0].Sex); PacketWriter.Write(Characters[1].CharacterID); PacketWriter.Write(Characters[1].GUID); PacketWriter.Write(Characters[1].LastCached); PacketWriter.Write(Characters[1].Name); PacketWriter.Write(Characters[1].Sex); PacketWriter.Write(Characters[2].CharacterID); PacketWriter.Write(Characters[2].GUID); PacketWriter.Write(Characters[2].LastCached); PacketWriter.Write(Characters[2].Name); PacketWriter.Write(Characters[2].Sex); PacketWriter.Flush(); } Packet.WriteByte((byte)Characters.Length); //Total number of characters. Packet.Write(PacketData.ToArray(), 0, (int)PacketData.Length); PacketWriter.Close(); Client.SendEncrypted(0x05, Packet.ToArray()); } } else //No characters existed for the account. { PacketStream Packet = new PacketStream(0x05, 0); Packet.WriteByte(0x00); //0 characters. Client.SendEncrypted(0x05, Packet.ToArray()); } }
/// <summary> /// Client wanted to log in! /// </summary> public static void HandleLoginRequest(NetworkClient Client, ProcessedPacket P) { Logger.LogInfo("Received LoginRequest!\r\n"); byte AccountStrLength = (byte)P.ReadByte(); byte[] AccountNameBuf = new byte[AccountStrLength]; P.Read(AccountNameBuf, 0, AccountStrLength); string AccountName = SanitizeAccount(Encoding.ASCII.GetString(AccountNameBuf)); Logger.LogInfo("Accountname: " + AccountName + "\r\n"); byte HashLength = (byte)P.ReadByte(); byte[] HashBuf = new byte[HashLength]; P.Read(HashBuf, 0, HashLength); if (AccountName == "") { PacketStream OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 2); OutPacket.WriteHeader(); OutPacket.WriteByte(0x01); Client.Send(OutPacket.ToArray()); Logger.LogInfo("Bad accountname - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } using (var db = DataAccess.Get()) { var account = db.Accounts.GetByUsername(AccountName); byte Version1 = (byte)P.ReadByte(); byte Version2 = (byte)P.ReadByte(); byte Version3 = (byte)P.ReadByte(); byte Version4 = (byte)P.ReadByte(); string ClientVersion = Version1.ToString() + "." + Version2.ToString() + "." + Version3.ToString() + "." + Version4.ToString(); if (ClientVersion != GlobalSettings.Default.ClientVersion) { PacketStream OutPacket = new PacketStream((byte)PacketType.INVALID_VERSION, 2); OutPacket.WriteHeader(); OutPacket.WriteByte(0x01); Client.Send(OutPacket.ToArray()); Logger.LogInfo("Bad version - sent SInvalidVersion!\r\n"); Client.Disconnect(); return; } if (!GlobalSettings.Default.CreateAccountsOnLogin) { Logger.LogInfo("Done reading LoginRequest, checking account...\r\n"); if (account == null) { PacketStream OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 2); OutPacket.WriteHeader(); OutPacket.WriteByte(0x01); Client.Send(OutPacket.ToArray()); Logger.LogInfo("Bad accountname - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } else { Client.ClientEncryptor = new ARC4Encryptor(account.Password); } } else { if (account == null) { try { db.Accounts.Create(new Account { AccountName = AccountName.ToLower(), Password = Convert.ToBase64String(HashBuf) }); } catch (Exception) { PacketStream OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 2); OutPacket.WriteHeader(); OutPacket.WriteByte(0x01); Client.Send(OutPacket.ToArray()); Logger.LogInfo("Bad accountname - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } account = db.Accounts.GetByUsername(AccountName); } Client.ClientEncryptor = new ARC4Encryptor(account.Password); } if (account.IsCorrectPassword(AccountName, HashBuf)) { //0x01 = InitLoginNotify PacketStream OutPacket = new PacketStream((byte)PacketType.LOGIN_NOTIFY, 1); OutPacket.WriteHeader(); OutPacket.WriteByte(0x01); Client.ClientEncryptor.Username = AccountName; Client.Send(OutPacket.ToArray()); Logger.LogInfo("Sent InitLoginNotify!\r\n"); } else { PacketStream OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 2); OutPacket.WriteHeader(); OutPacket.WriteByte(0x02); Client.Send(OutPacket.ToArray()); Logger.LogInfo("Bad password - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } } //Client was modified, update it. NetworkFacade.ClientListener.UpdateClient(Client); }
public void Send(PacketStream stream) { this.Send(stream.ToArray()); }
/// <summary> /// Client created a character! /// </summary> public static void HandleCharacterCreate(NetworkClient Client, ProcessedPacket P) { Logger.LogInfo("Received CharacterCreate!"); string AccountName = SanitizeAccount(P.ReadPascalString()); using (var db = DataAccess.Get()) { Account Acc = db.Accounts.GetByUsername(AccountName); //TODO: Send GUID to client... Sim Char = new Sim(Guid.NewGuid()); Char.Timestamp = P.ReadPascalString(); Char.Name = P.ReadPascalString(); Char.Sex = P.ReadPascalString(); Char.Description = P.ReadPascalString(); Char.HeadOutfitID = P.ReadUInt64(); Char.BodyOutfitID = P.ReadUInt64(); Char.Appearance = (AppearanceType)P.ReadByte(); Char.ResidingCity = new CityInfo(P.ReadPascalString(), "", P.ReadUInt64(), P.ReadPascalString(), P.ReadUInt64(), P.ReadPascalString(), P.ReadInt32()); Char.CreatedThisSession = true; var characterModel = new Character(); characterModel.Name = Char.Name; characterModel.Sex = Char.Sex; characterModel.Description = Char.Description; characterModel.LastCached = Char.Timestamp; characterModel.GUID = Char.GUID; characterModel.HeadOutfitID = (long)Char.HeadOutfitID; characterModel.BodyOutfitID = (long)Char.BodyOutfitID; characterModel.AccountID = Acc.AccountID; characterModel.AppearanceType = (int)Char.Appearance; characterModel.City = Char.ResidingCity.UUID; characterModel.CityName = Char.ResidingCity.Name; characterModel.CityThumb = (long)Char.ResidingCity.Thumbnail; characterModel.CityMap = (long)Char.ResidingCity.Map; characterModel.CityIp = Char.ResidingCity.IP; characterModel.CityPort = Char.ResidingCity.Port; var status = db.Characters.CreateCharacter(characterModel); //Need to be variable length, because the success packet contains a token. PacketStream CCStatusPacket = new PacketStream((byte)PacketType.CHARACTER_CREATION_STATUS, 0); switch (status) { case LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted: CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); break; case LoginDataModel.Entities.CharacterCreationStatus.ExceededCharacterLimit: CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.ExceededCharacterLimit); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); break; case LoginDataModel.Entities.CharacterCreationStatus.Success: CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.Success); CCStatusPacket.WritePascalString(Char.GUID.ToString()); Guid Token = Guid.NewGuid(); CCStatusPacket.WritePascalString(Token.ToString()); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); //This actually updates the record, not sure how. Acc.NumCharacters++; foreach (CityServerClient CServer in NetworkFacade.CServerListener.CityServers) { if (CServer.ServerInfo.UUID == Char.ResidingCity.UUID) { PacketStream CServerPacket = new PacketStream(0x01, 0); CServerPacket.WriteHeader(); ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 4 + (Client.RemoteIP.Length + 1) + (Char.GUID.ToString().Length + 1) + (Token.ToString().Length + 1)); CServerPacket.WriteUInt16(PacketLength); CServerPacket.WriteInt32(Acc.AccountID); CServerPacket.WritePascalString(Client.RemoteIP); CServerPacket.WritePascalString(Char.GUID.ToString()); CServerPacket.WritePascalString(Token.ToString()); CServer.Send(CServerPacket.ToArray()); break; } } break; } } //Client was modified, so update it. NetworkFacade.ClientListener.UpdateClient(Client); }
/// <summary> /// Handles incoming packets from connected clients. /// </summary> private void m_Listener_OnReceiveEvent(PacketStream P, LoginClient Client) { byte ID = (byte)P.ReadByte(); switch (ID) { case 0x00: PacketHandlers.HandleLoginRequest(P, ref Client); break; case 0x05: PacketHandlers.HandleCharacterInfoRequest(P, Client); break; case 0x06: PacketHandlers.HandleCityInfoRequest(P, Client); break; case 0x07: PacketHandlers.HandleCharacterCreate(P, ref Client, ref NetworkFacade.CServerListener); break; default: Logger.LogInfo("Received unhandled packet - ID: " + P.PacketID); break; } }
/// <summary> /// Callback-function for CheckAccount(). /// </summary> private static void EndCheckAccountName(IAsyncResult AR) { DatabaseAsyncObject AsyncObject = AR.AsyncState as DatabaseAsyncObject; bool FoundAccountName = false; using (SqlDataReader Reader = AsyncObject.Cmd.EndExecuteReader(AR)) { while (Reader.Read()) { if (((string)Reader[0]).ToUpper() == AsyncObject.AccountName.ToUpper()) { FoundAccountName = true; AsyncObject.Password = (string)Reader[1]; break; } } } if (FoundAccountName == true) { //0x01 = InitLoginNotify PacketStream P = new PacketStream(0x01, 2); SaltedHash SHash = new SaltedHash(new SHA512Managed(), AsyncObject.AccountName.Length); if (SHash.VerifyHash(Encoding.ASCII.GetBytes(AsyncObject.Password.ToUpper()), AsyncObject.Hash, Encoding.ASCII.GetBytes(AsyncObject.AccountName))) { AsyncObject.Client.Username = AsyncObject.AccountName.ToUpper(); AsyncObject.Client.Password = AsyncObject.Password.ToUpper(); P.WriteByte(0x01); P.WriteByte(0x01); } else //The client's password was wrong. { PacketStream RejectPacket = new PacketStream(0x02, 2); RejectPacket.WriteByte(0x02); RejectPacket.WriteByte(0x02); AsyncObject.Client.Send(RejectPacket.ToArray()); Logger.LogInfo("Bad password - sent SLoginFailResponse!\r\n"); return; } AsyncObject.Client.Send(P.ToArray()); Logger.LogInfo("Sent InitLoginNotify!\r\n"); } else { PacketStream P = new PacketStream(0x02, 2); P.WriteByte(0x02); P.WriteByte(0x01); AsyncObject.Client.Send(P.ToArray()); Logger.LogInfo("Bad accountname - sent SLoginFailResponse!\r\n"); AsyncObject.Client.Disconnect(); } //If this setting is true, it means an account will be created //if it doesn't exist. if (GlobalSettings.Default.CreateAccountsOnLogin == true) { if (FoundAccountName == false) { //No idea if this call is gonna succeed, given it's called from a callback function... CreateAccount(AsyncObject.AccountName, AsyncObject.Password); } } }
/// <summary> /// Called by CityServer instances /// when they've received some new data /// (a new packet). Should not be called /// from anywhere else. /// </summary> /// <param name="P"></param> public void OnReceivedData(PacketStream P, CityServerClient Client) { OnReceiveEvent(P, ref Client); }
/// <summary> /// Callback mehod for CheckCharacterTimestamp. /// This queries for the existence of a particular account /// in the DB and retrieves the character IDs associated with it. /// </summary> private static void EndCheckCharacterID(IAsyncResult AR) { DatabaseAsyncObject AsyncObject = AR.AsyncState as DatabaseAsyncObject; bool FoundAccountName = false; int NumCharacters = 0; int CharacterID1 = 0; int CharacterID2 = 0; int CharacterID3 = 0; using (SqlDataReader Reader = AsyncObject.Cmd.EndExecuteReader(AR)) { while (Reader.Read()) { if (((string)Reader[0]).ToUpper() == AsyncObject.AccountName.ToUpper()) { FoundAccountName = true; NumCharacters = (int)Reader[1]; if (NumCharacters == 0) { break; } else if (NumCharacters == 1) { CharacterID1 = (int)Reader[2]; } else if (NumCharacters == 2) { CharacterID1 = (int)Reader[2]; CharacterID2 = (int)Reader[3]; } else if (NumCharacters == 3) { CharacterID1 = (int)Reader[2]; CharacterID2 = (int)Reader[3]; CharacterID3 = (int)Reader[4]; } if (FoundAccountName == true) { break; } } } } if (FoundAccountName) { if (NumCharacters > 0) { SqlCommand Command = new SqlCommand("SELECT CharacterID, LastCached, Name, Sex FROM Character"); AsyncObject.NumCharacters = NumCharacters; AsyncObject.CharacterID1 = CharacterID1; AsyncObject.CharacterID2 = CharacterID2; AsyncObject.CharacterID3 = CharacterID3; Command.Connection = m_Connection; Command.BeginExecuteReader(new AsyncCallback(EndCheckCharacterTimestamp), AsyncObject); } else { PacketStream Packet = new PacketStream(0x05, 0); Packet.WriteByte(0x00); //0 characters. AsyncObject.Client.SendEncrypted(0x05, Packet.ToArray()); } } }
/// <summary> /// Called by LoginClient instances /// when they've received some new data /// (a new packet). Should not be called /// from anywhere else. /// </summary> /// <param name="P"></param> public void OnReceivedData(PacketStream P, LoginClient Client) { PacketHandlers.Handle(P, Client); //OnReceiveEvent(P, Client); }
/// <summary> /// Callback method for EndCheckCharacterID. /// This retrieves information about the characters /// corresponding to the IDs retrieved earlier. /// </summary> private static void EndCheckCharacterTimestamp(IAsyncResult AR) { DatabaseAsyncObject AsyncObject = AR.AsyncState as DatabaseAsyncObject; List <Sim> Sims = new List <Sim>(); using (SqlDataReader Reader = AsyncObject.Cmd.EndExecuteReader(AR)) { while (Reader.Read()) { if ((int)Reader[0] == AsyncObject.CharacterID1) { int CharacterID = AsyncObject.CharacterID1; Sim Character = new Sim((string)Reader[1]); Character.CharacterID = CharacterID; Character.Timestamp = (string)Reader[2]; Character.Name = (string)Reader[3]; Character.Sex = (string)Reader[4]; Sims.Add(Character); } if (AsyncObject.NumCharacters == 1) { break; } if (AsyncObject.NumCharacters > 1) { if ((int)Reader[1] == AsyncObject.CharacterID2) { int CharacterID = AsyncObject.CharacterID2; Sim Character = new Sim((string)Reader[1]); Character.CharacterID = CharacterID; Character.Timestamp = (string)Reader[2]; Character.Name = (string)Reader[3]; Character.Sex = (string)Reader[4]; Sims.Add(Character); } } if (AsyncObject.NumCharacters == 2) { break; } if (AsyncObject.NumCharacters > 2) { if ((int)Reader[2] == AsyncObject.CharacterID3) { int CharacterID = AsyncObject.CharacterID3; Sim Character = new Sim((string)Reader[1]); Character.CharacterID = CharacterID; Character.Timestamp = (string)Reader[2]; Character.Name = (string)Reader[3]; Character.Sex = (string)Reader[4]; Sims.Add(Character); //For now, assume that finding the third character means //all characters have been found. break; } } } } PacketStream Packet = new PacketStream(0x05, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter PacketWriter = new BinaryWriter(PacketData); //The timestamp for all characters should be equal, so just check the first character. if (AsyncObject.CharacterTimestamp < DateTime.Parse(Sims[0].Timestamp) || AsyncObject.CharacterTimestamp > DateTime.Parse(Sims[0].Timestamp)) { //Write the characterdata into a temporary buffer. if (AsyncObject.NumCharacters == 1) { PacketWriter.Write(Sims[0].CharacterID); PacketWriter.Write(Sims[0].GUID); PacketWriter.Write(Sims[0].Timestamp); PacketWriter.Write(Sims[0].Name); PacketWriter.Write(Sims[0].Sex); PacketWriter.Flush(); } else if (AsyncObject.NumCharacters == 2) { PacketWriter.Write(Sims[0].CharacterID); PacketWriter.Write(Sims[0].GUID); PacketWriter.Write(Sims[0].Timestamp); PacketWriter.Write(Sims[0].Name); PacketWriter.Write(Sims[0].Sex); PacketWriter.Write(Sims[1].CharacterID); PacketWriter.Write(Sims[0].GUID); PacketWriter.Write(Sims[1].Timestamp); PacketWriter.Write(Sims[1].Name); PacketWriter.Write(Sims[1].Sex); PacketWriter.Flush(); } else if (AsyncObject.NumCharacters == 3) { PacketWriter.Write(Sims[0].CharacterID); PacketWriter.Write(Sims[0].GUID); PacketWriter.Write(Sims[0].Timestamp); PacketWriter.Write(Sims[0].Name); PacketWriter.Write(Sims[0].Sex); PacketWriter.Write(Sims[1].CharacterID); PacketWriter.Write(Sims[0].GUID); PacketWriter.Write(Sims[1].Timestamp); PacketWriter.Write(Sims[1].Name); PacketWriter.Write(Sims[1].Sex); PacketWriter.Write(Sims[2].CharacterID); PacketWriter.Write(Sims[0].GUID); PacketWriter.Write(Sims[2].Timestamp); PacketWriter.Write(Sims[2].Name); PacketWriter.Write(Sims[2].Sex); PacketWriter.Flush(); } Packet.WriteByte((byte)AsyncObject.NumCharacters); //Total number of characters. Packet.Write(PacketData.ToArray(), 0, (int)PacketData.Length); AsyncObject.Client.SendEncrypted(0x05, Packet.ToArray()); } else if (AsyncObject.CharacterTimestamp == DateTime.Parse(Sims[0].Timestamp)) { PacketWriter.Write((byte)0x00); //0 characters. AsyncObject.Client.SendEncrypted(0x05, Packet.ToArray()); } PacketWriter.Close(); }
/// <summary> /// Callback-function for CheckAccount(). /// </summary> private static void EndCheckAccount(IAsyncResult AR) { DatabaseAsyncObject AsyncObject = AR.AsyncState as DatabaseAsyncObject; bool FoundAccountName = false; using (MySqlDataReader Reader = AsyncObject.MySQLCmd.EndExecuteReader(AR)) { while (Reader.Read()) { if (((string)Reader[0]).ToUpper() == AsyncObject.AccountName.ToUpper()) { FoundAccountName = true; AsyncObject.Password = (string)Reader[1]; } } } if (FoundAccountName == true) { //0x01 = InitLoginNotify PacketStream P = new PacketStream(0x01, 2); SaltedHash SHash = new SaltedHash(new SHA512Managed(), AsyncObject.AccountName.Length); if (SHash.VerifyHash(Encoding.ASCII.GetBytes(AsyncObject.Password.ToUpper()), AsyncObject.Hash, Encoding.ASCII.GetBytes(AsyncObject.AccountName))) { AsyncObject.Client.Username = AsyncObject.AccountName.ToUpper(); AsyncObject.Client.Password = AsyncObject.Password.ToUpper(); P.WriteByte(0x01); P.WriteByte(0x01); } else //The client's password was wrong. { PacketStream RejectPacket = new PacketStream(0x02, 2); RejectPacket.WriteByte(0x02); RejectPacket.WriteByte(0x02); AsyncObject.Client.Send(RejectPacket.ToArray()); Logger.LogInfo("Bad password - sent SLoginFailResponse!\r\n"); return; } AsyncObject.Client.Send(P.ToArray()); Logger.LogInfo("Sent InitLoginNotify!\r\n"); } else { PacketStream P = new PacketStream(0x02, 2); P.WriteByte(0x02); P.WriteByte(0x01); AsyncObject.Client.Send(P.ToArray()); Logger.LogInfo("Bad accountname - sent SLoginFailResponse!\r\n"); //AsyncObject.Client.Disconnect(); } //If this setting is true, it means an account will be created //if it doesn't exist. if (GlobalSettings.Default.CreateAccountsOnLogin == true) { if (FoundAccountName == false) { //No idea if this call is gonna succeed, given it's called from a callback function... CreateAccount(AsyncObject.AccountName, AsyncObject.Password); } } }
/// <summary> /// Handles incoming packets from a CityServer. /// </summary> void m_CServerListener_OnReceiveEvent(PacketStream P, CityServerClient Client) { byte ID = (byte)P.ReadByte(); switch (ID) { case 0x00: CityServerPacketHandlers.HandleCityServerLogin(P, ref Client); break; case 0x01: CityServerPacketHandlers.HandleKeyFetch(ref m_Listener, P, Client); break; } }
/// <summary> /// Callback method for EndCheckCharacterID. /// This retrieves information about the characters /// corresponding to the IDs retrieved earlier. /// </summary> private static void EndCheckCharacterTimestamp(IAsyncResult AR) { DatabaseAsyncObject AsyncObject = AR.AsyncState as DatabaseAsyncObject; List<Sim> Sims = new List<Sim>(); using (MySqlDataReader Reader = AsyncObject.MySQLCmd.EndExecuteReader(AR)) { while (Reader.Read()) { if ((int)Reader[0] == AsyncObject.CharacterID1) { int CharacterID = AsyncObject.CharacterID1; Sim Character = new Sim((string)Reader[1]); Character.CharacterID = CharacterID; Character.Timestamp = (string)Reader[2]; Character.Name = (string)Reader[3]; Character.Sex = (string)Reader[4]; Sims.Add(Character); } if (AsyncObject.NumCharacters == 1) break; if (AsyncObject.NumCharacters > 1) { if ((int)Reader[1] == AsyncObject.CharacterID2) { int CharacterID = AsyncObject.CharacterID2; Sim Character = new Sim((string)Reader[1]); Character.CharacterID = CharacterID; Character.Timestamp = (string)Reader[2]; Character.Name = (string)Reader[3]; Character.Sex = (string)Reader[4]; Sims.Add(Character); } } if (AsyncObject.NumCharacters == 2) break; if (AsyncObject.NumCharacters > 2) { if ((int)Reader[2] == AsyncObject.CharacterID3) { int CharacterID = AsyncObject.CharacterID3; Sim Character = new Sim((string)Reader[1]); Character.CharacterID = CharacterID; Character.Timestamp = (string)Reader[2]; Character.Name = (string)Reader[3]; Character.Sex = (string)Reader[4]; Sims.Add(Character); //For now, assume that finding the third character means //all characters have been found. break; } } } } PacketStream Packet = new PacketStream(0x05, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter PacketWriter = new BinaryWriter(PacketData); //The timestamp for all characters should be equal, so just check the first character. if (AsyncObject.CharacterTimestamp < DateTime.Parse(Sims[0].Timestamp) || AsyncObject.CharacterTimestamp > DateTime.Parse(Sims[0].Timestamp)) { //Write the characterdata into a temporary buffer. if (AsyncObject.NumCharacters == 1) { PacketWriter.Write(Sims[0].CharacterID); PacketWriter.Write(Sims[0].GUID); PacketWriter.Write(Sims[0].Timestamp); PacketWriter.Write(Sims[0].Name); PacketWriter.Write(Sims[0].Sex); PacketWriter.Flush(); } else if (AsyncObject.NumCharacters == 2) { PacketWriter.Write(Sims[0].CharacterID); PacketWriter.Write(Sims[0].GUID); PacketWriter.Write(Sims[0].Timestamp); PacketWriter.Write(Sims[0].Name); PacketWriter.Write(Sims[0].Sex); PacketWriter.Write(Sims[1].CharacterID); PacketWriter.Write(Sims[1].GUID); PacketWriter.Write(Sims[1].Timestamp); PacketWriter.Write(Sims[1].Name); PacketWriter.Write(Sims[1].Sex); PacketWriter.Flush(); } else if (AsyncObject.NumCharacters == 3) { PacketWriter.Write(Sims[0].CharacterID); PacketWriter.Write(Sims[0].GUID); PacketWriter.Write(Sims[0].Timestamp); PacketWriter.Write(Sims[0].Name); PacketWriter.Write(Sims[0].Sex); PacketWriter.Write(Sims[1].CharacterID); PacketWriter.Write(Sims[1].GUID); PacketWriter.Write(Sims[1].Timestamp); PacketWriter.Write(Sims[1].Name); PacketWriter.Write(Sims[1].Sex); PacketWriter.Write(Sims[2].CharacterID); PacketWriter.Write(Sims[2].GUID); PacketWriter.Write(Sims[2].Timestamp); PacketWriter.Write(Sims[2].Name); PacketWriter.Write(Sims[2].Sex); PacketWriter.Flush(); } Packet.WriteByte((byte)AsyncObject.NumCharacters); //Total number of characters. Packet.Write(PacketData.ToArray(), 0, (int)PacketData.Length); AsyncObject.Client.SendEncrypted(0x05, Packet.ToArray()); } else if (AsyncObject.CharacterTimestamp == DateTime.Parse(Sims[0].Timestamp)) { PacketWriter.Write((byte)0x00); //0 characters. AsyncObject.Client.SendEncrypted(0x05, Packet.ToArray()); } PacketWriter.Close(); }