/// <summary> /// /// </summary> /// <param name="numBytes"></param> protected override void OnReceive(int numBytes) { byte[] packet = new byte[numBytes]; Array.Copy(this.m_readBuffer.Array, this.m_readBuffer.Offset, packet, 0, numBytes); PacketReader reader = new PacketReader(packet); // TODO: make check here to see if packet starts with 0xDFDF reader.ReadBytes(2); // Packet type short type = reader.PopShort(); // Unknown? reader.PopShort(); // Packet Length reader.PopShort(); // Sender reader.PopInt(); // Receiver reader.PopInt(); // PacketID int id = reader.PopInt(); switch (type) { case 0x01: // SystemMessage { Program.zoneServer.SystemMessageHandler.Parse(this, packet, id); break; } case 0x05: // TextMessage { Program.zoneServer.TextMessageHandler.Parse(this, packet, id); break; } case 0x0A: // N3Message { N3Message.Parse(this, packet, id); break; } case 0x0B: // PingMessage { break; } case 0x0E: // OperatorMessage { break; } default: // UnknownMessage { // TODO: Handle Unknown Messages break; } } reader.Finish(); }
/// <summary> /// /// </summary> /// <param name="client"></param> /// <param name="packet"></param> /// <param name="messageNumber"></param> public void Parse(Client client, byte[] packet, uint messageNumber) { #region Setup... PacketReader packetReader = new PacketReader(packet); string encryptedPassword; int encPasswordLength; byte[] wrongLogin = LoginWrong.GetPacket(); CheckLogin cbl = new CheckLogin(); CharacterName characterName = new CharacterName(); #endregion switch (messageNumber) { case 0x22: SaltAuthentication salt = new SaltAuthentication(); // Username and version info packetReader.ReadBytes(24); client.AccountName = Encoding.ASCII.GetString(packetReader.ReadBytes(40)).TrimEnd(char.MinValue); client.ClientVersion = Encoding.ASCII.GetString(packetReader.ReadBytes(20)).TrimEnd(char.MinValue); packetReader.Finish(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine( "Client '" + client.AccountName + "' connected using version '" + client.ClientVersion + "'"); Console.ResetColor(); // Send Authentication Salt to client client.ServerSalt = salt.SendPacket(client); break; case 0x25: // Username and encrypted password // m_stream.Position = 20; packetReader.ReadBytes(20); string loginAccountName = packetReader.PopString(40).TrimEnd(char.MinValue); encPasswordLength = packetReader.PopInt(); encryptedPassword = packetReader.PopString(encPasswordLength).TrimEnd(char.MinValue); packetReader.Finish(); if (cbl.IsLoginAllowed(client, loginAccountName) == false) { /* * Account name not found or client banned/otherwise not permitted on the server * Note, this is done here not in the above packet (0x22), even though we have * the username or the client will complain. Also a security measure as you can * not tell if an account name is correct or not, only if both the username and * password are correct. * * We also double check that the Account Name is the same as origionally sent * or there could be a possibility to log in with someone elses account. * */ Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine( "Client '" + client.AccountName + "' banned, not a valid username, or sent a malformed Authentication Packet"); Console.ResetColor(); client.Send(wrongLogin); client.Server.DisconnectClient(client); break; } if (cbl.IsLoginCorrect(client, encryptedPassword) == false) { // Username/Password Incorrect Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Client '" + client.AccountName + "' failed Authentication."); Console.ResetColor(); client.Send(wrongLogin); client.Server.DisconnectClient(client); break; } else { // All's well, send CharacterList Packet CharacterListPacket charlist = new CharacterListPacket(); charlist.SendPacket(client, client.AccountName); } break; case 0x16: // Player selected a character and client sends us selected characters ID packetReader.ReadBytes(20); int selectedCharID = packetReader.PopInt(); packetReader.Finish(); if (cbl.IsCharacterOnAccount(client, selectedCharID) == false) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine( "Client '" + client.AccountName + "' tried to log in as CharID " + selectedCharID + " but it is not on their account!"); Console.ResetColor(); // NV: Is this really what we want to send? Should find out sometime... client.Send(wrongLogin); client.Server.DisconnectClient(client); break; } if (OnlineChars.IsOnline(selectedCharID)) { Console.WriteLine( "Client '" + client.AccountName + "' is trying to login, but the requested character is already logged in."); client.Send(wrongLogin); client.Server.DisconnectClient(client); break; } OnlineChars.SetOnline(selectedCharID); IPAddress tempIP; if (IPAddress.TryParse(ConfigReadWrite.Instance.CurrentConfig.ZoneIP, out tempIP) == false) { IPHostEntry zoneHost = Dns.GetHostEntry(ConfigReadWrite.Instance.CurrentConfig.ZoneIP); foreach (IPAddress ip in zoneHost.AddressList) { if (ip.AddressFamily == AddressFamily.InterNetwork) { tempIP = ip; break; } } } byte[] ZoneIP = tempIP.GetAddressBytes(); byte[] ZonePort = BitConverter.GetBytes(Convert.ToInt32(ConfigReadWrite.Instance.CurrentConfig.ZonePort)); PacketWriter writer = new PacketWriter(); writer.PushByte(0xDF); writer.PushByte(0xDF); writer.PushShort(1); // Packet type writer.PushShort(1); writer.PushShort(0); // Packet length (will be set in packet writer) writer.PushInt(1); writer.PushInt(0x615B); // Server ID writer.PushInt(23); // Packet ID writer.PushInt(selectedCharID); writer.PushBytes(ZoneIP); writer.PushByte(ZonePort[1]); writer.PushByte(ZonePort[0]); writer.PushShort(0); writer.PushInt(0); writer.PushInt(0); Byte[] pkt = writer.Finish(); client.Send(pkt); break; case 0x55: /* player ask for 'suggest name'; server sends 'random' name. */ characterName.GetRandomName(client, packetReader.PopInt()); packetReader.Finish(); break; case 0xf: /* client created new character */ Int32 characterId; bool startInShadowLands = false; characterName.AccountName = client.AccountName; /* start reading packet */ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // As of 18.5.1 heading for this packet is 69 bytes (65 bytes for lower versions) // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! packetReader.ReadBytes(69); /* name length */ int nameLen = packetReader.PopInt(); /* name */ characterName.Name = packetReader.PopString(nameLen); /* breed */ characterName.Breed = packetReader.PopInt(); /* gender */ characterName.Gender = packetReader.PopInt(); /* profession */ characterName.Profession = packetReader.PopInt(); /* level (should always be 0 )*/ characterName.Level = packetReader.PopInt(); /* lets skip some stuff */ int skipLen = packetReader.PopInt(); packetReader.ReadBytes(skipLen + 8); /* head mesh */ characterName.HeadMesh = packetReader.PopInt(); /* monster scale */ characterName.MonsterScale = packetReader.PopInt(); /* fatness */ characterName.Fatness = packetReader.PopInt(); /* start in SL? */ int sl = packetReader.PopInt(); if (sl == 1) { startInShadowLands = true; } /* close reader and stream */ packetReader.Finish(); /* now you got the data.. * do whatever you have to do with it * but please.. in some other class :) */ /* check name against database * * if name exist, return 0. * if name doesnt exist, creates default char setup and returns character_id * */ characterId = characterName.CheckAgainstDatabase(); if (characterId < 1) { characterName.SendNameInUse(client); } else { characterName.SendNameToStartPlayfield(client, startInShadowLands, characterId); } /* reply will work only if character creation * works, so its disabled for now and should be * handled in other class in /Packets/<class name> */ break; case 0x14: /* client deletes char */ Int32 uid; /* start reading packet */ packetReader.ReadBytes(20); uid = packetReader.PopInt(); characterName.DeleteChar(client, uid); packetReader.Finish(); break; default: packetReader.Finish(); client.Server.Warning(client, "Client sent unknown message {0}", messageNumber.ToString()); break; } }