Ejemplo n.º 1
0
        public async Task TestAttachChannel_AttachesSuccessfuly(Protocol protocol)
        {
            // Arrange
            var client = await GetRealtimeClient(protocol);

            Semaphore        signal = new Semaphore(0, 2);
            var              args   = new List <ChannelStateChange>();
            IRealtimeChannel target = client.Channels.Get("test");

            target.StateChanged += (s, e) =>
            {
                args.Add(e);
                signal.Release();
            };

            // Act
            target.Attach();

            // Assert
            signal.WaitOne(10000);
            args.Count.ShouldBeEquivalentTo(1);
            args[0].Current.ShouldBeEquivalentTo(ChannelState.Attaching);
            args[0].Error.ShouldBeEquivalentTo(null);
            target.State.ShouldBeEquivalentTo(ChannelState.Attaching);

            signal.WaitOne(10000);
            args.Count.ShouldBeEquivalentTo(2);
            args[1].Current.ShouldBeEquivalentTo(ChannelState.Attached);
            args[1].Error.ShouldBeEquivalentTo(null);
            target.State.ShouldBeEquivalentTo(ChannelState.Attached);
        }
Ejemplo n.º 2
0
        public IRealtimeChannel Get(string name, Rest.ChannelOptions options)
        {
            IRealtimeChannel channel = this.Get(name);

            channel.Options = options;
            return(channel);
        }
Ejemplo n.º 3
0
        public async Task SendingAMessageAttachesTheChannel_BeforeReceivingTheMessages(Protocol protocol)
        {
            Logger.LogLevel = LogLevel.Debug;
            ;
            // Arrange
            var client = await GetRealtimeClient(protocol);

            IRealtimeChannel target = client.Channels.Get("test");
            var messagesReceived    = new List <Message>();

            target.Subscribe(message =>
            {
                messagesReceived.Add(message);
                _resetEvent.Set();
            });

            // Act
            target.Publish("test", "test data");
            target.State.Should().Be(ChannelState.Attaching);
            _resetEvent.WaitOne(6000);

            // Assert
            target.State.Should().Be(ChannelState.Attached);
            messagesReceived.Count.ShouldBeEquivalentTo(1);
            messagesReceived[0].Name.ShouldBeEquivalentTo("test");
            messagesReceived[0].Data.ShouldBeEquivalentTo("test data");
        }
Ejemplo n.º 4
0
        private void Subscribe_Click(object sender, RoutedEventArgs e)
        {
            string channelName = this.channelBox.Text.Trim();

            if (string.IsNullOrEmpty(channelName))
            {
                return;
            }

            string key                  = RealtimeChat.Properties.Settings.Default.ApiKey;
            string clientId             = RealtimeChat.Properties.Settings.Default.ClientId;
            AblyRealtimeOptions options = new AblyRealtimeOptions(key)
            {
                UseBinaryProtocol = false, Tls = true, AutoConnect = false, ClientId = clientId
            };

            this.client = new AblyRealtime(options);
            this.client.Connection.ConnectionStateChanged += this.connection_ConnectionStateChanged;
            this.client.Connect();

            this.channel = this.client.Channels.Get(channelName);
            this.channel.ChannelStateChanged      += channel_ChannelStateChanged;
            this.channel.MessageReceived          += this.channel_MessageReceived;
            this.channel.Presence.MessageReceived += this.Presence_MessageReceived;
            this.channel.Attach();
            this.channel.Presence.Enter(null, null);
        }
Ejemplo n.º 5
0
        private async void Subscribe_Click(object sender, RoutedEventArgs e)
        {
            string channelName = this.channelBox.Text.Trim();

            if (string.IsNullOrEmpty(channelName))
            {
                return;
            }

            string key      = RealtimeChat.Properties.Settings.Default.ApiKey;
            string clientId = RealtimeChat.Properties.Settings.Default.ClientId;
            var    options  = new ClientOptions(key)
            {
                UseBinaryProtocol = true, Tls = true, AutoConnect = false, ClientId = clientId
            };

            this.client = new AblyRealtime(options);
            this.client.Connection.ConnectionStateChanged += this.connection_ConnectionStateChanged;
            this.client.Connect();

            this.channel = this.client.Channels.Get(channelName);
            this.channel.StateChanged += channel_ChannelStateChanged;
            this.channel.Subscribe(Handler);
            this.channel.Presence.Subscribe(Presence_MessageReceived);
            await channel.AttachAsync();

            await channel.Presence.EnterAsync(new PresenceData()
            {
                Data = new [] { "data1", "data2" }
            });
        }
Ejemplo n.º 6
0
 public Presence(IConnectionManager connection, IRealtimeChannel channel, string cliendId)
 {
     this.presence                    = new PresenceMap();
     this.pendingPresence             = new List <QueuedPresenceMessage>();
     this.connection                  = connection;
     this.connection.MessageReceived += OnConnectionMessageReceived;
     this.channel = channel;
     this.channel.ChannelStateChanged += this.OnChannelStateChanged;
     this.clientId = cliendId;
 }
Ejemplo n.º 7
0
 public ChannelAwaiter(IRealtimeChannel channel, ChannelState awaitedState, ILogger logger = null, Action onTimeout = null)
 {
     Logger        = logger ?? DefaultLogger.LoggerInstance;
     _name         = $"#{channel.Name}:{awaitedState} awaiter";
     _channel      = channel as RealtimeChannel;
     _awaitedState = awaitedState;
     _timer        = new CountdownTimer(_name + " timer", logger);
     _onTimeout    = onTimeout;
     AttachListener();
 }
Ejemplo n.º 8
0
        internal static Task WaitForState(this IRealtimeChannel channel, ChannelState awaitedState = ChannelState.Attached, TimeSpan?waitSpan = null)
        {
            var channelAwaiter = new ChannelAwaiter(channel, awaitedState);

            if (waitSpan.HasValue)
            {
                return(channelAwaiter.WaitAsync());
            }
            return(channelAwaiter.WaitAsync());
        }
Ejemplo n.º 9
0
        public static async Task WaitForState(this IRealtimeChannel channel, ChannelState awaitedState = ChannelState.Attached, TimeSpan?waitSpan = null)
        {
            var           channelAwaiter = new ChannelAwaiter(channel, awaitedState);
            var           timespan       = waitSpan.GetValueOrDefault(TimeSpan.FromSeconds(5));
            Result <bool> result         = await channelAwaiter.WaitAsync(timespan);

            if (result.IsFailure)
            {
                throw new Exception($"Channel '{channel.Name}' did not reach '{awaitedState}' in {timespan.TotalSeconds} seconds. Current state {channel.State}");
            }
        }
Ejemplo n.º 10
0
            public UnsubscribeSpecs(ITestOutputHelper output) : base(output)
            {
                _client  = GetConnectedClient(opts => opts.UseBinaryProtocol = false); //Easier to test encoding with the json protocol
                _channel = _client.Channels.Get("test");

                SetState(_channel, ChannelState.Attached);
                _handler = message =>
                {
                    throw new AssertionFailedException("This handler should no longer be called");
                };
            }
Ejemplo n.º 11
0
        public IRealtimeChannel Get(string name)
        {
            IRealtimeChannel channel = null;

            if (!this.channels.TryGetValue(name, out channel))
            {
                channel = this.channelFactory.Create(name);
                this.channels.Add(name, channel);
            }
            return(channel);
        }
Ejemplo n.º 12
0
        public async Task TestGetChannel_ReturnsValidChannel(Protocol protocol)
        {
            // Arrange
            var client = await GetRealtimeClient(protocol);

            // Act
            IRealtimeChannel target = client.Channels.Get("test");

            // Assert
            target.Name.ShouldBeEquivalentTo("test");
            target.State.ShouldBeEquivalentTo(ChannelState.Initialized);
        }
Ejemplo n.º 13
0
        public async Task ChannelSubscribe()
        {
            var realtime = new AblyRealtime(new ClientOptions(PlaceholderKey)
            {
                AutoConnect = false
            });
            IRealtimeChannel channel = realtime.Channels.Get("test");

            // Or ...
            IRealtimeChannel channel2 = realtime.Channels.Get("shortcut");

            channel.Subscribe(message =>
            {
                var name = message.Name;
                var data = message.Data;
            });

            channel.On(args =>
            {
                var state = args.Current;    // Current channel State
                var error = args.Error;      // If the channel error-ed it will be reflected here
            });

            channel.On(ChannelEvent.Attached, args =>
            {
                // Do stuff when channel is attached
            });

            channel.Publish("greeting", "Hello World!");
            channel.Publish("greeting", "Hello World!", (success, error) =>
            {
                // If 'Publish' succeeded 'success' is 'true'
                // If 'Publish' failed 'success' is 'false' and 'error' will contain the specific error
            });

            var result = await channel.PublishAsync("greeting", "Hello World!");

            // You can check if the message failed
            if (result.IsFailure)
            {
                var error = result.Error;    // The error reason can be accessed as well
            }

            var secret           = Crypto.GenerateRandomKey();
            var encryptedChannel = realtime.Channels.Get("encrypted", new ChannelOptions(secret));

            encryptedChannel.Subscribe(message =>
            {
                var data = message.Data;    // Sensitive data (encrypted before published)
            });

            encryptedChannel.Publish("name (not encrypted)", "sensitive data (encrypted before published)");
        }
Ejemplo n.º 14
0
 public void Open(string networkAddress)
 {
     _channel = _ably.Channels.Get(networkAddress);
     _channel.Subscribe((Message msg) =>
     {
         if (_publicAddress != msg.Name)
         {
             foreach (EventHandler <string> handler in _handlers)
             {
                 handler.Invoke(this, msg.Data.ToString());
             }
         }
     });
 }
Ejemplo n.º 15
0
        public async Task TestAttachChannel_Sending3Messages_EchoesItBack(Protocol protocol)
        {
            Logger.LogLevel = LogLevel.Debug;
            ;
            // Arrange
            var client = await GetRealtimeClient(protocol);

            await client.WaitForState(ConnectionState.Connected);

            ManualResetEvent resetEvent = new ManualResetEvent(false);
            IRealtimeChannel target     = client.Channels.Get("test" + protocol);

            target.Attach();
            await target.WaitForState(ChannelState.Attached);

            ConcurrentQueue <Message> messagesReceived = new ConcurrentQueue <Message>();
            int count = 0;

            target.Subscribe(message =>
            {
                messagesReceived.Enqueue(message);
                count++;
                if (count == 3)
                {
                    resetEvent.Set();
                }
            });

            // Act
            target.Publish("test1", "test 12");
            target.Publish("test2", "test 123");
            target.Publish("test3", "test 321");

            bool result = resetEvent.WaitOne(8000);
            await Task.Delay(100);

            result.Should().BeTrue();

            // Assert
            messagesReceived.Count.ShouldBeEquivalentTo(3);
            var messages = messagesReceived.ToList();

            messages[0].Name.ShouldBeEquivalentTo("test1");
            messages[0].Data.ShouldBeEquivalentTo("test 12");
            messages[1].Name.ShouldBeEquivalentTo("test2");
            messages[1].Data.ShouldBeEquivalentTo("test 123");
            messages[2].Name.ShouldBeEquivalentTo("test3");
            messages[2].Data.ShouldBeEquivalentTo("test 321");
        }
Ejemplo n.º 16
0
        static async Task Main(string[] args)
        {
            AblyRealtime     ably           = new AblyRealtime("HG2KVw.AjZP_A:W7VXUG9yw1-Cza6u");
            IRealtimeChannel channel        = ably.Channels.Get("[?delta=vcdiff]delta-sample-app");
            VcdiffDecoder    channelDecoder = new VcdiffDecoder();

            channel.Subscribe(message =>
            {
                object data = message.Data;
                try
                {
                    if (VcdiffDecoder.IsDelta(data))
                    {
                        data = channelDecoder.ApplyDelta(data).AsObject();
                    }
                    else
                    {
                        channelDecoder.SetBase(data);
                    }
                }
                catch (Exception e)
                {
                    /* Delta decoder error */
                }

                /* Process decoded data */
                Console.WriteLine(JsonHelper.DeserializeObject <Data>(data as JObject));
            });
            ably.Connection.On(ConnectionEvent.Connected, change =>
            {
                Data data = new Data()
                {
                    foo    = "bar",
                    count  = 1,
                    status = "active"
                };
                channel.Publish("data", data);
                data.count++;
                channel.Publish("data", data);
                data.status = "inactive";
                channel.Publish("data", data);
            });

            await Task.Run(() =>
            {
                Console.ReadLine();
            });
        }
Ejemplo n.º 17
0
        public void Release(string name)
        {
            IRealtimeChannel channel = null;

            if (this.channels.TryGetValue(name, out channel))
            {
                EventHandler <ChannelStateChangedEventArgs> eventHandler = null;
                eventHandler = (s, args) =>
                {
                    if (args.NewState == ChannelState.Detached || args.NewState == ChannelState.Failed)
                    {
                        channel.ChannelStateChanged -= eventHandler;
                        this.channels.Remove(name);
                    }
                };
                channel.ChannelStateChanged += eventHandler;
                channel.Detach();
            }
        }
Ejemplo n.º 18
0
        public async Task TestAttachChannel_Sending3Messages_EchoesItBack(Protocol protocol)
        {
            // Arrange
            var client = await GetRealtimeClient(protocol);

            ManualResetEvent resetEvent = new ManualResetEvent(false);
            IRealtimeChannel target     = client.Channels.Get("test" + protocol);

            target.Attach();

            List <Message> messagesReceived = new List <Message>();
            int            count            = 0;

            target.Subscribe(message =>
            {
                messagesReceived.Add(message);
                count++;
                if (count == 3)
                {
                    resetEvent.Set();
                }
            });

            // Act
            target.Publish("test1", "test 12");
            target.Publish("test2", "test 123");
            target.Publish("test3", "test 321");

            bool result = resetEvent.WaitOne(8000);

            result.Should().BeTrue();

            // Assert
            messagesReceived.Count.ShouldBeEquivalentTo(3);
            messagesReceived[0].Name.ShouldBeEquivalentTo("test1");
            messagesReceived[0].Data.ShouldBeEquivalentTo("test 12");
            messagesReceived[1].Name.ShouldBeEquivalentTo("test2");
            messagesReceived[1].Data.ShouldBeEquivalentTo("test 123");
            messagesReceived[2].Name.ShouldBeEquivalentTo("test3");
            messagesReceived[2].Data.ShouldBeEquivalentTo("test 321");
        }
Ejemplo n.º 19
0
        private async Task Connect()
        {
            string channelName = this.channelBox.Text.Trim();

            if (string.IsNullOrEmpty(channelName))
            {
                return;
            }

            string key      = "lNj80Q.iGyVcQ:2QKX7FFASfX-7H9H";
            string clientId = "Martin";
            var    options  = new ClientOptions(key)
            {
                UseBinaryProtocol = true, Tls = true, AutoConnect = false, ClientId = clientId
            };

            this.client = new AblyRealtime(options);
            this.client.Connection.ConnectionStateChanged += this.connection_ConnectionStateChanged;
            this.client.Connect();

            this.channel = this.client.Channels.Get(channelName);
            this.channel.StateChanged += channel_ChannelStateChanged;
            this.channel.Subscribe(Handler);
            this.channel.Presence.Subscribe(Presence_MessageReceived);
            try
            {
                await channel.AttachAsync();

                await channel.Presence.EnterAsync(new PresenceData()
                {
                    Data = new[] { "data1", "data2" }
                });
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
            }
        }
Ejemplo n.º 20
0
        protected void WebSocketOnMessageReceived(object sender, MessageReceivedEventArgs messageReceivedEventArgs)
        {
            OnRawMessageReceived(messageReceivedEventArgs.Message);
            RealtimeChannelResponse response;
            RealtimeMessage         message;

            if ((response = RealtimeChannelResponse.Deserialize(messageReceivedEventArgs.Message)) != null)
            {
                IRealtimeChannel realtimeChannel = null;
                lock (this)
                {
                    if (Channels.ContainsKey(response.ChannelId))
                    {
                        realtimeChannel = Channels[response.ChannelId];
                    }
                }
                realtimeChannel?.OnChannelResponse(response);
                OnChannelUpdated(realtimeChannel);
            }
            else if ((message = RealtimeMessage.Deserialize(messageReceivedEventArgs.Message)) != null)
            {
                OnMessageReceived(message);
            }
        }
Ejemplo n.º 21
0
        public async Task ChannelHistory()
        {
            var realtime             = new AblyRealtime(PlaceholderKey);
            IRealtimeChannel channel = realtime.Channels.Get("test");
            var history = await channel.HistoryAsync();

            // Loop through current history page
            foreach (var message in history.Items)
            {
                // Do something with message
            }

            var nextPage = await history.NextAsync();

            var presenceHistory = await channel.Presence.HistoryAsync();

            // Loop through the presence messages
            foreach (var presence in presenceHistory.Items)
            {
                // Do something with the messages
            }

            var presenceNextPage = await presenceHistory.NextAsync();
        }
Ejemplo n.º 22
0
 public ChannelAwaiter(IRealtimeChannel channel, ChannelState awaitedState)
 {
     _channel      = channel as RealtimeChannel;
     _awaitedState = awaitedState;
 }
Ejemplo n.º 23
0
 private void RegisterChannels()
 {
     tunnelChannel = ably.Client.Channels.Get("tunnels");
 }
Ejemplo n.º 24
0
        public BrimeRealtimeAPI(string channelName)
        {
            ClientOptions options = new ClientOptions(ABLY_TOKEN);

            options.AutoConnect = false;
            options.LogHandler  = new AblyLogHandler(Logger);
            options.LogLevel    = LogLevel.None;
            this.ably           = new AblyRealtime(options);

            this.ably.Connection.On((state) => {
                // onOpen / onClose
                switch (state.Current)
                {
                case IO.Ably.Realtime.ConnectionState.Connected:
                    isConnected = true;
                    foreach (BrimeRealtimeListener listener in listeners)
                    {
                        listener.onOpen();
                    }
                    break;

                case IO.Ably.Realtime.ConnectionState.Closed:
                case IO.Ably.Realtime.ConnectionState.Failed:
                    isConnected = false;
                    foreach (BrimeRealtimeListener listener in listeners)
                    {
                        listener.onClose();
                    }
                    break;
                }
            });

            this.ably.Channels.Get(channelName.ToLower() + "/alerts").Subscribe((message) => {
                // Follow Alerts
                if (message.Name == "alert")
                {
                    JObject data = JObject.Parse((string)message.Data);
                    string?type  = data.Value <string>("type");
                    if (type != null)
                    {
                        if (type.Equals("follow"))
                        {
                            string?follower   = data.Value <string>("follower");
                            string?followerID = data.Value <string>("followerID");
                            if (follower == null)
                            {
                                follower = "";
                            }
                            if (followerID == null)
                            {
                                followerID = "";
                            }
                            foreach (BrimeRealtimeListener listener in listeners)
                            {
                                listener.onFollow(follower, followerID);
                            }
                        }
                        else if (type.Equals("subscribe"))
                        {
                            string?subscriber   = data.Value <string>("subscriber");
                            string?subscriberID = data.Value <string>("subscriberID");
                            if (subscriber == null)
                            {
                                subscriber = "";
                            }
                            if (subscriberID == null)
                            {
                                subscriberID = "";
                            }
                            foreach (BrimeRealtimeListener listener in listeners)
                            {
                                listener.onSubscribe(subscriber, subscriberID, false);
                            }
                        }
                        else if (type.Equals("resubscribe"))
                        {
                            string?subscriber   = data.Value <string>("subscriber");
                            string?subscriberID = data.Value <string>("subscriberID");
                            if (subscriber == null)
                            {
                                subscriber = "";
                            }
                            if (subscriberID == null)
                            {
                                subscriberID = "";
                            }
                            foreach (BrimeRealtimeListener listener in listeners)
                            {
                                listener.onSubscribe(subscriber, subscriberID, true);
                            }
                        }
                    }
                }
            });

            IRealtimeChannel channel = this.ably.Channels.Get(channelName.ToLower());

            IEnumerable <PresenceMessage> msgs = channel.Presence.GetAsync().Result;
            int viewCount = 0; foreach (PresenceMessage msg in msgs)

            {
                viewCount++;
            }

            ViewCountTracker = new ViewCountTracker(viewCount);
            registerListener(ViewCountTracker); // register for tracking updates

            Task.Run(() => {
                while (isConnected)
                {
                    System.Threading.Thread.Sleep(VIEW_UPDATE);
                    IEnumerable <PresenceMessage> msgs = channel.Presence.GetAsync().Result;
                    int viewCount = 0; foreach (PresenceMessage msg in msgs)
                    {
                        viewCount++;
                    }
                    ViewCountTracker.ViewCount = viewCount;
                }
            });

            channel.Presence.Subscribe((message) => {
                // onJoin / onLeave
                switch (message.Action)
                {
                case PresenceAction.Absent:
                case PresenceAction.Leave:
                    foreach (BrimeRealtimeListener listener in listeners)
                    {
                        listener.onLeave(message.ClientId);
                    }
                    break;

                case PresenceAction.Enter:
                case PresenceAction.Present:
                case PresenceAction.Update:
                    foreach (BrimeRealtimeListener listener in listeners)
                    {
                        listener.onJoin(message.ClientId);
                    }
                    break;
                }
            });

            // Deprecated
            channel.Subscribe((message) => {
                // onChat
                if (message.Name == "greeting")
                {
                    Logger.Trace("Message Data: " + message.Data);
                    BrimeChatMessage chatMessage = new BrimeChatMessage(JObject.Parse((string)message.Data));
                    foreach (BrimeRealtimeListener listener in listeners)
                    {
                        listener.onChat(chatMessage);
                    }
                }
                else
                {
                    Logger.Trace("Message Name: " + message.Name);
                }

                /* TODO: Needs ChannelID, so will need Client-ID to use
                 * switch (message.Name) {
                 *  case "chat":    // updated chat messages
                 *      Logger.Trace("Chat Data: " + message.Data);
                 *      break;
                 *  case "delete":  // delete message
                 *      Logger.Trace("Delete Data: " + message.Data);
                 *      break;
                 * }
                 */
            });
        }
Ejemplo n.º 25
0
 public EventEmitterSpecs(ITestOutputHelper output) : base(output)
 {
     _channel = GetConnectedClient().Channels.Get("test");
 }
Ejemplo n.º 26
0
 public ConnectionStateChangeEffectSpecs(ITestOutputHelper output) : base(output)
 {
     _client  = GetConnectedClient();
     _channel = _client.Channels.Get("test");
 }
Ejemplo n.º 27
0
 public ChannelDetachSpecs(ITestOutputHelper output) : base(output)
 {
     _client  = GetConnectedClient();
     _channel = _client.Channels.Get("test");
 }
Ejemplo n.º 28
0
 protected void SetState(IRealtimeChannel channel, ChannelState state, ErrorInfo error = null, ProtocolMessage message = null)
 {
     (channel as RealtimeChannel).SetChannelState(state, error, message);
 }
Ejemplo n.º 29
0
        public async Task OpenChannelAsync(IRealtimeChannel channel, CancellationToken cancellationToken)
        {
            var subscriptionMessage = channel.GetSubscriptionMessage();
            var myTask = new TaskCompletionSource <SubscribedMessage>();

            while (!cancellationToken.IsCancellationRequested)
            {
                Task <SubscribedMessage> task;
                lock (this)
                {
                    if (OpenChannelCompletionSource == null)
                    {
                        OpenChannelCompletionSource = myTask;
                        break;
                    }
                    task = OpenChannelCompletionSource.Task;
                }
                try
                {
                    await task;
                }
                catch
                {
                    // ignore
                }
            }

            // SubscribeMessage to the event
            EventHandler <MessageReceivedEventArgs> messagEventHandler = null;

            messagEventHandler = (sender, args) =>
            {
                RealtimeMessage message;
                if ((message = RealtimeMessage.Deserialize(args.Message)) != null)
                {
                    if (message is SubscribedMessage)
                    {
                        WebSocket.MessageReceived -= messagEventHandler;
                        lock (this)
                        {
                            myTask.TrySetResult(message as SubscribedMessage);
                        }
                    }
                    else if (message is ErrorMessage)
                    {
                        WebSocket.MessageReceived -= messagEventHandler;
                        lock (this)
                        {
                            myTask.TrySetException(new Exception((message as ErrorMessage).Message));
                        }
                    }
                }
            };
            WebSocket.MessageReceived += messagEventHandler;

            // Cancellation token
            cancellationToken.Register(() =>
            {
                lock (this)
                {
                    myTask.TrySetCanceled();
                }
            });

            // Send subscription message
            WebSocket.Send(subscriptionMessage.Serialize());

            channel.OnChannelSubscribed(await myTask.Task);

            lock (this)
            {
                OpenChannelCompletionSource = null;
                if (Channels.ContainsKey(channel.ChannelId))
                {
                    Channels[channel.ChannelId] = channel;
                }
                else
                {
                    Channels.Add(channel.ChannelId, channel);
                }
            }
        }
Ejemplo n.º 30
0
 protected void OnChannelUpdated(IRealtimeChannel channel)
 {
     ChannelUpdated?.Invoke(this, new EventArgs());
 }