public void LoadGame()
    {
        lzf_Compression = new LZF();
        gameWorldData   = new GameData();
        //파일 생성.
        BinaryFormatter bf         = new BinaryFormatter();
        FileStream      fileStream = File.Open(fileDirectory, FileMode.Open);

        // DeSerialzing ( decode..)
        gameWorldData = (GameData)bf.Deserialize(fileStream);
        gameWorldData.MemoryAllocLoadArray();         // loadArray의 경우 serializing 이 되지 않았으므로, 다시 재할당한다.

        fileStream.Close();
        // 압축해제 작업.
        lzf_Compression.Decompress(gameWorldData.GetSaveByteArray(),
                                   ConstantGroup.saveBtyeArraySize,
                                   gameWorldData.GetLoadByteArray(),
                                   ConstantGroup.loadByteArraySize);
        // Load가 완료되었으므로, true로 값을 설정.
        IsLoadedData = true;

        UnityThreadHelper.Dispatcher.Dispatch(() =>
        {
            Application.LoadLevel("LoadingNextScene");
        });
    }
Beispiel #2
0
        public void Send(int id, byte[] bytes)
        {
            try
            {
                var    compress       = bytes.Length > 75;        //Because there is lots of overhead, we don't compress below 75 B
                byte[] compressedData = null;
                if (compress)
                {
                    compressedData = LZF.Compress(bytes, 0);
                }

                lock (WriterLock)
                {
                    BinaryWriter.Write(
                        (byte)(compress ? FromAdministrationPackage.SendCommandCompressed : FromAdministrationPackage.SendCommand));
                    BinaryWriter.Write((compress ? compressedData.Length : bytes.Length) + 5);
                    BinaryWriter.Write(BitConverter.GetBytes(id));
                    BinaryWriter.Write((byte)SendingType.Command);
                    BinaryWriter.Write(compress ? compressedData : bytes);
                    BinaryWriter.Flush();
                }
            }
            catch (Exception)
            {
                // ignored
            }
        }
Beispiel #3
0
        public void SendDynamicCommand(byte[] bytes)
        {
            try
            {
                byte[] compressedData = null;
                var    compressed     = false;
                if (bytes.Length > 75) //Because there is a lot of overhead, we don't compress below 75 B
                {
                    compressedData = LZF.Compress(bytes, 0);
                    if (bytes.Length > compressedData.Length)
                    {
                        //If the compression isn't larger than the source, we will send the compressed data
                        compressed = true;
                    }
                }

                lock (WriterLock)
                {
                    Connection.BinaryWriter.Write(
                        (byte)
                        (compressed
                                ? FromAdministrationPackage.SendDynamicCommandCompressed
                                : FromAdministrationPackage.SendDynamicCommand));
                    Connection.BinaryWriter.Write(compressed ? compressedData.Length : bytes.Length);
                    Connection.BinaryWriter.Write(compressed ? compressedData : bytes);
                    Connection.BinaryWriter.Flush();
                }
            }
            catch (Exception)
            {
                // ignored
            }
        }
    public void SaveGame()
    {
        lzf_Compression = new LZF();
        UnityThreadHelper.Dispatcher.Dispatch(() =>
        {
            // 월드 오브젝트에서 컴포넌트 추출.
            getWorld = GameObject.Find("World");
            m_world  = getWorld.GetComponent("World") as World;
        });
        // Init GameData class
        gameWorldData = new GameData();
        // 게임월드 배열을 저장 게임데이터로 옴긴다.
        gameWorldData.Flatten3dArray(m_world);
        // 압축시작.
        lzf_Compression.Compress(gameWorldData.GetWorldData(),
                                 gameWorldData.GetWorldData().Length,
                                 gameWorldData.GetSaveByteArray(),
                                 ConstantGroup.saveBtyeArraySize);
        // 파일 생성.
        BinaryFormatter bf         = new BinaryFormatter();
        FileStream      fileStream = File.Open(fileDirectory, FileMode.OpenOrCreate);

        // 시리얼라이징.
        bf.Serialize(fileStream, gameWorldData);
        fileStream.Close();

        UnityThreadHelper.Dispatcher.Dispatch(() =>
        {
            SysLogManager.SetLogMessage("<SYSTEM> : 현재 내용이 저장되었습니다. ");
        });
    }
Beispiel #5
0
        public static string DescribeSentData(byte[] data, int index)
        {
            data = LZF.Decompress(data, index);
            var functionNameLength = BitConverter.ToInt32(data, 16);
            var functionName       = Encoding.UTF8.GetString(data, 20, functionNameLength);

            return(functionName);
        }
        public unsafe byte[] Compress(IntPtr scan0, int stride, Size imageSize, PixelFormat pixelFormat)
        {
            var data = new byte[stride * imageSize.Height];

            fixed(byte *dataPtr = data)
            memcpy(dataPtr, (byte *)scan0, (UIntPtr)data.Length);

            return(LZF.Compress(data, 0));
        }
        public unsafe byte[] Decompress(IntPtr dataPtr, uint length, PixelFormat pixelFormat)
        {
            var buffer = new byte[length];

            fixed(byte *bufferPtr = buffer)
            memcpy(bufferPtr, (byte *)dataPtr, new UIntPtr(length));

            return(LZF.Decompress(buffer, 0));
        }
 public void PushExceptions(byte[] exceptions)
 {
     lock (SendLock)
     {
         BinaryWriter.Write((byte)FromClientPackage.SubmitExceptions);
         var data = LZF.Compress(exceptions, 0);
         BinaryWriter.Write(data.Length);
         BinaryWriter.Write(data);
     }
 }
        public unsafe void Compress(IntPtr scan0, int stride, Size imageSize, PixelFormat pixelFormat, Stream outStream)
        {
            var data = new byte[stride * imageSize.Height];

            fixed(byte *dataPtr = data)
            memcpy(dataPtr, (byte *)scan0, (UIntPtr)data.Length);

            int compressedLength;
            var compressed = LZF.Compress(data, 0, out compressedLength);

            outStream.Write(compressed, 0, compressedLength);
        }
        public unsafe void Decompress(IntPtr dataPtr, uint length, IntPtr outputPtr, int outputLength,
                                      PixelFormat pixelFormat)
        {
            var buffer = new byte[length];

            fixed(byte *bufferPtr = buffer)
            memcpy(bufferPtr, (byte *)dataPtr, new UIntPtr(length));

            var decompressedBuffer = LZF.Decompress(buffer, 0);

            fixed(byte *decompressedBufferPtr = decompressedBuffer)
            memcpy((byte *)outputPtr, decompressedBufferPtr, (UIntPtr)decompressedBuffer.Length);
        }
Beispiel #11
0
        private static byte[] ReadCompressedString(BinaryReader reader)
        {
            int compressedLength   = reader.ReadVariableLengthInt32();
            int uncompressedLength = reader.ReadVariableLengthInt32();

            byte[] compressed = reader.ReadBytes(compressedLength);

            var lzf = new LZF();

            byte[] uncompressed = new byte[uncompressedLength];
            lzf.Decompress(compressed, compressedLength, uncompressed, uncompressedLength);
            return(uncompressed);
        }
Beispiel #12
0
        /// <summary>
        ///     Receive data from the server and process it
        /// </summary>
        /// <param name="data">The data received by the server</param>
        /// <param name="position">The start position</param>
        public void Receive(byte[] data, int position)
        {
            data = LZF.Decompress(data, position);
            var guid = new Guid(data.Take(16).ToArray());

            MethodCaller methodCaller;

            if (guid == FunctionNotFoundExceptionGuid)
            {
                var sessionGuid = new Guid(data.Skip(16).Take(16).ToArray());
                if (!_methodDictionary.TryGetValue(sessionGuid, out methodCaller))
                {
                    throw new InvalidOperationException("Session was not registered");
                }

                _exceptionResponses.Add(sessionGuid, new InvalidOperationException(
                                            $"Method or function with name {Encoding.UTF8.GetString(data, 32, data.Length - 32)} not found"));
                methodCaller.AutoResetEvent.Set();
                return;
            }

            if (guid == ExceptionGuid)
            {
                var errorReport = new Serializer(typeof(DtpException)).Deserialize <DtpException>(data, 16);

                if (!_methodDictionary.TryGetValue(errorReport.SessionGuid, out methodCaller))
                {
                    throw new InvalidOperationException("Session was not registered");
                }

                _exceptionResponses.Add(errorReport.SessionGuid, new ServerException(errorReport));
                methodCaller.AutoResetEvent.Set();
                return;
            }

            if (!_methodDictionary.TryGetValue(guid, out methodCaller))
            {
                throw new InvalidOperationException("Session was not registered");
            }

            var valueLength = BitConverter.ToInt32(data, 16);

            if (valueLength > 0)
            {
                var buffer = new byte[valueLength];
                Array.Copy(data, 20, buffer, 0, valueLength);
                _methodResponses.Add(guid, buffer);
            }

            methodCaller.AutoResetEvent.Set();
        }
Beispiel #13
0
        public static byte[] Decompress(byte[] data)
        {
            if (data.Length == 0)
            {
                return(data);
            }

            LZF decompressor       = new LZF();
            int decompressedLength = decompressor.Decompress(data, data.Length, OutputBuffer, OutputBuffer.Length);

            byte[] result = new byte[decompressedLength];
            System.Array.Copy(OutputBuffer, result, decompressedLength);
            return(result);
        }
        public void Response(byte[] package, ResponseType responseType,
                             PackageCompression packageCompression = PackageCompression.Auto)
        {
            if (_isFailed)
            {
                return;
            }

            byte[] compressedData = null;
            var    compressed     = false;

            if ((package.Length > 75 && packageCompression == PackageCompression.Auto) ||
                packageCompression == PackageCompression.Compress)
            //Because there is a lot of overhead, we don't compress below 75 B
            {
                compressedData = LZF.Compress(package, 0);
                if (package.Length > compressedData.Length)
                {
                    //If the compression isn't larger than the source, we will send the compressed data
                    compressed = true;
                }
            }

            lock (_sendLock)
            {
                try
                {
                    ServerConnection.BinaryWriter.Write(
                        (byte)
                        (compressed
                                ? FromClientPackage.ResponseToAdministrationCompressed
                                : FromClientPackage.ResponseToAdministration));

                    ServerConnection.BinaryWriter.Write((compressed ? compressedData.Length : package.Length) + 3);
                    //1 for the responseType and 2 for the ushort
                    ServerConnection.BinaryWriter.Write(BitConverter.GetBytes(AdministrationId));
                    ServerConnection.BinaryWriter.Write((byte)responseType);
                    ServerConnection.BinaryWriter.Write(compressed ? compressedData : package);
                    ServerConnection.BinaryWriter.Flush();
                }
                catch (Exception)
                {
                    OnFailed();
                }
            }
        }
Beispiel #15
0
        public void LargeDataCompressionTest()
        {
            var sampleData = new byte[104857600]; //100 MiB
            var random     = new Random();

            random.NextBytes(sampleData);

            var sw             = Stopwatch.StartNew();
            var compressedData = LZF.Compress(sampleData, 0);

            Trace.WriteLine($"Compressed 100 MiB randomly generated bytes in {sw.ElapsedMilliseconds} ms");
            Assert.IsFalse(sampleData.SequenceEqual(compressedData));

            sw.Restart();
            var uncompressed = LZF.Decompress(compressedData, 0);

            Trace.WriteLine($"Decompressed 100 MiB randomly generated bytes in {sw.ElapsedMilliseconds} ms");
            Assert.IsTrue(sampleData.SequenceEqual(uncompressed));
        }
Beispiel #16
0
        public void SendCommand(int id, byte[] bytes, PackageCompression packageCompression = PackageCompression.Auto)
        {
            try
            {
                byte[] compressedData = null;
                var    compressed     = false;
                if ((bytes.Length > 75 && packageCompression == PackageCompression.Auto) || packageCompression == PackageCompression.Compress) //Because there is a lot of overhead, we don't compress below 75 B
                {
                    compressedData = LZF.Compress(bytes, 0);
                    if (bytes.Length > compressedData.Length)
                    {
                        //If the compression isn't larger than the source, we will send the compressed data
                        compressed = true;
                    }
                }

                lock (WriterLock)
                {
                    Connection.BinaryWriter.Write(
                        (byte)
                        (compressed
                                ? FromAdministrationPackage.SendCommandCompressed
                                : FromAdministrationPackage.SendCommand));
                    Connection.BinaryWriter.Write((compressed ? compressedData.Length : bytes.Length) + 5);
                    Connection.BinaryWriter.Write(BitConverter.GetBytes(id));
                    Connection.BinaryWriter.Write((byte)SendingType.Command);
                    Connection.BinaryWriter.Write(compressed ? compressedData : bytes);
                    Connection.BinaryWriter.Flush();
                }

                if (compressed)
                {
                    Debug.Print(
                        $"Saved {bytes.Length - compressedData.Length} ({compressedData.Length}/{bytes.Length}");
                }
            }
            catch (Exception)
            {
                // ignored
            }
        }
Beispiel #17
0
        public string DescribeReceivedData(byte[] data, int position)
        {
            data = LZF.Decompress(data, position);
            var guid = new Guid(data.Take(16).ToArray());

            MethodCaller methodCaller;

            if (guid == FunctionNotFoundExceptionGuid)
            {
                var sessionGuid = new Guid(data.Skip(16).Take(16).ToArray());
                if (!_methodDictionary.TryGetValue(sessionGuid, out methodCaller))
                {
                    return("Function not found (Session not registered)");
                }

                return($"Function not found ({methodCaller.MethodName})");
            }

            if (guid == ExceptionGuid)
            {
                var errorReport = new Serializer(typeof(DtpException)).Deserialize <DtpException>(data, 16);

                if (!_methodDictionary.TryGetValue(errorReport.SessionGuid, out methodCaller))
                {
                    return("Exception occurred (Session not registered)");
                }

                return($"Exception occurred ({methodCaller.MethodName})");
            }

            if (!_methodDictionary.TryGetValue(guid, out methodCaller))
            {
                return("Session not registered");
            }

            return(methodCaller.MethodName);
        }
        public void SendImageCompressed()
        {
            uint maxsize = 1024 * 64;

            LZF lzf = new LZF();

            uint compressSize = 0;
            uint originalSize = 0;

            var bss = linker.LinkerSections[(int)SectionKind.BSS];

            var message = new DebugMessage(DebugCode.ClearMemory, new int[] { (int)bss.VirtualAddress, (int)bss.Size });

            SendMessageAndWait(message);

            var compressed = new byte[maxsize * 2];

            foreach (var section in linker.LinkerSections)
            {
                if (section.SectionKind == SectionKind.BSS)
                {
                    continue;
                }

                var stream = new MemoryStream((int)section.Size);

                // similar code in the Section.WriteTo method
                foreach (var symbol in section.Symbols)
                {
                    stream.Seek(symbol.SectionOffset, SeekOrigin.Begin);
                    if (symbol.IsDataAvailable)
                    {
                        symbol.Stream.Position = 0;
                        symbol.Stream.WriteTo(stream);
                    }
                }

                stream.WriteZeroBytes((int)(section.AlignedSize - stream.Position));
                stream.Position = 0;

                var  array = stream.ToArray();
                uint at    = 0;

                while (at < array.Length)
                {
                    uint size = (uint)array.Length - at;

                    if (size > maxsize)
                    {
                        size = maxsize;
                    }

                    // compress
                    var raw = new byte[size];
                    Array.Copy(array, at, raw, 0, size);

                    uint crc = CRC.InitialCRC;

                    for (int i = 0; i < size; i++)
                    {
                        crc = CRC.Update(crc, raw[i]);
                    }

                    var len = lzf.Compress(raw, raw.Length, compressed, compressed.Length);

                    compressSize = compressSize + (uint)len;
                    originalSize = originalSize + size;

                    // data
                    var  data    = new byte[len + 16];
                    uint address = (uint)(section.VirtualAddress + at);

                    data[0] = (byte)(address & 0xFF);
                    data[1] = (byte)((address >> 8) & 0xFF);
                    data[2] = (byte)((address >> 16) & 0xFF);
                    data[3] = (byte)((address >> 24) & 0xFF);

                    data[4] = (byte)(len & 0xFF);
                    data[5] = (byte)((len >> 8) & 0xFF);
                    data[6] = (byte)((len >> 16) & 0xFF);
                    data[7] = (byte)((len >> 24) & 0xFF);

                    data[8]  = (byte)(size & 0xFF);
                    data[9]  = (byte)((size >> 8) & 0xFF);
                    data[10] = (byte)((size >> 16) & 0xFF);
                    data[11] = (byte)((size >> 24) & 0xFF);

                    data[12] = (byte)(crc & 0xFF);
                    data[13] = (byte)((crc >> 8) & 0xFF);
                    data[14] = (byte)((crc >> 16) & 0xFF);
                    data[15] = (byte)((crc >> 24) & 0xFF);

                    Array.Copy(compressed, 0, data, 16, len);

                    message = new DebugMessage(DebugCode.CompressedWriteMemory, data);

                    Console.WriteLine(section.SectionKind.ToString() + " @ 0x" + address.ToString("X") + " [size: " + size.ToString() + " compressed: " + len.ToString() + "]");

                    SendMessageAndWait(message);

                    at = at + size;
                }
            }

            Console.WriteLine("Original: " + originalSize.ToString());
            Console.WriteLine("Compressed: " + compressSize.ToString());
            Console.WriteLine("Compacted: " + (compressSize * 100 / originalSize).ToString());

            kernelInit = false;
            imageSent  = true;
        }
Beispiel #19
0
        public static Stream Compress(Stream inputStream, CompressionMethod level = CompressionMethod.Default)
        {
            switch (level)
            {
            // bypass compression
            case CompressionMethod.None:
                return(inputStream);

            // average compression using DeflateStream
            case CompressionMethod.DeflateStream:
            {
                var stream = new SmallBlockMemoryStream();
                using (var output = new DeflateStream(stream, CompressionMode.Compress, true))
                {
                    int read;
                    var buffer = new byte[BufferSize];

                    while ((read = inputStream.Read(buffer, 0, BufferSize)) > 0)
                    {
                        output.Write(buffer, 0, read);
                    }
                }

                stream.Seek(0, SeekOrigin.Begin);
                return(stream);
            }

            // fast compression using LZF
            case CompressionMethod.LZF:
            {
                var buffer    = new byte[BufferSize];
                var output    = new byte[BufferSize * 2];                      // safe value for uncompressible data
                var outStream = new SmallBlockMemoryStream();
                var lzf       = new LZF();

                while (true)
                {
                    var readCount = (short)inputStream.Read(buffer, 0, buffer.Length);
                    if (readCount == 0)
                    {
                        break;
                    }

                    var writeCount = (short)lzf.Compress(buffer, readCount, output, output.Length);
                    if (writeCount == 0)
                    {
                        throw new InvalidOperationException("Cannot compress input stream.");
                    }

                    // write source size
                    var temp = BitConverter.GetBytes(readCount);
                    outStream.Write(temp, 0, ShortSize);

                    // write destination size
                    temp = BitConverter.GetBytes(writeCount);
                    outStream.Write(temp, 0, ShortSize);

                    // write data chunk
                    outStream.Write(output, 0, writeCount);
                }

                // rewind the output stream
                outStream.Seek(0, SeekOrigin.Begin);
                return(outStream);
            }
            }

            // unknown compression method
            throw new InvalidOperationException();
        }
Beispiel #20
0
        public static Stream Decompress(Stream inputStream, CompressionMethod level = CompressionMethod.Default)
        {
            switch (level)
            {
            // bypass decompression
            case CompressionMethod.None:
                return(inputStream);

            // decompress using DeflateStream
            case CompressionMethod.DeflateStream:
            {
                var stream = new SmallBlockMemoryStream();
                using (var output = new DeflateStream(inputStream, CompressionMode.Decompress, true))
                {
                    int read;
                    var buffer = new byte[BufferSize];

                    while ((read = output.Read(buffer, 0, BufferSize)) > 0)
                    {
                        stream.Write(buffer, 0, read);
                    }
                }

                stream.Seek(0, SeekOrigin.Begin);
                return(stream);
            }

            // decompress using LZF
            case CompressionMethod.LZF:
            {
                var buffer    = new byte[BufferSize * 2];
                var output    = new byte[BufferSize];
                var temp      = new byte[ShortSize * 2];
                var outStream = new SmallBlockMemoryStream();
                var lzf       = new LZF();

                while (true)
                {
                    // read chunk sizes
                    if (inputStream.Read(temp, 0, ShortSize * 2) == 0)
                    {
                        break;
                    }

                    var sourceSize = BitConverter.ToInt16(temp, 0);
                    var destSize   = BitConverter.ToInt16(temp, ShortSize);

                    var readCount = inputStream.Read(buffer, 0, destSize);
                    if (readCount != destSize)
                    {
                        throw new InvalidOperationException("Cannot read input stream.");
                    }

                    var writeCount = lzf.Decompress(buffer, readCount, output, output.Length);
                    if (writeCount != sourceSize)
                    {
                        throw new InvalidOperationException("Cannot decompress input stream.");
                    }

                    outStream.Write(output, 0, writeCount);
                }

                // rewind the output stream
                outStream.Seek(0, SeekOrigin.Begin);
                return(outStream);
            }
            }

            // unknown compression method
            throw new InvalidOperationException();
        }
        private void EndRead(IAsyncResult asyncResult)
        {
            try
            {
                var parameter = _readByteDelegate.EndInvoke(asyncResult);
                var size      = Sender.BinaryReader.ReadInt32();
                var bytes     = Sender.BinaryReader.ReadBytes(size);

                switch ((FromClientPackage)parameter)
                {
                case FromClientPackage.ResponseToAdministration:
                case FromClientPackage.ResponseToAdministrationCompressed:
                    var data = parameter == (byte)FromClientPackage.ResponseToAdministrationCompressed
                                                ? LZF.Decompress(bytes, 1)
                                                : bytes.Skip(1).ToArray();

                    if (CurrentController != null)
                    {
                        CurrentController.PackageReceived(bytes[0], data);
                    }
                    break;

                case FromClientPackage.ResponseLoginOpen:
                    var clientId = BitConverter.ToInt32(bytes, 0);
                    var client   = Clients.FirstOrDefault(x => x.Id == clientId);
                    if (client == null)
                    {
                        break;
                    }

                    CurrentController = new ClientController(client, _tcpClient, Sender);
                    if (AttackOpened != null)
                    {
                        AttackOpened.Invoke(this, EventArgs.Empty);
                    }
                    break;

                case FromClientPackage.NewClientConnected:
                    lock (_clientListLock) {
                        ConnectClient(new Serializer(new[] { typeof(ClientInformation), typeof(OnlineClientInformation) }).Deserialize <OnlineClientInformation>(bytes));
                    }
                    break;

                case FromClientPackage.ClientConnected:
                    lock (_clientListLock) {
                        ConnectClient(new Serializer(new[] { typeof(ClientInformation), typeof(OnlineClientInformation) }).Deserialize <OnlineClientInformation>(bytes));
                    }
                    break;

                case FromClientPackage.ClientDisconnected:
                    lock (_clientListLock) {
                        var disconnectedClientId = BitConverter.ToInt32(bytes, 0);
                        var disconnectedClient   =
                            Clients
                            .FirstOrDefault(x => x.Id == disconnectedClientId);
                        if (disconnectedClient == null)
                        {
                            break;
                        }

                        if (CurrentController != null && CurrentController.Client == disconnectedClient)
                        {
                            CurrentController.Dispose();
                            CurrentController = null;
                        }

                        Clients.Remove(disconnectedClient);

                        if (ClientListChanged != null)
                        {
                            ClientListChanged.Invoke(this, EventArgs.Empty);
                        }

                        if (ClientDisconnected != null)
                        {
                            ClientDisconnected.Invoke(this, disconnectedClient);
                        }
                    }
                    break;

                case FromClientPackage.DataTransferProtocolResponse:
                    DataTransferProtocolFactory.Receive(bytes);
                    break;

                default:
                    break;
                }

                _readByteDelegate.BeginInvoke(EndRead, null);
            }
            catch (Exception)
            {
                Dispose();
                if (Disconnected != null)
                {
                    Disconnected.Invoke(this, EventArgs.Empty);
                }
            }
        }
        private void EndRead(IAsyncResult asyncResult)
        {
            try
            {
                var parameter = _readByteDelegate.EndInvoke(asyncResult);
                var size      = BinaryReader.ReadInt32();

                switch ((FromAdministrationPackage)parameter)
                {
                case FromAdministrationPackage.SendCommand:
                case FromAdministrationPackage.SendCommandCompressed:
                    var bytes = BinaryReader.ReadBytes(size);
                    //don't execute in a thread because it wants to be synchronized
                    var administrationId = BitConverter.ToUInt16(bytes, 0);
                    var isCompressed     = parameter == (byte)FromAdministrationPackage.SendCommandCompressed;
                    var packageData      = isCompressed ? LZF.Decompress(bytes, 3) : bytes;

                    AdministrationConnections.FirstOrDefault(x => x.Id == administrationId)?
                    .PackageReceived(bytes[2], packageData, isCompressed ? 0 : 3);
                    break;

                case FromAdministrationPackage.SendPlugin:
                    administrationId = BinaryReader.ReadUInt16();
                    var pluginLength = BinaryReader.ReadInt32();
                    var pluginGuid   = new Guid(BinaryReader.ReadBytes(16));
                    var hash         = BinaryReader.ReadBytes(16);
                    var versionData  = BinaryReader.ReadBytes(BinaryReader.ReadInt32());
                    var version      = Encoding.ASCII.GetString(versionData);

                    try
                    {
                        var pluginReceiver = new PluginReceiver(administrationId, pluginGuid, hash, version);

                        var buffer = new byte[8192];
                        int read;

                        while (pluginLength > 0 && (read = BinaryReader.Read(buffer, 0, Math.Min(buffer.Length, pluginLength))) > 0)
                        {
                            pluginReceiver.FileStream.Write(buffer, 0, read);
                            pluginLength -= read;
                        }

                        if (pluginReceiver.ImportPlugin() && LoadPlugin(pluginReceiver.Guid, PluginVersion.Parse(pluginReceiver.Version)))
                        {
                            lock (SendLock)
                            {
                                BinaryWriter.Write((byte)FromClientPackage.PluginLoaded);
                                BinaryWriter.Write(16 + versionData.Length);
                                BinaryWriter.Write(pluginGuid.ToByteArray());
                                BinaryWriter.Write(versionData);
                            }
                        }
                        else
                        {
                            lock (SendLock)
                            {
                                BinaryWriter.Write((byte)FromClientPackage.PluginLoadFailed);
                                BinaryWriter.Write(2 + 16 + versionData.Length);
                                BinaryWriter.Write(BitConverter.GetBytes(pluginReceiver.AdministrationId));
                                //administration id
                                BinaryWriter.Write(pluginGuid.ToByteArray());
                                BinaryWriter.Write(versionData);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        ErrorReporter.Current.ReportError(ex,
                                                          $"void ProcessResponse || Parameter: {(FromAdministrationPackage) parameter}, Size: {size} B");
                    }
                    break;

                case FromAdministrationPackage.SendLibraries:
                    administrationId = BinaryReader.ReadUInt16();
                    try
                    {
                        var portableLibraries =
                            (List <PortableLibraryInfo>)
                            new Serializer(typeof(List <PortableLibraryInfo>)).Deserialize(
                                BinaryReader.BaseStream);

                        var loadedLibraries = PortableLibrary.None;
                        foreach (var portableLibraryInfo in portableLibraries)
                        {
                            try
                            {
                                LibraryLoader.Current.LoadLibrary(portableLibraryInfo.Library, _sslStream,
                                                                  portableLibraryInfo.Length);
                            }
                            catch (Exception)
                            {
                                continue;
                            }
                            loadedLibraries |= portableLibraryInfo.Library;
                        }

                        lock (SendLock)
                        {
                            BinaryWriter.Write((byte)FromClientPackage.ResponseLibraryLoadingResult);
                            BinaryWriter.Write(2 + 4);
                            BinaryWriter.Write(BitConverter.GetBytes(administrationId));
                            BinaryWriter.Write(BitConverter.GetBytes((int)loadedLibraries));
                        }
                    }
                    catch (Exception ex)
                    {
                        ErrorReporter.Current.ReportError(ex,
                                                          $"void ProcessResponse || Parameter: {(FromAdministrationPackage) parameter}, Size: {size} B");
                    }
                    break;

                default:
                    bytes = BinaryReader.ReadBytes(size);
                    ThreadPool.QueueUserWorkItem(state =>
                    {
                        try
                        {
                            ProcessResponse(parameter, size, bytes);
                        }
                        catch (Exception ex)
                        {
                            ErrorReporter.Current.ReportError(ex,
                                                              $"void ProcessResponse || Parameter: {(FromAdministrationPackage) parameter}, Size: {size} B");
                        }
                    });
                    break;
                }

                _readByteDelegate.BeginInvoke(EndRead, null);
            }
            catch (Exception)
            {
                Dispose();
            }
        }
        private void ProcessResponse(byte parameter, int size, byte[] bytes)
        {
            switch ((FromAdministrationPackage)parameter)
            {
            case FromAdministrationPackage.InitializeNewSession:
                var id         = BitConverter.ToUInt16(bytes, 0);
                var connection = new AdministrationConnection(id, this, _clientInfo);
                connection.SendFailed += (sender, args) => Dispose();

                AdministrationConnections.Add(connection);
                lock (SendLock)
                {
                    BinaryWriter.Write((byte)FromClientPackage.ResponseLoginOpen);
                    BinaryWriter.Write(2);
                    BinaryWriter.Write(BitConverter.GetBytes(id));
                }
                break;

            case FromAdministrationPackage.SendStaticCommand:
                var potentialCommand =
                    new Serializer(typeof(PotentialCommand)).Deserialize <PotentialCommand>(bytes, 0);

                StaticCommandSelector.Current.ExecuteCommand(potentialCommand);
                break;

            case FromAdministrationPackage.SendStaticCommandCompressed:
                potentialCommand =
                    new Serializer(typeof(PotentialCommand)).Deserialize <PotentialCommand>(LZF.Decompress(bytes, 0), 0);

                StaticCommandSelector.Current.ExecuteCommand(potentialCommand);
                break;

            case FromAdministrationPackage.LoadPlugin:
                var guid    = new Guid(bytes.Skip(2).Take(16).ToArray());
                var version = new Serializer(typeof(PluginVersion)).Deserialize <PluginVersion>(bytes,
                                                                                                18);
                var versionData = Encoding.ASCII.GetBytes(version.ToString());
                if (LoadPlugin(guid, version))
                {
                    lock (SendLock)
                    {
                        BinaryWriter.Write((byte)FromClientPackage.PluginLoaded);
                        BinaryWriter.Write(16 + versionData.Length);
                        BinaryWriter.Write(guid.ToByteArray());
                        BinaryWriter.Write(versionData);
                    }
                }
                else
                {
                    lock (SendLock)
                    {
                        BinaryWriter.Write((byte)FromClientPackage.PluginLoadFailed);
                        BinaryWriter.Write(2 + 16 + versionData.Length);
                        BinaryWriter.Write(bytes, 0, 2);     //administration id
                        BinaryWriter.Write(guid.ToByteArray());
                        BinaryWriter.Write(versionData);
                    }
                }
                break;

            case FromAdministrationPackage.CloseSession:
                var closingSessionId = BitConverter.ToUInt16(bytes, 0);
                var session          = AdministrationConnections.FirstOrDefault(x => x.Id == closingSessionId);
                if (session != null)
                {
                    AdministrationConnections.Remove(session);
                    session.Dispose();
                }
                break;

            case FromAdministrationPackage.GetActiveWindow:
                try
                {
                    string windowTitle = "";

                    var lastInPut = new LASTINPUTINFO();
                    lastInPut.cbSize = (uint)Marshal.SizeOf(lastInPut);

                    //15 min
                    if (NativeMethods.GetLastInputInfo(ref lastInPut) &&
                        (uint)Environment.TickCount - lastInPut.dwTime > 900000)
                    {
                        windowTitle += "[Idle] ";
                    }

                    windowTitle += ActiveWindowHook.GetActiveWindowTitle() ?? "";
                    var windowTitleData = Encoding.UTF8.GetBytes(windowTitle);
                    lock (SendLock)
                    {
                        BinaryWriter.Write((byte)FromClientPackage.ResponseActiveWindow);
                        BinaryWriter.Write(windowTitleData.Length + 2);
                        BinaryWriter.Write(bytes);
                        BinaryWriter.Write(windowTitleData);
                    }
                }
                catch (Exception ex)
                {
                    ErrorReporter.Current.ReportError(ex,
                                                      "case FromAdministrationPackage.GetActiveWindow");
                }
                break;

            case FromAdministrationPackage.GetScreen:
                try
                {
                    using (var compressor = new JpgCompression(75))
                    {
                        byte[] screenshotData;
                        using (var memoryStream = new MemoryStream())
                            using (var screenshot = ScreenHelper.TakeScreenshot())
                            {
                                compressor.Compress(screenshot, memoryStream);
                                screenshotData = memoryStream.ToArray();
                            }

                        lock (SendLock)
                        {
                            BinaryWriter.Write((byte)FromClientPackage.ResponseScreenshot);
                            BinaryWriter.Write(screenshotData.Length + 2);
                            BinaryWriter.Write(bytes);
                            BinaryWriter.Write(screenshotData);
                        }
                    }
                }
                catch (Exception ex)
                {
                    ErrorReporter.Current.ReportError(ex, "case FromAdministrationPackage.GetScreen");
                }
                break;

            case FromAdministrationPackage.AcceptPush:
                FileTransferAccepted?.Invoke(this, new FileTransferEventArgs(new Guid(bytes)));
                break;

            case FromAdministrationPackage.TransferCompleted:
                FileTransferCompleted?.Invoke(this, new FileTransferEventArgs(new Guid(bytes)));
                break;

            case FromAdministrationPackage.IsAlive:
                lock (SendLock)
                {
                    BinaryWriter.Write((byte)FromClientPackage.StillAlive);
                    BinaryWriter.Write(0);
                }
                break;

            case FromAdministrationPackage.SendStaticCommandPlugin:
                var pluginDirectory = new DirectoryInfo(Consts.StaticCommandPluginsDirectory);
                if (!pluginDirectory.Exists)
                {
                    pluginDirectory.Create();
                }

                var filename = FileExtensions.GetUniqueFileName(pluginDirectory.FullName);
                using (var fileStream = new FileStream(filename, FileMode.CreateNew, FileAccess.Write))
                    fileStream.Write(bytes, 4, bytes.Length - 4);

                StaticCommandPluginReceived?.Invoke(this, new StaticCommandPluginReceivedEventArgs(filename,
                                                                                                   BitConverter.ToInt32(bytes, 0)));
                break;

            case FromAdministrationPackage.RequestLibraryInformation:
                var libraries     = (PortableLibrary)BitConverter.ToInt32(bytes, 2);
                var libraryHashes = (size - 6) / 16;
                var hashes        = new List <byte[]>(libraryHashes);
                for (int i = 0; i < libraryHashes; i++)
                {
                    var hash = new byte[16];
                    Buffer.BlockCopy(bytes, 6 + i * 16, hash, 0, 16);
                    hashes.Add(hash);
                }
                var result = LibraryLoader.Current.CheckLibraries(libraries, hashes);
                lock (SendLock)
                {
                    BinaryWriter.Write((byte)FromClientPackage.ResponseLibraryInformation);
                    BinaryWriter.Write(6);
                    BinaryWriter.Write(bytes, 0, 2);     //administration id
                    BinaryWriter.Write(BitConverter.GetBytes((int)result));
                }
                break;

            case FromAdministrationPackage.StopActiveCommand:
                StaticCommandSelector.Current.StopActiveCommand(BitConverter.ToInt32(bytes, 0));
                break;
            }
        }
Beispiel #24
0
        private void EndRead(IAsyncResult asyncResult)
        {
            try
            {
                byte parameter;
                try
                {
                    parameter = _readByteDelegate.EndInvoke(asyncResult); //no data available
                }
                catch (IOException)
                {
                    Dispose();
                    return;
                }

                var size = _binaryReader.ReadInt32();

                var bytes = _binaryReader.ReadBytes(size);
                LastAnswer = DateTime.UtcNow;

                ushort administrationId;
                switch ((FromClientPackage)parameter)
                {
                case FromClientPackage.ResponseToAdministration:
                case FromClientPackage.ResponseToAdministrationCompressed:
                    administrationId = BitConverter.ToUInt16(bytes, 0);

                    Logger.Debug("Client CI-{0} sends command response to administration AI-{1}", Id, administrationId);
                    SendToAdministration?.Invoke(this,
                                                 new SendPackageToAdministrationEventArgs(administrationId, parameter,
                                                                                          new WriterCall(bytes, 2, bytes.Length - 2)));
                    break;

                case FromClientPackage.ResponseLoginOpen:
                    administrationId = BitConverter.ToUInt16(bytes, 0);
                    Logger.Debug("Client CI-{0} opened session with AI-{1}", Id, administrationId);

                    SendToAdministration?.Invoke(this,
                                                 new SendPackageToAdministrationEventArgs(administrationId,
                                                                                          (byte)FromClientPackage.ResponseLoginOpen, new WriterCall(BitConverter.GetBytes(Id))));
                    break;

                case FromClientPackage.SubmitExceptions:
                    //log handled in server
                    ExceptionsReveived?.Invoke(this,
                                               new ExceptionsReveivedEventArgs(
                                                   ExceptionInfosSerializer.Value.Deserialize <List <ExceptionInfo> >(LZF.Decompress(bytes, 0))));
                    break;

                case FromClientPackage.ServerPackage:
                    //log handled in server
                    ProcessServerPackage(ServerPackageSerializer.Value.Deserialize <ServerPackage>(bytes));
                    break;

                case FromClientPackage.ResponseStaticCommandResult:
                    var          dynamicCommandId = BitConverter.ToInt32(bytes, 0);
                    var          message          = "";
                    ActivityType activityType;

                    if (ComputerInformation.ClientVersion >= 19)
                    {
                        activityType = (ActivityType)bytes[4];
                    }
                    else
                    {
                        activityType = bytes[4] == 0 ? ActivityType.Succeeded : ActivityType.Failed;
                    }

                    if (ComputerInformation.ClientVersion >= 13)
                    {
                        message = Encoding.UTF8.GetString(bytes, 5, bytes.Length - 5);
                    }

                    ReceivedStaticCommandResult?.Invoke(this,
                                                        new DynamicCommandEvent
                    {
                        ClientId       = Id,
                        DynamicCommand = dynamicCommandId,
                        Timestamp      = DateTime.UtcNow,
                        Message        = message,
                        Status         = activityType
                    });
                    break;

                case FromClientPackage.PluginLoaded:
                    var pluginInfo = new PluginInfo
                    {
                        Guid     = new Guid(bytes.Take(16).ToArray()),
                        Version  = Encoding.ASCII.GetString(bytes, 16, bytes.Length - 16),
                        IsLoaded = true
                    };

                    Logger.Debug("Client CI-{0} loaded plugin {1:D} successfully", Id, pluginInfo.Guid);

                    ComputerInformation.Plugins.Add(pluginInfo);
                    PluginLoaded?.Invoke(this, new PluginLoadedEventArgs(pluginInfo));
                    break;

                case FromClientPackage.PluginLoadFailed:
                    Logger.Debug("Client CI-{0} was unable to load plugin", Id);

                    SendToAdministration?.Invoke(this,
                                                 new SendPackageToAdministrationEventArgs(BitConverter.ToUInt16(bytes, 0),
                                                                                          (byte)FromClientPackage.PluginLoadFailed, new WriterCall(2 + bytes.Length, writer =>
                    {
                        writer.Write(Id);
                        writer.Write(bytes, 2, bytes.Length - 2);
                    })));
                    break;

                case FromClientPackage.ResponseActiveWindow:
                    administrationId = BitConverter.ToUInt16(bytes, 0);

                    //+ 4 because of client id int, -2 because of administration id ushort
                    SendToAdministration?.Invoke(this,
                                                 new SendPackageToAdministrationEventArgs(administrationId,
                                                                                          (byte)FromClientPackage.ResponseActiveWindow, new WriterCall(bytes.Length + 2,
                                                                                                                                                       writer =>
                    {
                        writer.Write(Id);
                        writer.Write(bytes, 2, bytes.Length - 2);
                    })));
                    break;

                case FromClientPackage.ResponseScreenshot:
                    administrationId = BitConverter.ToUInt16(bytes, 0);
                    //+ 4 because of client id int, -2 because of administration id ushort
                    SendToAdministration?.Invoke(this,
                                                 new SendPackageToAdministrationEventArgs(administrationId,
                                                                                          (byte)FromClientPackage.ResponseScreenshot, new WriterCall(bytes.Length + 2,
                                                                                                                                                     writer =>
                    {
                        writer.Write(Id);
                        writer.Write(bytes, 2, bytes.Length - 2);
                    })));
                    break;

                case FromClientPackage.InitializePushFile:
                    //log handled in PushManager
                    _tcpServerInfo.PushManager.PushRequest(new Guid(bytes), this);
                    break;

                case FromClientPackage.PushHeader:
                    FilePush?.Invoke(this,
                                     new FilePushEventArgs(FilePushPackageType.Header, bytes,
                                                           new Guid(bytes.Take(16).ToArray())));
                    break;

                case FromClientPackage.PushFileData:
                    FilePush?.Invoke(this,
                                     new FilePushEventArgs(FilePushPackageType.Data, bytes,
                                                           new Guid(bytes.Take(16).ToArray())));
                    break;

                case FromClientPackage.StillAlive:
                    break;

                case FromClientPackage.RequestStaticCommandPlugin:
                    _tcpServerInfo.DynamicCommandManager.DynamicCommandPluginSender.RequestPlugin(this,
                                                                                                  BitConverter.ToInt32(bytes, 0));
                    break;

                case FromClientPackage.ResponseLibraryInformation:
                    Logger.Debug("Client CI-{0} requests more detailed information about library", Id);

                    SendToAdministration?.Invoke(this,
                                                 new SendPackageToAdministrationEventArgs(BitConverter.ToUInt16(bytes, 0),
                                                                                          (byte)FromClientPackage.ResponseLibraryInformation, new WriterCall(2 + bytes.Length, writer =>
                    {
                        writer.Write(Id);
                        writer.Write(bytes, 2, bytes.Length - 2);
                    })));
                    break;

                case FromClientPackage.ResponseLibraryLoadingResult:
                    Logger.Debug("Client CI-{0} responded with the result of the library loading operation", Id);

                    SendToAdministration?.Invoke(this,
                                                 new SendPackageToAdministrationEventArgs(BitConverter.ToUInt16(bytes, 0),
                                                                                          (byte)FromClientPackage.ResponseLibraryLoadingResult, new WriterCall(2 + bytes.Length, writer =>
                    {
                        writer.Write(Id);
                        writer.Write(bytes, 2, bytes.Length - 2);
                    })));
                    break;

                case FromClientPackage.CheckStillAlive:
                    break;     //do nothing, TCP already responded when this package is here

                default:
                    throw new ArgumentOutOfRangeException();
                }

                _readByteDelegate.BeginInvoke(EndRead, null);
            }
            catch (Exception ex)
            {
                if (IsDisposed)
                {
                    return;
                }

                Logger.Fatal(ex, "Error on reading data from client CI-{0}", Id);
                Dispose();
            }
        }
Beispiel #25
0
        public static Stream Decompress(Stream inputStream, CompressionMethod level = CompressionMethod.Default)
        {
            switch (level)
            {
                // bypass decompression
                case CompressionMethod.None:
                    return inputStream;

                // decompress using DeflateStream
                case CompressionMethod.DeflateStream:
                {
                    var stream = new MemoryStream();
                    using (var output = new DeflateStream(inputStream, CompressionMode.Decompress, true))
                    {
                        int read;
                        var buffer = new byte[BufferSize];

                        while ((read = output.Read(buffer, 0, BufferSize)) > 0)
                        {
                            stream.Write(buffer, 0, read);
                        }
                    }

                    stream.Seek(0, SeekOrigin.Begin);
                    return stream;
                }

                // decompress using LZF
                case CompressionMethod.LZF:
                {
                    var buffer = new byte[BufferSize * 2];
                    var output = new byte[BufferSize];
                    var temp = new byte[ShortSize * 2];
                    var outStream = new MemoryStream();
                    var lzf = new LZF();

                    while (true)
                    {
                        // read chunk sizes
                        if (inputStream.Read(temp, 0, ShortSize * 2) == 0)
                        {
                            break;
                        }

                        var sourceSize = BitConverter.ToInt16(temp, 0);
                        var destSize = BitConverter.ToInt16(temp, ShortSize);

                        var readCount = inputStream.Read(buffer, 0, destSize);
                        if (readCount != destSize)
                        {
                            throw new InvalidOperationException("Cannot read input stream.");
                        }

                        var writeCount = lzf.Decompress(buffer, readCount, output, output.Length);
                        if (writeCount != sourceSize)
                        {
                            throw new InvalidOperationException("Cannot decompress input stream.");
                        }

                        outStream.Write(output, 0, writeCount);
                    }

                    // rewind the output stream
                    outStream.Seek(0, SeekOrigin.Begin);
                    return outStream;
                }
            }

            // unknown compression method
            throw new InvalidOperationException();
        }
Beispiel #26
0
        /// <summary>
        ///     Execute a function on the server
        /// </summary>
        /// <typeparam name="T">The response type</typeparam>
        /// <param name="functionName">The name of the function</param>
        /// <param name="specialParameterTypes">
        ///     Types which aren't obvious (e. g. if abstract classes are used) for the parameter
        ///     in order to serialize it correctly
        /// </param>
        /// <param name="specialReturnTypes">
        ///     Types which aren't obvious (e. g. if abstract classes are used) for the response in
        ///     order to deserialize it correctly
        /// </param>
        /// <param name="parameters">The parameters of the function</param>
        /// <returns>Returns the response from the server</returns>
        public T ExecuteFunction <T>(string functionName, List <Type> specialParameterTypes, List <Type> specialReturnTypes,
                                     params object[] parameters)
        {
            var methodGuid = Guid.NewGuid();

            while (methodGuid == ExceptionGuid || methodGuid == FunctionNotFoundExceptionGuid) //possibilities are everywhere
            {
                methodGuid = Guid.NewGuid();
            }

            var parameterData = new List <byte[]>();

            foreach (var parameter in parameters)
            {
                var parameterType = parameter.GetType();
                var types         = new Type[1 + (specialParameterTypes?.Count ?? 0)];
                types[0] = parameterType;

                if (specialParameterTypes != null && specialParameterTypes.Count > 0)
                {
                    for (int i = 0; i < specialParameterTypes.Count; i++)
                    {
                        types[i + 1] = specialParameterTypes[i];
                    }
                }

                parameterData.Add(GetSerializer(parameterType, types).Serialize(parameter));
            }

            var functionNameData = Encoding.UTF8.GetBytes(functionName);
            var data             =
                new byte[16 + 4 + functionNameData.Length + 4 + parameterData.Count * 4 + parameterData.Sum(x => x.Length)
                ];

            //Protocol
            //HEAD  - 16 Bytes                  - Guid
            //HEAD  - 4 Bytes                   - Function Name Length
            //HEAD  - UTF8(FunctionName).Length - Function Name
            //INFO  - 4 Bytes                   - Parameter count
            //PINF  - COUNT(Paramters)*4        - Information about the length of the parameters
            //DATA  - SUM(Parameters.Length)    - The parameter data

            Buffer.BlockCopy(methodGuid.ToByteArray(), 0, data, 0, 16);
            Buffer.BlockCopy(BitConverter.GetBytes(functionNameData.Length), 0, data, 16, 4);
            Buffer.BlockCopy(functionNameData, 0, data, 20, functionNameData.Length);
            Buffer.BlockCopy(BitConverter.GetBytes(parameters.Length), 0, data, 20 + functionNameData.Length, 4);
            for (int i = 0; i < parameterData.Count; i++)
            {
                Buffer.BlockCopy(BitConverter.GetBytes(parameterData[i].Length), 0, data, 24 + functionNameData.Length + i * 4,
                                 4);
            }

            int offset = 0;

            foreach (var parameter in parameterData)
            {
                Buffer.BlockCopy(parameter, 0, data, 24 + functionNameData.Length + parameterData.Count * 4 + offset,
                                 parameter.Length);
                offset += parameter.Length;
            }

            using (var autoResetEvent = new AutoResetEvent(false))
            {
                _methodDictionary.Add(methodGuid, new MethodCaller(functionName, autoResetEvent));
                _sendDataAction.Invoke(LZF.Compress(data, 0));
                if (!autoResetEvent.WaitOne(Timeout))
                {
                    throw new InvalidOperationException("Timeout");
                }

                _methodDictionary.Remove(methodGuid);

                Exception exception;
                if (_exceptionResponses.TryGetValue(methodGuid, out exception))
                {
                    _exceptionResponses.Remove(methodGuid);
                    throw exception;
                }

                byte[] response;
                if (_methodResponses.TryGetValue(methodGuid, out response))
                {
                    _methodResponses.Remove(methodGuid);
                    var types = new Type[1 + (specialReturnTypes?.Count ?? 0)];
                    types[0] = typeof(T);
                    if (specialReturnTypes != null && specialReturnTypes.Count > 0)
                    {
                        for (int i = 0; i < specialReturnTypes.Count; i++)
                        {
                            types[i + 1] = specialReturnTypes[i];
                        }
                    }

                    return(GetSerializer(typeof(T), types).Deserialize <T>(response));
                }

                return(default(T));
            }
        }
Beispiel #27
0
        public static Stream Compress(Stream inputStream, CompressionMethod level = CompressionMethod.Default)
        {
            switch (level)
            {
                // bypass compression
                case CompressionMethod.None:
                    return inputStream;

                // average compression using DeflateStream
                case CompressionMethod.DeflateStream:
                {
                    var stream = new MemoryStream();
                    using (var output = new DeflateStream(stream, CompressionMode.Compress, true))
                    {
                        int read;
                        var buffer = new byte[BufferSize];

                        while ((read = inputStream.Read(buffer, 0, BufferSize)) > 0)
                        {
                            output.Write(buffer, 0, read);
                        }
                    }

                    stream.Seek(0, SeekOrigin.Begin);
                    return stream;
                }

                // fast compression using LZF
                case CompressionMethod.LZF:
                {
                    var buffer = new byte[BufferSize];
                    var output = new byte[BufferSize * 2]; // safe value for uncompressible data
                    var outStream = new MemoryStream();
                    var lzf = new LZF();

                    while (true)
                    {
                        var readCount = (short)inputStream.Read(buffer, 0, buffer.Length);
                        if (readCount == 0)
                        {
                            break;
                        }

                        var writeCount = (short)lzf.Compress(buffer, readCount, output, output.Length);
                        if (writeCount == 0)
                        {
                            throw new InvalidOperationException("Cannot compress input stream.");
                        }

                        // write source size
                        var temp = BitConverter.GetBytes(readCount);
                        outStream.Write(temp, 0, ShortSize);

                        // write destination size
                        temp = BitConverter.GetBytes(writeCount);
                        outStream.Write(temp, 0, ShortSize);

                        // write data chunk
                        outStream.Write(output, 0, writeCount);
                    }

                    // rewind the output stream
                    outStream.Seek(0, SeekOrigin.Begin);
                    return outStream;
                }
            }

            // unknown compression method
            throw new InvalidOperationException();
        }
        public static SqliteConnection UpgradeDatabase(string fileName, SqliteConnection sqliteConnection)
        {
            sqliteConnection.Close(); //we don't need that
            sqliteConnection.Dispose();

            Logger.Info("Create new database");
            var newDatabase = new FileInfo(Path.Combine(Path.GetDirectoryName(fileName), Guid.NewGuid().ToString("N")));

            SqliteConnection.CreateFile(newDatabase.FullName);

            using (var newDatabaseConnection = new SqliteConnection($"Data Source={newDatabase.FullName};Version=3;"))
            {
                newDatabaseConnection.Open();
                Logger.Info("Create tables");
                DatabaseBuilder.CreateTables(newDatabaseConnection);

                Logger.Info("Import data");
                //attach old database
                using (
                    var command = new SqliteCommand($"ATTACH DATABASE '{fileName}' AS 'OldDatabase'", newDatabaseConnection)
                    )
                    command.ExecuteNonQuery();

                using (var command = new SqliteCommand("INSERT INTO main.Client (Id, UserName, HardwareId, ClientGroup, OSName, OSType, Language, LastSeen) SELECT Id, UserName, HardwareId, ClientGroup, OperatingSystemName, OSType, Language, LastSeen FROM OldDatabase.Client", newDatabaseConnection))
                    command.ExecuteNonQuery();

                using (var command = new SqliteCommand("INSERT INTO main.Exception SELECT * FROM OldDatabase.Exception", newDatabaseConnection))
                    command.ExecuteNonQuery();

                using (var command = new SqliteCommand("INSERT INTO main.RecoveredPassword SELECT * FROM OldDatabase.RecoveredPassword", newDatabaseConnection))
                    command.ExecuteNonQuery();

                using (var command = new SqliteCommand("INSERT INTO main.RecoveredCookie SELECT * FROM OldDatabase.RecoveredCookies", newDatabaseConnection))
                    command.ExecuteNonQuery();

                using (var command = new SqliteCommand("INSERT INTO main.NewClientsStatistic SELECT * FROM OldDatabase.NewClientsStatistics", newDatabaseConnection))
                    command.ExecuteNonQuery();

                using (var command = new SqliteCommand("INSERT INTO main.ClientsConnected SELECT * FROM OldDatabase.ClientsConnected", newDatabaseConnection))
                    command.ExecuteNonQuery();

                using (var command = new SqliteCommand("INSERT INTO main.ClientsConnectedStatistic SELECT * FROM OldDatabase.ClientsConnectedStatistics", newDatabaseConnection))
                    command.ExecuteNonQuery();

                DirectoryInfo dataDirectory = null;
                using (var command = new SqliteCommand("SELECT ClientId, Data, Timestamp FROM OldDatabase.KeyLog", newDatabaseConnection))
                    using (var reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            if (dataDirectory == null)
                            {
                                dataDirectory = new DirectoryInfo("data");
                                if (!dataDirectory.Exists)
                                {
                                    dataDirectory.Create();
                                }
                            }

                            Guid fileNameGuid;
                            var  dataFileName = Path.Combine(dataDirectory.FullName, (fileNameGuid = Guid.NewGuid()).ToString("D"));
                            while (File.Exists(dataFileName))
                            {
                                dataFileName = Path.Combine(dataDirectory.FullName, (fileNameGuid = Guid.NewGuid()).ToString("D"));
                            }

                            var data = LZF.Decompress((byte[])reader["Data"], 0);
                            File.WriteAllBytes(dataFileName, data);
                            using (
                                var command2 =
                                    new SqliteCommand(
                                        $"INSERT INTO main.Data (ClientId, Timestamp, Length, FileName, DataMode, EntryName, IsCsvData) VALUES ({reader.GetInt32(0)}, @timestamp, {data.Length}, '{fileNameGuid.ToString("N")}', 'e10e9542f6324f68bdf6f0ef1c9d04d2', @entryName, 0)",
                                        newDatabaseConnection)
                                )
                            {
                                command2.Parameters.AddWithValue("@timestamp", DateTime.Parse(reader.GetString(2), CultureInfo.InvariantCulture));
                                command2.Parameters.AddWithValue("@entryName", "Automatic Key Log");
                                command2.ExecuteNonQuery();
                            }
                        }
                    }

                using (var command = new SqliteCommand("SELECT Id, Succeeded, Failed, SentTo, Done, DynamicCommand, Parameter FROM OldDatabase.DynamicCommand", newDatabaseConnection))
                    using (var reader = command.ExecuteReader())
                    {
                        var types = DynamicCommandInfo.RequiredTypes.ToList();
                        types.Remove(typeof(EveryClientOnceTransmissionEvent));
                        var serializer    = new Serializer(types);
                        var xmlSerializer = new XmlSerializer(typeof(DynamicCommand));

                        using (var transaction = newDatabaseConnection.BeginTransaction())
                            using (var command2 = newDatabaseConnection.CreateCommand())
                            {
                                command2.Transaction = transaction;
                                while (reader.Read())
                                {
                                    //no reason to reuse the StringWriter
                                    using (var stringWriter = new StringWriter())
                                    {
                                        command2.CommandText =
                                            $"INSERT INTO main.DynamicCommand (Id, Succeeded, Failed, SentTo, Done, DynamicCommand, Parameter) VALUES ({reader.GetInt32(0)}, {reader.GetInt32(1)}, {reader.GetInt32(2)}, {reader.GetInt32(3)}, {reader.GetInt32(4)}, @dynamicCommand, @parameter)";
                                        DynamicCommand dynamicCommand;
                                        try
                                        {
                                            dynamicCommand =
                                                serializer.Deserialize <DynamicCommand>((byte[])reader["DynamicCommand"]);
                                        }
                                        catch (Exception)
                                        {
                                            continue;
                                        }

                                        xmlSerializer.Serialize(stringWriter, dynamicCommand);
                                        command2.Parameters.AddWithValue("@dynamicCommand", stringWriter.ToString());
                                        command2.Parameters.AddWithValue("@parameter", reader["Parameter"]);
                                        command2.ExecuteNonQuery();
                                        command2.Parameters.Clear();
                                    }
                                }

                                transaction.Commit();
                            }
                    }
            }

            Logger.Info("Upgrade finished, cleaning up");
            GC.Collect(); //necessary to free the database file, see here: https://stackoverflow.com/questions/8511901/system-data-sqlite-close-not-releasing-database-file
            GC.WaitForPendingFinalizers();
            File.Delete(fileName);
            newDatabase.MoveTo(fileName);

            var connection = new SqliteConnection($"Data Source={fileName};Version=3;");

            connection.Open();
            Logger.Info("Database opened");
            return(connection);
        }
Beispiel #29
0
        private static List <int> ExecuteStaticCommand(IEnumerable <Client> clients, PotentialCommand potentialCommand)
        {
            Logger.Debug("Execute static command {0}", potentialCommand.CallbackId);

            var data         = new Serializer(typeof(PotentialCommand)).Serialize(potentialCommand);
            var isCompressed = false;

            if (data.Length > 512)
            {
                var compressedData = LZF.Compress(data, 0);
                if (compressedData.Length < data.Length)
                {
                    isCompressed = true;
                    data         = compressedData;
                }
            }

            var updateCommandCompatibilityParameter =
                new Lazy <byte[]>(() => CompatibilityManager.UpdateCommandToOldUpdateCommand(potentialCommand));
            var updateFromUrlCompatibilityParameter =
                new Lazy <byte[]>(
                    () => CompatibilityManager.UpdateFromUrlCommandToOldUpdateFromUrlCommand(potentialCommand));
            var compatibilityData = new Lazy <byte[]>(() => CompatibilityManager.GetOldPotentialCommand(potentialCommand));

            var clientList = new List <int>();

            foreach (var client in clients)
            {
                try
                {
                    if (client.ComputerInformation.ClientVersion >= 19)
                    {
                        client.SendStaticCommand(data, isCompressed);
                        clientList.Add(client.Id);
                    }
                    else if (client.ComputerInformation.ClientVersion >= 13 && client.ComputerInformation.ClientVersion <= 18)
                    {
                        client.SendStaticCommand(compatibilityData.Value, isCompressed);
                        clientList.Add(client.Id);
                    }
                    else
                    {
                        //UpdateCommand
                        if (potentialCommand.CommandId ==
                            new Guid(0xafd0841b, 0x0035, 0x7045, 0x96, 0x32, 0x36, 0x98, 0x6c,
                                     0xb1, 0x83, 0x1c))
                        {
                            client.SendStaticCommand(updateCommandCompatibilityParameter.Value, false);
                            clientList.Add(client.Id);
                        }

                        //UpdateFromUrlCommand
                        else if (potentialCommand.CommandId ==
                                 new Guid(0xe08e79f0, 0xcaea, 0xe341, 0x8a, 0xb2, 0xef, 0x84, 0xe1,
                                          0x8f, 0xa2, 0x5f))
                        {
                            client.SendStaticCommand(updateFromUrlCompatibilityParameter.Value, false);
                            clientList.Add(client.Id);
                        }
                    }
                }
                catch (Exception)
                {
                    // ignored
                }
            }

            Logger.Debug("Static command {0} successfully executed on {1} clients", potentialCommand.CallbackId, clientList.Count);

            return(clientList);
        }
Beispiel #30
0
        /// <summary>
        ///     Process the received data from a <see cref="DtpFactory" />
        /// </summary>
        /// <param name="data">The data which was given using the <see cref="DtpFactory.SendDataAction" /> delegate</param>
        /// <param name="start">The start position of the byte array</param>
        /// <returns>Returns the response which must get processed in <see cref="DtpFactory.Receive" /></returns>
        public byte[] Receive(byte[] data, int start)
        {
            data = LZF.Decompress(data, start);
            var functionNameLength = BitConverter.ToInt32(data, 16);
            var functionName       = Encoding.UTF8.GetString(data, 20, functionNameLength);

            if (!_procedures.ContainsKey(functionName) && !_functions.ContainsKey(functionName))
            {
                ExceptionOccurred?.Invoke(this,
                                          new UnhandledExceptionEventArgs(
                                              new InvalidOperationException($"Method with name {functionName} not found")));

                var errorResponse = new byte[16 + functionNameLength];
                Array.Copy(DtpFactory.FunctionNotFoundExceptionGuid.ToByteArray(), errorResponse, 16);
                Array.Copy(data, 20, errorResponse, 16, functionNameLength);
                return(errorResponse);
            }

            var parameterCount = BitConverter.ToInt32(data, 20 + functionNameLength);

            var parameterLengths = new List <int>();
            var parameters       = new Dictionary <int, byte[]>();

            for (int i = 0; i < parameterCount; i++)
            {
                parameterLengths.Add(BitConverter.ToInt32(data, 24 + functionNameLength + i * 4));
            }

            var offset = 0;

            for (int i = 0; i < parameterCount; i++)
            {
                var parameterData = new byte[parameterLengths[i]];
                Array.Copy(data, 24 + functionNameLength + parameterCount * 4 + offset, parameterData, 0,
                           parameterData.Length);
                parameters.Add(i, parameterData);
                offset += parameterData.Length;
            }

            var dtpParameters = new DtpParameters(parameters);

            byte[] result = null;

            try
            {
                DtpProcedure procedure;
                if (_procedures.TryGetValue(functionName, out procedure))
                {
                    procedure.Invoke(dtpParameters);
                }
                else
                {
                    DtpFunction function;
                    if (_functions.TryGetValue(functionName, out function))
                    {
                        var returnedObject = function.Invoke(dtpParameters);

                        if (returnedObject != null)
                        {
                            var typeList = new List <Type> {
                                returnedObject.GetType()
                            };
                            Type[] specialTypes;
                            if (_specialTypes.TryGetValue(functionName, out specialTypes))
                            {
                                typeList.AddRange(specialTypes);
                            }

                            result = new Serializer(typeList).Serialize(returnedObject);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                var exception = new DtpException
                {
                    Message              = ex.Message,
                    StackTrace           = ex.StackTrace,
                    FunctionName         = functionName,
                    ParameterInformation = string.Join(", ",
                                                       parameters.Select(x => x.Key + " - " + x.Value.Length + " B").ToArray()),
                    SessionGuid = new Guid(data.Take(16).ToArray())
                };

                var exceptionData = new Serializer(typeof(DtpException)).Serialize(exception);
                var errorResponse = new byte[16 + exceptionData.Length];
                Array.Copy(DtpFactory.ExceptionGuid.ToByteArray(), errorResponse, 16);
                Array.Copy(exceptionData, 0, errorResponse, 16, exceptionData.Length);

                ExceptionOccurred?.Invoke(this, new UnhandledExceptionEventArgs(ex));
                return(LZF.Compress(errorResponse, 0));
            }

            var response = new byte[16 + 4 + (result?.Length ?? 0)];

            //Protocol
            //HEAD  - 16 Bytes      - Guid
            //HEAD  - 4 Bytes       - Response Length
            //DATA  - result.Length - Result Length
            Array.Copy(data, 0, response, 0, 16); //copy guid
            Array.Copy(BitConverter.GetBytes(result?.Length ?? 0), 0, response, 16, 4);
            if (result != null)
            {
                Array.Copy(result, 0, response, 20, result.Length);
            }

            return(LZF.Compress(response, 0));
        }
        private void EndRead(IAsyncResult asyncResult)
        {
            try
            {
                var        parameter = _readByteDelegate.EndInvoke(asyncResult);
                var        size      = Sender.Connection.BinaryReader.ReadInt32();
                var        bytes     = Sender.Connection.BinaryReader.ReadBytes(size);
                Serializer serializer;
                OnlineClientInformation client;
                int clientId;

                PackageInformation packageInformation = null;
                if (PackageReceived != null)
                {
                    packageInformation = new PackageInformation
                    {
                        Size       = bytes.Length + 1,
                        Timestamp  = DateTime.Now,
                        IsReceived = true
                    }
                }
                ;

                switch ((FromClientPackage)parameter)
                {
                case FromClientPackage.ResponseToAdministration:
                case FromClientPackage.ResponseToAdministrationCompressed:
                    var isCompressed = parameter == (byte)FromClientPackage.ResponseToAdministrationCompressed;
                    var data         = isCompressed
                            ? LZF.Decompress(bytes, 1)
                            : bytes;

                    if (packageInformation != null)
                    {
                        packageInformation.Description = (FromClientPackage)parameter + " " +
                                                         CurrentController.DescribePackage(bytes[0], data,
                                                                                           isCompressed ? 0 : 1);
                    }
                    CurrentController?.PackageReceived(bytes[0], data, isCompressed ? 0 : 1);
                    break;

                case FromClientPackage.ResponseLoginOpen:
                    clientId = BitConverter.ToInt32(bytes, 0);
                    client   = _loginsPending.FirstOrDefault(x => x.Id == clientId);
                    if (client == null)
                    {
                        Logger.Error((string)Application.Current.Resources["CouldNotFindClient"]);
                        break;
                    }
                    _loginsPending.Remove(client);
                    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        CurrentController = new ClientController(client, Sender, this);
                        ((Commander)CurrentController.Commander).ConnectionInfo.PackageSent +=
                            _packageSentEventHandler;
                        LoginOpened?.Invoke(this, EventArgs.Empty);
                    }));
                    break;

                case FromClientPackage.NewClientConnected:
                    serializer =
                        new Serializer(new[] { typeof(ClientInformation), typeof(OnlineClientInformation) });
                    client = serializer.Deserialize <OnlineClientInformation>(bytes);
                    Logger.Info(string.Format((string)Application.Current.Resources["NewClientConnected"],
                                              client.IpAddress, client.Port, client.UserName));

                    lock (_clientListUpdateLock)
                        Application.Current.Dispatcher.Invoke(() => ClientProvider.NewClientConnected(client));
                    NewClientConnected?.Invoke(this, client);
                    break;

                case FromClientPackage.ClientConnected:
                    serializer =
                        new Serializer(new[] { typeof(ClientInformation), typeof(OnlineClientInformation) });
                    client = serializer.Deserialize <OnlineClientInformation>(bytes);
                    Logger.Info(string.Format((string)Application.Current.Resources["NewClientConnected"],
                                              client.IpAddress, client.Port, client.UserName));

                    lock (_clientListUpdateLock)
                        Application.Current.Dispatcher.Invoke(() => ClientProvider.ClientConnected(client));

                    ClientConnected?.Invoke(this, client);
                    break;

                case FromClientPackage.ClientDisconnected:
                    var disconnectedClientId = BitConverter.ToInt32(bytes, 0);
                    if (CurrentController != null && CurrentController.Client.Id == disconnectedClientId)
                    {
                        CurrentController.Dispose();
                        CurrentController = null;
                    }

                    lock (_clientListUpdateLock)
                        Application.Current.Dispatcher.Invoke(
                            () => ClientProvider.ClientDisconnected(disconnectedClientId));
                    ClientDisconnected?.Invoke(this, disconnectedClientId);
                    break;

                case FromClientPackage.ComputerInformationAvailable:
                    var clientWithComputerInformationId = BitConverter.ToInt32(bytes, 0);
                    Application.Current.Dispatcher.BeginInvoke(
                        new Action(
                            () => ClientProvider.ComputerInformationAvailable(clientWithComputerInformationId)));
                    break;

                case FromClientPackage.PasswordsAvailable:
                    var clientWithPasswordsId = BitConverter.ToInt32(bytes, 0);
                    ClientProvider.PasswordsAvailable(clientWithPasswordsId);
                    break;

                case FromClientPackage.GroupChanged:
                    var newGroupNameLength = BitConverter.ToInt32(bytes, 0);
                    var newGroupName       = Encoding.UTF8.GetString(bytes, 4, newGroupNameLength);
                    var clients            = new Serializer(typeof(List <int>)).Deserialize <List <int> >(bytes,
                                                                                                          4 + newGroupNameLength);

                    ClientProvider.ClientGroupChanged(clients, newGroupName);
                    Logger.Receive((string)Application.Current.Resources["GroupChanged"]);
                    break;

                case FromClientPackage.ClientsRemoved:
                    serializer = new Serializer(typeof(List <int>));
                    var removedClientsIds = serializer.Deserialize <List <int> >(bytes);
                    lock (_clientListUpdateLock)
                        Application.Current.Dispatcher.Invoke(
                            () => ClientProvider.ClientRemoved(removedClientsIds));

                    if (removedClientsIds.Count == 1)
                    {
                        Logger.Receive((string)Application.Current.Resources["ClientRemoved"]);
                    }
                    else
                    {
                        Logger.Receive(string.Format((string)Application.Current.Resources["ClientsRemoved"],
                                                     removedClientsIds.Count));
                    }
                    break;

                case FromClientPackage.DynamicCommandsRemoved:
                    DynamicCommandsRemoved?.Invoke(this,
                                                   new Serializer(typeof(List <int>)).Deserialize <List <int> >(bytes));
                    break;

                case FromClientPackage.PluginLoaded:
                    clientId = BitConverter.ToInt32(bytes, 0);
                    var pluginInfo = new Serializer(typeof(PluginInfo)).Deserialize <PluginInfo>(bytes, 4);
                    ClientProvider.ClientPluginAvailable(clientId, pluginInfo);
                    PluginLoaded?.Invoke(this,
                                         new PluginLoadedEventArgs(clientId, pluginInfo.Guid, pluginInfo.Version, true));
                    break;

                case FromClientPackage.PluginLoadFailed:
                    clientId = BitConverter.ToInt32(bytes, 0);
                    PluginLoadingFailed?.Invoke(this,
                                                new PluginLoadedEventArgs(clientId, new Guid(bytes.Skip(4).Take(16).ToArray()),
                                                                          Encoding.ASCII.GetString(bytes.Skip(20).ToArray()), false));
                    break;

                case FromClientPackage.DataTransferProtocolResponse:
                    if (packageInformation != null)
                    {
                        packageInformation.Description = "DataTransferProtocolResponse - " +
                                                         DataTransferProtocolFactory.DescribeReceivedData(bytes, 0);
                    }
                    DataTransferProtocolFactory.Receive(bytes);
                    break;

                case FromClientPackage.ResponseActiveWindow:
                    clientId = BitConverter.ToInt32(bytes, 0);

                    var clientViewModel = ClientProvider.Clients.FirstOrDefault(x => x.Id == clientId);
                    if (clientViewModel != null)
                    {
                        clientViewModel.ActiveWindow = Encoding.UTF8.GetString(bytes, 4, bytes.Length - 4);
                    }
                    break;

                case FromClientPackage.ResponseScreenshot:
                    clientId = BitConverter.ToInt32(bytes, 0);

                    var clientViewModel2 = ClientProvider.Clients.FirstOrDefault(x => x.Id == clientId);
                    if (clientViewModel2 != null)
                    {
                        using (var stream = new MemoryStream(bytes, 4, bytes.Length - 4))
                            using (var image = (Bitmap)Image.FromStream(stream))
                                clientViewModel2.Thumbnail = BitmapConverter.ToBitmapSource(image);
                    }
                    break;

                case FromClientPackage.DataRemoved:
                    DataRemoved?.Invoke(this, new Serializer(typeof(List <int>)).Deserialize <List <int> >(bytes));
                    break;

                case FromClientPackage.PasswordsRemoved:
                    var clientIds = new Serializer(typeof(List <int>)).Deserialize <List <int> >(bytes);
                    foreach (var id in clientIds)
                    {
                        ClientProvider.PasswordsRemoved(id);
                    }

                    PasswordsRemoved?.Invoke(this, clientIds);
                    break;

                case FromClientPackage.DataDownloadPackage:
                    DownloadDataReceived?.Invoke(this, bytes);
                    break;

                case FromClientPackage.StaticCommandPluginReceived:
                    StaticCommandReceived?.Invoke(this, bytes);
                    break;

                case FromClientPackage.StaticCommandPluginTransmissionFailed:
                    StaticCommandTransmissionFailed?.Invoke(this, bytes);
                    break;

                case FromClientPackage.DynamicCommandAdded:
                    DynamicCommandAdded?.Invoke(this,
                                                new Serializer(RegisteredDynamicCommand.RequiredTypes).Deserialize <RegisteredDynamicCommand>(bytes));
                    break;

                case FromClientPackage.DynamicCommandEventsAdded:
                    DynamicCommandEventsAdded?.Invoke(this,
                                                      new Serializer(typeof(List <DynamicCommandEvent>)).Deserialize <List <DynamicCommandEvent> >(
                                                          bytes));
                    break;

                case FromClientPackage.DynamicCommandStatusUpdate:
                    DynamicCommandStatusUpdated?.Invoke(this,
                                                        new DynamicCommandStatusUpdatedEventArgs(BitConverter.ToInt32(bytes, 0),
                                                                                                 (DynamicCommandStatus)bytes[4]));
                    break;

                case FromClientPackage.ResponseLibraryInformation:
                    LibraryInformationReceived?.Invoke(this,
                                                       new LibraryInformationEventArgs(BitConverter.ToInt32(bytes, 0),
                                                                                       (PortableLibrary)BitConverter.ToInt32(bytes, 4)));
                    break;

                case FromClientPackage.ResponseLibraryLoadingResult:
                    LibraryLoadingResultReceived?.Invoke(this,
                                                         new LibraryInformationEventArgs(BitConverter.ToInt32(bytes, 0),
                                                                                         (PortableLibrary)BitConverter.ToInt32(bytes, 4)));
                    break;

                case FromClientPackage.ActiveCommandsChanged:
                    ActiveCommandsChanged?.Invoke(this,
                                                  new Serializer(typeof(ActiveCommandsUpdate)).Deserialize <ActiveCommandsUpdate>(bytes, 0));
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (packageInformation != null)
                {
                    if (string.IsNullOrEmpty(packageInformation.Description))
                    {
                        packageInformation.Description = ((FromClientPackage)parameter).ToString();
                    }
                    PackageReceived?.Invoke(this, packageInformation);
                }

                _readByteDelegate.BeginInvoke(EndRead, null);
            }
            catch (Exception ex)
            {
                if (!(ex is IOException) || ex.HResult != -2147024858)
                {
                    LogManager.GetCurrentClassLogger().Warn(ex, "Disconnected from server");
                    if (Application.Current != null)
                    {
                        Logger.Error(string.Format((string)Application.Current.Resources["DisconnectedFromServerException"],
                                                   ex.Message));
                    }
                }
                else if (Application.Current != null)
                {
                    Logger.Warn((string)Application.Current.Resources["DisconnectedFromServer"]);
                }

                else
                {
                    LogManager.GetCurrentClassLogger().Warn("NullReference");
                }

                Dispose();
                Disconnected?.Invoke(this, EventArgs.Empty);
            }
        }
        private void Read(BinaryReader binaryReader)
        {
            Logger.Debug("Begin reading data from stream of administration AI-{0}", Id);

            try
            {
                while (true)
                {
                    var parameter = binaryReader.ReadByte();
                    var size      = Connection.BinaryReader.ReadInt32();

                    var bytes = new Lazy <byte[]>(() => Connection.BinaryReader.ReadBytes(size));
                    int clientId;
                    switch ((FromAdministrationPackage)parameter)
                    {
                    case FromAdministrationPackage.InitializeNewSession:
                        clientId = BitConverter.ToInt32(bytes.Value, 0);
                        SendPackageToClient?.Invoke(this,
                                                    new SendPackageToClientEventArgs(clientId,
                                                                                     (byte)FromAdministrationPackage.InitializeNewSession,
                                                                                     new WriterCall(2, writer => writer.Write(Id))));
                        _openClientSessions.Add(clientId);
                        Logger.Info("Administration AI-{0} initializes session with client CI-{1}", Id, clientId);
                        break;

                    case FromAdministrationPackage.CloseSession:
                        clientId = BitConverter.ToInt32(bytes.Value, 0);
                        _openClientSessions.Remove(clientId);
                        SendPackageToClient?.Invoke(this,
                                                    new SendPackageToClientEventArgs(clientId, (byte)FromAdministrationPackage.CloseSession,
                                                                                     new WriterCall(2, writer => writer.Write(Id))));
                        Logger.Info("Administration AI-{0} closed session with client CI-{1}", Id, clientId);
                        break;

                    case FromAdministrationPackage.SendCommandCompressed:
                    case FromAdministrationPackage.SendCommand:
                        clientId = BitConverter.ToInt32(bytes.Value, 0);
                        Logger.Debug("Administration AI-{0} sends command to client CI-{1}", Id, clientId);

                        SendPackageToClient?.Invoke(this,
                                                    new SendPackageToClientEventArgs(clientId, parameter,
                                                                                     new WriterCall(bytes.Value.Length - 2,
                                                                                                    writer =>
                        {
                            writer.Write(Id);
                            writer.Write(bytes.Value, 4, bytes.Value.Length - 4);
                        })));
                        break;

                    case FromAdministrationPackage.SendDynamicCommand:
                        DynamicCommandReceived(
                            new Serializer(DynamicCommandInfo.RequiredTypes).Deserialize <DynamicCommand>(
                                bytes.Value, 0));
                        break;

                    case FromAdministrationPackage.SendDynamicCommandCompressed:
                        DynamicCommandReceived(
                            new Serializer(DynamicCommandInfo.RequiredTypes).Deserialize <DynamicCommand>(
                                LZF.Decompress(bytes.Value, 0)));
                        break;

                    case FromAdministrationPackage.LoadPlugin:
                        clientId = BitConverter.ToInt32(bytes.Value, 0);
                        Logger.Debug("Administration AI-{0} requests plugin loading on client CI-{1}", Id, clientId);

                        SendPackageToClient?.Invoke(this,
                                                    new SendPackageToClientEventArgs(clientId, parameter,
                                                                                     new WriterCall(bytes.Value.Length - 2,
                                                                                                    writer =>
                        {
                            writer.Write(Id);
                            writer.Write(bytes.Value, 4, bytes.Value.Length - 4);
                        })));
                        break;

                    case FromAdministrationPackage.DataTransferProtocol:
                        Logger.Debug("Data Transfer Protocol package received");
                        var result = _dtpProcessor.Receive(bytes.Value);
                        Logger.Debug("Data Transfer Protocol package processed");
                        lock (_sendLock)
                        {
                            Connection.BinaryWriter.Write((byte)FromClientPackage.DataTransferProtocolResponse);
                            Connection.BinaryWriter.Write(result.Length);
                            Connection.BinaryWriter.Write(result);
                        }
                        break;

                    case FromAdministrationPackage.SendStaticCommandPlugin:
                        Logger.Debug("Send dynamic command plugin with size {0} B", size);
                        ReceiveStaticCommandPlugin(binaryReader, size);
                        break;

                    case FromAdministrationPackage.ClientRedirect:
                        ClientRedirect(binaryReader, size);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
            }
            catch (Exception ex)
            {
                if (Logger.IsDebugEnabled)
                {
                    Logger.Debug(ex, "Exception occurred in administration AI-{0} receive handler", Id);
                }
                else if (!(ex is EndOfStreamException))
                {
                    Logger.Fatal(ex, "Exception occurred in administration AI-{0} receive handler", Id);
                }

                if (_openClientSessions.Count > 0)
                {
                    Logger.Info(
                        "Administration AI-{0} is disconnecting but has still opened sessions. Closing open sessions ({1} session{2})",
                        Id, _openClientSessions.Count, _openClientSessions.Count > 1 ? "s" : "");

                    foreach (var openClientSession in _openClientSessions)
                    {
                        SendPackageToClient?.Invoke(this,
                                                    new SendPackageToClientEventArgs(openClientSession,
                                                                                     (byte)FromAdministrationPackage.CloseSession, new WriterCall(BitConverter.GetBytes(Id))));
                    }
                    Logger.Debug("Open sessions closed");
                    _openClientSessions.Clear();
                }

                Dispose();
            }
        }