internal static MessageClient Parse(ZonePacket packet, bool isLobby = false) { byte[] rawMessageData = packet.Data; var parsedMessageStructure = new Message(); parsedMessageStructure.TypeID = BitConverter.ToInt32(rawMessageData, 0); parsedMessageStructure.Size = BitConverter.ToInt32(rawMessageData, 4); if (parsedMessageStructure.TypeID != (Int32)Messages.SIGNATURE.PING_MSG) { parsedMessageStructure.Data = new byte[parsedMessageStructure.Size]; if (parsedMessageStructure.Data.Length > rawMessageData.Length - 8) { throw new Protocol.Packet.ZonePacket.NotEnoughBytesException(); // this should really not happen since it show had been thrown in ZonePacket.Parse before it got here } else { Array.Copy(rawMessageData, 8, parsedMessageStructure.Data, 0, parsedMessageStructure.Size); } } var messageClientParser = Messages.getAllClientMessages() .SingleOrDefault(message => message.CanParse(parsedMessageStructure, isLobby)); if (messageClientParser == null) { Log.Debug("Message", "Message Client Parser not found for Type ID[" + parsedMessageStructure.TypeID + "]"); return(null); } var parsedMessage = messageClientParser.Parse(parsedMessageStructure); return(parsedMessage); }
public static void SetCurrentUserStateAndAppID( ZoneClient zoneClient, ZoneClient.UserState userState, ZoneClient.AppID appID, List <IZonePacket> packets = null) { zoneClient.CurrentAppID = ((Int32)appID == 16) ? ZoneClient.AppID.AoT : ZoneClient.AppID.AoM; zoneClient.CurrentUserState = userState; Log.Inform("Zone", "User [" + zoneClient.Username.TrimEnd('\0') + "]:" + " AppID[" + zoneClient.CurrentAppID + "]" + " UserState[" + zoneClient.CurrentUserState + "]"); var stateAckMessage = new Messages.Messages.StateAckMessage(); if (packets == null) { zoneClient.packetsToBeSent.Add( ZonePacket.FromMessage(stateAckMessage, zoneClient)); } else { packets.Add( ZonePacket.FromMessage(stateAckMessage, zoneClient)); } var userMessage = new Messages.Messages.UserMessage(zoneClient.Username, zoneClient.CurrentAppID, zoneClient.CurrentUserState); Zone.OnlineClients .Where(client => string.Equals(client.Username, zoneClient.Username, StringComparison.OrdinalIgnoreCase) == false && client.WatchList.Contains(zoneClient.Username.TrimEnd('\0'), StringComparer.OrdinalIgnoreCase)) .ForEach(_ => _.packetsToBeSent.Add( ZonePacket.FromMessage(userMessage, _))); }
public static FirstZonePacket Parse(byte[] rawData) { ZonePacket.xorBytes(ref rawData, -131647931); var parsedPacket = new FirstZonePacket(); parsedPacket.Signature = BitConverter.ToInt32(rawData, 0); parsedPacket.UnionType = BitConverter.ToInt32(rawData, 4); if (parsedPacket.UnionType != 18414848) { //chat server UnionType = 8322048 //throw new Exception("Unsupported union type."); } parsedPacket.SecureKey = BitConverter.ToInt32(rawData, 8); parsedPacket.SequenceID = BitConverter.ToInt32(rawData, 12); return(parsedPacket); }
public static List <IZonePacket> Process(ZoneClient zoneClient, byte[] data) { var packetsToSend = new List <IZonePacket>(); ZonePacket packet; try { packet = ZonePacket.Parse(ref data, zoneClient.SecureKey); } catch (Packet.ZonePacket.CRCMismatchException ex) { packet = ex.ParsedPacket; Log.Warning("Zone", "CRC Mismatch. Expected[" + ex.ComputedCRC + "] Got[" + packet.CRC + "]"); // This should not happen... but we shall ignore } if (packet.Signature != ZonePacket.ZONE_SIGNATURE) { Log.Debug("Zone", "Wrong signature. " + "Expected[" + ZonePacket.ZONE_SIGNATURE + "] Got[" + packet.Signature + "]"); } switch (zoneClient.CurrentProtocolState) { case ZoneClient.UserProtocolState.Connecting: { Random random = new Random(); byte key = (byte)random.Next(byte.MaxValue); UInt32 secureKey = BitConverter.ToUInt32(new byte[] { key, key, key, key }, 0); UInt32 sequenceID = BitConverter.ToUInt32( new byte[] { (byte)random.Next(byte.MaxValue), (byte)random.Next(byte.MaxValue), (byte)random.Next(byte.MaxValue), (byte)random.Next(byte.MaxValue) }, 0); zoneClient.CurrentProtocolState = ZoneClient.UserProtocolState.ExchangingFirstSecureMessage; secureKey = 2694881440; sequenceID = 2693930841; zoneClient.SecureKey = (Int32)secureKey; zoneClient.SequenceID = sequenceID; var unionType = zoneClient.IsOnLobby ? FirstZonePacket.UnionTypes.ZCHAT_FIRST_MSG : FirstZonePacket.UnionTypes.ZCONN_FIRST_MSG; return(new List <IZonePacket>() { new FirstZonePacket(secureKey, sequenceID, unionType) }); } case ZoneClient.UserProtocolState.ExchangingFirstSecureMessage: { zoneClient.CurrentProtocolState = ZoneClient.UserProtocolState.GeneratingSecurityContext; var messageClient = Message.Parse(packet); var messageServer = new Messages.Messages.FirstSecureMessageServer(); return(new List <IZonePacket>() { ZonePacket.FromMessage(messageServer, zoneClient) }); } case ZoneClient.UserProtocolState.GeneratingSecurityContext: { zoneClient.CurrentProtocolState = ZoneClient.UserProtocolState.Authenticating; var messageClient = Message.Parse(packet); int userID = ((Messages.Messages.GenerateSecurityContext)messageClient).UserID; Log.Inform("ZoneService", "Client ID[" + userID + "]"); zoneClient.UserID = userID; // TODO: Resolve username here... zoneClient.Username = Zone.getUsernameByID(userID); if (string.IsNullOrEmpty(zoneClient.Username)) // what do to ? { zoneClient.Username = "******"; } zoneClient.Username += '\0'; var messageServer = new Messages.Messages.SecurityContextServer(); return(new List <IZonePacket>() { ZonePacket.FromMessage(messageServer, zoneClient) }); } case ZoneClient.UserProtocolState.Authenticating: { zoneClient.CurrentProtocolState = ZoneClient.UserProtocolState.ConnectingProtocol; var messageClient = Message.Parse(packet); Log.Inform("ZoneService", "Access granted to client"); var messageServer = new Messages.Messages.ServerAccessGranted(zoneClient.UserID, zoneClient.Username); return(new List <IZonePacket>() { ZonePacket.FromMessage(messageServer, zoneClient) }); } case ZoneClient.UserProtocolState.ConnectingProtocol: { zoneClient.CurrentProtocolState = ZoneClient.UserProtocolState.Online; var messageClient = Message.Parse(packet); if (messageClient is Messages.Messages.RoomConnectMessage) { zoneClient.UserLobbyID = zoneClient.Lobby.GetNextAvailableUserLobbyID(); var roomAccessedMessage = new Messages.Messages.RoomAccessedMessage(zoneClient.UserLobbyID); zoneClient.Lobby.Users.Add(zoneClient); return(new List <IZonePacket>() { ZonePacket.FromMessage(roomAccessedMessage, zoneClient), }); } else { Zone.OnlineClients.Add(zoneClient); var messageServer = new Messages.Messages.ConnectAckMessage(zoneClient.Username); var welcomeServerMessage = new Messages.Messages.DataMessageStringServer( "Server", "Welcome online! Please send your feedback using /feedback {insert suggestion here} on the chat."); return(new List <IZonePacket>() { ZonePacket.FromMessage(messageServer, zoneClient), ZonePacket.FromMessage(welcomeServerMessage, zoneClient) }); } } case ZoneClient.UserProtocolState.Online: { var messageClient = Message.Parse(packet, zoneClient.IsOnLobby); if (messageClient is Messages.Messages.TalkMessage) { var talkMessageClient = (messageClient as Messages.Messages.TalkMessage); zoneClient.Lobby.Messages.Add(Tuple.Create(zoneClient.UserLobbyID, talkMessageClient.Message)); } else if (messageClient is Messages.Messages.WatchMessage) { var watchMessage = messageClient as Messages.Messages.WatchMessage; zoneClient.WatchList.Add(watchMessage.Username); var watchAckMessage = new Messages.Messages.WatchAckMessage(watchMessage.Username); packetsToSend.Add( ZonePacket.FromMessage(watchAckMessage, zoneClient)); // TODO: Replace with proper awnser var otherClient = Zone.OnlineClients.SingleOrDefault(client => string.Equals(client.Username, watchMessage.Username, StringComparison.InvariantCultureIgnoreCase)); if (otherClient != null) { var userMessage = new Messages.Messages.UserMessage( otherClient.Username, otherClient.CurrentAppID, otherClient.CurrentUserState); packetsToSend.Add( ZonePacket.FromMessage(userMessage, zoneClient)); } // TODO: else } else if (messageClient is Messages.Messages.StateMessage) { var stateMessage = messageClient as Messages.Messages.StateMessage; Zone.SetCurrentUserStateAndAppID(zoneClient, stateMessage.GetUserState(), stateMessage.GetAppID(), packetsToSend); } else if (messageClient is Messages.Messages.DataMessageClient) { var dataMessage = messageClient as Messages.Messages.DataMessageClient; var dataAckMessage = new Messages.Messages.DataMessageAck(zoneClient.Username); packetsToSend.Add( ZonePacket.FromMessage(dataAckMessage, zoneClient)); switch (dataMessage.Type) { case Messages.Messages.DataMessageType.String: { Log.Inform("Zone", "User [" + zoneClient.Username.TrimEnd('\0') + "]:" + " ToUser[" + dataMessage.Username.TrimEnd('\0') + "]" + " Message[" + dataMessage.DataString.TrimEnd('\0') + "]"); if (string.Equals("feedback", dataMessage.Username, StringComparison.InvariantCultureIgnoreCase)) { string messageFormat = "{0}: {1}\n"; string messageFormatted = string.Format(messageFormat, zoneClient.Username.TrimEnd('\0'), dataMessage.DataString.TrimEnd('\0')); File.AppendAllText("Feedback.txt", messageFormatted, Encoding.BigEndianUnicode); break; } var otherClient = Zone.OnlineClients.SingleOrDefault(client => string.Equals(client.Username, dataMessage.Username, StringComparison.InvariantCultureIgnoreCase)); if (otherClient != null) { var stringMessage = new Messages.Messages.DataMessageStringServer( zoneClient.Username, dataMessage.DataString); otherClient.packetsToBeSent.Add(ZonePacket.FromMessage(stringMessage, otherClient)); } else { // TODO } break; } //case Messages.Messages.DataMessageType.Invitation: //case Messages.Messages.DataMessageType.InvitationResponse: //case Messages.Messages.DataMessageType.InvitationClientToJoinGame: //case Messages.Messages.DataMessageType.InvitationTimeout: // not sure if needed //case Messages.Messages.DataMessageType.InvitationTimeout2: //case Messages.Messages.DataMessageType.ClientToJoinGame: //case Messages.Messages.DataMessageType.ClientToJoinGameResponse: default: { var otherClient = Zone.OnlineClients.SingleOrDefault(client => string.Equals(client.Username, dataMessage.Username, StringComparison.InvariantCultureIgnoreCase)); if (otherClient != null) { var dataMessageServer = new Messages.Messages.DataMessageServer( zoneClient.Username, dataMessage.Data); otherClient.packetsToBeSent.Add(ZonePacket.FromMessage(dataMessageServer, otherClient)); } else { Log.Warning("Zone", "User [" + zoneClient.Username.TrimEnd('\0') + "]:" + " ToUser[" + dataMessage.Username.TrimEnd('\0') + "]" + " UnkownMessage"); // TODO } break; } } } break; } } // Check if there are more packets to process if (data.Length > 0) { packetsToSend.AddRange(Process(zoneClient, data)); } return(packetsToSend); }
public ZoneLobby() { Users.CollectionChanged += (sender, args) => { if (Users.Count == 0) { Messages.Clear(); UsernamesByID.Clear(); } else { switch (args.Action) { case NotifyCollectionChangedAction.Add: { var zoneClient = args.NewItems[0] as ZoneClient; // Notify others var enterMessage = new Messages.Messages.EnterMessage( new Messages.Messages.InfoRecord(zoneClient)); Users.ForEach(_ => { _.packetsToBeSent.Add(ZonePacket.FromMessage(enterMessage, _)); }); // Send Room Info to user var roomInfoMessage = new Messages.Messages.RoomInfoMessage(); roomInfoMessage.InfoRecords = Users.Select(_ => new Messages.Messages.InfoRecord(_)).ToArray(); zoneClient.packetsToBeSent.Add(ZonePacket.FromMessage(roomInfoMessage, zoneClient)); // Send Messages // What if player left?... Using TalkResponse instead var chatLog = Messages.Select(message => { MessageServer talkMessage; if (Users.Count(zClient => zClient.UserLobbyID == message.Item1) == 0) { talkMessage = new Messages.Messages.TalkResponseMessage(UsernamesByID[(short)message.Item1], message.Item2); } else { talkMessage = new Messages.Messages.TalkResponseIDMessage(message.Item1, message.Item2); } return(ZonePacket.FromMessage(talkMessage, zoneClient)); }).ToList(); zoneClient.packetsToBeSent.AddRange(chatLog); break; } case NotifyCollectionChangedAction.Remove: { var zoneClient = args.OldItems[0] as ZoneClient; if (Messages.Count(message => ((short)message.Item1) == zoneClient.UserLobbyID) > 0) { UsernamesByID.Add(zoneClient.UserLobbyID, zoneClient.Username); } var leaveMessage = new Messages.Messages.LeaveMessage( new Messages.Messages.InfoRecord(zoneClient)); Users.ForEach(_ => { _.packetsToBeSent.Add(ZonePacket.FromMessage(leaveMessage, _)); }); break; } } } }; Messages.CollectionChanged += (sender, args) => { switch (args.Action) { case NotifyCollectionChangedAction.Remove: { var userLobbyID = ((Tuple <short, string>)args.OldItems[0]).Item1; if (Messages.Count(message => ((short)message.Item1) == userLobbyID) == 0) { UsernamesByID.Remove(userLobbyID); } return; } case NotifyCollectionChangedAction.Reset: return; case NotifyCollectionChangedAction.Add: { var userLobbyID = ((Tuple <short, string>)args.NewItems[0]).Item1; var message = ((Tuple <short, string>)args.NewItems[0]).Item2; var talkMessage = new Messages.Messages.TalkResponseIDMessage(userLobbyID, message); Users.ForEach(_ => { _.packetsToBeSent.Add(ZonePacket.FromMessage(talkMessage, _)); }); return; } } }; }