public static InternalPacket ProtoDeserialize(byte[] data, int pos, int size) { InternalPacket ret = new InternalPacket(); PacketProto protoPacket = new PacketProto(); MemoryStream ms = new MemoryStream(data, pos, size); protoPacket.MergeFrom(ms); ret.MsgId = protoPacket.MsgId; ret.FullMethodName = protoPacket.FullMethodName; ret.Options = protoPacket.Options; if (protoPacket.DataTypeCase == PacketProto.DataTypeOneofCase.Payload) { ret.Payload = protoPacket.Payload.Data.ToByteArray(); int payloadSize = protoPacket.Payload.Size; if (payloadSize < 0 || payloadSize > ms.Length || ret.Payload.Length != payloadSize) { throw new InvalidDataException("Pacote inválido: tamanho de payload inválido"); } } if (protoPacket.DataTypeCase == PacketProto.DataTypeOneofCase.Exception) { ret.Exception = RpcExceptionFactory.CreateFrom(protoPacket.Exception); } return(ret); }
/// <summary> /// Encerra o RPC conforme o resultado da finalização da task de entrada. /// Caso a task tenha sido encerrada com sucesso, o RPC é desconectado com o envio do /// valor de retorno da task, encerrando as chamadas remotas com sucesso usando o valor /// de retorno em questão. /// Caso a task tenha sido encerrada com erro, um erro RpcException é enviado /// para o ponto remoto, encerrando as chamadas remotas com erro. /// Em qualquer caso, as chamadas locais são canceladas/encerradas por desconexão. /// </summary> /// <param name="taskSend">Task de processamento do retorno do RPC</param> public void Close(Task <TSend> taskSend) { if (m_State != StreamState.Open) { return; } m_State = StreamState.Closed; InternalPacket packet; if (taskSend.IsFaulted || taskSend.IsCanceled) { var rpcException = RpcExceptionFactory.CreateFrom(taskSend.Exception); packet = PacketFactory.NewPacket(m_MsgId, P_OPTIONS_RPC_ERROR, rpcException); } else { var data = taskSend.Result; packet = PacketFactory.NewPacket(m_MsgId, P_OPTIONS_RPC_RETURN, m_Method.RequestMarshaller, data); } m_Session.TrySend(packet); m_ReturnValueTcs.TrySetCanceled(); Finish(); }
/// <summary> /// Cancela o RPC atual. /// As chamadas locais pendentes são canceladas/encerradas por desconexão. /// As chamadas remotas pendentes são canceladas caso ainda conectado. /// </summary> public void Cancel() { if (m_State == StreamState.Open) { m_State = StreamState.Canceled; var rpcException = RpcExceptionFactory.Create(StatusCode.Cancelled, "A operação foi cancelada."); var packet = PacketFactory.NewPacket(m_MsgId, P_OPTIONS_RPC_ERROR, rpcException); m_Session.Send(packet); m_ReturnValueTcs.TrySetCanceled(); Finish(); } }
// --------------------------------- // ----- PAYLOAD IS TASKRESULT ----- // --------------------------------- public static Task <InternalPacket> NewPacket <TSend>(int msgId, Marshaller <TSend> marshaller, Task <TSend> taskResult) { GrpcPreconditions.CheckNotNull(marshaller, nameof(marshaller)); GrpcPreconditions.CheckNotNull(taskResult, nameof(taskResult)); return(taskResult.ContinueWith((tResult) => { if (taskResult.IsFaulted) { var rpcException = RpcExceptionFactory.CreateFrom(taskResult.Exception); return NewInternalPacket(msgId, P_DEFAULT_OPTIONS, null, rpcException); } if (taskResult.IsCanceled) { return null; } return NewInternalPacket(msgId, P_DEFAULT_OPTIONS, null, marshaller, taskResult.Result); })); }
/// <summary> /// Encerra o RPC conforme o resultado da finalização da task de entrada. /// Caso a task tenha sido encerrada com sucesso, o RPC é desconectado sem o envio de /// um valor de retorno, encerrando as chamadas remotas por desconexão (close). /// Caso a task tenha sido encerrada com erro, um erro RpcException é enviado /// para o ponto remoto, encerrando as chamadas remotas com erro. /// Em qualquer caso, as chamadas locais são canceladas/encerradas por desconexão. /// </summary> /// <param name="taskSend">Task de processamento do retorno do RPC</param> public void Close(Task taskSend) { if (m_State != StreamState.Open) { return; } m_State = StreamState.Closed; InternalPacket packet; Exception ex = null; if (taskSend.IsFaulted) { ex = taskSend.Exception; } else if (taskSend.IsCanceled) { ex = new OperationCanceledException(); } if (taskSend.IsFaulted || taskSend.IsCanceled) { // Failed return var rpcException = RpcExceptionFactory.CreateFrom(ex); packet = PacketFactory.NewPacket(m_MsgId, P_OPTIONS_RPC_ERROR, rpcException); } else { // Normal return packet = PacketFactory.NewPacket(m_MsgId, P_OPTIONS_RPC_CLOSE); } m_Session.TrySend(packet); m_ReturnValueTcs.TrySetCanceled(); Finish(); }