Ejemplo n.º 1
0
        public static string ToBase64String(byte[] inArray)
        {
            var arrayString = Convert.ToBase64String(inArray);
            var chars       = arrayString.AsSpan();

            int filteredLength = chars.Length;

            if (chars.Length > 0 && chars[chars.Length - 1] == '=')
            {
                filteredLength--;
                if (chars.Length > 1 && chars[chars.Length - 2] == '=')
                {
                    filteredLength--;
                }
            }

            var filtered = BufferArrayPool <char> .Rent(filteredLength);

            for (var i = 0; i < filteredLength; i++)
            {
                var c = chars[i];
                filtered[i] = c switch
                {
                    '+' => '-',
                    '/' => '_',
                    _ => c,
                };
            }
            var filteredString = new String(filtered, 0, filteredLength);

            Array.Clear(filtered, 0, filteredLength);
            BufferArrayPool <char> .Return(filtered);

            return(filteredString);
        }
Ejemplo n.º 2
0
        public static byte[] ToArray(this Stream stream)
        {
            var bufferOwner = BufferArrayPool <byte> .Rent(1024 * 16);

            var buffer    = bufferOwner.AsSpan();
            var totalRead = 0;
            int read;

            try
            {
                while ((read = stream.Read(buffer.Slice(totalRead, buffer.Length - totalRead))) > 0)
                {
                    totalRead += read;
                    if (totalRead == buffer.Length)
                    {
                        BufferArrayPool <byte> .Grow(ref bufferOwner, bufferOwner.Length * 2);

                        buffer = bufferOwner.AsSpan();
                    }
                }

                var bytes = new byte[totalRead];
                Buffer.BlockCopy(bufferOwner, 0, bytes, 0, totalRead);
                return(bytes);
            }
            finally
            {
                buffer.Slice(0, totalRead).Clear();
                BufferArrayPool <byte> .Return(bufferOwner);
            }
        }
Ejemplo n.º 3
0
        public static async Task <byte[]> ToArrayAsync(this Stream stream, CancellationToken cancellationToken = default)
        {
            var buffer = BufferArrayPool <byte> .Rent(1024 * 16);

            var totalRead = 0;
            int read;

            try
            {
                while ((read = await stream.ReadAsync(buffer, totalRead, buffer.Length - totalRead, cancellationToken)) > 0)
                {
                    totalRead += read;
                    if (totalRead == buffer.Length)
                    {
                        BufferArrayPool <byte> .Grow(ref buffer, buffer.Length * 2);
                    }
                }

                var bytes = new byte[totalRead];
                Buffer.BlockCopy(buffer, 0, bytes, 0, totalRead);
                return(bytes);
            }
            finally
            {
                Array.Clear(buffer, 0, totalRead);
                BufferArrayPool <byte> .Return(buffer);
            }
        }
Ejemplo n.º 4
0
        public static async Task <byte[]> ToArrayAsync(this Stream stream, CancellationToken cancellationToken = default)
        {
            var bufferOwner = BufferArrayPool <byte> .Rent(1024 * 16);

            var buffer    = bufferOwner.AsMemory();
            var totalRead = 0;
            int read;

            try
            {
                while ((read = await stream.ReadAsync(buffer.Slice(totalRead, buffer.Length - totalRead), cancellationToken)) > 0)
                {
                    totalRead += read;
                    if (totalRead == buffer.Length)
                    {
                        BufferArrayPool <byte> .Grow(ref bufferOwner, buffer.Length * 2);

                        buffer = bufferOwner.AsMemory();
                    }
                }

                var bytes = new byte[totalRead];
                buffer.Slice(0, totalRead).Span.CopyTo(bytes.AsSpan());
                return(bytes);
            }
            finally
            {
                buffer.Span.Slice(0, totalRead).Clear();
                BufferArrayPool <byte> .Return(bufferOwner);
            }
        }
Ejemplo n.º 5
0
        protected override void Dispose(bool disposing)
        {
            if (segmentLengthBufferSource != null)
            {
                BufferArrayPool <byte> .Return(segmentLengthBufferSource);

                segmentLengthBufferSource = null;
                segmentLengthBuffer       = null;
            }
            base.Dispose(disposing);
        }
Ejemplo n.º 6
0
        public override ValueTask DisposeAsync()
        {
            if (segmentLengthBufferSource != null)
            {
                BufferArrayPool <byte> .Return(segmentLengthBufferSource);

                segmentLengthBufferSource = null;
                segmentLengthBuffer       = null;
            }
            return(base.DisposeAsync());
        }
Ejemplo n.º 7
0
        public TcpRawProtocolBodyStream(Stream stream, ReadOnlyMemory <byte> readStartBufferPosition, bool leaveOpen) : base(stream, leaveOpen)
        {
            this.readStartBuffer         = readStartBufferPosition;
            this.readStartBufferPosition = 0;
            this.position                  = 0;
            this.segmentPosition           = 0;
            this.segmentLength             = -1;
            this.ended                     = false;
            this.segmentLengthBufferSource = BufferArrayPool <byte> .Rent(segmentLengthBufferLength);

            this.segmentLengthBuffer = segmentLengthBufferSource;
        }
Ejemplo n.º 8
0
        public CryptoShiftStream(Stream stream, int cryptoBlockSize, CryptoStreamMode mode, bool deshift, bool leaveOpen) : base(stream, leaveOpen)
        {
            if (cryptoBlockSize < 16 || cryptoBlockSize % 8 != 0)
            {
                throw new ArgumentException($"must be minimum of 16 and a multiple of 8.", nameof(cryptoBlockSize));
            }

            this.cryptoStream   = stream as CryptoStream;
            this.blockSizeBytes = cryptoBlockSize / 8;
            this.keySizeBytes   = blockSizeBytes;
            this.mode           = mode;
            this.deshift        = deshift;

            this.keyBufferOwner = BufferArrayPool <byte> .Rent(this.keySizeBytes);

            this.keyBuffer = this.keyBufferOwner.AsMemory().Slice(0, this.keySizeBytes);
#if NETSTANDARD2_0
            this.workingBufferOwner = BufferArrayPool <byte> .Rent(bufferSize);

            this.workingBuffer = this.workingBufferOwner.AsMemory();
#else
            if (mode == CryptoStreamMode.Write)
            {
                this.workingBufferOwner = BufferArrayPool <byte> .Rent(bufferSize);

                this.workingBuffer = this.workingBufferOwner.AsMemory();
            }
            else
            {
                this.workingBufferOwner = null;
                this.workingBuffer      = null;
            }
#endif

            if (!deshift)
            {
                using (var rng = RandomNumberGenerator.Create())
                {
#if NETSTANDARD2_0
                    rng.GetBytes(keyBufferOwner, 0, keySizeBytes);
#else
                    rng.GetBytes(keyBuffer.Span);
#endif
                }
            }

            this.keyPosition = 0;
            this.position    = 0;
        }
Ejemplo n.º 9
0
        public static int ReadToSpan(this StreamReader stream, Span <char> span)
        {
            var buffer = BufferArrayPool <char> .Rent(span.Length);

            var totalRead = 0;

            try
            {
                totalRead = stream.Read(buffer, 0, span.Length);
                buffer.AsSpan().Slice(0, totalRead).CopyTo(span);
            }
            finally
            {
                Array.Clear(buffer, 0, totalRead);
                BufferArrayPool <char> .Return(buffer);
            }
            return(totalRead);
        }
Ejemplo n.º 10
0
        public static async Task <int> ReadToMemoryAsync(this Stream stream, Memory <byte> memory, CancellationToken cancellationToken = default)
        {
            var buffer = BufferArrayPool <byte> .Rent(memory.Length);

            var totalRead = 0;

            try
            {
                totalRead = await stream.ReadAsync(buffer, 0, memory.Length, cancellationToken);

                buffer.AsSpan().Slice(0, totalRead).CopyTo(memory.Span);
            }
            finally
            {
                Array.Clear(buffer, 0, totalRead);
                BufferArrayPool <byte> .Return(buffer);
            }
            return(totalRead);
        }
Ejemplo n.º 11
0
        public static async Task <int> ReadToMemoryAsync(this StreamReader stream, Memory <char> memory)
        {
            var buffer = BufferArrayPool <char> .Rent(memory.Length);

            var totalRead = 0;

            try
            {
                totalRead = await stream.ReadAsync(buffer, 0, memory.Length);

                buffer.AsSpan().Slice(0, totalRead).CopyTo(memory.Span);
            }
            finally
            {
                Array.Clear(buffer, 0, totalRead);
                BufferArrayPool <char> .Return(buffer);
            }
            return(totalRead);
        }
Ejemplo n.º 12
0
        public static byte[] FromBase64String(string s)
        {
            var chars          = s.ToCharArray();
            var filteredLength = (chars.Length % 4) switch
            {
                0 => chars.Length,
                2 => chars.Length + 2,
                3 => chars.Length + 1,
                _ => throw new FormatException("Invalid string"),
            };
            var filtered = BufferArrayPool <char> .Rent(filteredLength);

            for (var i = 0; i < chars.Length; i++)
            {
                var c = chars[i];
                filtered[i] = c switch
                {
                    '-' => '+',
                    '_' => '/',
                    _ => c,
                };
            }

            switch (chars.Length % 4)
            {
            case 2:
                filtered[filteredLength - 2] = '=';
                filtered[filteredLength - 1] = '=';
                break;

            case 3:
                filtered[filteredLength - 1] = '=';
                break;
            }

            var filteredString = new String(filtered, 0, filteredLength);

            Array.Clear(filtered, 0, filteredLength);
            BufferArrayPool <char> .Return(filtered);

            return(Convert.FromBase64String(filteredString));
        }
Ejemplo n.º 13
0
        protected override void Dispose(bool disposing)
        {
            if (keyBufferOwner != null)
            {
                Array.Clear(keyBufferOwner, 0, keyBufferOwner.Length);
                BufferArrayPool <byte> .Return(keyBufferOwner);

                keyBufferOwner = null;
                keyBuffer      = null;
            }
            if (workingBufferOwner != null)
            {
                Array.Clear(workingBufferOwner, 0, workingBufferOwner.Length);
                BufferArrayPool <byte> .Return(workingBufferOwner);

                workingBufferOwner = null;
                workingBuffer      = null;
            }
            base.Dispose(disposing);
        }
Ejemplo n.º 14
0
        public override ValueTask DisposeAsync()
        {
            if (keyBufferOwner != null)
            {
                Array.Clear(keyBufferOwner, 0, keyBufferOwner.Length);
                BufferArrayPool <byte> .Return(keyBufferOwner);

                keyBufferOwner = null;
                keyBuffer      = null;
            }
            if (workingBufferOwner != null)
            {
                Array.Clear(workingBufferOwner, 0, workingBufferOwner.Length);
                BufferArrayPool <byte> .Return(workingBufferOwner);

                workingBufferOwner = null;
                workingBuffer      = null;
            }
            return(base.DisposeAsync());
        }
Ejemplo n.º 15
0
        public HttpProtocolBodyStream(int?contentLength, Stream stream, ReadOnlyMemory <byte> readStartBuffer, bool leaveOpen) : base(stream, leaveOpen)
        {
            this.contentLength               = contentLength;
            this.readStartBuffer             = readStartBuffer;
            this.readStartBufferPosition     = 0;
            this.segmentPosition             = 0;
            this.segmentLength               = -1;
            this.segmentLengthBufferLength   = 0;
            this.segmentLengthBufferPosition = 0;
            this.ended = false;
            if (!contentLength.HasValue)
            {
                this.segmentLengthBufferSource = BufferArrayPool <byte> .Rent(segmentLengthBufferMaxLength);

                this.segmentLengthBuffer = segmentLengthBufferSource;
            }
            else
            {
                this.segmentLengthBufferSource = null;
                this.segmentLengthBuffer       = null;
            }
        }
Ejemplo n.º 16
0
        public static unsafe T Deserialize <T>(string queryString)
        {
            var model      = Instantiator.CreateInstance <T>();
            var typeDetail = TypeAnalyzer.GetTypeDetail(typeof(T));

            var bufferOwner = BufferArrayPool <char> .Rent(256);

            var buffer       = bufferOwner.AsSpan();
            var bufferLength = 0;

            try
            {
                fixed(char *pFixed = queryString)
                {
                    char * p    = pFixed;
                    string name = null;

                    for (var i = 0; i < queryString.Length; i++)
                    {
                        var c = *p;
                        switch (c)
                        {
                        case '=':
                            if (name != null)
                            {
                                throw new Exception($"Invalid query string at position {i}");
                            }
#if NETSTANDARD2_0
                            name = new String(bufferOwner, 0, bufferLength);
#else
                            name = new String(buffer.Slice(0, bufferLength));
#endif
                            bufferLength = 0;
                            break;

                        case '&':
                            if (name == null)
                            {
                                throw new Exception($"Invalid query string at position {i}");
                            }
#if NETSTANDARD2_0
                            var value = new String(bufferOwner, 0, bufferLength);
#else
                            var value = new String(buffer.Slice(0, bufferLength));
#endif
                            SetValue(typeDetail, model, WebUtility.UrlDecode(name), WebUtility.UrlDecode(value));
                            name         = null;
                            bufferLength = 0;
                            break;

                        default:
                            if (bufferLength == buffer.Length)
                            {
                                BufferArrayPool <char> .Grow(ref bufferOwner, bufferOwner.Length * 2);

                                buffer = bufferOwner.AsSpan();
                            }
                            buffer[bufferLength++] = c;
                            break;
                        }
                        p++;
                    }

                    if (name != null)
                    {
#if NETSTANDARD2_0
                        var value = new String(bufferOwner, 0, bufferLength);
#else
                        var value = new String(buffer.Slice(0, bufferLength));
#endif
                        SetValue(typeDetail, model, WebUtility.UrlDecode(name), WebUtility.UrlDecode(value));
                        bufferLength = 0;
                    }
                }
            }
            finally
            {
                BufferArrayPool <char> .Return(bufferOwner);
            }

            return(model);
        }
Ejemplo n.º 17
0
        protected override TReturn CallInternal <TReturn>(bool isStream, Type interfaceType, string methodName, object[] arguments)
        {
            var data = new CQRSRequestData()
            {
                ProviderType   = interfaceType.Name,
                ProviderMethod = methodName
            };

            data.AddProviderArguments(arguments);

            switch (networkType)
            {
            case NetworkType.Internal:
                data.AddClaims();
                break;

            case NetworkType.Api:
                break;

            default: throw new NotImplementedException();
            }

            var stopwatch = Stopwatch.StartNew();

            var client = new TcpClient(endpoint.AddressFamily);

            var bufferOwner = BufferArrayPool <byte> .Rent(TcpRawCommon.BufferLength);

            var              buffer                  = bufferOwner.AsMemory();
            Stream           stream                  = null;
            Stream           requestBodyStream       = null;
            FinalBlockStream requestBodyCryptoStream = null;
            Stream           responseBodyStream      = null;

            try
            {
                client.Connect(endpoint.Address, endpoint.Port);

                stream = client.GetStream();

                //Request Header
                var requestHeaderLength = TcpRawCommon.BufferHeader(buffer, data.ProviderType, contentType);
#if NETSTANDARD2_0
                stream.Write(bufferOwner, 0, requestHeaderLength);
#else
                stream.Write(buffer.Span.Slice(0, requestHeaderLength));
#endif

                requestBodyStream = new TcpRawProtocolBodyStream(stream, null, true);

                if (encryptionKey != null)
                {
                    requestBodyCryptoStream = SymmetricEncryptor.Encrypt(encryptionAlgorithm, encryptionKey, requestBodyStream, true, true);
                    ContentTypeSerializer.Serialize(contentType, requestBodyCryptoStream, data);
                    requestBodyCryptoStream.FlushFinalBlock();
                    requestBodyCryptoStream.Dispose();
                    requestBodyCryptoStream = null;
                }
                else
                {
                    ContentTypeSerializer.Serialize(contentType, requestBodyStream, data);
                    requestBodyStream.Flush();
                }

                requestBodyStream.Dispose();
                requestBodyStream = null;

                //Response Header
                var headerPosition   = 0;
                var headerLength     = 0;
                var requestHeaderEnd = false;
                while (!requestHeaderEnd)
                {
                    if (headerLength == buffer.Length)
                    {
                        throw new Exception($"{nameof(TcpRawCQRSClient)} Header Too Long");
                    }

#if NETSTANDARD2_0
                    var bytesRead = stream.Read(bufferOwner, headerPosition, buffer.Length - headerPosition);
#else
                    var bytesRead = stream.Read(buffer.Span.Slice(headerPosition, buffer.Length - headerPosition));
#endif

                    if (bytesRead == 0)
                    {
                        throw new EndOfStreamException();
                    }
                    headerLength += bytesRead;

                    requestHeaderEnd = TcpRawCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                }
                var responseHeader = TcpRawCommon.ReadHeader(buffer, headerPosition, headerLength);

                responseBodyStream = new TcpRawProtocolBodyStream(stream, responseHeader.BodyStartBuffer, false);

                if (encryptionKey != null)
                {
                    responseBodyStream = SymmetricEncryptor.Decrypt(encryptionAlgorithm, encryptionKey, responseBodyStream, false, false);
                }

                if (responseHeader.IsError)
                {
                    var responseException = ContentTypeSerializer.DeserializeException(contentType, responseBodyStream);
                    throw responseException;
                }

                stopwatch.Stop();
                _ = Log.TraceAsync($"{nameof(TcpRawCQRSClient)} Query: {interfaceType.GetNiceName()}.{data.ProviderMethod} {stopwatch.ElapsedMilliseconds}");

                if (isStream)
                {
                    return((TReturn)(object)responseBodyStream); //TODO better way to convert type???
                }
                else
                {
                    var model = ContentTypeSerializer.Deserialize <TReturn>(contentType, responseBodyStream);
                    responseBodyStream.Dispose();
                    client.Dispose();
                    return(model);
                }
            }
            catch
            {
                try
                {
                    //crypto stream can error, we want to throw the actual error
                    if (responseBodyStream != null)
                    {
                        responseBodyStream.Dispose();
                    }
                }
                catch { }
                if (requestBodyStream != null)
                {
                    requestBodyStream.Dispose();
                }
                if (requestBodyCryptoStream != null)
                {
                    requestBodyCryptoStream.Dispose();
                }
                if (stream != null)
                {
                    stream.Dispose();
                }
                client.Dispose();
                throw;
            }
            finally
            {
                BufferArrayPool <byte> .Return(bufferOwner);
            }
        }
Ejemplo n.º 18
0
        protected override async Task DispatchInternal(ICommand command, bool messageAwait)
        {
            var messageType     = command.GetType();
            var messageTypeName = messageType.GetNiceName();

            var messageData = System.Text.Json.JsonSerializer.Serialize(command, messageType);

            var data = new CQRSRequestData()
            {
                MessageType  = messageTypeName,
                MessageData  = messageData,
                MessageAwait = messageAwait
            };

            switch (networkType)
            {
            case NetworkType.Internal:
                data.AddClaims();
                break;

            case NetworkType.Api:
                break;

            default:
                throw new NotImplementedException();
            }

            var stopwatch = Stopwatch.StartNew();

            var client = new TcpClient(endpoint.AddressFamily);

            client.NoDelay = true;

            var bufferOwner = BufferArrayPool <byte> .Rent(TcpRawCommon.BufferLength);

            var              buffer                  = bufferOwner.AsMemory();
            Stream           stream                  = null;
            Stream           requestBodyStream       = null;
            FinalBlockStream requestBodyCryptoStream = null;
            Stream           responseBodyStream      = null;

            try
            {
                await client.ConnectAsync(endpoint.Address, endpoint.Port);

                stream = client.GetStream();

                //Request Header
                var requestHeaderLength = TcpRawCommon.BufferHeader(buffer, data.MessageType, contentType);
#if NETSTANDARD2_0
                await stream.WriteAsync(bufferOwner, 0, requestHeaderLength);
#else
                await stream.WriteAsync(buffer.Slice(0, requestHeaderLength));
#endif

                requestBodyStream = new TcpRawProtocolBodyStream(stream, null, true);

                if (encryptionKey != null)
                {
                    requestBodyCryptoStream = SymmetricEncryptor.Encrypt(encryptionAlgorithm, encryptionKey, requestBodyStream, true, true);
                    await ContentTypeSerializer.SerializeAsync(contentType, requestBodyCryptoStream, data);

#if NET5_0_OR_GREATER
                    await requestBodyCryptoStream.FlushFinalBlockAsync();
#else
                    requestBodyCryptoStream.FlushFinalBlock();
#endif
#if NETSTANDARD2_0
                    requestBodyCryptoStream.Dispose();
#else
                    await requestBodyCryptoStream.DisposeAsync();
#endif
                    requestBodyCryptoStream = null;
                }
                else
                {
                    await ContentTypeSerializer.SerializeAsync(contentType, requestBodyStream, data);

                    await requestBodyStream.FlushAsync();
                }

#if NETSTANDARD2_0
                requestBodyStream.Dispose();
#else
                await requestBodyStream.DisposeAsync();
#endif
                requestBodyStream = null;

                //Response Header
                var headerPosition   = 0;
                var headerLength     = 0;
                var requestHeaderEnd = false;
                while (!requestHeaderEnd)
                {
                    if (headerLength == buffer.Length)
                    {
                        throw new Exception($"{nameof(TcpRawCQRSClient)} Header Too Long");
                    }

#if NETSTANDARD2_0
                    var bytesRead = await stream.ReadAsync(bufferOwner, headerPosition, buffer.Length - headerPosition);
#else
                    var bytesRead = await stream.ReadAsync(buffer.Slice(headerPosition, buffer.Length - headerPosition));
#endif

                    if (bytesRead == 0)
                    {
                        throw new EndOfStreamException();
                    }
                    headerLength += bytesRead;

                    requestHeaderEnd = TcpRawCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                }
                var responseHeader = TcpRawCommon.ReadHeader(buffer, headerPosition, headerLength);

                //Response Body
                responseBodyStream = new TcpRawProtocolBodyStream(stream, responseHeader.BodyStartBuffer, false);

                if (responseHeader.IsError)
                {
                    if (encryptionKey != null)
                    {
                        responseBodyStream = SymmetricEncryptor.Decrypt(encryptionAlgorithm, encryptionKey, responseBodyStream, false, false);
                    }

                    var responseException = await ContentTypeSerializer.DeserializeExceptionAsync(contentType, responseBodyStream);

                    throw responseException;
                }

                if (responseBodyStream != null)
                {
#if NETSTANDARD2_0
                    responseBodyStream.Dispose();
#else
                    await responseBodyStream.DisposeAsync();
#endif
                }
                client.Dispose();

                stopwatch.Stop();
                _ = Log.TraceAsync($"{nameof(TcpRawCQRSClient)}Sent: {messageTypeName} {stopwatch.ElapsedMilliseconds}");
            }
            catch
            {
                if (responseBodyStream != null)
                {
#if NETSTANDARD2_0
                    responseBodyStream.Dispose();
#else
                    await responseBodyStream.DisposeAsync();
#endif
                }
                if (requestBodyStream != null)
                {
#if NETSTANDARD2_0
                    requestBodyStream.Dispose();
#else
                    await requestBodyStream.DisposeAsync();
#endif
                }
                if (stream != null)
                {
#if NETSTANDARD2_0
                    stream.Dispose();
#else
                    await stream.DisposeAsync();
#endif
                }
                client.Dispose();
                throw;
            }
            finally
            {
                BufferArrayPool <byte> .Return(bufferOwner);
            }
        }
Ejemplo n.º 19
0
        protected override async void Handle(TcpClient client, CancellationToken cancellationToken)
        {
            TcpClient             outgoingClient = null;
            CQRSProtocolType?     protocolType   = null;
            RelayConnectedService service        = null;
            Stopwatch             stopwatch      = null;
            bool responseStarted = false;

            var bufferOwner = BufferArrayPool <byte> .Rent(bufferLength);

            var buffer = bufferOwner.AsMemory();

            Stream incommingStream           = null;
            Stream incommingBodyStream       = null;
            Stream outgoingWritingBodyStream = null;

            Stream outgoingStream             = null;
            Stream outgoingBodyStream         = null;
            Stream incommingWritingBodyStream = null;

            try
            {
                incommingStream = client.GetStream();

                var headerPosition = 0;
                var headerLength   = 0;
                var headerEnd      = false;
                while (headerLength < TcpCommon.MaxProtocolHeaderPrefixLength)
                {
                    if (headerLength == buffer.Length)
                    {
                        throw new Exception($"{nameof(TcpRelay)} Header Too Long");
                    }

                    headerLength += await incommingStream.ReadAsync(buffer.Slice(headerPosition, buffer.Length - headerPosition), cancellationToken);
                }
                protocolType = TcpCommon.ReadProtocol(buffer.Span);

                string providerType;

                switch (protocolType.Value)
                {
                case CQRSProtocolType.TcpRaw:
                {
                    headerEnd = TcpRawCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                    while (!headerEnd)
                    {
                        if (headerLength == buffer.Length)
                        {
                            throw new Exception($"{nameof(TcpRelay)} Header Too Long");
                        }

                        headerLength += await incommingStream.ReadAsync(buffer.Slice(headerLength, buffer.Length - headerLength), cancellationToken);

                        headerEnd = TcpRawCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                    }
                    var header = TcpRawCommon.ReadHeader(buffer, headerPosition, headerLength);
                    providerType        = header.ProviderType;
                    incommingBodyStream = new TcpRawProtocolBodyStream(incommingStream, header.BodyStartBuffer, true);
                    break;
                }

                case CQRSProtocolType.Http:
                {
                    headerEnd = HttpCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                    while (!headerEnd)
                    {
                        if (headerLength == buffer.Length)
                        {
                            throw new Exception($"{nameof(TcpRelay)} Header Too Long");
                        }

                        headerLength += await incommingStream.ReadAsync(buffer.Slice(headerLength, buffer.Length - headerLength), cancellationToken);

                        headerEnd = HttpCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                    }
                    var header = HttpCommon.ReadHeader(buffer, headerPosition, headerLength);
                    providerType        = header.ProviderType;
                    incommingBodyStream = new HttpProtocolBodyStream(header.ContentLength, incommingStream, header.BodyStartBuffer, true);

                    if (header.RelayServiceAddRemove.HasValue)
                    {
                        if (header.RelayKey != relayKey)
                        {
                            throw new SecurityException("Invalid Relay Key");
                        }

                        var serviceInfo = await System.Text.Json.JsonSerializer.DeserializeAsync <ServiceInfo>(incommingBodyStream);

                        await incommingBodyStream.DisposeAsync();

                        incommingBodyStream = null;

                        if (header.RelayServiceAddRemove == true)
                        {
                            RelayConnectedServicesManager.AddOrUpdate(serviceInfo);
                        }
                        else
                        {
                            RelayConnectedServicesManager.Remove(serviceInfo.Url);
                        }

                        var requestHeaderLength = HttpCommon.BufferOkHeader(buffer);
                        await incommingStream.WriteAsync(buffer.Slice(0, requestHeaderLength), cancellationToken);

                        await incommingStream.FlushAsync();

                        await incommingStream.DisposeAsync();

                        incommingStream = null;
                        client.Dispose();
                        return;
                    }
                    break;
                }

                default: throw new NotImplementedException();
                }

                while (outgoingClient == null)
                {
                    service = RelayConnectedServicesManager.GetBestService(providerType);
                    if (service == null)
                    {
                        break;
                    }

                    try
                    {
                        _ = Log.TraceAsync($"Relaying {providerType} to {service.Url}");

                        var outgoingEndpoint = IPResolver.GetIPEndPoints(service.Url, 80).First();
                        if (outgoingEndpoint != null)
                        {
                            outgoingClient         = new TcpClient(outgoingEndpoint.AddressFamily);
                            outgoingClient.NoDelay = true;
                            await outgoingClient.ConnectAsync(outgoingEndpoint.Address, outgoingEndpoint.Port);

                            service.FlagConnectionSuccess();
                        }
                        else
                        {
                            service.FlagConnectionFailed();
                        }
                    }
                    catch
                    {
                        service.FlagConnectionFailed();
                    }
                }

                if (outgoingClient == null)
                {
                    _ = Log.TraceAsync($"Destination not found {providerType}");
                    switch (protocolType.Value)
                    {
                    case CQRSProtocolType.TcpRaw:
                    {
                        var requestHeaderLength = HttpCommon.BufferNotFoundHeader(buffer);
                        await incommingStream.WriteAsync(buffer.Slice(0, requestHeaderLength));

                        return;
                    }

                    case CQRSProtocolType.Http:
                    {
                        var requestHeaderLength = TcpRawCommon.BufferErrorHeader(buffer, null, default);
                        await incommingStream.WriteAsync(buffer.Slice(0, requestHeaderLength));

                        return;
                    }

                    default: throw new NotImplementedException();
                    }
                }

                outgoingStream = outgoingClient.GetStream();

                stopwatch = service.StartRequestRunning();

                responseStarted = true;
                await outgoingStream.WriteAsync(buffer.Slice(0, headerPosition), cancellationToken);

                switch (protocolType.Value)
                {
                case CQRSProtocolType.TcpRaw:
                {
                    outgoingWritingBodyStream = new TcpRawProtocolBodyStream(outgoingStream, null, true);
                    await incommingBodyStream.CopyToAsync(outgoingWritingBodyStream, cancellationToken);

                    await outgoingWritingBodyStream.FlushAsync();

                    break;
                }

                case CQRSProtocolType.Http:
                {
                    outgoingWritingBodyStream = new HttpProtocolBodyStream(null, outgoingStream, null, true);
                    await incommingBodyStream.CopyToAsync(outgoingWritingBodyStream, cancellationToken);

                    await outgoingWritingBodyStream.FlushAsync();

                    break;
                }

                default: throw new NotImplementedException();
                }

                await incommingBodyStream.DisposeAsync();

                incommingBodyStream = null;
                await outgoingWritingBodyStream.DisposeAsync();

                outgoingWritingBodyStream = null;

                //Response
                //-----------------------------------------------------------------------------------------------------------------------

                headerPosition = 0;
                headerLength   = 0;
                headerEnd      = false;
                switch (protocolType.Value)
                {
                case CQRSProtocolType.TcpRaw:
                {
                    while (!headerEnd)
                    {
                        if (headerLength == buffer.Length)
                        {
                            throw new Exception($"{nameof(TcpRelay)} Header Too Long");
                        }

                        headerLength += await outgoingStream.ReadAsync(buffer.Slice(headerLength, buffer.Length - headerLength));

                        headerEnd = TcpRawCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                    }
                    outgoingBodyStream = new TcpRawProtocolBodyStream(outgoingStream, buffer.Slice(headerPosition, headerLength - headerPosition), false);
                    break;
                }

                case CQRSProtocolType.Http:
                {
                    while (!headerEnd)
                    {
                        if (headerLength == buffer.Length)
                        {
                            throw new Exception($"{nameof(TcpRelay)} Header Too Long");
                        }

                        headerLength += await outgoingStream.ReadAsync(buffer.Slice(headerLength, buffer.Length - headerLength));

                        headerEnd = HttpCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                    }
                    var header = HttpCommon.ReadHeader(buffer, headerPosition, headerLength);
                    outgoingBodyStream = new HttpProtocolBodyStream(header.ContentLength, outgoingStream, header.BodyStartBuffer, false);
                    break;
                }
                }

                await incommingStream.WriteAsync(buffer.Slice(0, headerPosition), cancellationToken);

                switch (protocolType.Value)
                {
                case CQRSProtocolType.TcpRaw:
                {
                    incommingWritingBodyStream = new TcpRawProtocolBodyStream(incommingStream, null, false);
                    await outgoingBodyStream.CopyToAsync(incommingWritingBodyStream, cancellationToken);

                    await incommingWritingBodyStream.FlushAsync();

                    break;
                }

                case CQRSProtocolType.Http:
                {
                    incommingWritingBodyStream = new HttpProtocolBodyStream(null, incommingStream, null, false);
                    await outgoingBodyStream.CopyToAsync(incommingWritingBodyStream, cancellationToken);

                    await incommingWritingBodyStream.FlushAsync();

                    break;
                }

                default: throw new NotImplementedException();
                }

                await outgoingBodyStream.DisposeAsync();

                outgoingBodyStream = null;
                await incommingWritingBodyStream.DisposeAsync();

                incommingWritingBodyStream = null;
                outgoingClient.Dispose();
                client.Dispose();
            }
            catch (Exception ex)
            {
                if (ex is IOException ioException)
                {
                    if (ioException.InnerException != null && ioException.InnerException is SocketException socketException)
                    {
                        if (socketException.SocketErrorCode == SocketError.ConnectionAborted)
                        {
                            return;
                        }
                    }
                }

                _ = Log.ErrorAsync(null, ex);

                if (!responseStarted && incommingStream != null && protocolType.HasValue)
                {
                    try
                    {
                        switch (protocolType.Value)
                        {
                        case CQRSProtocolType.TcpRaw:
                        {
                            var requestHeaderLength = HttpCommon.BufferErrorHeader(buffer, null);
                            await incommingStream.WriteAsync(buffer.Slice(0, requestHeaderLength), cancellationToken);

                            break;
                        }

                        case CQRSProtocolType.Http:
                        {
                            var requestHeaderLength = TcpRawCommon.BufferErrorHeader(buffer, null, default);
                            await incommingStream.WriteAsync(buffer.Slice(0, requestHeaderLength), cancellationToken);

                            break;
                        }

                        default: throw new NotImplementedException();
                        }
                    }
                    catch (Exception ex2)
                    {
                        _ = Log.ErrorAsync(null, ex2);
                    }
                }

                if (outgoingWritingBodyStream != null)
                {
                    await outgoingWritingBodyStream.DisposeAsync();
                }
                if (outgoingBodyStream != null)
                {
                    await outgoingBodyStream.DisposeAsync();
                }
                if (outgoingStream != null)
                {
                    await outgoingStream.DisposeAsync();
                }
                if (incommingWritingBodyStream != null)
                {
                    await incommingWritingBodyStream.DisposeAsync();
                }
                if (incommingBodyStream != null)
                {
                    await incommingBodyStream.DisposeAsync();
                }
                if (incommingStream != null)
                {
                    await incommingStream.DisposeAsync();
                }

                if (outgoingClient != null)
                {
                    outgoingClient.Dispose();
                }

                client.Dispose();
            }
            finally
            {
                BufferArrayPool <byte> .Return(bufferOwner);

                if (service != null && stopwatch != null)
                {
                    service.EndRequestRunning(stopwatch);
                }
            }
        }
Ejemplo n.º 20
0
        protected override TReturn CallInternal <TReturn>(bool isStream, Type interfaceType, string methodName, object[] arguments)
        {
            var data = new CQRSRequestData()
            {
                ProviderType   = interfaceType.Name,
                ProviderMethod = methodName
            };

            data.AddProviderArguments(arguments);

            HttpAuthHeaders authHeaders = null;

            switch (networkType)
            {
            case NetworkType.Internal:
                data.AddClaims();
                break;

            case NetworkType.Api:
                if (apiAuthorizer != null)
                {
                    authHeaders = apiAuthorizer.BuildAuthHeaders();
                }
                break;

            default:
                throw new NotImplementedException();
            }

            var stopwatch = Stopwatch.StartNew();

            var client = new TcpClient(endpoint.AddressFamily);

            client.NoDelay = true;

            var bufferOwner = BufferArrayPool <byte> .Rent(HttpCommon.BufferLength);

            var    buffer             = bufferOwner.AsMemory();
            Stream stream             = null;
            Stream requestBodyStream  = null;
            Stream responseBodyStream = null;

            try
            {
                client.Connect(endpoint.Address, endpoint.Port);

                stream = client.GetStream();

                //Request Header
                var requestHeaderLength = HttpCommon.BufferHeader(buffer, data.ProviderType, contentType, serviceUrl, authHeaders);
#if NETSTANDARD2_0
                stream.Write(bufferOwner, 0, requestHeaderLength);
#else
                stream.Write(buffer.Span.Slice(0, requestHeaderLength));
#endif

                requestBodyStream = new HttpProtocolBodyStream(null, stream, null, true);

                ContentTypeSerializer.Serialize(contentType, requestBodyStream, data);
                requestBodyStream.Flush();

                requestBodyStream.Dispose();
                requestBodyStream = null;

                //Response Header
                var headerPosition = 0;
                var headerLength   = 0;
                var headerEnd      = false;
                while (!headerEnd)
                {
                    if (headerLength == buffer.Length)
                    {
                        throw new Exception($"{nameof(HttpCQRSClient)} Header Too Long");
                    }

#if NETSTANDARD2_0
                    var bytesRead = stream.Read(bufferOwner, headerPosition, buffer.Length - headerPosition);
#else
                    var bytesRead = stream.Read(buffer.Span.Slice(headerPosition, buffer.Length - headerPosition));
#endif

                    if (bytesRead == 0)
                    {
                        throw new EndOfStreamException();
                    }
                    headerLength += bytesRead;

                    headerEnd = HttpCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                }
                var responseHeader = HttpCommon.ReadHeader(buffer, headerPosition, headerLength);

                //Response Body
                responseBodyStream = new HttpProtocolBodyStream(null, stream, responseHeader.BodyStartBuffer, false);

                if (responseHeader.IsError)
                {
                    var responseException = ContentTypeSerializer.DeserializeException(contentType, responseBodyStream);
                    throw responseException;
                }

                stopwatch.Stop();
                _ = Log.TraceAsync($"{nameof(HttpCQRSClient)} Query: {interfaceType.GetNiceName()}.{data.ProviderMethod} {stopwatch.ElapsedMilliseconds}");

                if (isStream)
                {
                    return((TReturn)(object)responseBodyStream);
                }
                else
                {
                    var model = ContentTypeSerializer.Deserialize <TReturn>(contentType, responseBodyStream);
                    responseBodyStream.Dispose();
                    client.Dispose();
                    return(model);
                }
            }
            catch
            {
                if (responseBodyStream != null)
                {
                    responseBodyStream.Dispose();
                }
                if (requestBodyStream != null)
                {
                    requestBodyStream.Dispose();
                }
                if (stream != null)
                {
                    stream.Dispose();
                }
                client.Dispose();
                throw;
            }
            finally
            {
                BufferArrayPool <byte> .Return(bufferOwner);
            }
        }
Ejemplo n.º 21
0
        public static HttpRequestHeader ReadHeader(ReadOnlyMemory <byte> buffer, int position, int length)
        {
#if NETSTANDARD2_0
            var chars       = encoding.GetChars(buffer.Span.Slice(0, position).ToArray());
            var charsLength = chars.Length;
#else
            var chars = BufferArrayPool <char> .Rent(encoding.GetMaxCharCount(position));

            try
            {
                var charsLength = encoding.GetChars(buffer.Span.Slice(0, position), chars.AsSpan());
#endif
            (var declarations, var headers) = ParseHeaders(chars.AsSpan().Slice(0, charsLength));

            if (declarations.Count == 0 || headers.Count == 0)
            {
                throw new Exception("Invalid Header");
            }

            var headerInfo = new HttpRequestHeader()
            {
                Declarations = declarations,
                Headers      = headers
            };

            headerInfo.IsError = declarations[0].StartsWith(serverErrorResponse);

            if (headers.TryGetValue(contentTypeHeader, out IList <string> contentTypeHeaderValue))
            {
                if (String.Equals(contentTypeHeaderValue[0], contentTypeBytes, StringComparison.InvariantCultureIgnoreCase))
                {
                    headerInfo.ContentType = ContentType.Bytes;
                }
                else if (String.Equals(contentTypeHeaderValue[0], contentTypeJson, StringComparison.InvariantCultureIgnoreCase))
                {
                    headerInfo.ContentType = ContentType.Json;
                }
                else if (String.Equals(contentTypeHeaderValue[0], contentTypeJsonNameless, StringComparison.InvariantCultureIgnoreCase))
                {
                    headerInfo.ContentType = ContentType.JsonNameless;
                }
                else
                {
                    throw new Exception("Invalid Header");
                }
            }

            if (headers.TryGetValue(contentLengthHeader, out IList <string> contentLengthHeaderValue))
            {
                if (int.TryParse(contentLengthHeaderValue[0], out int contentLengthHeaderValueParsed))
                {
                    headerInfo.ContentLength = contentLengthHeaderValueParsed;
                }
            }

            if (headers.TryGetValue(transferEncodingHeader, out IList <string> transferEncodingHeaderValue))
            {
                if (transferEncodingHeaderValue[0] == transferEncodingChunked)
                {
                    headerInfo.Chuncked = true;
                }
            }

            if (headers.TryGetValue(providerTypeHeader, out IList <string> providerTypeHeaderValue))
            {
                headerInfo.ProviderType = providerTypeHeaderValue[0];
            }

            if (headers.TryGetValue(originHeader, out IList <string> originHeaderValue))
            {
                headerInfo.Origin = originHeaderValue[0];
            }

            if (declarations.Count > 0 && declarations[0] == optionsHeader)
            {
                headerInfo.Preflight = true;
            }

            if (headers.TryGetValue(RelayServiceHeader, out IList <string> relayServiceHeaderValue))
            {
                if (relayServiceHeaderValue[0] == RelayServiceAdd)
                {
                    headerInfo.RelayServiceAddRemove = true;
                }
                else if (relayServiceHeaderValue[0] == RelayServiceRemove)
                {
                    headerInfo.RelayServiceAddRemove = false;
                }
            }

            if (headers.TryGetValue(RelayKeyHeader, out IList <string> relayKeyHeaderValue))
            {
                headerInfo.RelayKey = relayKeyHeaderValue[0];
            }

            headerInfo.BodyStartBuffer = buffer.Slice(position, length - position);

            return(headerInfo);

#if !NETSTANDARD2_0
        }

        finally
        {
            BufferArrayPool <char> .Return(chars);
        }
#endif
        }
Ejemplo n.º 22
0
        protected override async void Handle(TcpClient client, CancellationToken cancellationToken)
        {
            HttpRequestHeader requestHeader = null;
            bool responseStarted            = false;

            var bufferOwner = BufferArrayPool <byte> .Rent(HttpCommon.BufferLength);

            var    buffer             = bufferOwner.AsMemory();
            Stream stream             = null;
            Stream requestBodyStream  = null;
            Stream responseBodyStream = null;

            try
            {
                stream = client.GetStream();

                //Read Request Header
                //------------------------------------------------------------------------------------------------------------
                var headerPosition = 0;
                var headerLength   = 0;
                var headerEnd      = false;
                while (!headerEnd)
                {
                    if (headerLength == buffer.Length)
                    {
                        throw new Exception($"{nameof(HttpCQRSServer)} Header Too Long");
                    }

#if NETSTANDARD2_0
                    var bytesRead = await stream.ReadAsync(bufferOwner, headerLength, buffer.Length - headerLength, cancellationToken);
#else
                    var bytesRead = await stream.ReadAsync(buffer.Slice(headerLength, buffer.Length - headerLength), cancellationToken);
#endif

                    if (bytesRead == 0)
                    {
                        throw new EndOfStreamException();
                    }
                    headerLength += bytesRead;

                    headerEnd = HttpCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                }
                requestHeader = HttpCommon.ReadHeader(buffer, headerPosition, headerLength);

                if (contentType.HasValue && requestHeader.ContentType.HasValue && requestHeader.ContentType != contentType)
                {
                    _ = Log.ErrorAsync($"{nameof(HttpCQRSServer)} Received Invalid Content Type {requestHeader.ContentType}");
                    throw new Exception("Invalid Content Type");
                }

                if (requestHeader.Preflight)
                {
                    _ = Log.TraceAsync($"{nameof(HttpCQRSServer)} Received Preflight {client.Client.RemoteEndPoint}");

                    var preflightLength = HttpCommon.BufferPreflight(buffer, requestHeader.Origin);
#if NETSTANDARD2_0
                    await stream.WriteAsync(bufferOwner, 0, preflightLength, cancellationToken);
#else
                    await stream.WriteAsync(buffer.Slice(0, preflightLength), cancellationToken);
#endif

                    await stream.FlushAsync(cancellationToken);

                    return;
                }

                if (!requestHeader.ContentType.HasValue)
                {
                    _ = Log.ErrorAsync($"{nameof(HttpCQRSServer)} Received Invalid Content Type {requestHeader.ContentType}");
                    throw new Exception("Invalid Content Type");
                }

                _ = Log.TraceAsync($"{nameof(HttpCQRSServer)} Received On {client.Client.LocalEndPoint} From {client.Client.RemoteEndPoint} {requestHeader.ProviderType}");
                if (allowOrigins != null && allowOrigins.Length > 0)
                {
                    if (allowOrigins.Contains(requestHeader.Origin))
                    {
                        throw new Exception($"Origin Not Allowed {requestHeader.Origin}");
                    }
                }

                //Read Request Body
                //------------------------------------------------------------------------------------------------------------

                requestBodyStream = new HttpProtocolBodyStream(requestHeader.ContentLength, stream, requestHeader.BodyStartBuffer, true);

                var data = await ContentTypeSerializer.DeserializeAsync <CQRSRequestData>(requestHeader.ContentType.Value, requestBodyStream);

                if (data == null)
                {
                    throw new Exception("Empty request body");
                }

#if NETSTANDARD2_0
                requestBodyStream.Dispose();
#else
                await requestBodyStream.DisposeAsync();
#endif
                requestBodyStream = null;

                //Authroize
                //------------------------------------------------------------------------------------------------------------
                switch (networkType)
                {
                case NetworkType.Internal:
                    if (data.Claims != null)
                    {
                        var claimsIdentity = new ClaimsIdentity(data.Claims.Select(x => new Claim(x.Type, x.Value)), "CQRS");
                        Thread.CurrentPrincipal = new ClaimsPrincipal(claimsIdentity);
                    }
                    else
                    {
                        Thread.CurrentPrincipal = null;
                    }
                    break;

                case NetworkType.Api:
                    if (this.apiAuthorizer != null)
                    {
                        this.apiAuthorizer.Authorize(requestHeader);
                    }
                    break;

                default:
                    throw new NotImplementedException();
                }

                //Process and Respond
                //----------------------------------------------------------------------------------------------------
                if (!String.IsNullOrWhiteSpace(data.ProviderType))
                {
                    var providerType = Discovery.GetTypeFromName(data.ProviderType);
                    var typeDetail   = TypeAnalyzer.GetTypeDetail(providerType);

                    if (!this.interfaceTypes.Contains(providerType))
                    {
                        throw new Exception($"Unhandled Provider Type {providerType.FullName}");
                    }

                    bool exposed = typeDetail.Attributes.Any(x => x is ServiceExposedAttribute attribute && (!attribute.NetworkType.HasValue || attribute.NetworkType == networkType)) &&
                                   !typeDetail.Attributes.Any(x => x is ServiceBlockedAttribute attribute && (!attribute.NetworkType.HasValue || attribute.NetworkType == networkType));
                    if (!exposed)
                    {
                        throw new Exception($"Provider {data.MessageType} is not exposed to {networkType}");
                    }

                    _ = Log.TraceAsync($"Received Call: {providerType.GetNiceName()}.{data.ProviderMethod}");

                    var result = await this.providerHandlerAsync.Invoke(providerType, data.ProviderMethod, data.ProviderArguments);


                    //Response Header
                    var responseHeaderLength = HttpCommon.BufferHeader(buffer, requestHeader.ProviderType, contentType, requestHeader.Origin, null);
#if NETSTANDARD2_0
                    await stream.WriteAsync(bufferOwner, 0, responseHeaderLength);
#else
                    await stream.WriteAsync(buffer.Slice(0, responseHeaderLength));
#endif

                    //Response Body
                    responseBodyStream = new HttpProtocolBodyStream(null, stream, null, false);

                    int bytesRead;
                    if (result.Stream != null)
                    {
#if NETSTANDARD2_0
                        while ((bytesRead = await result.Stream.ReadAsync(bufferOwner, 0, bufferOwner.Length, cancellationToken)) > 0)
                        {
                            await responseBodyStream.WriteAsync(bufferOwner, 0, bytesRead, cancellationToken);
                        }
#else
                        while ((bytesRead = await result.Stream.ReadAsync(buffer, cancellationToken)) > 0)
                        {
                            await responseBodyStream.WriteAsync(buffer.Slice(0, bytesRead), cancellationToken);
                        }
#endif
                        await responseBodyStream.FlushAsync();

#if NETSTANDARD2_0
                        responseBodyStream.Dispose();
#else
                        await responseBodyStream.DisposeAsync();
#endif
                        client.Dispose();
                        return;
                    }
                    else
                    {
                        await ContentTypeSerializer.SerializeAsync(requestHeader.ContentType.Value, responseBodyStream, result.Model);

                        await responseBodyStream.FlushAsync();

#if NETSTANDARD2_0
                        responseBodyStream.Dispose();
#else
                        await responseBodyStream.DisposeAsync();
#endif
                        client.Dispose();
                        return;
                    }
                }
                else if (!String.IsNullOrWhiteSpace(data.MessageType))
                {
                    var commandType = Discovery.GetTypeFromName(data.MessageType);
                    var typeDetail  = TypeAnalyzer.GetTypeDetail(commandType);

                    if (!typeDetail.Interfaces.Contains(typeof(ICommand)))
                    {
                        throw new Exception($"Type {data.MessageType} is not a command");
                    }

                    bool exposed = typeDetail.Attributes.Any(x => x is ServiceExposedAttribute attribute && (!attribute.NetworkType.HasValue || attribute.NetworkType == networkType)) &&
                                   !typeDetail.Attributes.Any(x => x is ServiceBlockedAttribute attribute && (!attribute.NetworkType.HasValue || attribute.NetworkType == networkType));
                    if (!exposed)
                    {
                        throw new Exception($"Command {data.MessageType} is not exposed to {networkType}");
                    }

                    var command = (ICommand)System.Text.Json.JsonSerializer.Deserialize(data.MessageData, commandType);

                    if (data.MessageAwait)
                    {
                        await handlerAwaitAsync(command);
                    }
                    else
                    {
                        await handlerAsync(command);
                    }

                    //Response Header
                    var responseHeaderLength = HttpCommon.BufferHeader(buffer, requestHeader.ProviderType, contentType, requestHeader.Origin, null);
#if NETSTANDARD2_0
                    await stream.WriteAsync(bufferOwner, 0, responseHeaderLength, cancellationToken);
#else
                    await stream.WriteAsync(buffer.Slice(0, responseHeaderLength), cancellationToken);
#endif

                    //Response Body Empty
                    responseBodyStream = new HttpProtocolBodyStream(null, stream, null, false);
                    await responseBodyStream.FlushAsync(cancellationToken);

#if NETSTANDARD2_0
                    responseBodyStream.Dispose();
#else
                    await responseBodyStream.DisposeAsync();
#endif
                    client.Dispose();
                    return;
                }

                throw new Exception("Invalid Request");
            }
            catch (Exception ex)
            {
                if (ex is IOException ioException)
                {
                    if (ioException.InnerException != null && ioException.InnerException is SocketException socketException)
                    {
                        if (socketException.SocketErrorCode == SocketError.ConnectionAborted)
                        {
                            return;
                        }
                    }
                }

                _ = Log.ErrorAsync(null, ex);

                if (client.Connected && !responseStarted && requestHeader != null && requestHeader.ContentType.HasValue)
                {
                    try
                    {
                        //Response Header
                        var responseHeaderLength = HttpCommon.BufferErrorHeader(buffer, requestHeader.Origin);
#if NETSTANDARD2_0
                        await stream.WriteAsync(bufferOwner, 0, responseHeaderLength, cancellationToken);
#else
                        await stream.WriteAsync(buffer.Slice(0, responseHeaderLength), cancellationToken);
#endif

                        //Response Body
                        responseBodyStream = new HttpProtocolBodyStream(null, stream, null, false);
                        await ContentTypeSerializer.SerializeExceptionAsync(requestHeader.ContentType.Value, responseBodyStream, ex);

#if NETSTANDARD2_0
                        responseBodyStream.Dispose();
#else
                        await responseBodyStream.DisposeAsync();
#endif
                        client.Dispose();
                    }
                    catch (Exception ex2)
                    {
                        if (responseBodyStream != null)
                        {
#if NETSTANDARD2_0
                            responseBodyStream.Dispose();
#else
                            await responseBodyStream.DisposeAsync();
#endif
                        }
                        if (stream != null)
                        {
#if NETSTANDARD2_0
                            stream.Dispose();
#else
                            await stream.DisposeAsync();
#endif
                        }
                        client.Dispose();
                        _ = Log.ErrorAsync($"{nameof(HttpCQRSServer)} Error {client.Client.RemoteEndPoint}", ex2);
                    }
                    return;
                }

                if (responseBodyStream != null)
                {
#if NETSTANDARD2_0
                    responseBodyStream.Dispose();
#else
                    await responseBodyStream.DisposeAsync();
#endif
                }
                if (requestBodyStream != null)
                {
#if NETSTANDARD2_0
                    requestBodyStream.Dispose();
#else
                    await requestBodyStream.DisposeAsync();
#endif
                }
                if (stream != null)
                {
#if NETSTANDARD2_0
                    stream.Dispose();
#else
                    await stream.DisposeAsync();
#endif
                }
                client.Dispose();
            }
            finally
            {
                BufferArrayPool <byte> .Return(bufferOwner);
            }
        }
Ejemplo n.º 23
0
        public static unsafe TcpRequestHeader ReadHeader(ReadOnlyMemory <byte> buffer, int position, int length)
        {
#if NETSTANDARD2_0
            var chars       = encoding.GetChars(buffer.Span.Slice(0, position).ToArray());
            var charsLength = chars.Length;
#else
            var chars = BufferArrayPool <char> .Rent(encoding.GetMaxCharCount(position));

            try
            {
                var charsLength = encoding.GetChars(buffer.Span.Slice(0, position), chars.AsSpan());
#endif
            string prefix           = null;
            string providerType     = null;
            ContentType?contentType = null;

            int propertyIndex = 0;
            int startIndex    = 0;
            int indexLength   = 0;
            fixed(char *pChars = chars)
            {
                for (var index = 0; index < charsLength; index++)
                {
                    var c = pChars[index];
                    switch (c)
                    {
                    case headerSeperator:
                    case headerEnder:
                        switch (propertyIndex)
                        {
                        case 0:
                        {
                            prefix      = new String(pChars, startIndex, indexLength);
                            startIndex  = index + 1;
                            indexLength = 0;
                        }
                        break;

                        case 1:
                        {
                            providerType = new String(pChars, startIndex, indexLength);
                            startIndex   = index + 1;
                            indexLength  = 0;
                        }
                        break;

                        case 2:
                        {
                            var contentTypeString = new String(pChars, startIndex, indexLength);
                            if (Int32.TryParse(contentTypeString, out int contentTypeValue))
                            {
                                contentType = (ContentType)contentTypeValue;
                            }

                            startIndex  = index + 1;
                            indexLength = 0;
                        }
                        break;
                        }
                        propertyIndex++;
                        break;

                    default:
                        indexLength++;
                        break;
                    }
                }
            }

            if (propertyIndex != 3)
            {
                throw new Exception("Invalid Header");
            }

            var isError = prefix == protocolErrorPrefix;

            if (providerType == nullProviderType)
            {
                providerType = null;
            }

            return(new TcpRequestHeader()
            {
                BodyStartBuffer = buffer.Slice(position, length - position),
                IsError = isError,
                ContentType = contentType.Value,
                ProviderType = providerType
            });

#if !NETSTANDARD2_0
        }

        finally
        {
            BufferArrayPool <char> .Return(chars);
        }
#endif
        }