Ejemplo n.º 1
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);
        }