private async Task StartReceiving()

in src/Microsoft.Azure.SignalR.Common/ServiceConnections/Internal/WebSocketsTransport.cs [266:344]


    private async Task StartReceiving(ClientWebSocket socket)
    {
        try
        {
            while (true)
            {
#if NETCOREAPP
                // Do a 0 byte read so that idle connections don't allocate a buffer when waiting for a read
                var result = await socket.ReceiveAsync(Memory<byte>.Empty, CancellationToken.None);

                if (result.MessageType == WebSocketMessageType.Close)
                {
                    Log.WebSocketClosed(_logger, _webSocket.CloseStatus);

                    if (_webSocket.CloseStatus != WebSocketCloseStatus.NormalClosure)
                    {
                        throw new InvalidOperationException($"Websocket closed with error: {_webSocket.CloseStatus}.");
                    }

                    return;
                }
#endif
                var memory = _application.Output.GetMemory(2048);
#if NETCOREAPP
                // Because we checked the CloseStatus from the 0 byte read above, we don't need to check again after reading
                var receiveResult = await socket.ReceiveAsync(memory, CancellationToken.None);
#else
                var isArray = MemoryMarshal.TryGetArray<byte>(memory, out var arraySegment);
                Debug.Assert(isArray);

                // Exceptions are handled above where the send and receive tasks are being run.
                var receiveResult = await socket.ReceiveAsync(arraySegment, CancellationToken.None);
#endif
                // Need to check again for netstandard2.1 because a close can happen between a 0-byte read and the actual read
                if (receiveResult.MessageType == WebSocketMessageType.Close)
                {
                    Log.WebSocketClosed(_logger, _webSocket.CloseStatus);

                    if (_webSocket.CloseStatus != WebSocketCloseStatus.NormalClosure)
                    {
                        throw new InvalidOperationException($"Websocket closed with error: {_webSocket.CloseStatus}.");
                    }

                    return;
                }

                Log.MessageReceived(_logger, receiveResult.MessageType, receiveResult.Count, receiveResult.EndOfMessage);

                _application.Output.Advance(receiveResult.Count);

                var flushResult = await _application.Output.FlushAsync();

                // We canceled in the middle of applying back pressure
                // or if the consumer is done
                if (flushResult.IsCanceled || flushResult.IsCompleted)
                {
                    break;
                }
            }
        }
        catch (OperationCanceledException)
        {
            Log.ReceiveCanceled(_logger);
        }
        catch (Exception ex)
        {
            if (!_aborted)
            {
                _application.Output.Complete(ex);
            }
        }
        finally
        {
            // We're done writing
            _application.Output.Complete();

            Log.ReceiveStopped(_logger);
        }
    }