示例#1
0
 /// <summary>
 /// Disposes the socket dependencies.
 /// </summary>
 public virtual void Dispose()
 {
     Socket?.Close();
     SslStream?.Close();
     CancellationTokenSourceManager?.Dispose();
     IsDisposed = true;
 }
示例#2
0
        private static async Task DecodeContentLengthAsync(this SslStream sslStream, StringBuilder placeHolder, Memory <byte> buffer, string bufferString,
                                                           int readTimeout, CancellationTokenSourceManager timeoutCancellationTokenSourceWrapper)
        {
            var(contentLength, totalBytesRead) = ExtractContentLength(placeHolder, bufferString);

            while (totalBytesRead < contentLength)
            {
                var innerBytesRead = await sslStream.ReadAsync(buffer, readTimeout, timeoutCancellationTokenSourceWrapper);

                if (innerBytesRead == 0)
                {
                    throw new ProxyException("Stream ended without reaching expected limit.");
                }

                totalBytesRead += innerBytesRead;
                placeHolder.Append(Encoding.ASCII.GetString(buffer.Span.Slice(0, innerBytesRead)));
            }
        }
示例#3
0
        private static async Task DecodeChunkedAsync(this SslStream sslStream, StringBuilder placeHolder, Memory <byte> buffer, string bufferString,
                                                     int readTimeout, CancellationTokenSourceManager timeoutCancellationTokenSourceWrapper)
        {
            var splitBuffer = bufferString.Split(new[] { RequestConstants.CONTENT_SEPERATOR }, 2, StringSplitOptions.RemoveEmptyEntries);

            if (splitBuffer.Length == 1)
            {
                var peekBytesRead = await sslStream.ReadAsync(buffer.Slice(0, PeekBufferSize), readTimeout, timeoutCancellationTokenSourceWrapper);

                bufferString = Encoding.ASCII.GetString(buffer.Span.Slice(0, peekBytesRead));
                placeHolder.Append(bufferString);
            }
            else
            {
                bufferString = splitBuffer[1];
            }

            var(chunkSize, totalBytesRead) = ExtractChunkSize(bufferString);

            while (chunkSize != 0)
            {
                while (totalBytesRead < chunkSize)
                {
                    var remainingReadSize = chunkSize - totalBytesRead;
                    var readSize          = remainingReadSize > BufferSize ? BufferSize : remainingReadSize;

                    var innerBytesRead = await sslStream.ReadAsync(buffer.Slice(0, readSize), readTimeout, timeoutCancellationTokenSourceWrapper);

                    if (innerBytesRead == 0)
                    {
                        throw new ProxyException("Stream ended without reaching expected limit.");
                    }

                    totalBytesRead += innerBytesRead;
                    placeHolder.Append(Encoding.ASCII.GetString(buffer.Span.Slice(0, innerBytesRead)));
                }

                var peekBytesRead = await sslStream.ReadAsync(buffer.Slice(0, PeekBufferSize), readTimeout, timeoutCancellationTokenSourceWrapper);

                bufferString = Encoding.ASCII.GetString(buffer.Span.Slice(0, peekBytesRead));

                (chunkSize, totalBytesRead) = ExtractChunkSize(bufferString);
            }
        }
示例#4
0
        /// <summary>
        /// Asynchronously receives the response from the destination server.
        /// </summary>
        /// <param name="socket">Underlying socket.</param>
        /// <param name="readTimeout">Socket Read Timeout.</param>
        /// <param name="cancellationTokenSourceManager">Cancellation Token Source manager.</param>
        /// <returns>The raw response and the time to first byte</returns>
        public static async Task <(string response, float firstByteTime)> ReceiveAllAsync(this Socket socket, int readTimeout, CancellationTokenSourceManager cancellationTokenSourceManager)
        {
            var buffer      = new byte[BufferSize].AsMemory();
            var placeHolder = new StringBuilder();
            var bytesRead   = 0;

            var firstByteTime = await TimingHelper.MeasureAsync(async() =>
            {
                bytesRead = await socket.ReceiveAsync(buffer, readTimeout, cancellationTokenSourceManager);
            });

            if (bytesRead == 0)
            {
                throw new ProxyException("Destination Server has no data to send.");
            }

            var bufferString = Encoding.ASCII.GetString(buffer.Span.Slice(0, bytesRead));

            placeHolder.Append(bufferString);

            while (!bufferString.Contains(RequestConstants.CONTENT_SEPERATOR))
            {
                bytesRead = await socket.ReceiveAsync(buffer, readTimeout, cancellationTokenSourceManager);

                if (bytesRead == 0)
                {
                    return(placeHolder.ToString(), firstByteTime);
                }

                bufferString = Encoding.ASCII.GetString(buffer.Span.Slice(0, bytesRead));
                placeHolder.Append(bufferString);
            }

            var readString = placeHolder.ToString();

            if (readString.Contains(RequestConstants.CONTENT_LENGTH_HEADER))
            {
                await socket.DecodeContentLengthAsync(placeHolder, buffer, bufferString, readTimeout, cancellationTokenSourceManager);
            }
            else if (readString.Contains(RequestConstants.TRANSFER_ENCODING_CHUNKED_HEADER))
            {
                await socket.DecodeChunkedAsync(placeHolder, buffer, bufferString, readTimeout, cancellationTokenSourceManager);
            }
            else
            {
                throw new ProxyException("Unknown Transfer Encoding provided by Destination Server.");
            }

            return(placeHolder.ToString(), firstByteTime);
        }
示例#5
0
        /// <summary>
        /// Asynchronously reads data from the Destination Server through an SSL connection given a read timeout.
        /// </summary>
        /// <param name="sslStream">Underlying SSL Stream.</param>
        /// <param name="buffer">Read byte buffer.</param>
        /// <param name="readTimeout">Socket Read Timeout.</param>
        /// <param name="cancellationTokenSourceManager">Cancellation Token Source manager.</param>
        /// <returns>Number of read bytes</returns>
        public static async ValueTask <int> ReadAsync(this SslStream sslStream, Memory <byte> buffer, int readTimeout, CancellationTokenSourceManager cancellationTokenSourceManager)
        {
            cancellationTokenSourceManager.Start(readTimeout);

            var readBytes = await sslStream.ReadAsync(buffer, cancellationTokenSourceManager.Token);

            cancellationTokenSourceManager.Stop();

            return(readBytes);
        }
示例#6
0
        /// <summary>
        /// Asynchronously sends data to the Destination Server through an SSL connection given a write timeout.
        /// </summary>
        /// <param name="sslStream">Underlying SSL Stream.</param>
        /// <param name="buffer">Send request byte buffer.</param>
        /// <param name="writeTimeout">Socket Write Timeout.</param>
        /// <param name="cancellationTokenSourceManager">Cancellation Token Source manager.</param>
        public static async ValueTask WriteAsync(this SslStream sslStream, ReadOnlyMemory <byte> buffer, int writeTimeout, CancellationTokenSourceManager cancellationTokenSourceManager)
        {
            cancellationTokenSourceManager.Start(writeTimeout);

            await sslStream.WriteAsync(buffer, cancellationTokenSourceManager.Token);

            cancellationTokenSourceManager.Stop();
        }
示例#7
0
        /// <summary>
        /// Asynchronously reads data from the Destination Server given a read timeout.
        /// </summary>
        /// <param name="socket">Underlying socket.</param>
        /// <param name="buffer">Read byte buffer.</param>
        /// <param name="readTimeout">Socket Read Timeout.</param>
        /// <param name="cancellationTokenSourceManager">Cancellation Token Source manager.</param>
        /// <returns>Number of read bytes</returns>
        public static async ValueTask <int> ReceiveAsync(this Socket socket, Memory <byte> buffer, int readTimeout, CancellationTokenSourceManager cancellationTokenSourceManager)
        {
            cancellationTokenSourceManager.Start(readTimeout);

            var readBytes = await socket.ReceiveAsync(buffer, SocketFlags.None, cancellationTokenSourceManager.Token);

            cancellationTokenSourceManager.Stop();

            return(readBytes);
        }
示例#8
0
        /// <summary>
        /// Asynchronously sends data to the Destination Server given a write timeout.
        /// </summary>
        /// <param name="socket">Underlying socket.</param>
        /// <param name="buffer">Send request byte buffer.</param>
        /// <param name="writeTimeout">Socket Write Timeout.</param>
        /// <param name="cancellationTokenSourceManager">Cancellation Token Source manager.</param>
        /// <returns>Number of sent bytes</returns>
        public static async ValueTask <int> SendAsync(this Socket socket, ReadOnlyMemory <byte> buffer, int writeTimeout, CancellationTokenSourceManager cancellationTokenSourceManager)
        {
            cancellationTokenSourceManager.Start(writeTimeout);

            var sentBytes = await socket.SendAsync(buffer, SocketFlags.None, cancellationTokenSourceManager.Token);

            cancellationTokenSourceManager.Stop();

            return(sentBytes);
        }
示例#9
0
        /// <summary>
        /// Asynchronously Connects to the Destination Server given a connect timeout.
        /// </summary>
        /// <param name="socket">Underlying socket.</param>
        /// <param name="host">Destination Host.</param>
        /// <param name="port">Destination Port.</param>
        /// <param name="connectTimeout">Socket Connect Timeout.</param>
        /// <param name="cancellationTokenSourceManager">Cancellation Token Source manager.</param>
        public static async ValueTask ConnectAsync(this Socket socket, string host, int port, int connectTimeout, CancellationTokenSourceManager cancellationTokenSourceManager)
        {
            cancellationTokenSourceManager.Start(connectTimeout);

            await socket.ConnectAsync(host, port, cancellationTokenSourceManager.Token);

            cancellationTokenSourceManager.Stop();
        }
示例#10
0
        /// <summary>
        /// Executes the task provided with a specific timeout value.
        /// </summary>
        /// <typeparam name="T">Task Type.</typeparam>
        /// <param name="task">The task to apply timeout on.</param>
        /// <param name="client">The Proxy Client firing the task.</param>
        /// <param name="totalTimeout">Total Request Timeout in ms.</param>
        /// <param name="cancellationTokenSourceManager">Cancellation Token Source manager.</param>
        /// <returns>Current task result if it completes within the specified timeout, or TimeoutException if it times out.</returns>
        public static async Task <T> ExecuteTaskWithTimeout <T>(this Task <T> task, BaseProxyClient client, int totalTimeout, CancellationTokenSourceManager cancellationTokenSourceManager)
        {
            if (await Task.WhenAny(task, Task.Delay(totalTimeout)) == task)
            {
                if (task.IsFaulted)
                {
                    throw task.Exception.InnerException;
                }

                return(task.Result);
            }
            else
            {
                cancellationTokenSourceManager?.Cancel();
                client.IsFaulted = true;

                throw new TimeoutException();
            }
        }