private bool GroupBroadcastDataMessagesEqual(GroupBroadcastDataMessage x, GroupBroadcastDataMessage y)
 {
     return(StringEqual(x.GroupName, y.GroupName) &&
            SequenceEqual(x.ExcludedList, y.ExcludedList) &&
            PayloadsEqual(x.Payloads, y.Payloads) &&
            x.TracingId == y.TracingId);
 }
Exemplo n.º 2
0
 public static void StartToBroadcastMessageToGroup(ILogger logger, GroupBroadcastDataMessage message)
 {
     if (message.ExcludedList == null || message.ExcludedList.Count == 0)
     {
         _startToBroadcastMessageToGroup(logger, message.TracingId, message.GroupName, null);
     }
     else
     {
         var connections = string.Join(", ", message.ExcludedList);
         _startToBroadcastMessageToGroupWithExcludedConnections(logger, message.TracingId, message.GroupName, message.ExcludedList.Count, connections, null);
     }
 }
Exemplo n.º 3
0
        public override Task SendGroupExceptAsync(string groupName, string methodName, object[] args, IReadOnlyList <string> excludedIds, CancellationToken cancellationToken = default)
        {
            if (IsInvalidArgument(groupName) || IsInvalidArgument(methodName))
            {
                return(Task.CompletedTask);
            }

            var message = new GroupBroadcastDataMessage(groupName, excludedIds, SerializeAllProtocols(methodName, args));

            // Send this message from a fixed service connection, so that message order can be reserved.
            return(_serviceConnectionManager.WriteAsync(groupName, message));
        }
Exemplo n.º 4
0
        public override Task SendGroupAsync(string groupName, string methodName, object[] args, CancellationToken cancellationToken = default)
        {
            if (IsInvalidArgument(groupName))
            {
                throw new ArgumentException(NullOrEmptyStringErrorMessage, nameof(groupName));
            }

            if (IsInvalidArgument(methodName))
            {
                throw new ArgumentException(NullOrEmptyStringErrorMessage, nameof(methodName));
            }

            var message = new GroupBroadcastDataMessage(groupName, null, SerializeAllProtocols(methodName, args));

            return(ServiceConnectionContainer.WriteAsync(message));
        }
Exemplo n.º 5
0
        public override Task SendGroupExceptAsync(string groupName, string methodName, object[] args, IReadOnlyList <string> excludedIds, CancellationToken cancellationToken = default)
        {
            if (IsInvalidArgument(groupName))
            {
                throw new ArgumentException(NullOrEmptyStringErrorMessage, nameof(groupName));
            }

            if (IsInvalidArgument(methodName))
            {
                throw new ArgumentException(NullOrEmptyStringErrorMessage, nameof(methodName));
            }

            var message = new GroupBroadcastDataMessage(groupName, excludedIds, SerializeAllProtocols(methodName, args)).WithTracingId();

            Log.StartToBroadcastMessageToGroup(Logger, message);
            return(WriteAsync(message));
        }
Exemplo n.º 6
0
        public override Task SendGroupExceptAsync(string groupName, string methodName, object[] args, IReadOnlyList <string> excludedIds, CancellationToken cancellationToken = default)
        {
            if (IsInvalidArgument(groupName))
            {
                throw new ArgumentException(NullOrEmptyStringErrorMessage, nameof(groupName));
            }

            if (IsInvalidArgument(methodName))
            {
                throw new ArgumentException(NullOrEmptyStringErrorMessage, nameof(methodName));
            }

            var message = new GroupBroadcastDataMessage(groupName, excludedIds, SerializeAllProtocols(methodName, args));

            // Send this message from a fixed service connection, so that message order can be reserved.
            return(ServiceConnectionContainer.WriteAsync(groupName, message));
        }
Exemplo n.º 7
0
        public IEnumerable <AppMessage> GetMessages(Message message)
        {
            if (message.IsCommand)
            {
                var command = _serializer.Parse <Command>(message.Value, message.Encoding);
                switch (command.CommandType)
                {
                case CommandType.AddToGroup:
                {
                    // name is hg-{HubName}.{GroupName}, consider the whole as the actual group name
                    // this message always goes through the appName-connection
                    var groupName               = command.Value;
                    var connectionId            = GetName(message.Key, PrefixHelper.ConnectionIdPrefix);
                    var joinGroupWithAckMessage = new JoinGroupWithAckMessage(connectionId, groupName).WithTracingId();
                    if (joinGroupWithAckMessage.TracingId != null)
                    {
                        MessageLog.StartToAddConnectionToGroup(_logger, joinGroupWithAckMessage);
                    }

                    // go through the app connection
                    // use groupName as the partitionkey so that commands towards the same group always goes into the same service connection
                    yield return(new AppMessage(joinGroupWithAckMessage, message));

                    yield break;
                }

                case CommandType.RemoveFromGroup:
                {
                    // this message always goes through the appName-connection
                    var groupName                = command.Value;
                    var connectionId             = GetName(message.Key, PrefixHelper.ConnectionIdPrefix);
                    var leaveGroupWithAckMessage = new LeaveGroupWithAckMessage(connectionId, groupName).WithTracingId();
                    if (leaveGroupWithAckMessage.TracingId != null)
                    {
                        MessageLog.StartToRemoveConnectionFromGroup(_logger, leaveGroupWithAckMessage);
                    }

                    // go through the app connection
                    // use groupName as the partitionkey so that commands towards the same group always goes into the same service connection
                    yield return(new AppMessage(leaveGroupWithAckMessage, message));

                    yield break;
                }

                case CommandType.Initializing:
                    yield break;

                case CommandType.Abort:
                    yield break;
                }
            }

            var segment = GetPayload(message);

            // broadcast case
            if (TryGetName(message.Key, PrefixHelper.HubPrefix, out var hubName))
            {
                var broadcastDataMessage = new BroadcastDataMessage(excludedList: GetExcludedIds(message.Filter), payloads: GetPayloads(segment)).WithTracingId();
                if (broadcastDataMessage.TracingId != null)
                {
                    MessageLog.StartToBroadcastMessage(_logger, broadcastDataMessage);
                }
                yield return(new HubMessage(hubName, broadcastDataMessage, message));
            }
            // echo case
            else if (TryGetName(message.Key, PrefixHelper.HubConnectionIdPrefix, out _))
            {
                // naming: hc-{HubName}.{ConnectionId}
                // ConnectionId can NEVER contain .
                var index = message.Key.LastIndexOf('.');
                if (index < 0 || index == message.Key.Length - 1)
                {
                    throw new ArgumentException($"Key must contain '.' in between but it is not: {message.Key}");
                }

                var connectionId = message.Key.Substring(index + 1);

                var connectionDataMessage = new ConnectionDataMessage(connectionId, segment).WithTracingId();
                if (connectionDataMessage.TracingId != null)
                {
                    MessageLog.StartToSendMessageToConnection(_logger, connectionDataMessage);
                }

                // Go through the app connection
                yield return(new AppMessage(connectionDataMessage, message));
            }
            // group broadcast case
            else if (TryGetName(message.Key, PrefixHelper.HubGroupPrefix, out _))
            {
                // naming: hg-{HubName}.{GroupName}, it as a whole is the group name per the JoinGroup implementation
                // go through the app connection
                // use groupName as the partitionkey so that commands towards the same group always goes into the same service connection
                var groupName = message.Key;
                var groupBroadcastDataMessage = new GroupBroadcastDataMessage(groupName, excludedList: GetExcludedIds(message.Filter), payloads: GetPayloads(segment)).WithTracingId();
                if (groupBroadcastDataMessage.TracingId != null)
                {
                    MessageLog.StartToBroadcastMessageToGroup(_logger, groupBroadcastDataMessage);
                }
                yield return(new AppMessage(groupBroadcastDataMessage, message));
            }
            // user case
            else if (TryGetName(message.Key, PrefixHelper.HubUserPrefix, out var userWithHubPrefix))
            {
                // naming: hu-{HubName}.{UserName}, HubName can contain '.' and UserName can contain '.'
                // Go through all the possibilities
                foreach (var(hub, user) in GetPossibleNames(userWithHubPrefix))
                {
                    var userDataMessage = new UserDataMessage(user, GetPayloads(segment)).WithTracingId();
                    if (userDataMessage.TracingId != null)
                    {
                        MessageLog.StartToSendMessageToUser(_logger, userDataMessage);
                    }
                    // For old protocol, it is always single user per message https://github.com/SignalR/SignalR/blob/dev/src/Microsoft.AspNet.SignalR.Core/Infrastructure/Connection.cs#L162
                    yield return(new HubMessage(hub, userDataMessage, message));
                }
            }
            else
            {
                throw new NotSupportedException($"Message {message.Key} is not supported.");
            }
        }