public static void OnCharacterCreationStatus(NetworkClient Client, ProcessedPacket Packet) { CharacterCreationStatus CCStatus = (CharacterCreationStatus)Packet.ReadByte(); switch (CCStatus) { case CharacterCreationStatus.Success: Guid CharacterGUID = new Guid(); //CityToken didn't exist, so transition to CityServer hasn't happened yet. if (PlayerAccount.CityToken == "") { CharacterGUID = new Guid(Packet.ReadPascalString()); PlayerAccount.CityToken = Packet.ReadPascalString(); } NetworkFacade.Controller._OnCharacterCreationStatus(CCStatus); if(PlayerAccount.CityToken == "") PlayerAccount.CurrentlyActiveSim.AssignGUID(CharacterGUID.ToString()); break; case CharacterCreationStatus.ExceededCharacterLimit: NetworkFacade.Controller._OnCharacterCreationStatus(CCStatus); break; case CharacterCreationStatus.NameAlreadyExisted: NetworkFacade.Controller._OnCharacterCreationStatus(CCStatus); break; case CharacterCreationStatus.GeneralError: NetworkFacade.Controller._OnCharacterCreationStatus(CCStatus); break; default: break; } }
/// <summary> /// Received CharacterCreation packet from LoginServer. /// </summary> /// <returns>The result of the character creation.</returns> public static CharacterCreationStatus OnCharacterCreationProgress(NetworkClient Client, ProcessedPacket Packet) { CharacterCreationStatus CCStatus = (CharacterCreationStatus)Packet.ReadByte(); if (CCStatus == CharacterCreationStatus.Success) { Guid CharacterGUID = new Guid(); CharacterGUID = new Guid(Packet.ReadPascalString()); PlayerAccount.CityToken = Packet.ReadPascalString(); PlayerAccount.CurrentlyActiveSim.AssignGUID(CharacterGUID.ToString()); } return CCStatus; }
/// <summary> /// A client requested login. /// </summary> /// <param name="Client">NetworkClient instance.</param> /// <param name="Packet">ProcessedPacket instance.</param> public static void InitialClientConnect(NetworkClient Client, ProcessedPacket Packet) { Console.WriteLine("Server receives data - test 1"); //AES is used to encrypt all further communication between client and server. AesCryptoServiceProvider AesCrypto = new AesCryptoServiceProvider(); AesCrypto.GenerateKey(); AesCrypto.GenerateIV(); AES AesEncryptor = new AES(AesCrypto.Key, AesCrypto.IV); SessionKey = AesCrypto.Key; IV = AesCrypto.IV; Guid Nonce = new Guid(Packet.ReadPascalString()); //Username would normally be used to lookup client's public key in DB (only time such a use is valid). string Username = Packet.ReadPascalString(); ECDiffieHellmanPublicKey ClientPub = StaticStaticDiffieHellman.ImportKey("ClientPublic.dat"); PacketStream EncryptedPacket = new PacketStream(0x02, 0); EncryptedPacket.WriteHeader(); MemoryStream StreamToEncrypt = new MemoryStream(); BinaryWriter Writer = new BinaryWriter(StreamToEncrypt); Writer.Write((byte)ChallengeResponse.ToByteArray().Length); Writer.Write(ChallengeResponse.ToByteArray(), 0, ChallengeResponse.ToByteArray().Length); Writer.Write((byte)SessionKey.Length); Writer.Write(SessionKey, 0, SessionKey.Length); Writer.Write((byte)IV.Length); Writer.Write(IV, 0, IV.Length); Writer.Flush(); byte[] EncryptedData = StaticStaticDiffieHellman.Encrypt(ServerKey, ClientPub, Nonce.ToByteArray(), StreamToEncrypt.ToArray()); EncryptedPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1 + EncryptedData.Length)); EncryptedPacket.WriteByte((byte)EncryptedData.Length); EncryptedPacket.Write(EncryptedData, 0, EncryptedData.Length); Client.Send(EncryptedPacket.ToArray()); Console.WriteLine("Test 1: passed!"); }
public static void HandleClientToken(NetworkClient Client, ProcessedPacket P) { try { ClientToken Token = new ClientToken(); Token.AccountID = P.ReadInt32(); Token.ClientIP = P.ReadPascalString(); Token.CharacterGUID = P.ReadPascalString(); Token.Token = P.ReadPascalString(); NetworkFacade.TransferringClients.AddItem(Token); } catch (Exception E) { Logger.LogDebug("Exception in HandleClientToken: " + E.ToString()); } }
/// <summary> /// A player joined a session (game) in progress. /// </summary> public static Sim OnPlayerJoinedSession(ProcessedPacket Packet) { Sim Avatar = new Sim(Packet.ReadPascalString()); Avatar.Name = Packet.ReadPascalString(); Avatar.Sex = Packet.ReadPascalString(); Avatar.Description = Packet.ReadPascalString(); Avatar.HeadOutfitID = Packet.ReadUInt64(); Avatar.BodyOutfitID = Packet.ReadUInt64(); Avatar.Appearance = (AppearanceType)Packet.ReadInt32(); lock (NetworkFacade.AvatarsInSession) { NetworkFacade.AvatarsInSession.Add(Avatar); } return(Avatar); }
/// <summary> /// A client decided to retire a character. /// </summary> public static void HandleCharacterRetirement(NetworkClient Client, ProcessedPacket P) { int AccountID = P.ReadInt32(); string GUID = P.ReadPascalString(); using (DataAccess db = DataAccess.Get()) { IQueryable <Character> Query = db.Characters.GetForAccount(AccountID); //F**K, I hate LINQ. Guid CharGUID = new Guid(GUID); Character Char = Query.Where(x => x.GUID == CharGUID).SingleOrDefault(); //If char is null, it most likely didn't exist in DB. Do nothing... if (Char != null) { db.Characters.RetireCharacter(Char); } } }
public static string OnReceivedMessage(ProcessedPacket Packet) { string Subject = Packet.ReadPascalString(); return(Packet.ReadPascalString()); //Message. }
/// <summary> /// Received from the LoginServer in response to a CITY_TOKEN_REQUEST packet. /// </summary> public static void OnCityTokenRequest(NetworkClient Client, ProcessedPacket Packet) { PlayerAccount.CityToken = Packet.ReadPascalString(); Debug.WriteLine("CityToken: " + PlayerAccount.CityToken); }
public static void HandleCharacterCreate(NetworkClient Client, ProcessedPacket P) { try { Logger.LogInfo("Received CharacterCreate!"); bool ClientAuthenticated = false; byte AccountStrLength = (byte)P.ReadByte(); byte[] AccountNameBuf = new byte[AccountStrLength]; P.Read(AccountNameBuf, 0, AccountStrLength); string AccountName = Encoding.ASCII.GetString(AccountNameBuf); byte HashLength = (byte)P.ReadByte(); byte[] HashBuf = new byte[HashLength]; P.Read(HashBuf, 0, HashLength); using (DataAccess db = DataAccess.Get()) { Client.ClientEncryptor = new ARC4Encryptor(Convert.ToBase64String(HashBuf)); Client.ClientEncryptor.Username = AccountName; string Token = P.ReadString(); string GUID = ""; int AccountID = 0; foreach (ClientToken CToken in NetworkFacade.TransferringClients.GetList()) { if (CToken.ClientIP == Client.RemoteIP) { if (CToken.Token == Token) { PacketStream SuccessPacket = new PacketStream((byte)PacketType.CHARACTER_CREATE_CITY, (int)(PacketHeaders.ENCRYPTED + 1)); SuccessPacket.WriteByte((byte)CityDataModel.Entities.CharacterCreationStatus.Success); Client.SendEncrypted((byte)PacketType.CHARACTER_CREATE_CITY, SuccessPacket.ToArray()); ClientAuthenticated = true; GUID = CToken.CharacterGUID; AccountID = CToken.AccountID; } break; } } Sim Char = new Sim(new Guid(GUID)); 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.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 = AccountID; characterModel.AppearanceType = (int)Char.Appearance; var status = db.Characters.CreateCharacter(characterModel); } //Invalid token, should never occur... if (!ClientAuthenticated) { PacketStream SuccessPacket = new PacketStream(0x65, (int)(PacketHeaders.ENCRYPTED + 1)); SuccessPacket.WriteByte((byte)CityDataModel.Entities.CharacterCreationStatus.GeneralError); Client.SendEncrypted(0x64, SuccessPacket.ToArray()); Client.Disconnect(); } } catch (Exception E) { Logger.LogDebug("Exception in HandleCharacterCreate: " + E.ToString()); } }
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... SimBase Char = new SimBase(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()); 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); }
public static void HandleCityTokenRequest(NetworkClient Client, ProcessedPacket P) { string AccountName = P.ReadPascalString(); string CityGUID = P.ReadPascalString(); string CharGUID = P.ReadPascalString(); string Token = new Guid().ToString(); foreach (CityServerClient CServer in NetworkFacade.CServerListener.CityServers) { if (CityGUID == CServer.ServerInfo.UUID) { using (var db = DataAccess.Get()) { Account Acc = db.Accounts.GetByUsername(AccountName); PacketStream CServerPacket = new PacketStream(0x01, 0); CServerPacket.WriteHeader(); ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 4 + (Client.RemoteIP.Length + 1) + (CharGUID.ToString().Length + 1) + (Token.ToString().Length + 1)); CServerPacket.WriteUInt16(PacketLength); CServerPacket.WriteInt32(Acc.AccountID); CServerPacket.WritePascalString(Client.RemoteIP); CServerPacket.WritePascalString(CharGUID.ToString()); CServerPacket.WritePascalString(Token.ToString()); CServer.Send(CServerPacket.ToArray()); break; } } } PacketStream Packet = new PacketStream((byte)PacketType.REQUEST_CITY_TOKEN, 0); Packet.WritePascalString(Token); Client.SendEncrypted((byte)PacketType.REQUEST_CITY_TOKEN, Packet.ToArray()); }
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); /** * 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((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.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()); } }
/// <summary> /// Received from the LoginServer in response to a CITY_TOKEN_REQUEST packet. /// </summary> public static void OnCityToken(NetworkClient Client, ProcessedPacket Packet) { PlayerAccount.CityToken = Packet.ReadPascalString(); }