/// <summary> /// Gets the <see cref="RpcResult"/> content of this message or throws an exception, if it /// is no valid message of this type. /// <see cref="IsRpcResult"/> can be called before to find out the type of this message. /// </summary> public RpcResult DecodeRpcResult() { if (false == IsRpcResult()) { throw new FormatException("Header wrong"); } try { int pos = 2; var ret = new RpcResult(); // ID ret.MethodID = BitConverter.ToUInt64(Data, pos); pos += 8; // Success or failure bool isSuccess = Data[pos++] == (byte)'S'; if (isSuccess) { // Successful int returnValueLength = BitConverter.ToInt32(Data, pos); pos += 4; if (returnValueLength > 0) { ret.ReturnValue = new ArraySegment <byte>(Data, pos, returnValueLength).ToArray(); pos += returnValueLength; } } else { // Failure ret.Failure = new RpcFailure(); // Failure type int failureTypeEnd = Array.FindIndex(Data, pos, it => it == (byte)';'); if (failureTypeEnd == -1) { throw new FormatException("FailureType end not found"); } ret.Failure.Type = Enum.Parse <RpcFailureType>( Encoding.UTF8.GetString(Data, pos, failureTypeEnd - pos)); pos = failureTypeEnd + 1; // Message int messageLength = BitConverter.ToInt32(Data, pos); pos += 4; if (messageLength > 0) { ret.Failure.Message = Encoding.UTF8.GetString(Data, pos, messageLength); pos += messageLength; } } return(ret); } catch (Exception ex) { throw new FormatException("Content wrong: " + ex.Message, ex); } }
/// <summary> /// Call this method as soon as a result was received for this call. /// </summary> public void Finish(RpcResult result) => completionHelper.TrySetResult(result);
/// <summary> /// Encodes the given RPC result to a RPC message. /// </summary> public static RpcMessage Encode(RpcResult result) { int length = 2 /* Header */ + 8 /* ID */ + 1 /* Success/Failure */; byte[]? failureType = null; int failureMessageLength = 0; byte[]? failureMessage = null; int returnValueLength = result.ReturnValue?.Length ?? 0; if (result.Failure == null) { // Successful length += 4 + returnValueLength; /* Length and data */ } else { // Failure failureType = Encoding.UTF8.GetBytes("" + result.Failure.Type); failureMessageLength = result.Failure.Message?.Length ?? 0; if (failureMessageLength > 0) { failureMessage = Encoding.UTF8.GetBytes(result.Failure.Message !); } length += failureType.Length + 1 /* ";" */ + 4 + failureMessageLength; } byte[] data = new byte[length]; int pos = 0; data[pos++] = (byte)'1'; // Header data[pos++] = (byte)'R'; Array.Copy(BitConverter.GetBytes(result.MethodID), 0, data, pos, 8); // ID pos += 8; // Success or failure if (result.Failure == null) { // Successful data[pos++] = (byte)'S'; Array.Copy(BitConverter.GetBytes(returnValueLength), 0, data, pos, 4); // Return value length pos += 4; if (returnValueLength > 0) { Array.Copy(result.ReturnValue !, 0, data, pos, returnValueLength); // Return value data pos += returnValueLength; } } else { // Failure data[pos++] = (byte)'F'; Array.Copy(failureType !, 0, data, pos, failureType !.Length); // Failure type pos += failureType !.Length; data[pos++] = (byte)';'; Array.Copy(BitConverter.GetBytes(failureMessageLength), 0, data, pos, 4); // Failure message length pos += 4; if (failureMessageLength > 0) { Array.Copy(failureMessage !, 0, data, pos, failureMessageLength); // Failure message pos += failureMessageLength; } } return(new RpcMessage { Data = data }); }