コード例 #1
0
        private async Task OpenConnection(IDuplexPipe application, Uri url, TaskCompletionSource <object> startTcs, CancellationToken cancellationToken)
        {
            Log.StartReceive(_logger);

            var request = new HttpRequestMessage(HttpMethod.Get, url);

            SendUtils.PrepareHttpRequest(request, _httpOptions);
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream"));

            HttpResponseMessage response;

            try
            {
                response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);

                response.EnsureSuccessStatusCode();
                startTcs.TrySetResult(null);
            }
            catch (Exception ex)
            {
                Log.TransportStopping(_logger);
                startTcs.TrySetException(ex);
                return;
            }

            using (var stream = await response.Content.ReadAsStreamAsync())
            {
                var pipeOptions    = new PipeOptions(pauseWriterThreshold: 0, resumeWriterThreshold: 0);
                var pipelineReader = StreamPipeConnection.CreateReader(pipeOptions, stream);
                var readCancellationRegistration = cancellationToken.Register(
                    reader => ((PipeReader)reader).CancelPendingRead(), pipelineReader);
                try
                {
                    while (true)
                    {
                        var result = await pipelineReader.ReadAsync();

                        var input = result.Buffer;
                        if (result.IsCanceled || (input.IsEmpty && result.IsCompleted))
                        {
                            Log.EventStreamEnded(_logger);
                            break;
                        }

                        var consumed = input.Start;
                        var examined = input.End;
                        try
                        {
                            Log.ParsingSSE(_logger, input.Length);
                            var parseResult = _parser.ParseMessage(input, out consumed, out examined, out var buffer);

                            switch (parseResult)
                            {
                            case ServerSentEventsMessageParser.ParseResult.Completed:
                                Log.MessageToApp(_logger, buffer.Length);
                                await _application.Output.WriteAsync(buffer);

                                _parser.Reset();
                                break;

                            case ServerSentEventsMessageParser.ParseResult.Incomplete:
                                if (result.IsCompleted)
                                {
                                    throw new FormatException("Incomplete message.");
                                }
                                break;
                            }
                        }
                        finally
                        {
                            pipelineReader.AdvanceTo(consumed, examined);
                        }
                    }
                }
                catch (OperationCanceledException)
                {
                    Log.ReceiveCanceled(_logger);
                }
                finally
                {
                    readCancellationRegistration.Dispose();
                    _transportCts.Cancel();
                    Log.ReceiveStopped(_logger);
                }
            }
        }
コード例 #2
0
        private async Task OpenConnection(Channel <byte[], SendMessage> application, Uri url, CancellationToken cancellationToken)
        {
            _logger.StartReceive();

            var request = new HttpRequestMessage(HttpMethod.Get, url);

            SendUtils.PrepareHttpRequest(request, _httpOptions);
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream"));
            var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);

            var stream = await response.Content.ReadAsStreamAsync();

            var pipelineReader = StreamPipeConnection.CreateReader(new PipeOptions(_memoryPool), stream);
            var readCancellationRegistration = cancellationToken.Register(
                reader => ((IPipeReader)reader).CancelPendingRead(), pipelineReader);

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

                    var input = result.Buffer;
                    if (result.IsCancelled || (input.IsEmpty && result.IsCompleted))
                    {
                        _logger.EventStreamEnded();
                        break;
                    }

                    var consumed = input.Start;
                    var examined = input.End;

                    try
                    {
                        var parseResult = _parser.ParseMessage(input, out consumed, out examined, out var buffer);

                        switch (parseResult)
                        {
                        case ServerSentEventsMessageParser.ParseResult.Completed:
                            _application.Writer.TryWrite(buffer);
                            _parser.Reset();
                            break;

                        case ServerSentEventsMessageParser.ParseResult.Incomplete:
                            if (result.IsCompleted)
                            {
                                throw new FormatException("Incomplete message.");
                            }
                            break;
                        }
                    }
                    finally
                    {
                        pipelineReader.Advance(consumed, examined);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                _logger.ReceiveCanceled();
            }
            finally
            {
                readCancellationRegistration.Dispose();
                _transportCts.Cancel();
                stream.Dispose();
                _logger.ReceiveStopped();
            }
        }