예제 #1
0
        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, _)));
        }
예제 #2
0
        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);
        }
예제 #3
0
        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;
                }
                }
            };
        }