public override void Complete() { switch (_state) { case InternalState.IncompleteBufferWriter: _state = InternalState.CompleteBufferWriter; if (!DirectSerializationSupported) { Debug.Assert(_bufferWriter != null, "Buffer writer has been set to get to this state."); var data = _bufferWriter.WrittenSpan; GrpcServerLog.SerializedMessage(_serverCallContext.Logger, typeof(object), data.Length); WriteMessage(data); } else { GrpcServerLog.SerializedMessage(_serverCallContext.Logger, _serverCallContext.ResponseType, _payloadLength.GetValueOrDefault()); } break; default: ThrowInvalidState(_state); break; } }
public override void Complete(byte[] payload) { switch (_state) { case InternalState.Initialized: _state = InternalState.CompleteArray; GrpcServerLog.SerializedMessage(_serverCallContext.Logger, _serverCallContext.ResponseType, payload.Length); WriteMessage(payload); break; default: ThrowInvalidState(_state); break; } }
public static async Task WriteMessageAsync <TResponse>(this PipeWriter pipeWriter, TResponse response, HttpContextServerCallContext serverCallContext, Action <TResponse, SerializationContext> serializer, bool canFlush) where TResponse : class { var logger = serverCallContext.Logger; try { GrpcServerLog.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."); } GrpcServerLog.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 canCompress = GrpcProtocolHelpers.CanWriteCompressed(serverCallContext.WriteOptions) && !string.Equals(serverCallContext.ResponseGrpcEncoding, GrpcProtocolConstants.IdentityGrpcEncoding, StringComparison.Ordinal); var isCompressed = false; if (canCompress) { Debug.Assert( serverCallContext.ServiceOptions.ResolvedCompressionProviders != null, "Compression providers should have been resolved for service."); if (TryCompressMessage( serverCallContext.Logger, serverCallContext.ResponseGrpcEncoding !, serverCallContext.ServiceOptions.ResponseCompressionLevel, serverCallContext.ServiceOptions.ResolvedCompressionProviders, responsePayload, out var result)) { responsePayload = result; isCompressed = true; } } if (responsePayload.Length > serverCallContext.ServiceOptions.MaxSendMessageSize) { 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; } GrpcServerLog.MessageSent(serverCallContext.Logger); GrpcEventSource.Log.MessageSent(); } catch (Exception ex) { GrpcServerLog.ErrorSendingMessage(logger, ex); throw; } }