public override Result <ProcessedPayload> Encode(IPayload payload, DecodingContext context) { var options = context.ChannelOptions; var currentPayload = new ProcessedPayload(payload); if (IsEmpty(payload.Data) || IsEncrypted(currentPayload)) { return(Result.Ok(new ProcessedPayload(currentPayload))); } if (options.Encrypted == false) { return(Result.Ok(new ProcessedPayload(currentPayload))); } if (currentPayload.Data is string data) { currentPayload.Data = data.GetBytes(); currentPayload.Encoding = AddEncoding(payload, "utf-8"); } var cipher = Crypto.GetCipher(options.CipherParams); var result = new ProcessedPayload( cipher.Encrypt(currentPayload.Data as byte[]), AddEncoding(currentPayload, $"{EncodingName}+{options.CipherParams.CipherType.ToLower()}")); return(Result.Ok(result)); }
internal static Result EncodePayloads(DecodingContext context, IEnumerable <IMessage> payloads) { var result = Result.Ok(); foreach (var payload in payloads) { result = Result.Combine(result, EncodePayload(payload, context)); } return(result); }
private static Result DecodePayloads(DecodingContext context, IEnumerable <IMessage> payloads, IEnumerable <MessageEncoder> encoders = null) { var result = Result.Ok(); foreach (var payload in payloads) { result = Result.Combine(result, DecodePayload(payload, context, encoders)); } return(result); }
public Result EncodeProtocolMessage(ProtocolMessage protocolMessage, DecodingContext context) { var result = Result.Ok(); if (protocolMessage.Messages != null) { result = Result.Combine(EncodePayloads(context, protocolMessage.Messages)); } if (protocolMessage.Presence != null) { result = Result.Combine(EncodePayloads(context, protocolMessage.Presence)); } return(result); }
public override Result <ProcessedPayload> Encode(IPayload payload, DecodingContext context) { if (IsEmpty(payload.Data)) { return(Result.Ok(new ProcessedPayload(payload))); } if (NeedsJsonEncoding(payload)) { return(Result.Ok(new ProcessedPayload( JsonHelper.Serialize(payload.Data), AddEncoding(payload, EncodingName)))); } return(Result.Ok(new ProcessedPayload(payload))); }
private IEnumerable <Message> ParseMessagesResponse(AblyResponse response, DecodingContext context) { if (response.Type == ResponseType.Json) { var messages = JsonHelper.Deserialize <List <Message> >(response.TextResponse); ProcessMessages(messages, context); return(messages); } #if MSGPACK var payloads = MsgPackHelper.Deserialise(response.Body, typeof(List <Message>)) as List <Message>; ProcessMessages(payloads, options); return(payloads); #else throw new AblyException($"Response of type '{response.Type}' is invalid because MsgPack support was not enabled for this build."); #endif }
public override Result <ProcessedPayload> Decode(IPayload payload, DecodingContext context) { var options = context.ChannelOptions; var logger = options?.Logger ?? DefaultLogger.LoggerInstance; if (IsEmpty(payload.Data)) { return(Result.Ok(new ProcessedPayload(payload))); } var currentEncoding = GetCurrentEncoding(payload); if (currentEncoding.Contains(EncodingName) == false) { return(Result.Ok(new ProcessedPayload(payload))); } var cipherType = GetCipherType(currentEncoding); if (cipherType.EqualsTo(options.CipherParams.CipherType) == false) { logger.Error( $"Cipher algorithm {options.CipherParams.CipherType.ToLower()} does not match message cipher algorithm of {currentEncoding}"); return(Result.Fail <ProcessedPayload>(new ErrorInfo($"Cipher algorithm {options.CipherParams.CipherType.ToLower()} does not match message cipher algorithm of {currentEncoding}"))); } var cipher = Crypto.GetCipher(options.CipherParams); try { if (payload.Data is byte[] == false) { return(Result.Fail <ProcessedPayload>(new ErrorInfo("Expected data to be byte[] but received " + payload.Data.GetType()))); } return(Result.Ok(new ProcessedPayload( payload.Data = cipher.Decrypt(payload.Data as byte[]), RemoveCurrentEncodingPart(payload)))); } catch (AblyException ex) { logger.Error($"Error decrypting payload using cypher {options.CipherParams.CipherType}. Leaving it encrypted", ex); return(Result.Fail <ProcessedPayload>(new ErrorInfo($"Error decrypting payload using cypher {options.CipherParams.CipherType}. Leaving it encrypted"))); } }
public Result DecodeMessages( ProtocolMessage protocolMessage, IEnumerable <IMessage> messages, DecodingContext context) { var result = Result.Ok(); var index = 0; foreach (var message in messages ?? Enumerable.Empty <IMessage>()) { SetMessageIdConnectionIdAndTimestamp(message, index); var decodeResult = DecodePayload(message, context, DefaultEncoders) .IfFailure(error => Logger.Warning($"Error decoding message with id: {message.Id}. Error: {error.Message}. Exception: {error.InnerException?.Message}")); result = Result.Combine(result, decodeResult); if (result.IsFailure) { break; } index++; } return(result); void SetMessageIdConnectionIdAndTimestamp(IMessage message, int i) { if (message.Id.IsEmpty()) { message.Id = $"{protocolMessage.Id}:{i}"; } if (message.ConnectionId.IsEmpty()) { message.ConnectionId = protocolMessage.ConnectionId; } if (message.Timestamp.HasValue == false) { message.Timestamp = protocolMessage.Timestamp; } } }
public override Result <ProcessedPayload> Decode(IPayload payload, DecodingContext context) { var options = context.ChannelOptions; var logger = options?.Logger ?? DefaultLogger.LoggerInstance; if (IsEmpty(payload.Data) || !CurrentEncodingIs(payload, EncodingName)) { return(Result.Ok(new ProcessedPayload(payload))); } try { return(Result.Ok(new ProcessedPayload( JsonHelper.Deserialize(payload.Data as string), RemoveCurrentEncodingPart(payload)))); } catch (Exception ex) { logger.Error($"Invalid Json data: '{payload.Data}'", ex); return(Result.Fail <ProcessedPayload>(new ErrorInfo($"Invalid Json data: '{payload.Data}'"))); } }
internal static Result EncodePayload(IMessage payload, DecodingContext context, IEnumerable <MessageEncoder> encoders = null) { ValidatePayloadDataType(payload); var result = Result.Ok(); foreach (var encoder in encoders ?? DefaultEncoders) { var encodeResult = encoder.Encode(payload, context); if (encodeResult.IsSuccess) { payload.Data = encodeResult.Value.Data; payload.Encoding = encodeResult.Value.Encoding; } result = Result.Combine(result, encodeResult); if (result.IsFailure) { break; } } return(result); }
private static void ProcessMessages <T>(IEnumerable <T> payloads, DecodingContext context) where T : IMessage { // TODO: What happens with rest request where we can't decode messages _ = DecodePayloads(context, payloads as IEnumerable <IMessage>); }
internal static Result DecodePayload(IMessage payload, DecodingContext context, IEnumerable <MessageEncoder> encoders = null, ILogger logger = null) { var actualEncoders = (encoders ?? DefaultEncoders).ToList(); var pp = context.PreviousPayload; // We take a chance that this will not be modified but replaced var(processResult, decodedPayload) = Decode(); // None of the encoders updated the PreviousPayload // then we need to set the default one Result overallResult = processResult; if (pp == context.PreviousPayload) { var originalPayloadResult = GetOriginalMessagePayload(); _ = originalPayloadResult.IfSuccess(x => { context.PreviousPayload = x; }); overallResult = Result.Combine(overallResult, originalPayloadResult); } payload.Data = decodedPayload.Data; payload.Encoding = decodedPayload.Encoding; return(overallResult); Result <PayloadCache> GetOriginalMessagePayload() { if (payload.Data is byte[] data) { return(Result.Ok(new PayloadCache(data, payload.Encoding))); } bool isFirstEncodingBase64 = MessageEncoder.CurrentEncodingIs(payload, Base64Encoder.EncodingNameStr); if (isFirstEncodingBase64) { var result = Base64Encoder.Decode(payload, new DecodingContext()); return(result.Map(x => new PayloadCache((byte[])x.Data, MessageEncoder.RemoveCurrentEncodingPart(payload)))); } return(Result.Ok(new PayloadCache((string)payload.Data, payload.Encoding))); } // Local function that tidies the processing // the first part of the tuple will return the result. We don't have `true` or `false` because // we care about the error message that came from the encoder that failed. // The processed payload is returned separately so we can still update the message. (Result <Unit> processResult, IPayload processedPayload) Decode() { int processedEncodings = 0; var numberOfEncodings = payload.Encoding.IsNotEmpty() ? payload.Encoding.Count(x => x == '/') + 1 : 0; if (numberOfEncodings == 0 || payload.Data == null) { return(Result.Ok(Unit.Default), payload); } IPayload currentPayload = payload; while (true) { var currentEncoding = MessageEncoder.GetCurrentEncoding(currentPayload); if (currentEncoding.IsEmpty()) { return(Result.Ok(Unit.Default), currentPayload); } var decoder = actualEncoders.FirstOrDefault(x => x.CanProcess(currentEncoding)); if (decoder == null) { logger?.Warning($"Missing decoder for '{currentEncoding}'. Leaving as it is"); return(Result.Ok(Unit.Default), currentPayload); } var result = decoder.Decode(currentPayload, context); if (result.IsSuccess) { currentPayload = result.Value; } else { // If an encoder fails we want to return the result up to this encoder return(Result.Fail <Unit>(result), currentPayload); } // just to be safe if (processedEncodings > numberOfEncodings) { // TODO: Send to Sentry return(Result.Fail <Unit>(new ErrorInfo("Failed to decode message encoding")), currentPayload); } processedEncodings++; } } }
public override Result <ProcessedPayload> Decode(IPayload payload, DecodingContext context) { var logger = context.ChannelOptions?.Logger ?? DefaultLogger.LoggerInstance; if (payload == null) { return(Result.Ok(new ProcessedPayload())); } try { var payloadBytes = DataHelpers.ConvertToByteArray(payload.Data); var previousPayload = context.PreviousPayload?.GetBytes(); if (previousPayload is null) { return(Result.Fail <ProcessedPayload>(new VcDiffErrorInfo("Missing previous payload"))); } var result = DeltaDecoder.ApplyDelta(previousPayload, payloadBytes); var nextEncoding = RemoveCurrentEncodingPart(payload); context.PreviousPayload = new PayloadCache(result.AsByteArray(), nextEncoding); return(Result.Ok(new ProcessedPayload( result.AsByteArray(), RemoveCurrentEncodingPart(payload)))); } catch (Exception ex) { var error = $"Payload Encoding: {payload.Encoding}. Payload data: {GetPayloadString()}"; logger.Error("Error decoding vcdiff message: " + error, ex); return(Result.Fail <ProcessedPayload>(new VcDiffErrorInfo("Failed to decode vcdiff message", ex))); } string GetPayloadString() { try { if (payload.Data == null) { return("null"); } if (payload.Data is byte[]) { return((payload.Data as byte[]).ToBase64()); } if (payload.Data is string) { return(payload.Data as string); } return(string.Empty); } catch { return(string.Empty); } } }
public override Result <ProcessedPayload> Encode(IPayload payload, DecodingContext context) { return(Result.Ok(new ProcessedPayload(payload))); }
public abstract Result <ProcessedPayload> Decode(IPayload payload, DecodingContext context);