public override async Task OnConnectedAsync(ConnectionContext connection)
        {
            Logger.Debug($"Connecting to {_proxySettings.RemoteHost}:{_proxySettings.RemotePort}");
            var proxyClient = new TcpClient();
            await proxyClient.ConnectAsync(_proxySettings.RemoteHost, _proxySettings.RemotePort);

            var ogStream = proxyClient.GetStream();

            Stream proxyStream = ogStream;

            if (_proxySettings.Secure)
            {
                var protocol = new TlsClientProtocol(proxyStream, new Org.BouncyCastle.Security.SecureRandom());
                protocol.Connect(new BlazeTlsClient());
                proxyStream = protocol.Stream;
            }

            var blazeProtocol = new BlazeProxyProtocol();
            var localReader   = connection.CreateReader();
            var localWriter   = connection.CreateWriter();

            var remoteReader = new ProtocolReader(proxyStream);
            var remoteWriter = new ProtocolWriter(proxyStream);


            while (true)
            {
                try
                {
                    var result = await localReader.ReadAsync(blazeProtocol);

                    var message = result.Message;

                    if (message != null)
                    {
                        var header = message.Header;
                        Logger.Debug(
                            $"Client -> Proxy; Length:{header.Length} Component:{header.Component} Command:0x{header.Command:X2} ErrorCode:{header.ErrorCode} MessageType:{header.MessageType} MessageId:{header.MessageId}");

                        var requestPayload = message.Payload;

                        if (!requestPayload.IsEmpty)
                        {
                            if (!_parser.TryParseBody(requestPayload))
                            {
                                Logger.Error("Failed to parse request message");
                            }
                        }

                        await remoteWriter.WriteAsync(blazeProtocol, message);
                    }

                    if (result.IsCompleted)
                    {
                        break;
                    }
                }
                finally
                {
                    localReader.Advance();
                }

                do
                {
                    try
                    {
                        var result = await remoteReader.ReadAsync(blazeProtocol);

                        var message = result.Message;

                        if (message != null)
                        {
                            var header = message.Header;
                            Logger.Debug(
                                $"Proxy <- Server; Length:{header.Length} Component:{header.Component} Command:0x{header.Command:X2} ErrorCode:{header.ErrorCode} MessageType:{header.MessageType} MessageId:{header.MessageId}");

                            var responsePayload = message.Payload;

                            if (!responsePayload.IsEmpty)
                            {
                                if (!_parser.TryParseBody(responsePayload))
                                {
                                    Logger.Error("Failed to parse response message");
                                }
                            }

                            await localWriter.WriteAsync(blazeProtocol, message);
                        }

                        if (result.IsCompleted)
                        {
                            break;
                        }
                    }
                    finally
                    {
                        remoteReader.Advance();
                    }
                } while (ogStream.DataAvailable);
            }
        }
        public override async Task OnConnectedAsync(ConnectionContext connection)
        {
            Logger.Debug($"Redirecting to {_proxySettings.RedirectHost} {_proxySettings.RedirectIp}:{_proxySettings.LocalPort}");

            var blazeProtocol = new BlazeProxyProtocol();
            var localReader   = connection.CreateReader();
            var localWriter   = connection.CreateWriter();

            while (true)
            {
                try
                {
                    var result = await localReader.ReadAsync(blazeProtocol);

                    var message = result.Message;

                    if (message != null)
                    {
                        if (message.Header.Component == BlazeComponent.Redirector &&
                            message.Header.Command == (ushort)RedirectorCommand.ServerInfo)
                        {
                            var hostBytes = new List <byte>(Encoding.ASCII.GetBytes(_proxySettings.RedirectHost));
                            var payload   = new List <byte>();
                            payload.AddRange(new byte[] {
                                0x86, 0x49, 0x32, //ADDR
                                0xD0, 0x00,       //union(0)
                                0xDA, 0x1B, 0x35, //VALU
                                0x00,             //start struct
                                0xA2, 0xFC, 0xF4, //HOST
                            });
                            payload.AddRange(GetStringLengthBytes((uint)hostBytes.Count + 1));
                            payload.AddRange(hostBytes);
                            payload.AddRange(new byte[] {
                                0x00,             //endbyte for string
                                0xA7, 0x00, 0x00, //IP
                                0x74,             //uint32
                            });
                            var ipBytes = BitConverter.GetBytes(Convert.ToUInt32(IPAddress.Parse(_proxySettings.RedirectIp).Address));
                            Array.Reverse(ipBytes); //big endian
                            payload.AddRange(ipBytes);
                            payload.AddRange(new byte[] {
                                0xC2, 0xFC, 0xB4, //PORT
                                0x52,             //uint16
                            });
                            var portBytes = BitConverter.GetBytes(Convert.ToUInt16(_proxySettings.LocalPort));
                            Array.Reverse(portBytes); //big endian
                            payload.AddRange(portBytes);
                            payload.AddRange(new byte[] {
                                0x00,                   //end struct
                                0xCE, 0x58, 0xF5,       //SECU
                                0x21,                   //int8
                                0x00,                   //0
                                0xE2, 0x4B, 0xB3,       //XDNS
                                0x74,                   //uint32
                                0x00, 0x00, 0x00, 0x00, //0
                            });
                            var response = new BlazeMessageData
                            {
                                Header = new BlazeHeader
                                {
                                    Command     = message.Header.Command,
                                    Component   = message.Header.Component,
                                    MessageType = BlazeMessageType.Reply,
                                    MessageId   = message.Header.MessageId,
                                    ErrorCode   = 0
                                },
                                Payload = new ReadOnlySequence <byte>(payload.ToArray())
                            };
                            await localWriter.WriteAsync(blazeProtocol, response);
                        }
                    }

                    if (result.IsCompleted)
                    {
                        break;
                    }
                }
                finally
                {
                    localReader.Advance();
                }
            }
        }