System.Net.WebSockets.WebSocketHandle.ReadResponseHeaderLineAsync C# (CSharp) Method

ReadResponseHeaderLineAsync() private static method

Reads a line from the stream.
private static ReadResponseHeaderLineAsync ( System.Stream stream, CancellationToken cancellationToken ) : Task
stream System.Stream The stream from which to read.
cancellationToken System.Threading.CancellationToken The CancellationToken used to cancel the websocket.
return Task
        private static async Task<string> ReadResponseHeaderLineAsync(Stream stream, CancellationToken cancellationToken)
        {
            StringBuilder sb = t_cachedStringBuilder;
            if (sb != null)
            {
                t_cachedStringBuilder = null;
                Debug.Assert(sb.Length == 0, $"Expected empty StringBuilder");
            }
            else
            {
                sb = new StringBuilder();
            }

            var arr = new byte[1];
            char prevChar = '\0';
            try
            {
                // TODO: Reading one byte is extremely inefficient.  The problem, however,
                // is that if we read multiple bytes, we could end up reading bytes post-headers
                // that are part of messages meant to be read by the managed websocket after
                // the connection.  The likely solution here is to wrap the stream in a BufferedStream,
                // though a) that comes at the expense of an extra set of virtual calls, b) 
                // it adds a buffer when the managed websocket will already be using a buffer, and
                // c) it's not exposed on the version of the System.IO contract we're currently using.
                while (await stream.ReadAsync(arr, 0, 1, cancellationToken).ConfigureAwait(false) == 1)
                {
                    // Process the next char
                    char curChar = (char)arr[0];
                    if (prevChar == '\r' && curChar == '\n')
                    {
                        break;
                    }
                    sb.Append(curChar);
                    prevChar = curChar;
                }

                if (sb.Length > 0 && sb[sb.Length - 1] == '\r')
                {
                    sb.Length = sb.Length - 1;
                }

                return sb.ToString();
            }
            finally
            {
                sb.Clear();
                t_cachedStringBuilder = sb;
            }
        }
    }