예제 #1
0
        public Task <bool> MessageReceived(ProtocolMessage protocolMessage, RealtimeState state)
        {
            if (protocolMessage.Channel.IsEmpty())
            {
                return(Task.FromResult(false));
            }

            var channel = _channels.Exists(protocolMessage.Channel) ? GetChannel(protocolMessage.Channel) : null;

            if (channel == null)
            {
                Logger.Warning($"Message received {protocolMessage} for a channel that does not exist {protocolMessage.Channel}");
                return(Task.FromResult(false));
            }

            switch (protocolMessage.Action)
            {
            case ProtocolMessage.MessageAction.Error:
                channel.SetChannelState(ChannelState.Failed, protocolMessage);
                break;

            case ProtocolMessage.MessageAction.Attached:
                channel.Properties.AttachSerial = protocolMessage.ChannelSerial;

                if (protocolMessage.Flags.HasValue)
                {
                    var modes = new ChannelModes(((ProtocolMessage.Flag)protocolMessage.Flags.Value).FromFlag());
                    channel.Modes = new ReadOnlyChannelModes(modes.ToList());
                }

                if (protocolMessage.Params != null)
                {
                    channel.Params = new ReadOnlyChannelParams(protocolMessage.Params);
                }

                if (channel.State == ChannelState.Attached)
                {
                    // RTL12
                    if (!protocolMessage.HasFlag(ProtocolMessage.Flag.Resumed))
                    {
                        channel.Presence.ChannelAttached(protocolMessage);
                        channel.EmitUpdate(protocolMessage.Error, false, protocolMessage);
                    }
                }
                else
                {
                    channel.SetChannelState(ChannelState.Attached, protocolMessage);
                }

                break;

            case ProtocolMessage.MessageAction.Detach:
            case ProtocolMessage.MessageAction.Detached:
                if (channel.State != ChannelState.Detached)
                {
                    channel.SetChannelState(ChannelState.Detached, protocolMessage);
                }

                break;

            case ProtocolMessage.MessageAction.Message:

                if (channel.State == ChannelState.Attaching)
                {
                    Logger.Warning(
                        $"Channel #{channel.Name} is currently in Attaching state. Messages received in this state are ignored. Ignoring ${protocolMessage.Messages?.Length ?? 0} messages");
                    return(TaskConstants.BooleanTrue);
                }

                if (ValidateIfDeltaItHasCorrectPreviousMessageId(protocolMessage, channel.LastSuccessfulMessageIds) == false)
                {
                    var message =
                        "Delta message decode failure. Previous message id does not equal expected message id.";
                    var reason = new ErrorInfo(message, ErrorCodes.VcDiffDecodeError);
                    channel.StartDecodeFailureRecovery(reason);
                    return(TaskConstants.BooleanTrue);
                }

                var result = _messageHandler.DecodeMessages(
                    protocolMessage,
                    protocolMessage.Messages,
                    channel.MessageDecodingContext);

                if (result.IsFailure)
                {
                    Logger.Error($"{channel.Name} - failed to decode message. ErrorCode: {result.Error.Code}, Message: {result.Error.Message}");
                    if (result.Error is VcDiffErrorInfo)
                    {
                        channel.StartDecodeFailureRecovery(result.Error);

                        // Break any further message processing
                        return(TaskConstants.BooleanTrue);
                    }
                }

                channel.LastSuccessfulMessageIds = LastMessageIds.Create(protocolMessage);

                foreach (var msg in protocolMessage.Messages)
                {
                    channel.OnMessage(msg);
                }

                break;

            case ProtocolMessage.MessageAction.Presence:
            case ProtocolMessage.MessageAction.Sync:

                var presenceDecodeResult = _messageHandler.DecodeMessages(
                    protocolMessage,
                    protocolMessage.Presence,
                    channel.Options);

                if (presenceDecodeResult.IsFailure)
                {
                    Logger.Error($"{channel.Name} - failed to decode presence message. ErrorCode: {presenceDecodeResult.Error.Code}, Message: {presenceDecodeResult.Error.Message}");

                    channel.OnError(presenceDecodeResult.Error);
                }

                string syncSerial = protocolMessage.Action == ProtocolMessage.MessageAction.Sync
                            ? protocolMessage.ChannelSerial
                            : null;

                channel.Presence.OnPresence(protocolMessage.Presence, syncSerial);

                break;
            }

            return(Task.FromResult(true));
        }
예제 #2
0
        private bool ValidateIfDeltaItHasCorrectPreviousMessageId(ProtocolMessage protocolMessage, LastMessageIds channelSuccessfulMessageIds)
        {
            if (protocolMessage.Messages == null || protocolMessage.Messages.Length == 0)
            {
                return(true);
            }

            var firstMessage = protocolMessage.Messages.First();
            var deltaFrom    = firstMessage.Extras?.Delta?.From;

            if (deltaFrom != null && deltaFrom.EqualsTo(channelSuccessfulMessageIds.LastMessageId) == false)
            {
                Logger.Warning($"Delta message decode failure. Previous message id does not equal expected message id. PreviousMessageId: {channelSuccessfulMessageIds.LastMessageId}. ExpectedMessageId: {deltaFrom}");
                return(false);
            }

            return(true);
        }