Exemplo n.º 1
0
        /// <summary>
        /// Create packet from received bytes.
        /// Use this for buffers that contain multiple packets.
        /// The stxIndex and etxIndex will tell you where the extracted packet was located within the provided buffer.
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="stxIndex">Start of the packet within the provided byte array.</param>
        /// <param name="etxIndex">End of the packet within the provided byte array.</param>
        /// <returns></returns>
        public static NetworkPacket FromByteArray(byte[] buffer, out int stxIndex, out int etxIndex)
        {
            etxIndex = -1;
            stxIndex = -1;
            NetworkPacket packet = null;

            if (buffer == null)
            {
                return(null);
            }

            // Do a sweep and unescape the packet
            var rawByteList = new List <byte>(buffer.Length);

            for (int i = 0; i < buffer.Length; ++i)
            {
                if (stxIndex < 0)
                {
                    if (buffer[i] == STX)
                    {
                        stxIndex = i;
                        rawByteList.Add(buffer[i]);
                    }
                    continue;
                }
                if (buffer[i] == ETX)
                {
                    etxIndex = i;
                    rawByteList.Add(buffer[i]);
                    break;
                }
                if (buffer[i] == ESC)
                {
                    rawByteList.Add((byte)(buffer[++i] ^ MASK));
                }
                else
                {
                    rawByteList.Add(buffer[i]);
                }
            }
            var rawBytes = rawByteList.ToArray();

            // Check if packet is valid:
            // Incomplete
            if (stxIndex == -1 || etxIndex == -1)
            {
                return(null);
            }
            // Too short
            if (rawBytes.Length < 6)
            {
                return(null);
            }
            // Length check
            var length = rawBytes[1] << 8 | rawBytes[2];

            if (length != rawBytes.Length - 6)
            {
                return(null);
            }
            // Checksum check
            var chsumIndex = rawBytes.Length - 2;
            var sum        = 0;

            for (int i = 2; i < chsumIndex; ++i)
            {
                sum ^= rawBytes[i];
            }
            if (sum != rawBytes[chsumIndex])
            {
                return(null);
            }

            var type = rawBytes[3];
            var data = new byte[length];

            Array.Copy(rawBytes, 4, data, 0, length);

            packet = new NetworkPacket(data, type);

            return(packet);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Processes received packets.
        /// </summary>
        /// <param name="packet">Received packet.</param>
        void ProcessPacket(NetworkPacket packet)
        {
            // Decrypt data
            var data = packet.Data;

            if (data != null && data.Length > 0 && packet.PacketType != NetworkPacketType.PublicKey)
            {
                if (packet.PacketType != NetworkPacketType.ServerInfo)
                {
                    data = _decrypter.Decrypt(packet.Data);
                }
                if (data == null)
                {
                    Log.WriteLine(LogPriority.Error, "NetworkGameClient: Error! Could not decrypt message from server");
                    return;
                }
            }
            switch (packet.PacketType)
            {
            case NetworkPacketType.PublicKey:
                try
                {
                    var serverPubKey = Encoding.ASCII.GetString(packet.Data);
                    _encrypter = new CryptoHelper(serverPubKey);
                }
                catch (Exception ex)
                {
                    _encrypter = null;
                    Log.WriteLine(LogPriority.Error, "NetworkGameClient: Received key is invalid! " + ex.Message);
                }
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
#pragma warning disable CC0004   // Catch block cannot be empty
                finally { try { _encrypterWaiter?.Cancel(); } catch { /* Ignore*/ } }
#pragma warning restore CC0004   // Catch block cannot be empty
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
                break;

            case NetworkPacketType.ListGames:
                try
                {
                    var glistString = Encoding.ASCII.GetString(data);
                    var glist       = JsonConvert.DeserializeObject <List <GameInfo> >(glistString);
                    Log.WriteLine(LogPriority.Verbose, "NetworkGameClient: Received list of games on server. Game count: " + glist.Count);
                    GameListReceived?.Invoke(this, new GameListEventArgs(glist));
                }
                catch (Exception e)
                {
                    Log.WriteLine(LogPriority.Error, "NetworkGameClient: Received list of games from server could not be read. " + e.Message);
                }
                break;

            case NetworkPacketType.ClientLogin:
                try
                {
                    if (data.Length > 0 && data[0] == 0)
                    {
                        IsLoggedIn = true;
                        Log.WriteLine(LogPriority.Information, "NetworkGameClient: Login to server successful!");
                    }
                    else
                    {
                        IsLoggedIn = false;
                        var error = "NetworkGameClient: Login to server failed! ";
                        if (data[0] == 1)
                        {
                            error += "Invalid user name";
                        }
                        else if (data[0] == 2)
                        {
                            error += "Invalid password";
                        }
                        else if (data[0] == 3)
                        {
                            error += "Database error";
                        }
                        else
                        {
                            error += "Unknown error";
                        }
                    }
                    LoggedIn?.Invoke(this, new LoggedInEventArgs(IsLoggedIn == true));
                }
                catch (Exception e)
                {
                    Log.WriteLine(LogPriority.Error, "NetworkGameClient: Received login confirmation could not be read." + e.Message);
                }
                break;

            case NetworkPacketType.CreateGame:
                try
                {
                    // Check if an UID was assigned
                    var ginfo = JsonConvert.DeserializeObject <GameInfo>(Encoding.ASCII.GetString(data));
                    if (ginfo != null)
                    {
                        if (ginfo.UID != 0)
                        {
                            GameCreated?.Invoke(this, new GameCreatedEventArgs(ginfo));
                        }
                    }
                    else
                    {
                        Log.WriteLine(LogPriority.Error, "NetworkGameClient: Received CreateGame confirmation could not be read.");
                    }
                }
                catch (Exception e)
                {
                    Log.WriteLine(LogPriority.Error, "NetworkGameClient: Received CreateGame confirmation could not be read." + e.Message);
                }
                break;

            case NetworkPacketType.JoinGame:
                try
                {
                    var jMsg = JsonConvert.DeserializeObject <JoinMessage>(Encoding.ASCII.GetString(data));
                    if (jMsg != null)
                    {
                        GameJoinRequested?.Invoke(this, new GameJoinRequestedEventArgs(jMsg));

                        // If joining and other side declined then set IsJoined to false
                        if (jMsg.Request == JoinRequestType.Decline)
                        {
                            IsJoined = false;
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.WriteLine(LogPriority.Error, "NetworkGameClient: Received JoinGame confirmation could not be read." + e.Message);
                }
                break;

            case NetworkPacketType.ServerInfo:
                try
                {
                    // Server data is always unencrypted
                    var jMsg = JsonConvert.DeserializeObject <ServerInfo>(Encoding.ASCII.GetString(packet.Data));
                    if (jMsg != null)
                    {
                        ServerRequiresLogin = jMsg.RequiresLogin;
                        ServerInfoReceived?.Invoke(this, new ServerInfoEventArgs(jMsg));
                    }
                }
                catch (Exception e)
                {
                    Log.WriteLine(LogPriority.Error, "NetworkGameClient: Received ServerInfo could not be read." + e.Message);
                }
                break;

            case NetworkPacketType.ExitGame:
                try
                {
                    var eMsg = JsonConvert.DeserializeObject <ExitGame>(Encoding.ASCII.GetString(data));
                    if (eMsg != null)
                    {
                        if (eMsg.UID == UID)
                        {
                            IsJoined = false;
                            UID      = 0;
                            GameExitReceived?.Invoke(this, EventArgs.Empty);
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.WriteLine(LogPriority.Error, "NetworkGameClient: Received ExitGame message could not be read." + e.Message);
                }
                break;

            case NetworkPacketType.GameSync:
                try
                {
                    var eMsg = JsonConvert.DeserializeObject <GameSync>(Encoding.ASCII.GetString(data));
                    if (eMsg != null && eMsg.UID == UID)
                    {
                        GameSyncReceived?.Invoke(this, new GameSyncEventArgs(eMsg));
                    }
                }
                catch (Exception e)
                {
                    Log.WriteLine(LogPriority.Error, "NetworkGameClient: Received GameSync message could not be read." + e.Message);
                }
                break;

            case NetworkPacketType.GameCommand:
                try
                {
                    var eMsg = JsonConvert.DeserializeObject <GameCommand>(Encoding.ASCII.GetString(data));
                    if (eMsg != null)
                    {
                        GameCommandReceived?.Invoke(this, new GameCommandEventArgs(eMsg));
                    }
                }
                catch (Exception e)
                {
                    Log.WriteLine(LogPriority.Error, "NetworkGameClient: Received GameSync message could not be read." + e.Message);
                }
                break;

            default:
                Log.WriteLine(LogPriority.Error, "NetworkGameClient: Packet type " + packet.PacketType + " not recognized!");
                break;
            }
        }