Beispiel #1
0
        private static Task WriteMessageCoreAsync(this PipeWriter pipeWriter, byte[] messageData, HttpContextServerCallContext serverCallContext, bool flush)
        {
            Debug.Assert(serverCallContext.ResponseGrpcEncoding != null);

            var isCompressed =
                serverCallContext.CanWriteCompressed() &&
                !string.Equals(serverCallContext.ResponseGrpcEncoding, GrpcProtocolConstants.IdentityGrpcEncoding, StringComparison.Ordinal);

            if (isCompressed)
            {
                messageData = GrpcProtocolHelpers.CompressMessage(
                    serverCallContext.ResponseGrpcEncoding,
                    serverCallContext.ServiceOptions.ResponseCompressionLevel,
                    serverCallContext.ServiceOptions.CompressionProviders,
                    messageData);
            }

            WriteHeader(pipeWriter, messageData.Length, isCompressed);
            pipeWriter.Write(messageData);

            if (flush)
            {
                serverCallContext.HasBufferedMessage = false;
                return(pipeWriter.FlushAsync().GetAsTask());
            }
            else
            {
                // Set flag so buffered message will be written at the end
                serverCallContext.HasBufferedMessage = true;
            }

            return(Task.CompletedTask);
        }
Beispiel #2
0
        private static Task WriteMessageCoreAsync(this PipeWriter pipeWriter, byte[] messageData, HttpContextServerCallContext serverCallContext, bool flush)
        {
            Debug.Assert(serverCallContext.ResponseGrpcEncoding != null);

            var isCompressed =
                serverCallContext.CanWriteCompressed() &&
                !string.Equals(serverCallContext.ResponseGrpcEncoding, GrpcProtocolConstants.IdentityGrpcEncoding, StringComparison.Ordinal);

            if (isCompressed)
            {
                messageData = GrpcProtocolHelpers.CompressMessage(
                    serverCallContext.ResponseGrpcEncoding,
                    serverCallContext.ServiceOptions.ResponseCompressionLevel,
                    serverCallContext.ServiceOptions.CompressionProviders,
                    messageData);
            }

            WriteHeader(pipeWriter, messageData.Length, isCompressed);
            pipeWriter.Write(messageData);

            if (flush)
            {
                var valueTask = pipeWriter.FlushAsync();

                if (valueTask.IsCompletedSuccessfully)
                {
                    // We do this to reset the underlying value task (which happens in GetResult())
                    valueTask.GetAwaiter().GetResult();
                    return(Task.CompletedTask);
                }

                return(valueTask.AsTask());
            }

            return(Task.CompletedTask);
        }
Beispiel #3
0
        public static async Task WriteMessageAsync <TResponse>(this PipeWriter pipeWriter, TResponse response, HttpContextServerCallContext serverCallContext, Action <TResponse, SerializationContext> serializer, bool canFlush)
        {
            var logger = serverCallContext.Logger;

            try
            {
                Log.SendingMessage(logger);

                var serializationContext = serverCallContext.SerializationContext;
                serializer(response, serializationContext);
                var responsePayload = serializationContext.Payload;
                serializationContext.Payload = null;

                if (responsePayload == null)
                {
                    throw new InvalidOperationException("Serialization did not return a payload.");
                }

                Log.SerializedMessage(serverCallContext.Logger, typeof(TResponse), responsePayload.Length);

                // Must call StartAsync before the first pipeWriter.GetSpan() in WriteHeader
                var httpResponse = serverCallContext.HttpContext.Response;
                if (!httpResponse.HasStarted)
                {
                    await httpResponse.StartAsync();
                }

                var isCompressed =
                    serverCallContext.CanWriteCompressed() &&
                    !string.Equals(serverCallContext.ResponseGrpcEncoding, GrpcProtocolConstants.IdentityGrpcEncoding, StringComparison.Ordinal);

                if (isCompressed)
                {
                    responsePayload = CompressMessage(
                        serverCallContext.Logger,
                        serverCallContext.ResponseGrpcEncoding !,
                        serverCallContext.ServiceOptions.ResponseCompressionLevel,
                        serverCallContext.ServiceOptions.CompressionProviders,
                        responsePayload);
                }

                if (responsePayload.Length > serverCallContext.ServiceOptions.SendMaxMessageSize)
                {
                    throw new RpcException(SendingMessageExceedsLimitStatus);
                }

                WriteHeader(pipeWriter, responsePayload.Length, isCompressed);
                pipeWriter.Write(responsePayload);

                // Flush messages unless WriteOptions.Flags has BufferHint set
                var flush = canFlush && ((serverCallContext.WriteOptions?.Flags ?? default) & WriteFlags.BufferHint) != WriteFlags.BufferHint;

                if (flush)
                {
                    serverCallContext.HasBufferedMessage = false;
                    await pipeWriter.FlushAsync();
                }
                else
                {
                    // Set flag so buffered message will be written at the end
                    serverCallContext.HasBufferedMessage = true;
                }

                Log.MessageSent(serverCallContext.Logger);
                GrpcEventSource.Log.MessageSent();
            }
            catch (Exception ex)
            {
                Log.ErrorSendingMessage(logger, ex);
                throw;
            }
        }