public override void RemoveClient(NetworkClient Client) { CityInfo Info = CityServers.FirstOrDefault(x => x.Client == Client); if (CityServers.TryTake(out Info)) { lock (NetworkFacade.ClientListener.Clients) { PacketStream ClientPacket = new PacketStream((byte)PacketType.CITY_SERVER_OFFLINE, 0); ClientPacket.WriteString(Info.Name); ClientPacket.WriteString(Info.Description); ClientPacket.WriteString(Info.IP); ClientPacket.WriteInt32(Info.Port); ClientPacket.WriteByte((byte)Info.Status); ClientPacket.WriteUInt64(Info.Thumbnail); ClientPacket.WriteString(Info.UUID); ClientPacket.WriteUInt64(Info.Map); foreach (NetworkClient Receiver in NetworkFacade.ClientListener.Clients) { Receiver.SendEncrypted((byte)PacketType.CITY_SERVER_OFFLINE, ClientPacket.ToArray()); } } Debug.WriteLine("Removed CityServer!"); } }
/// <summary> /// Client wanted to transfer to a city server. /// </summary> public static void HandleCityTokenRequest(NetworkClient Client, ProcessedPacket P) { string AccountName = P.ReadString(); string CityGUID = P.ReadString(); string CharGUID = P.ReadString(); if (AccountName == string.Empty || CityGUID == string.Empty || CharGUID == string.Empty) { return; } Guid Token = Guid.NewGuid(); CityInfo CServer = NetworkFacade.CServerListener.GetCityServer(CityGUID); using (var db = DataAccess.Get()) { Account Acc = db.Accounts.GetByUsername(AccountName); PacketStream CServerPacket = new PacketStream(0x01, 0); CServerPacket.WriteHeader(); ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 1 + 4 + (Client.RemoteIP.Length + 1) + 4 + (CharGUID.ToString().Length + 1) + (Token.ToString().Length + 1)); CServerPacket.WriteUInt16(PacketLength); CServerPacket.WriteByte(0); //CharacterCreate = false. CServerPacket.WriteInt32(Acc.AccountID); CServerPacket.WriteString(Client.RemoteIP); CServerPacket.WriteInt32(Client.RemotePort); CServerPacket.WriteString(CharGUID.ToString()); CServerPacket.WriteString(Token.ToString("")); CServer.Client.Send(CServerPacket.ToArray()); } }
/// <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); }
/// <summary> /// A cityserver requested a decryptionkey for a client! /// </summary> public static void HandleKeyFetch(NetworkClient Client, ProcessedPacket P) { string AccountName = P.ReadString(); byte[] EncKey = new byte[1]; foreach (NetworkClient Cl in NetworkFacade.CServerListener.Clients) { if (Cl.ClientEncryptor.Username == AccountName) { EncKey = Cl.ClientEncryptor.GetDecryptionArgsContainer().ARC4DecryptArgs.EncryptionKey; //TODO: Figure out what to do about CurrentlyActiveSim... //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. NetworkFacade.CServerListener.TransferringClients.Remove(Client); }
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 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(); } }
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> /// Client wanted to retire a character. /// </summary> public static void HandleCharacterRetirement(NetworkClient Client, ProcessedPacket P) { PacketStream Packet; string AccountName = P.ReadString(); string GUID = P.ReadString(); if (AccountName == string.Empty || GUID == string.Empty) { return; } using (var db = DataAccess.Get()) { Account Acc = db.Accounts.GetByUsername(AccountName); IQueryable <Character> Query = db.Characters.GetForAccount(Acc.AccountID); //F**K, I hate LINQ. Guid CharGUID = new Guid(GUID); Character Char = Query.Where(x => x.GUID == CharGUID).SingleOrDefault(); if (Char != null) { db.Characters.RetireCharacter(Char); } else { return; } //This actually updates the record, not sure how. Acc.NumCharacters--; if (Char != null) { CityInfo CInfo = NetworkFacade.CServerListener.GetCityServer(Char.City); //Just in case... if (CInfo != null) { Packet = new PacketStream(0x02, 0); Packet.WriteHeader(); ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 4 + GUID.Length + 1); Packet.WriteUInt16(PacketLength); Packet.WriteInt32(Acc.AccountID); Packet.WriteString(GUID); CInfo.Client.Send(Packet.ToArray()); } } } Packet = new PacketStream((byte)PacketType.RETIRE_CHARACTER_STATUS, 0); Packet.WriteString(GUID); Client.SendEncrypted((byte)PacketType.RETIRE_CHARACTER_STATUS, 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 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()); } }
/// <summary> /// Client wanted to retire a character. /// </summary> public static void HandleCharacterRetirement(NetworkClient Client, ProcessedPacket P) { PacketStream Packet; string AccountName = P.ReadPascalString(); string GUID = P.ReadPascalString(); using (var db = DataAccess.Get()) { Account Acc = db.Accounts.GetByUsername(AccountName); IQueryable <Character> Query = db.Characters.GetForAccount(Acc.AccountID); //F**K, I hate LINQ. Guid CharGUID = new Guid(GUID); Character Char = Query.Where(x => x.GUID == CharGUID).SingleOrDefault(); //If this is the case, char likely didn't exist in DB, so proceed as normal, client will delete cache. if (Char != null) { db.Characters.RetireCharacter(Char); } //This actually updates the record, not sure how. Acc.NumCharacters--; for (int i = 0; i < NetworkFacade.CServerListener.CityServers.Count; i++) { if (Char != null) //Assume char didn't exist in city either. { if (NetworkFacade.CServerListener.CityServers[i].ServerInfo.Name == Char.CityName) { Packet = new PacketStream(0x02, 0); Packet.WriteHeader(); ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 4 + GUID.Length + 1); Packet.WriteUInt16(PacketLength); Packet.WriteInt32(Acc.AccountID); Packet.WritePascalString(GUID); NetworkFacade.CServerListener.CityServers[i].Send(Packet.ToArray()); break; } } } } Packet = new PacketStream((byte)PacketType.RETIRE_CHARACTER_STATUS, 0); Packet.WritePascalString(GUID); Client.SendEncrypted((byte)PacketType.RETIRE_CHARACTER_STATUS, Packet.ToArray()); }
/// <summary> /// Client requested information about a city. /// </summary> public static void HandleCityInfoRequest(NetworkClient Client, ProcessedPacket P) { //This packet only contains a dummy byte, don't bother reading it. PacketStream Packet = new PacketStream((byte)PacketType.CITY_LIST, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter PacketWriter = new BinaryWriter(PacketData); PacketWriter.Write((byte)NetworkFacade.CServerListener.CityServers.Count); //foreach (CityServerClient City in NetworkFacade.CServerListener.CityServers) for (int i = 0; i < NetworkFacade.CServerListener.CityServers.Count; i++) { PacketWriter.Write((string)NetworkFacade.CServerListener.CityServers[i].ServerInfo.Name); PacketWriter.Write((string)NetworkFacade.CServerListener.CityServers[i].ServerInfo.Description); PacketWriter.Write((string)NetworkFacade.CServerListener.CityServers[i].ServerInfo.IP); PacketWriter.Write((int)NetworkFacade.CServerListener.CityServers[i].ServerInfo.Port); //Hack (?) to ensure status is written correctly. switch (NetworkFacade.CServerListener.CityServers[i].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)NetworkFacade.CServerListener.CityServers[i].ServerInfo.Thumbnail); PacketWriter.Write((string)NetworkFacade.CServerListener.CityServers[i].ServerInfo.UUID); PacketWriter.Write((ulong)NetworkFacade.CServerListener.CityServers[i].ServerInfo.Map); PacketWriter.Flush(); } Packet.Write(PacketData.ToArray(), 0, PacketData.ToArray().Length); PacketWriter.Close(); Client.SendEncrypted((byte)PacketType.CITY_LIST, Packet.ToArray()); }
/// <summary> /// A cityserver logged in! /// </summary> public static void HandleCityServerLogin(NetworkClient Client, ProcessedPacket P) { Logger.LogInfo("CityServer logged in!\r\n"); string Name = P.ReadString(); string Description = P.ReadString(); string IP = P.ReadString(); int Port = P.ReadInt32(); CityInfoStatus Status = (CityInfoStatus)P.ReadByte(); ulong Thumbnail = P.ReadUInt64(); string UUID = P.ReadString(); ulong Map = P.ReadUInt64(); CityInfo Info = new CityInfo(true); Info.Name = Name; Info.Description = Description; Info.IP = IP; Info.Port = Port; Info.Status = Status; Info.Thumbnail = Thumbnail; Info.UUID = UUID; Info.Map = Map; Info.Client = Client; Info.Online = true; NetworkFacade.CServerListener.CityServers.Add(Info); NetworkFacade.CServerListener.PotentialLogins.TryTake(out Client); NetworkClient[] Clients = new NetworkClient[NetworkFacade.ClientListener.Clients.Count]; NetworkFacade.ClientListener.Clients.CopyTo(Clients, 0); PacketStream ClientPacket = new PacketStream((byte)PacketType.NEW_CITY_SERVER, 0); ClientPacket.WriteString(Name); ClientPacket.WriteString(Description); ClientPacket.WriteString(IP); ClientPacket.WriteInt32(Port); ClientPacket.WriteByte((byte)Status); ClientPacket.WriteUInt64(Thumbnail); ClientPacket.WriteString(UUID); ClientPacket.WriteUInt64(Map); foreach (NetworkClient Receiver in Clients) { Receiver.SendEncrypted((byte)PacketType.NEW_CITY_SERVER, ClientPacket.ToArray()); } }
/// <summary> /// Client requested information about a city. /// </summary> public static void HandleCityInfoRequest(NetworkClient Client, ProcessedPacket P) { //This packet only contains a dummy byte, don't bother reading it. PacketStream Packet = new PacketStream((byte)PacketType.CITY_LIST, 0); Packet.WriteByte((byte)NetworkFacade.CServerListener.CityServers.Count); if (NetworkFacade.CServerListener.CityServers.Count > 0) { lock (NetworkFacade.CServerListener.CityServers) { foreach (CityInfo CInfo in NetworkFacade.CServerListener.CityServers) { Packet.WriteString(CInfo.Name); Packet.WriteString(CInfo.Description); Packet.WriteString(CInfo.IP); Packet.WriteInt32(CInfo.Port); //Hack (?) to ensure status is written correctly. switch (CInfo.Status) { case CityInfoStatus.Ok: Packet.WriteByte(1); break; case CityInfoStatus.Busy: Packet.WriteByte(2); break; case CityInfoStatus.Full: Packet.WriteByte(3); break; case CityInfoStatus.Reserved: Packet.WriteByte(4); break; } Packet.WriteUInt64(CInfo.Thumbnail); Packet.WriteString(CInfo.UUID); Packet.WriteUInt64(CInfo.Map); } } } Client.SendEncrypted((byte)PacketType.CITY_LIST, Packet.ToArray()); }
public static void HandlePlayerOnlineResponse(NetworkClient Client, ProcessedPacket P) { byte Result = (byte)P.ReadByte(); string Token = P.ReadString(); //NOTE: Might have to find another way to identify a client, since two people // can be on the same account from the same IP. string RemoteIP = P.ReadString(); int RemotePort = P.ReadInt32(); PacketStream Packet; NetworkClient FoundClient; switch (Result) { case 0x01: Packet = new PacketStream((byte)PacketType.REQUEST_CITY_TOKEN, 0); Packet.WriteString(Token); FoundClient = NetworkFacade.ClientListener.GetClient(RemoteIP, RemotePort); if (FoundClient != null) { FoundClient.SendEncrypted((byte)PacketType.REQUEST_CITY_TOKEN, Packet.ToArray()); } break; case 0x02: //Write player was already online packet! Packet = new PacketStream((byte)PacketType.PLAYER_ALREADY_ONLINE, 0); Packet.WriteByte(0x00); //Dummy FoundClient = NetworkFacade.ClientListener.GetClient(RemoteIP, RemotePort); if (FoundClient != null) { FoundClient.SendEncrypted((byte)PacketType.PLAYER_ALREADY_ONLINE, Packet.ToArray()); } break; } }
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 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()); 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); }
/** * Actual packet handlers */ 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 KeyLength = (byte)P.ReadByte(); byte[] EncKey = new byte[KeyLength]; P.Read(EncKey, 0, KeyLength); //TODO: Do something with this... 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, EncKey); } } 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, EncKey); } 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 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()); } }
public void Send(PacketStream stream) { this.Send(stream.ToArray()); }
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> /// 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> /// 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()); } } }
/** * 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"); } } }
/// <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()); } }
/// <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()); } } }
/// <summary> /// Client requested information about its characters. /// </summary> public static void HandleCharacterInfoRequest(NetworkClient Client, ProcessedPacket P) { Logger.LogInfo("Received CharacterInfoRequest!"); string DateTimeStr = P.ReadString(); DateTime Timestamp; if (DateTimeStr != string.Empty) { Timestamp = DateTime.Parse(DateTimeStr); } else { //Unix epoch Timestamp = new DateTime(1970, 1, 1, 0, 0, 1); } 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(); } int NumChars = 0, NewChars = 0; if (Characters != null) { PacketStream Packet = new PacketStream((byte)PacketType.CHARACTER_LIST, 0); MemoryStream PacketData = new MemoryStream(); BinaryWriter PacketWriter = new BinaryWriter(PacketData); NumChars = Characters.Length; 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, avatar.LastCached) < 0) { NewChars++; PacketWriter.Write((int)avatar.CharacterID); PacketWriter.Write(avatar.GUID.ToString()); PacketWriter.Write(avatar.LastCached.ToString("yyyy.MM.dd hh:mm:ss", CultureInfo.InvariantCulture)); 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); PacketWriter.Write((int)avatar.Money); } } //NOTE: If Characters != null, but no chars were new, NumChars will be however many characters, // and NewChars will be 0. Packet.WriteByte((byte)NumChars); Packet.WriteByte((byte)NewChars); Packet.Write(PacketData.ToArray(), 0, (int)PacketData.Length); PacketWriter.Close(); Client.SendEncrypted((byte)PacketType.CHARACTER_LIST, Packet.ToArray()); } else //No characters existed for the account. { PacketStream Packet = new PacketStream(0x05, 0); Packet.WriteByte((byte)NumChars); //0 characters. Packet.WriteByte((byte)NewChars); //0 new characters. Client.SendEncrypted((byte)PacketType.CHARACTER_LIST, Packet.ToArray()); } }
/// <summary> /// Client wanted to log in! /// </summary> public static void HandleLoginRequest(NetworkClient Client, ProcessedPacket P) { try { Logger.LogInfo("Received LoginRequest!\r\n"); 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; } PacketStream EncryptedPacket = new PacketStream((byte)PacketType.LOGIN_NOTIFY, 0); EncryptedPacket.WriteHeader(); AESEncryptor Enc = (AESEncryptor)Client.ClientEncryptor; if (Enc == null) { Enc = new AESEncryptor(""); } Enc.PublicKey = P.ReadBytes((P.ReadByte())); Enc.NOnce = P.ReadBytes((P.ReadByte())); Enc.PrivateKey = NetworkFacade.ServerKey; Client.ClientEncryptor = Enc; MemoryStream StreamToEncrypt = new MemoryStream(); BinaryWriter Writer = new BinaryWriter(StreamToEncrypt); Writer.Write(Enc.Challenge, 0, Enc.Challenge.Length); Writer.Flush(); byte[] EncryptedData = StaticStaticDiffieHellman.Encrypt(NetworkFacade.ServerKey, System.Security.Cryptography.ECDiffieHellmanCngPublicKey.FromByteArray(Enc.PublicKey, System.Security.Cryptography.CngKeyBlobFormat.EccPublicBlob), Enc.NOnce, StreamToEncrypt.ToArray()); EncryptedPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + (1 + NetworkFacade.ServerPublicKey.Length) + (1 + EncryptedData.Length))); EncryptedPacket.WriteByte((byte)NetworkFacade.ServerPublicKey.Length); EncryptedPacket.WriteBytes(NetworkFacade.ServerPublicKey); EncryptedPacket.WriteByte((byte)EncryptedData.Length); EncryptedPacket.WriteBytes(EncryptedData); Client.Send(EncryptedPacket.ToArray()); } //This should HOPEFULLY wade off clients sending unreadable (I.E old protocol) packets... catch (Exception E) { Logger.LogDebug("Error while handling login request, disconnecting client: " + E.ToString()); Client.Disconnect(); return; } }
public void OnReceivedData(IAsyncResult AR) { 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(); } }
/// <summary> /// Client sent a response to our challenge, as well as account name and password. /// </summary> public static void HandleChallengeResponse(NetworkClient Client, ProcessedPacket P) { PacketStream OutPacket; if (P.BufferLength <= 1) { OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0); OutPacket.WriteByte(0x03); //Bad challenge response. Client.Send(OutPacket.ToArray()); Logger.LogInfo("Bad challenge response - sent SLoginFailResponse!\r\n"); return; //How does this even happen?! } int Length = P.ReadByte(); byte[] CResponse; if (P.BufferLength >= Length) { CResponse = P.ReadBytes(Length); } else { return; } AESDecryptionArgs DecryptionArgs = Client.ClientEncryptor.GetDecryptionArgsContainer().AESDecryptArgs; if (DecryptionArgs.Challenge.SequenceEqual(CResponse)) { string AccountName = SanitizeAccount(P.ReadString()); Length = P.ReadByte(); byte[] PasswordHash; if (P.BufferLength >= Length) { PasswordHash = P.ReadBytes(Length); } else { return; } // Check whether the accountname is empty or is/contains "username" if (AccountName == string.Empty || AccountName.ToLower().Equals("username") || AccountName.ToLower().Contains("username")) { OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x01); Client.Send(OutPacket.ToArray()); Logger.LogInfo(@"Bad accountname (""" + AccountName + @""") - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } using (var db = DataAccess.Get()) { var account = db.Accounts.GetByUsername(AccountName); if (!GlobalSettings.Default.CreateAccountsOnLogin) { Logger.LogInfo("Done reading LoginRequest, checking account...\r\n"); if (account == null) { OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x01); Client.Send(OutPacket.ToArray()); Logger.LogInfo(@"Bad accountname (""" + AccountName + @""") - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } } else { if (account == null) { try { if (!AccountName.ToLower().Equals("username") || !AccountName.ToLower().Contains("username")) { db.Accounts.Create(new Account { AccountName = AccountName.ToLower(), Password = Convert.ToBase64String(PasswordHash) }); } } catch (Exception) { OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x01); Client.Send(OutPacket.ToArray()); Logger.LogInfo(@"Bad accountname (""" + AccountName + @""") - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } account = db.Accounts.GetByUsername(AccountName); } } if (account.IsCorrectPassword(AccountName, PasswordHash)) { OutPacket = new PacketStream((byte)PacketType.LOGIN_SUCCESS, 0); OutPacket.WriteByte(0x01); Client.ClientEncryptor.Username = AccountName; Client.SendEncrypted((byte)PacketType.LOGIN_SUCCESS, OutPacket.ToArray()); Logger.LogInfo("Sent SLoginSuccessResponse!\r\n"); return; } else { OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x02); Client.Send(OutPacket.ToArray()); Logger.LogInfo("Bad password - sent SLoginFailResponse!\r\n"); Client.Disconnect(); return; } } } OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0); OutPacket.WriteHeader(); OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1)); OutPacket.WriteByte(0x03); //Bad challenge response. Client.Send(OutPacket.ToArray()); Logger.LogInfo("Bad challenge response - sent SLoginFailResponse!\r\n"); return; }
/// <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(); }
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 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 { 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); /** Get the packet type **/ byte ID = TempPacket.PeekByte(0); var handler = FindPacketHandler(ID); if (handler != null) { var PacketLength = handler.Length; 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 > (int)PacketHeaders.UNENCRYPTED) //Header is 3 bytes. { PacketLength = TempPacket.PeekUShort(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); handler = FindPacketHandler(ID); //This SHOULD be an existing ID, but let's sanity-check it... if (handler != null) { m_TempPacket = new PacketStream(ID, handler.Length, 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(); } }
/// <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(); }
/// <summary> /// Client created a character! /// </summary> public static void HandleCharacterCreate(NetworkClient Client, ProcessedPacket P) { Logger.LogInfo("Received CharacterCreate!"); string AccountName = SanitizeAccount(P.ReadString()); //Need to be variable length, because the success packet contains a token. PacketStream CCStatusPacket = new PacketStream((byte)PacketType.CHARACTER_CREATION_STATUS, 0); using (var db = DataAccess.Get()) { Account Acc = db.Accounts.GetByUsername(AccountName); if (Acc.NumCharacters >= 3) { CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.ExceededCharacterLimit); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); return; } //TODO: Send GUID to client... var Char = new Character(); string LastCached = P.ReadString(); if (LastCached == string.Empty) { //TODO: Proper error... CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); return; } Char.LastCached = ProtoHelpers.ParseDateTime(LastCached); Char.Name = P.ReadString(); Char.Sex = P.ReadString(); Char.Description = P.ReadString(); Char.GUID = Guid.NewGuid(); Char.HeadOutfitID = (long)P.ReadUInt64(); Char.BodyOutfitID = (long)P.ReadUInt64(); Char.AccountID = Acc.AccountID; Char.AppearanceType = P.ReadByte(); Char.CityName = P.ReadString(); Char.CityThumb = (long)P.ReadUInt64(); Char.City = P.ReadString(); Char.CityMap = (long)P.ReadUInt64(); Char.CityIp = P.ReadString(); Char.CityPort = P.ReadInt32(); Char.Money = NetworkFacade.INITIAL_MONEY; //These are going into DB, so be nazi. Sieg heil! if (Char.Name == string.Empty || Char.Sex == string.Empty || Char.Description == string.Empty) { CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); return; } var status = db.Characters.CreateCharacter(Char); 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.NameTooLong: CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameTooLong); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); break; case LoginDataModel.Entities.CharacterCreationStatus.Success: Guid Token = Guid.NewGuid(); //This actually updates the record, not sure how. Acc.NumCharacters++; //THIS NEEDS TO HAPPEN FIRST FOR CITY SERVER AUTHENTICATION TO WORK! CityInfo CServer = NetworkFacade.CServerListener.GetCityServer(Char.City); //Just in case... if (CServer != null) { PacketStream CServerPacket = new PacketStream(0x01, 0); CServerPacket.WriteHeader(); ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 1 + 4 + (Client.RemoteIP.Length + 1) + 4 + (Char.GUID.ToString().Length + 1) + (Token.ToString().Length + 1)); CServerPacket.WriteUInt16(PacketLength); CServerPacket.WriteByte(1); //CharacterCreate = true CServerPacket.WriteInt32(Acc.AccountID); CServerPacket.WriteString(Client.RemoteIP); CServerPacket.WriteInt32(Client.RemotePort); CServerPacket.WriteString(Char.GUID.ToString()); CServerPacket.WriteString(Token.ToString("")); CServer.Client.Send(CServerPacket.ToArray()); } CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.Success); CCStatusPacket.WriteString(Char.GUID.ToString()); CCStatusPacket.WriteString(Token.ToString()); Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray()); break; } } }