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 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; } } }; }