/// <summary> /// /// </summary> /// <param name="netState"></param> /// <param name="packetReader"></param> internal static void WorldServerExit( NetState netState, PacketReader packetReader ) { netState.Send( new ExitAck( 3 ) ); netState.Dispose( true, 3 ); }
public bool OnReceive(NetState ns) { ByteQueue buffer = ns.Buffer; if (buffer == null || buffer.Length <= 0) return true; lock (buffer) { int length = buffer.Length; while (length > 0) { int packetID = buffer.GetPacketID(); PacketHandler handler = ns.GetHandler(packetID); if (handler == null) { byte[] data = new byte[length]; length = buffer.Dequeue(data, 0, length); new PacketReader(data, length, false).Trace(ns); break; } int packetLength = handler.Length; if (packetLength <= 0) { if (length >= 3) { packetLength = buffer.GetPacketLength(); if (packetLength < 3) { ns.Dispose(); break; } } else { break; } } if (length < packetLength) break; byte[] packetBuffer = BufferSize >= packetLength ? _buffers.AcquireBuffer() : new byte[packetLength]; packetLength = buffer.Dequeue(packetBuffer, 0, packetLength); PacketReader r = new PacketReader(packetBuffer, packetLength, handler.Length != 0); handler.OnReceive(ns, r); length = buffer.Length; if (BufferSize >= packetLength) _buffers.ReleaseBuffer(packetBuffer); } } return true; }
// Try to decrypt incoming data. public void DecodeIncomingPacket(NetState from, ref byte[] buffer, ref int length) { #region m_Encryption != null if (m_Encryption != null) { // If we're decrypting using LoginCrypt and we've already been relayed, // only decrypt a single packet using logincrypt and then disable it if (m_AlreadyRelayed && m_Encryption is LoginEncryption) { uint newSeed = ((((LoginEncryption)(m_Encryption)).Key1 + 1) ^ ((LoginEncryption)(m_Encryption)).Key2); // Swap the seed newSeed = ((newSeed >> 24) & 0xFF) | ((newSeed >> 8) & 0xFF00) | ((newSeed << 8) & 0xFF0000) | ((newSeed << 24) & 0xFF000000); // XOR it with the old seed newSeed ^= m_Seed; IClientEncryption newEncryption = new GameEncryption(newSeed); // Game Encryption comes first newEncryption.ClientDecrypt(ref buffer, length); // The login encryption is still used for this one packet m_Encryption.ClientDecrypt(ref buffer, length); // Swap the encryption schemes m_Encryption = newEncryption; m_Seed = newSeed; return; } m_Encryption.ClientDecrypt(ref buffer, length); return; } #endregion #region Port Scan bool handle = false; for (int i = 0; i < Listener.EndPoints.Length; i++) { IPEndPoint ipep = Listener.EndPoints[i]; if (((IPEndPoint)from.Socket.LocalEndPoint).Port == ipep.Port) { handle = true; } } if (!handle) { m_Encryption = new NoEncryption(); return; } #endregion #region !m_Seeded // For simplicities sake, enqueue what we just received as long as we're not initialized m_Buffer.Enqueue(buffer, 0, length); // Clear the array length = 0; if (!m_Seeded) { if ((m_Buffer.Length == 83 || m_Buffer.Length == 21) && (m_Buffer.GetPacketID() == 239)) //New Client { length = m_Buffer.Length; byte[] m_Peek = new byte[21]; m_Buffer.Dequeue(m_Peek, 0, 21); m_Seed = (uint)((m_Peek[1] << 24) | (m_Peek[2] << 16) | (m_Peek[3] << 8) | m_Peek[4]); m_Seeded = true; Buffer.BlockCopy(m_Peek, 0, buffer, 0, 21); // We need to wait the next packet if (length == 21) { return; } length = 21; } else if (m_Buffer.Length >= 4) // Old Client { byte[] m_Peek = new byte[4]; m_Buffer.Dequeue(m_Peek, 0, 4); m_Seed = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]); m_Seeded = true; Buffer.BlockCopy(m_Peek, 0, buffer, 0, 4); length = 4; } else { //Console.WriteLine("Encryption: Failed - Invalid Client."); return; } } #endregion // If the context isn't initialized yet, that means we haven't decided on an encryption method yet #region m_Encryption == null if (m_Encryption == null) { int packetLength = m_Buffer.Length; int packetOffset = length; m_Buffer.Dequeue(buffer, length, packetLength); // Dequeue everything length += packetLength; // This is special handling for the "special" UOG packet if (packetLength >= 3) { if (buffer[packetOffset] == 0xf1 && buffer[packetOffset + 1] == ((packetLength >> 8) & 0xFF) && buffer[packetOffset + 2] == (packetLength & 0xFF)) { m_Encryption = new NoEncryption(); return; } } // Check if the current buffer contains a valid login packet (62 byte + 4 byte header) // Please note that the client sends these in two chunks. One 4 byte and one 62 byte. if (packetLength == 62) { // Check certain indices in the array to see if the given data is unencrypted if (buffer[packetOffset] == 0x80 && buffer[packetOffset + 30] == 0x00 && buffer[packetOffset + 60] == 0x00) { if (Configuration.AllowUnencryptedClients) { m_Encryption = new NoEncryption(); } else { RejectNoEncryption(from); from.Dispose(); return; } } else { LoginEncryption encryption = new LoginEncryption(); if (encryption.Initialize(m_Seed, buffer, packetOffset, packetLength, from)) { Console.WriteLine("Client: {0}: Encrypted client detected, using keys for client v{1}.", from, encryption.Name); m_Encryption = encryption; byte[] packet = new byte[packetLength]; Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength); encryption.ClientDecrypt(ref packet, packet.Length); Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength); } else { Console.WriteLine("Client: Unknown client detected, disconnecting."); from.Dispose(); } } } else if (packetLength == 65) { // If its unencrypted, use the NoEncryption class if (buffer[packetOffset] == '\x91' && buffer[packetOffset + 1] == ((m_Seed >> 24) & 0xFF) && buffer[packetOffset + 2] == ((m_Seed >> 16) & 0xFF) && buffer[packetOffset + 3] == ((m_Seed >> 8) & 0xFF) && buffer[packetOffset + 4] == (m_Seed & 0xFF)) { if (Configuration.AllowUnencryptedClients) { m_Encryption = new NoEncryption(); } else { RejectNoEncryption(from); } } else { // If it's not an unencrypted packet, simply assume it's encrypted with the seed m_Encryption = new GameEncryption(m_Seed); byte[] packet = new byte[packetLength]; Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength); m_Encryption.ClientDecrypt(ref packet, packet.Length); Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength); } } // If it's still not initialized, copy the data back to the queue and wait for more if (m_Encryption == null) { m_Buffer.Enqueue(buffer, packetOffset, packetLength); length -= packetLength; return; } } #endregion }
private static void EventSink_ClientVersionReceived(ClientVersionReceivedArgs e) { string kickMessage = null; NetState state = e.State; ClientVersion version = e.Version; if (state.Mobile != null && state.Mobile.IsStaff()) { return; } ClientVersion required = Required; if (required != null && version < required && (m_OldClientResponse == OldClientResponse.Kick || (m_OldClientResponse == OldClientResponse.LenientKick && (DateTime.UtcNow - state.Mobile.CreationTime) > m_AgeLeniency && state.Mobile is PlayerMobile && ((PlayerMobile)state.Mobile).GameTime > m_GameTimeLeniency))) { kickMessage = string.Format("This server requires your client version be at least {0}.", required); } else if (!AllowGod || !AllowRegular || !AllowUOTD) { if (!AllowGod && version.Type == ClientType.God) { kickMessage = "This server does not allow god clients to connect."; } else if (!AllowRegular && version.Type == ClientType.Regular) { kickMessage = "This server does not allow regular clients to connect."; } else if (!AllowUOTD && state.IsUOTDClient) { kickMessage = "This server does not allow UO:TD clients to connect."; } if (!AllowGod && !AllowRegular && !AllowUOTD) { kickMessage = "This server does not allow any clients to connect."; } else if (AllowGod && !AllowRegular && !AllowUOTD && version.Type != ClientType.God) { kickMessage = "This server requires you to use the god client."; } else if (kickMessage != null) { if (AllowRegular && AllowUOTD) { kickMessage += " You can use regular or UO:TD clients."; } else if (AllowRegular) { kickMessage += " You can use regular clients."; } else if (AllowUOTD) { kickMessage += " You can use UO:TD clients."; } } } if (kickMessage != null) { state.Mobile.SendMessage(0x22, kickMessage); state.Mobile.SendMessage(0x22, "You will be disconnected in {0} seconds.", KickDelay.TotalSeconds); Timer.DelayCall(KickDelay, delegate { if (state.Socket != null) { Utility.PushColor(ConsoleColor.Red); Console.WriteLine("Client: {0}: Disconnecting, bad version", state); Utility.PopColor(); state.Dispose(); } }); } else if (Required != null && version < Required) { switch (m_OldClientResponse) { case OldClientResponse.Warn: { state.Mobile.SendMessage(0x22, "Your client is out of date. Please update your client.", Required); state.Mobile.SendMessage(0x22, "This server recommends that your client version be at least {0}.", Required); break; } case OldClientResponse.LenientKick: case OldClientResponse.Annoy: { SendAnnoyGump(state.Mobile); break; } } } }
/// <summary> /// /// </summary> /// <param name="netState"></param> /// <param name="packetReader"></param> internal static void WorldServerExit(NetState netState, PacketReader packetReader) { netState.Send(new ExitAck(3)); netState.Dispose(true, 3); }
public override void OnResponse(NetState state, RelayInfo info) { if (m_State == null) { return; } Mobile focus = m_State.Mobile; Mobile from = state.Mobile; if (focus == null) { from.SendMessage("That character is no longer online."); return; } else if (focus.Deleted) { from.SendMessage("That character no longer exists."); return; } else if (from != focus && focus.Hidden && from.AccessLevel < focus.AccessLevel && (!(focus is PlayerMobile) || !((PlayerMobile)focus).VisibilityList.Contains(from))) { from.SendMessage("That character is no longer visible."); return; } switch (info.ButtonID) { case 1: // Tell { TextRelay text = info.GetTextEntry(0); if (text != null) { focus.SendMessage(0x482, "{0} tells you:", from.Name); focus.SendMessage(0x482, text.Text); CommandLogging.WriteLine(from, "{0} {1} telling {2} \"{3}\" ", from.AccessLevel, CommandLogging.Format(from), CommandLogging.Format(focus), text.Text); } from.SendGump(new ClientGump(from, m_State)); break; } case 4: // Props { Resend(from, info); if (!BaseCommand.IsAccessible(from, focus)) { from.SendMessage("That is not accessible."); } else { from.SendGump(new PropertiesGump(from, focus)); CommandLogging.WriteLine(from, "{0} {1} opening properties gump of {2} ", from.AccessLevel, CommandLogging.Format(from), CommandLogging.Format(focus)); } break; } case 5: // Go to { if (focus.Map == null || focus.Map == Map.Internal) { from.SendMessage("That character is not in the world."); } else { from.MoveToWorld(focus.Location, focus.Map); Resend(from, info); CommandLogging.WriteLine(from, "{0} {1} going to {2}, Location {3}, Map {4}", from.AccessLevel, CommandLogging.Format(from), CommandLogging.Format(focus), focus.Location, focus.Map); } break; } case 6: // Get { if (from.Map == null || from.Map == Map.Internal) { from.SendMessage("You cannot bring that person here."); } else { focus.MoveToWorld(from.Location, from.Map); Resend(from, info); CommandLogging.WriteLine(from, "{0} {1} bringing {2} to Location {3}, Map {4}", from.AccessLevel, CommandLogging.Format(from), CommandLogging.Format(focus), from.Location, from.Map); } break; } case 7: // Move { from.Target = new MoveTarget(focus); Resend(from, info); break; } case 8: // Kick { if (from.AccessLevel >= AccessLevel.GameMaster && from.AccessLevel > focus.AccessLevel) { focus.Say("I've been kicked!"); m_State.Dispose(); CommandLogging.WriteLine(from, "{0} {1} kicking {2} ", from.AccessLevel, CommandLogging.Format(from), CommandLogging.Format(focus)); } break; } case 9: // Kill { if (from.AccessLevel >= AccessLevel.GameMaster && from.AccessLevel > focus.AccessLevel) { focus.Kill(); CommandLogging.WriteLine(from, "{0} {1} killing {2} ", from.AccessLevel, CommandLogging.Format(from), CommandLogging.Format(focus)); } Resend(from, info); break; } case 10: //Res { if (from.AccessLevel >= AccessLevel.GameMaster && from.AccessLevel > focus.AccessLevel) { focus.PlaySound(0x214); focus.FixedEffect(0x376A, 10, 16); focus.Resurrect(); CommandLogging.WriteLine(from, "{0} {1} resurrecting {2} ", from.AccessLevel, CommandLogging.Format(from), CommandLogging.Format(focus)); } Resend(from, info); break; } case 11: // Skills { Resend(from, info); if (from.AccessLevel > focus.AccessLevel) { from.SendGump(new SkillsGump(from, focus)); CommandLogging.WriteLine(from, "{0} {1} Opening Skills gump of {2} ", from.AccessLevel, CommandLogging.Format(from), CommandLogging.Format(focus)); } break; } } }
public static void DisplayGumpResponse(NetState state, PacketReader pvSrc) { int serial = pvSrc.ReadInt32(); int typeID = pvSrc.ReadInt32(); int buttonID = pvSrc.ReadInt32(); //List<Gump> gumps = state.Gumps; List <Gump> gumps = state.Gumps as List <Gump>; for (int i = 0; i < gumps.Count; ++i) { Gump gump = gumps[i]; if (gump.Serial == serial && gump.TypeID == typeID) { int switchCount = pvSrc.ReadInt32(); if (switchCount < 0) { Console.WriteLine("Client: {0}: Invalid gump response, disconnecting...", state); state.Dispose(); return; } int[] switches = new int[switchCount]; for (int j = 0; j < switches.Length; ++j) { switches[j] = pvSrc.ReadInt32(); } int textCount = pvSrc.ReadInt32(); if (textCount < 0) { Console.WriteLine("Client: {0}: Invalid gump response, disconnecting...", state); state.Dispose(); return; } TextRelay[] textEntries = new TextRelay[textCount]; for (int j = 0; j < textEntries.Length; ++j) { int entryID = pvSrc.ReadUInt16(); int textLength = pvSrc.ReadUInt16(); if (textLength > 239) { return; } string text = pvSrc.ReadUnicodeStringSafe(textLength); textEntries[j] = new TextRelay(entryID, text); } state.RemoveGump(i); if (!CheckResponse(gump, state.Mobile, buttonID)) { return; } gump.OnResponse(state, new RelayInfo(buttonID, switches, textEntries)); return; } } if (typeID == 461) // Virtue gump { int switchCount = pvSrc.ReadInt32(); if (buttonID == 1 && switchCount > 0) { Mobile beheld = World.FindMobile(pvSrc.ReadInt32()); if (beheld != null) { EventSink.InvokeVirtueGumpRequest(new VirtueGumpRequestEventArgs(state.Mobile, beheld)); } } else { Mobile beheld = World.FindMobile(serial); if (beheld != null) { EventSink.InvokeVirtueItemRequest(new VirtueItemRequestEventArgs(state.Mobile, beheld, buttonID)); } } } }
public static void Next(string nput) { string input = nput.ToLower(); if (input.StartsWith("bc")) { string imput = input.Replace("bc", ""); BroadcastMessage(AccessLevel.Player, 0x35, String.Format("[Admin] {0}", imput)); Console.WriteLine("Players will see: {0}", imput); } else if (input.StartsWith("sc")) { string imput = input.Replace("staff", ""); BroadcastMessage(AccessLevel.Counselor, 0x32, String.Format("[Admin] {0}", imput)); Console.WriteLine("Staff will see: {0}", imput); } else if (input.StartsWith("ban")) { string imput = input.Replace("ban", ""); List <NetState> states = NetState.Instances; if (states.Count == 0) { Console.WriteLine("There are no players online."); } for (int i = 0; i < states.Count; ++i) { Account a = states[i].Account as Account; if (a == null) { continue; } Mobile m = states[i].Mobile; if (m == null) { continue; } string innput = imput.ToLower(); if (m.Name.ToLower() == innput.Trim()) { NetState m_ns = m.NetState; Console.WriteLine("Mobile name: '{0}' Account name: '{1}'", m.Name, a.Username); a.Banned = true; m_ns.Dispose(); Console.WriteLine("Banning complete."); } } } else if (input.StartsWith("kick")) { string imput = input.Replace("kick", ""); List <NetState> states = NetState.Instances; if (states.Count == 0) { Console.WriteLine("There are no players online."); } for (int i = 0; i < states.Count; ++i) { Account a = states[i].Account as Account; if (a == null) { continue; } Mobile m = states[i].Mobile; if (m == null) { continue; } string innput = imput.ToLower(); if (m.Name.ToLower() == innput.Trim()) { NetState m_ns = m.NetState; Console.WriteLine("Mobile name: '{0}' Account name: '{1}'", m.Name, a.Username); m_ns.Dispose(); Console.WriteLine("Kicking complete."); } } } else { switch (input.Trim()) { case "shutdown nosave": Core.Process.Kill(); break; case "restart nosave": Process.Start(Core.ExePath, Core.Arguments); Core.Process.Kill(); break; case "online": { List <NetState> states = NetState.Instances; if (states.Count == 0) { Console.WriteLine("There are no users online at this time."); } for (int i = 0; i < states.Count; ++i) { Account a = states[i].Account as Account; if (a == null) { continue; } Mobile m = states[i].Mobile; if (m != null) { Console.WriteLine("- Account: {0}, Name: {1}, IP: {2}", a.Username, m.Name, states[i]); } } break; } case "pages": { paging = true; ArrayList list = PageQueue.List; PageEntry e; for (int i = 0; i < list.Count;) { e = (PageEntry)list[i]; if (e.Sender.Deleted || e.Sender.NetState == null) { e.AddResponse(e.Sender, "[Logout]"); PageQueue.Remove(e); } else { ++i; } } m_List = (PageEntry[])list.ToArray(typeof(PageEntry)); if (m_List.Length > 0) { for (int i = 0; i < m_List.Length; ++i) { e = m_List[i]; string type = PageQueue.GetPageTypeName(e.Type); Console.WriteLine("--------------Page Number: " + i + " --------------------"); Console.WriteLine("Player :" + e.Sender.Name); Console.WriteLine("Catagory :" + type); Console.WriteLine("Message :" + e.Message); } Console.WriteLine("Type the number of the page to respond to."); object[] oj = new object[] { 1, 2 }; ThreadPool.QueueUserWorkItem(new WaitCallback(PageResp), oj); } else { Console.WriteLine("No pages to display."); paging = false; } break; } case "help": case "list": //Credit to HomeDaddy for this wonderful list! default: { Console.WriteLine(" "); Console.WriteLine("Commands:"); Console.WriteLine("shutdown nosave - Shuts down the server without saving."); Console.WriteLine("restart nosave - Restarts the server without saving."); Console.WriteLine("online - Shows a list of every person online:"); Console.WriteLine(" Account, Char Name, IP."); Console.WriteLine("bc <message> - Type this command and your message after it. It will then be"); Console.WriteLine(" sent to all players."); Console.WriteLine("sc <message> - Type this command and your message after it.It will then be "); Console.WriteLine(" sent to all staff."); Console.WriteLine("pages - Shows all the pages in the page queue,you type the page"); Console.WriteLine(" number ,then you type your response to the player."); Console.WriteLine("ban <playername>- Kicks and bans the users account."); Console.WriteLine("kick <playername>- Kicks the user."); Console.WriteLine("list or help - Shows this list."); Console.WriteLine(" "); break; } } } if (!paging) { ThreadPool.QueueUserWorkItem(new WaitCallback(ConsoleListen)); } }
public bool OnReceive(NetState ns) { ByteQueue buffer = ns.Buffer; if (buffer == null || buffer.Length <= 0) { return(true); } lock (buffer) { int length = buffer.Length; while (length > 0) { int packetID = buffer.GetPacketID(); PacketHandler handler = ns.GetHandler(packetID); if (handler == null) { var data = new byte[length]; length = buffer.Dequeue(data, 0, length); new PacketReader(data, length, false).Trace(ns); break; } int packetLength = handler.Length; if (packetLength <= 0) { if (length >= 3) { packetLength = buffer.GetPacketLength(); if (packetLength < 3) { ns.Dispose(); break; } } else { break; } } if (length < packetLength) { break; } var packetBuffer = BufferSize >= packetLength?_buffers.AcquireBuffer() : new byte[packetLength]; packetLength = buffer.Dequeue(packetBuffer, 0, packetLength); PacketReader r = new PacketReader(packetBuffer, packetLength, handler.Length != 0); handler.OnReceive(ns, r); length = buffer.Length; if (BufferSize >= packetLength) { _buffers.ReleaseBuffer(packetBuffer); } } } return(true); }
private static void EventSink_DeleteRequest(DeleteRequestEventArgs e) { NetState state = e.State; int index = e.Index; Account acct = state.Account as Account; IPAddress[] accessList = new IPAddress[] {}; if (acct != null) { accessList = acct.LoginIPs; } if (acct == null) { state.Dispose(); } else if (index < 0 || index >= acct.Length) { state.Send(new DeleteResult(DeleteResultType.BadRequest)); state.Send(new CharacterListUpdate(acct)); } else { try { Mobile m = acct[index]; IPAddress ipAddress = state.Address; PlayerMobile pm = null; if (m != null && m.Player) { pm = (PlayerMobile)m; } if (m == null) { state.Send(new DeleteResult(DeleteResultType.CharNotExist)); state.Send(new CharacterListUpdate(acct)); } else if (m.NetState != null) { state.Send(new DeleteResult(DeleteResultType.CharBeingPlayed)); state.Send(new CharacterListUpdate(acct)); } else if (RestrictDeletion && DateTime.Now < (m.CreationTime + DeleteDelay)) { state.Send(new DeleteResult(DeleteResultType.CharTooYoung)); state.Send(new CharacterListUpdate(acct)); } else if (m.AccessLevel == AccessLevel.Player && Region.Find(m.LogoutLocation, m.LogoutMap).GetRegion(typeof(Jail)) != null) //Don't need to check current location, if netstate is null, they're logged out { state.Send(new DeleteResult(DeleteResultType.BadRequest)); state.Send(new CharacterListUpdate(acct)); } /* * else if ( (pm != null && !pm.AllowDelete) && !Utility.IPMatchClassC(accessList[0], ipAddress)) * { * Console.WriteLine("Client: {0}: Trying to delete character {1} (0x{2:X})", state, index, m.Serial.Value); * state.Send(new DeleteResult(DeleteResultType.BadRequest)); * state.Send(new CharacterListUpdate(acct)); * }*/ else { Console.WriteLine(@"Client: {0}: Deleting character {1} (0x{2:X})", state, index, m.Serial.Value); acct.Comments.Add(new AccountComment("System", String.Format("Character #{0} {1} deleted by {2}", index + 1, m, state))); m.Delete(); state.Send(new CharacterListUpdate(acct)); } } catch { } } }
// Try to decrypt incoming data. public void DecodeIncomingPacket(NetState from, ref byte[] buffer, ref int length) { if (m_Encryption != null) { // If we're decrypting using LoginCrypt and we've already been relayed, // only decrypt a single packet using logincrypt and then disable it if (m_AlreadyRelayed && m_Encryption is LoginEncryption) { uint newSeed = ((((LoginEncryption)(m_Encryption)).Key1 + 1) ^ ((LoginEncryption)(m_Encryption)).Key2); // Swap the seed newSeed = ((newSeed >> 24) & 0xFF) | ((newSeed >> 8) & 0xFF00) | ((newSeed << 8) & 0xFF0000) | ((newSeed << 24) & 0xFF000000); // XOR it with the old seed newSeed ^= m_Seed; IClientEncryption newEncryption = new GameEncryption(newSeed); // Game Encryption comes first newEncryption.clientDecrypt(ref buffer, length); // The login encryption is still used for this one packet m_Encryption.clientDecrypt(ref buffer, length); // Swap the encryption schemes m_Encryption = newEncryption; m_Seed = newSeed; return; } m_Encryption.clientDecrypt(ref buffer, length); return; } // If the client did not connect on the game server port, // it's not our business to handle encryption for it if (((IPEndPoint)from.Socket.LocalEndPoint).Port != Listener.Port) { m_Encryption = new NoEncryption(); return; } // For simplicities sake, enqueue what we just received as long as we're not initialized m_Buffer.Enqueue(buffer, 0, length); // Clear the array length = 0; // If we didn't receive the seed yet, queue data until we can read the seed if (!m_Seeded) { // Now check if we have at least 4 bytes to get the seed if (m_Buffer.Length >= 4) { byte[] m_Peek = new byte[m_Buffer.Length]; m_Buffer.Dequeue(m_Peek, 0, m_Buffer.Length); // Dequeue everything m_Seed = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]); m_Seeded = true; Buffer.BlockCopy(m_Peek, 0, buffer, 0, 4); length = 4; } else { return; } } // If the context isn't initialized yet, that means we haven't decided on an encryption method yet if (m_Encryption == null) { int packetLength = m_Buffer.Length; int packetOffset = length; m_Buffer.Dequeue(buffer, length, packetLength); // Dequeue everything length += packetLength; // This is special handling for the "special" UOG packet if (packetLength >= 3) { if (buffer[packetOffset] == 0xf1 && buffer[packetOffset + 1] == ((packetLength >> 8) & 0xFF) && buffer[packetOffset + 2] == (packetLength & 0xFF)) { m_Encryption = new NoEncryption(); return; } } // Check if the current buffer contains a valid login packet (62 byte + 4 byte header) // Please note that the client sends these in two chunks. One 4 byte and one 62 byte. if (packetLength == 62) { // Check certain indices in the array to see if the given data is unencrypted if (buffer[packetOffset] == 0x80 && buffer[packetOffset + 30] == 0x00 && buffer[packetOffset + 60] == 0x00) { if (Configuration.AllowUnencryptedClients) { m_Encryption = new NoEncryption(); } else { RejectNoEncryption(from); from.Dispose(); return; } } else { LoginEncryption encryption = new LoginEncryption(); if (encryption.init(m_Seed, buffer, packetOffset, packetLength)) { Console.WriteLine("Client: {0}: Encrypted client detected, using keys of client {1}", from, encryption.Name); m_Encryption = encryption; byte[] packet = new byte[packetLength]; Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength); encryption.clientDecrypt(ref packet, packet.Length); Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength); } else { Console.WriteLine("Detected an unknown client."); } } } else if (packetLength == 65) { // If its unencrypted, use the NoEncryption class if (buffer[packetOffset] == '\x91' && buffer[packetOffset + 1] == ((m_Seed >> 24) & 0xFF) && buffer[packetOffset + 2] == ((m_Seed >> 16) & 0xFF) && buffer[packetOffset + 3] == ((m_Seed >> 8) & 0xFF) && buffer[packetOffset + 4] == (m_Seed & 0xFF)) { if (Configuration.AllowUnencryptedClients) { m_Encryption = new NoEncryption(); } else { RejectNoEncryption(from); from.Dispose(); return; } } else { // If it's not an unencrypted packet, simply assume it's encrypted with the seed m_Encryption = new GameEncryption(m_Seed); byte[] packet = new byte[packetLength]; Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength); m_Encryption.clientDecrypt(ref packet, packet.Length); Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength); } } // If it's still not initialized, copy the data back to the queue and wait for more if (m_Encryption == null) { m_Buffer.Enqueue(buffer, packetOffset, packetLength); length -= packetLength; return; } } }
private static void ProcessCommand(string input) { input = input.Trim(); if (_Pages != null) { HandlePaging(input); return; } if (input.StartsWith("pages", StringComparison.OrdinalIgnoreCase)) { HandlePaging(input.Substring(5).Trim()); return; } if (input.StartsWith("bc", StringComparison.OrdinalIgnoreCase)) { string sub = input.Substring(2).Trim(); BroadcastMessage(AccessLevel.Player, 0x35, string.Format("[Admin] {0}", sub)); Console.WriteLine("[World]: {0}", sub); return; } if (input.StartsWith("sc", StringComparison.OrdinalIgnoreCase)) { string sub = input.Substring(2).Trim(); BroadcastMessage(AccessLevel.Counselor, 0x32, string.Format("[Admin] {0}", sub)); Console.WriteLine("[Staff]: {0}", sub); return; } if (input.StartsWith("ban", StringComparison.OrdinalIgnoreCase)) { string sub = input.Substring(3).Trim(); System.Collections.Generic.List <NetState> states = NetState.Instances; if (states.Count == 0) { Console.WriteLine("There are no players online."); return; } NetState ns = states.Find(o => o.Account != null && o.Mobile != null && Insensitive.StartsWith(sub, o.Mobile.RawName)); if (ns != null) { Console.WriteLine("[Ban]: {0}: Mobile: '{1}' Account: '{2}'", ns, ns.Mobile.RawName, ns.Account.Username); ns.Dispose(); } return; } if (input.StartsWith("kick", StringComparison.OrdinalIgnoreCase)) { string sub = input.Substring(4).Trim(); System.Collections.Generic.List <NetState> states = NetState.Instances; if (states.Count == 0) { Console.WriteLine("There are no players online."); return; } NetState ns = states.Find(o => o.Account != null && o.Mobile != null && Insensitive.StartsWith(sub, o.Mobile.RawName)); if (ns != null) { Console.WriteLine("[Kick]: {0}: Mobile: '{1}' Account: '{2}'", ns, ns.Mobile.RawName, ns.Account.Username); ns.Dispose(); } return; } switch (input.Trim()) { case "crash": { Timer.DelayCall(() => { throw new Exception("Forced Crash"); }); } break; case "shutdown": { AutoSave.Save(); Core.Kill(false); } break; case "shutdown nosave": { Core.Kill(false); } break; case "restart": { AutoSave.Save(); Core.Kill(true); } break; case "save recompile": { var path = AutoRestart.RecompilePath; if (!File.Exists(path)) { Console.WriteLine("Unable to Re-Compile due to missing file: {0}", AutoRestart.RecompilePath); } else { AutoSave.Save(); System.Diagnostics.Process.Start(path); Core.Kill(); } } break; case "nosave recompile": { var path = AutoRestart.RecompilePath; if (!File.Exists(path)) { Console.WriteLine("Unable to Re-Compile due to missing file: {0}", AutoRestart.RecompilePath); } else { System.Diagnostics.Process.Start(path); Core.Kill(); } } break; case "restart nosave": { Core.Kill(true); } break; case "online": { System.Collections.Generic.List <NetState> states = NetState.Instances; if (states.Count == 0) { Console.WriteLine("There are no users online at this time."); } foreach (NetState t in states) { Account a = t.Account as Account; if (a == null) { continue; } Mobile m = t.Mobile; if (m != null) { Console.WriteLine("- Account: {0}, Name: {1}, IP: {2}", a.Username, m.Name, t); } } } break; case "save": AutoSave.Save(); break; case "hear": // Credit to Zippy for the HearAll script! { _HearConsole = !_HearConsole; Console.WriteLine("{0} sending speech to the console.", _HearConsole ? "Now" : "No longer"); } break; default: DisplayHelp(); break; } }
public static void Next(string input) { input = input.ToLower(); if (input.StartsWith("bc")) { string sub = input.Replace("bc", ""); BroadcastMessage(AccessLevel.Player, 0x35, String.Format("[Admin] {0}", sub)); Console.WriteLine("Players will see: {0}", sub); } else if (input.StartsWith("sc")) { string sub = input.Replace("staff", ""); BroadcastMessage(AccessLevel.Counselor, 0x32, String.Format("[Admin] {0}", sub)); Console.WriteLine("Staff will see: {0}", sub); } else if (input.StartsWith("ban")) { string sub = input.Replace("ban", ""); var states = NetState.Instances; if (states.Count == 0) { Console.WriteLine("There are no players online."); } foreach (NetState t in states) { Account a = t.Account as Account; if (a == null) { continue; } Mobile m = t.Mobile; if (m == null) { continue; } sub = sub.ToLower(); if (m.Name.ToLower() != sub.Trim()) { continue; } NetState m_ns = m.NetState; Console.WriteLine("Mobile name: '{0}' Account name: '{1}'", m.Name, a.Username); a.Banned = true; m_ns.Dispose(); Console.WriteLine("Banning complete."); } } else if (input.StartsWith("kick")) { string sub = input.Replace("kick", ""); var states = NetState.Instances; if (states.Count == 0) { Console.WriteLine("There are no players online."); } foreach (NetState t in states) { Account a = t.Account as Account; if (a == null) { continue; } Mobile m = t.Mobile; if (m == null) { continue; } sub = sub.ToLower(); if (m.Name.ToLower() != sub.Trim()) { continue; } NetState m_ns = m.NetState; Console.WriteLine("Mobile name: '{0}' Account name: '{1}'", m.Name, a.Username); m_ns.Dispose(); Console.WriteLine("Kicking complete."); } } else { switch (input.Trim()) { case "shutdown": { AutoSave.Save(); Core.Process.Kill(); } break; case "shutdown nosave": Core.Process.Kill(); break; case "restart": { BroadcastMessage(AccessLevel.Player, 0x35, String.Format("[Server] We are restarting...")); AutoSave.Save(); Process.Start(Core.ExePath, Core.Arguments); Core.Process.Kill(); } break; case "restart nosave": { Process.Start(Core.ExePath, Core.Arguments); Core.Process.Kill(); } break; case "online": { var states = NetState.Instances; if (states.Count == 0) { Console.WriteLine("There are no users online at this time."); } foreach (NetState t in states) { Account a = t.Account as Account; if (a == null) { continue; } Mobile m = t.Mobile; if (m != null) { Console.WriteLine("- Account: {0}, Name: {1}, IP: {2}", a.Username, m.Name, t); } } } break; case "save": AutoSave.Save(true); break; case "hear": //credit to Zippy for the HearAll script! { _HearConsole = !_HearConsole; Console.WriteLine( _HearConsole ? "Now sending all speech to the console." : "No longer sending speech to the console."); } break; case "pages": { Paging = true; ArrayList list = PageQueue.List; PageEntry e; for (int i = 0; i < list.Count;) { e = (PageEntry)list[i]; if (e.Sender.Deleted || e.Sender.NetState == null) { e.AddResponse(e.Sender, "[Logout]"); PageQueue.Remove(e); } else { ++i; } } _List = (PageEntry[])list.ToArray(typeof(PageEntry)); if (_List.Length > 0) { for (int i = 0; i < _List.Length; ++i) { e = _List[i]; string type = PageQueue.GetPageTypeName(e.Type); Console.WriteLine("--------------Page Number: " + i + " --------------------"); Console.WriteLine("Player :" + e.Sender.Name); Console.WriteLine("Catagory :" + type); Console.WriteLine("Message :" + e.Message); } Console.WriteLine("Type the number of the page to respond to."); ThreadPool.QueueUserWorkItem(PageResp, new object[] { 1, 2 }); } else { Console.WriteLine("No pages to display."); Paging = false; } } break; //case "help": //case "list": default: { Console.WriteLine(" "); Console.WriteLine("Commands:"); Console.WriteLine("save - Performs a forced save."); Console.WriteLine("shutdown - Performs a forced save then shuts down the server."); Console.WriteLine("shutdown nosave - Shuts down the server without saving."); Console.WriteLine("restart - Sends a message to players informing them that the server is"); Console.WriteLine(" restarting, performs a forced save, then shuts down and"); Console.WriteLine(" restarts the server."); Console.WriteLine("restart nosave - Restarts the server without saving."); Console.WriteLine("online - Shows a list of every person online:"); Console.WriteLine(" Account, Char Name, IP."); Console.WriteLine("bc <message> - Type this command and your message after it. It will then be"); Console.WriteLine(" sent to all players."); Console.WriteLine("sc <message> - Type this command and your message after it.It will then be "); Console.WriteLine(" sent to all staff."); Console.WriteLine("hear - Copies all local speech to this console:"); Console.WriteLine(" Char Name (Region name): Speech."); Console.WriteLine("pages - Shows all the pages in the page queue,you type the page"); Console.WriteLine(" number ,then you type your response to the player."); Console.WriteLine("ban <playername>- Kicks and bans the users account."); Console.WriteLine("kick <playername>- Kicks the user."); Console.WriteLine("list or help - Shows this list."); Console.WriteLine(" "); } break; } } if (!Paging) { ThreadPool.QueueUserWorkItem(ConsoleListen); } }
private void RunTaskNetStateDisconnect(NetState netState) { m_netStateManager.InternalRemoveNetState(netState.Serial); // 通知业务逻辑有客户端连接上来可以做一些初始化 // 或者判断是否允许本次连接 var tempEV = NetStateDisconnect; if (tempEV != null) { var arg = new NetStateDisconnectEventArgs { NetState = netState, }; tempEV(this, arg); } netState.ExitWorld(); netState.Dispose(); }
public void DecodeIncomingPacket(NetState from, ref byte[] buffer, ref int length) { if (m_Encryption != null) { if (m_AlreadyRelayed && m_Encryption is LoginEncryption) { uint newSeed = ((((LoginEncryption)(m_Encryption)).Key1 + 1) ^ ((LoginEncryption)(m_Encryption)).Key2); newSeed = ((newSeed >> 24) & 0xFF) | ((newSeed >> 8) & 0xFF00) | ((newSeed << 8) & 0xFF0000) | ((newSeed << 24) & 0xFF000000); newSeed ^= m_Seed; IClientEncryption newEncryption = new GameEncryption(newSeed); newEncryption.clientDecrypt(ref buffer, length); m_Encryption.clientDecrypt(ref buffer, length); m_Encryption = newEncryption; m_Seed = newSeed; return; } m_Encryption.clientDecrypt(ref buffer, length); return; } bool handle = false; for (int i = 0; i < Listener.EndPoints.Length; i++) { IPEndPoint ipep = (IPEndPoint)Listener.EndPoints[i]; if (((IPEndPoint)from.Socket.LocalEndPoint).Port == ipep.Port) { handle = true; } } if (!handle) { m_Encryption = new NoEncryption(); return; } m_Buffer.Enqueue(buffer, 0, length); length = 0; if (!m_Seeded) { if (m_Buffer.Length <= 3) { Console.WriteLine("Encryption: Failed - Short Lenght"); return; } else if ((m_Buffer.Length == 83 || m_Buffer.Length == 21) && (m_Buffer.GetPacketID() == 239)) //New Client { length = m_Buffer.Length; byte[] m_Peek = new byte[21]; m_Buffer.Dequeue(m_Peek, 0, 21); m_Seed = (uint)((m_Peek[1] << 24) | (m_Peek[2] << 16) | (m_Peek[3] << 8) | m_Peek[4]); m_Seeded = true; Buffer.BlockCopy(m_Peek, 0, buffer, 0, 21); Console.WriteLine("Encryption: Passed - New Client"); if (length == 21) { return; } length = 21; } else if (m_Buffer.Length >= 4) { byte[] m_Peek = new byte[4]; m_Buffer.Dequeue(m_Peek, 0, 4); m_Seed = (uint)((m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]); m_Seeded = true; Buffer.BlockCopy(m_Peek, 0, buffer, 0, 4); length = 4; Console.WriteLine("Encryption: Passed - Old Client"); } else { Console.WriteLine("Encryption: Failed - It should never reach here"); return; } } if (m_Encryption == null) { int packetLength = m_Buffer.Length; int packetOffset = length; m_Buffer.Dequeue(buffer, length, packetLength); length += packetLength; if (packetLength >= 3) { if (buffer[packetOffset] == 0xf1 && buffer[packetOffset + 1] == ((packetLength >> 8) & 0xFF) && buffer[packetOffset + 2] == (packetLength & 0xFF)) { m_Encryption = new NoEncryption(); return; } } if (packetLength == 62) { if (buffer[packetOffset] == 0x80 && buffer[packetOffset + 30] == 0x00 && buffer[packetOffset + 60] == 0x00) { if (Configuration.AllowUnencryptedClients) { m_Encryption = new NoEncryption(); } else { RejectNoEncryption(from); from.Dispose(); return; } } else { LoginEncryption encryption = new LoginEncryption(); if (encryption.init(m_Seed, buffer, packetOffset, packetLength)) { Console.WriteLine("Client: {0}: Encrypted client detected, using keys of client {1}", from, encryption.Name); m_Encryption = encryption; byte[] packet = new byte[packetLength]; Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength); encryption.clientDecrypt(ref packet, packet.Length); Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength); } else { Console.WriteLine("Client: {0}: Detected an unknown client.", from); } } } else if (packetLength == 65) { if (buffer[packetOffset] == '\x91' && buffer[packetOffset + 1] == ((m_Seed >> 24) & 0xFF) && buffer[packetOffset + 2] == ((m_Seed >> 16) & 0xFF) && buffer[packetOffset + 3] == ((m_Seed >> 8) & 0xFF) && buffer[packetOffset + 4] == (m_Seed & 0xFF)) { if (Configuration.AllowUnencryptedClients) { m_Encryption = new NoEncryption(); } else { RejectNoEncryption(from); from.Dispose(); } } else { m_Encryption = new GameEncryption(m_Seed); byte[] packet = new byte[packetLength]; Buffer.BlockCopy(buffer, packetOffset, packet, 0, packetLength); m_Encryption.clientDecrypt(ref packet, packet.Length); Buffer.BlockCopy(packet, 0, buffer, packetOffset, packetLength); } } if (m_Encryption == null) { Console.WriteLine("Encryption: Check - Waiting"); m_Buffer.Enqueue(buffer, packetOffset, packetLength); length -= packetLength; return; } } }
void RunTaskNetStateConnect(NetState netState) { // 通知业务逻辑有客户端连接上来可以做一些初始化 // 或者判断是否允许本次连接 var tempEV = NetStateConnect; if (tempEV != null) { var arg = new NetStateConnectEventArgs { NetState = netState, AllowConnect = true }; tempEV(this, arg); if (arg.AllowConnect == false) { netState.Dispose(); return; } } netState.Serial = netStateId++; m_netStateManager.InternalAddNetState(netState.Serial, netState); netState.Start(); }
private static void EventSink_ClientVersionReceived(ClientVersionReceivedArgs e) { string kickMessage = null; NetState state = e.State; ClientVersion version = e.Version; if (state.Mobile.AccessLevel > AccessLevel.Player) { return; } if (Required != null && m_OldClientResponse == OldClientResponse.Kick && version < Required) { kickMessage = String.Format("This server requires your client version be at least {0}.", Required); } else if (!AllowGod || !AllowRegular || !AllowUOTD) { if (!AllowGod && version.Type == ClientType.God) { kickMessage = "This server does not allow god clients to connect."; } else if (!AllowRegular && version.Type == ClientType.Regular) { kickMessage = "This server does not allow regular clients to connect."; } else if (!AllowUOTD && state.IsUOTDClient) { kickMessage = "This server does not allow UO:TD clients to connect."; } if (!AllowGod && !AllowRegular && !AllowUOTD) { kickMessage = "This server does not allow any clients to connect."; } else if (AllowGod && !AllowRegular && !AllowUOTD && version.Type != ClientType.God) { kickMessage = "This server requires you to use the god client."; } else if (kickMessage != null) { if (AllowRegular && AllowUOTD) { kickMessage += " You can use regular or UO:TD clients."; } else if (AllowRegular) { kickMessage += " You can use regular clients."; } else if (AllowUOTD) { kickMessage += " You can use UO:TD clients."; } } } if (kickMessage != null) { state.Mobile.SendMessage(0x22, kickMessage); state.Mobile.SendMessage(0x22, "You will be disconnected in {0} seconds.", KickDelay.TotalSeconds); Timer.DelayCall(KickDelay, delegate { if (state.Socket != null) { Console.WriteLine("Client: {0}: Disconnecting, bad version", state); state.Dispose(); } }); } else if (Required != null && version < Required) { switch (m_OldClientResponse) { case OldClientResponse.Warn: { state.Mobile.SendMessage(0x22, "Your client is out of date. Please update your client.", Required); state.Mobile.SendMessage(0x22, "This server recommends that your client version be at least {0}.", Required); break; } case OldClientResponse.Annoy: { SendAnnoyGump(state.Mobile); break; } } } }