예제 #1
0
        /// Websocket methods
        public static async Task AddClientToChannelAsync(ConnectedClient ws, string channel)
        {
            if (ws.Channels.Contains(channel))
            {
                return;
            }

            IdentityHandler.InternalIdentity identity = null;
            if (channel.StartsWith("https://") || channel.StartsWith("http://"))
            {
                // Check if this client is allowed to join this channel
                identity = await IdentityHandler.GetIdentityAsync(ws.ClientId, channel);

                if (identity == null)
                {
                    return;
                }
            }

            InternalChannel internalChannel = null;

            lock (Channels)
            {
                if (!Channels.ContainsKey(channel))
                {
                    Channels.Add(channel, new InternalChannel()
                    {
                        Channel     = channel,
                        LastMessage = DateTime.UtcNow,
                        Messages    = new ChannelMessageData[MaxMessageBuffer],
                        CurIndex    = 0,
                        Clients     = new List <ConnectedClient>()
                    });
                }
                internalChannel = Channels[channel];
            }
            lock (internalChannel.Clients)
                internalChannel.Clients.Add(ws);
            ws.Channels.Add(channel);
        }
예제 #2
0
        public static async Task <ChannelData> GetMessagesForChannelSinceIndexAsync(string clientId, string channel, long index)
        {
            // If Channel starts with https:// , use the clientId to request the identity from the url
            IdentityHandler.InternalIdentity identity = null;
            if (channel.StartsWith("https://") || channel.StartsWith("http://"))
            {
                identity = await IdentityHandler.GetIdentityAsync(clientId, channel);

                if (identity == null)
                {
                    return(null);
                }
            }

            InternalChannel internalChannel = null;

            lock (Channels)
            {
                if (!Channels.ContainsKey(channel))
                {
                    return(null);
                }
                internalChannel = Channels[channel];
            }

            var container = new ChannelData()
            {
                Channel = channel
            };

            if (identity != null && !identity.Data.allowChannelReceive) // Check if we are allowed to receive messages
            {
                container.Messages = new List <ChannelMessageData>();
                return(container);
            }

            if (index == -1) // On the first request from the client (index == -1), we will only give back at what position we are.
            {
                container.Index    = internalChannel.CurIndex;
                container.Messages = new List <ChannelMessageData>();
                return(container);
            }

            // Find out count to pre-allocate the memory space before going into our locked section
            var count = internalChannel.CurIndex - index;

            if (count > MaxMessageBuffer)
            {
                count = MaxMessageBuffer;
            }
            if (count <= 0)
            {
                container.Messages = new List <ChannelMessageData>();
                container.Index    = internalChannel.CurIndex;
                return(container);
            }
            container.Messages = new List <ChannelMessageData>((int)count);

            lock (internalChannel.Messages)
            {
                // In case the CurIndex is changed before we got the lock
                container.Index = internalChannel.CurIndex;
                count           = internalChannel.CurIndex - index;
                if (count > MaxMessageBuffer || count < 0)
                {
                    count = MaxMessageBuffer;
                }

                for (var i = internalChannel.CurIndex - count; i < internalChannel.CurIndex; i++)
                {
                    var arrayIndex = i % MaxMessageBuffer;
                    var messageObj = internalChannel.Messages[(int)arrayIndex];
                    if (messageObj.ClientId == clientId)
                    {
                        continue;
                    }
                    container.Messages.Add(messageObj);
                }
            }
            return(container);
        }
예제 #3
0
        public static async Task SendMessageAsync(string clientId, string channel, string data, ConnectedClient filterClient = null)
        {
            if (data.Length > 1024 * 4)
            {
                return;
            }

            // If Channel starts with https:// , use the clientId to request the identity from the url
            IdentityHandler.InternalIdentity identity = null;
            if (channel.StartsWith("https://") || channel.StartsWith("http://"))
            {
                identity = await IdentityHandler.GetIdentityAsync(clientId, channel);

                if (identity == null || !identity.Data.allowChannelSend)
                {
                    return;
                }
            }

            // Add to channel message hub
            InternalChannel internalChannel = null;

            lock (Channels)
            {
                if (!Channels.ContainsKey(channel))
                {
                    Channels.Add(channel, new InternalChannel()
                    {
                        Channel     = channel,
                        LastMessage = DateTime.UtcNow,
                        Messages    = new ChannelMessageData[MaxMessageBuffer],
                        CurIndex    = 0,
                        Clients     = new List <ConnectedClient>()
                    });
                }
                internalChannel = Channels[channel];
            }
            var message = new ChannelMessageData()
            {
                Data     = data,
                Identity = identity,
                ClientId = clientId
            };

            lock (internalChannel.Messages)
            {
                var arrayIndex = internalChannel.CurIndex % MaxMessageBuffer;
                internalChannel.Messages[arrayIndex] = message;
                internalChannel.CurIndex++;
                internalChannel.LastMessage = DateTime.UtcNow;
            }

            // Broadcast to all websocket connected clients
            List <ConnectedClient> clients = null;

            lock (internalChannel.Clients)
                clients = internalChannel.Clients.Where(a => (filterClient != null && a != filterClient) || (filterClient == null && a.ClientId != clientId)).ToList();

            if (clients.Count > 0)
            {
                var json = System.Text.Json.JsonSerializer.Serialize(new CommandMessageData()
                {
                    Channel  = channel,
                    Identity = identity?.Data?.publicIdentifier,
                    Data     = data
                });

                var dataBytes = System.Text.ASCIIEncoding.UTF8.GetBytes("MSG|" + json.Length + "|" + json); // MSG = 'Channel Message' Command Type
                foreach (var client in clients)
                {
                    _ = client.SendDataAsync(dataBytes);
                }
            }
        }