public IEnumerable GetMessages()

in src/Microsoft.Azure.SignalR.AspNet/HubHost/SignalRMessageParser.cs [54:169]


        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.");
            }
        }