protected override void ProcessMessage(SocketSubscription subscription, string data) { foreach (var handler in subscription.MessageHandlers) { handler.Value(subscription, JToken.Parse(data)); } }
private async Task <CallResult <bool> > Authenticate(SocketSubscription subscription) { if (authProvider == null) { return(new CallResult <bool>(false, new NoApiCredentialsError())); } log.Write(LogVerbosity.Debug, "Starting authentication"); var socket = (ISignalRSocket)subscription.Socket; var result = await socket.InvokeProxy <string>("GetAuthContext", authProvider.Credentials.Key.GetString()).ConfigureAwait(false); if (!result.Success) { log.Write(LogVerbosity.Error, "Authentication failed, api key is probably invalid"); return(new CallResult <bool>(false, result.Error)); } log.Write(LogVerbosity.Debug, "Auth context retrieved"); var signed = authProvider.Sign(result.Data); var authResult = await socket.InvokeProxy <bool>("Authenticate", authProvider.Credentials.Key.GetString(), signed).ConfigureAwait(false); if (!authResult.Success || !authResult.Data) { log.Write(LogVerbosity.Error, "Authentication failed, api secret is probably invalid"); return(new CallResult <bool>(false, authResult.Error ?? new ServerError("Authentication failed"))); } log.Write(LogVerbosity.Info, "Authentication successful"); return(new CallResult <bool>(true, null)); }
private bool AuthenticationHandler(SocketSubscription subscription, JToken data) { if ((string)data["op"] != "auth") { return(false); } var authResponse = Deserialize <HuobiSocketAuthDataResponse <object> >(data, false); if (!authResponse.Success) { log.Write(LogVerbosity.Warning, "Authorization failed: " + authResponse.Error); subscription.SetEventByName(AuthenticationEvent, false, authResponse.Error); return(true); } if (!authResponse.Data.IsSuccessful) { log.Write(LogVerbosity.Warning, "Authorization failed: " + authResponse.Data.ErrorMessage); subscription.SetEventByName(AuthenticationEvent, false, new ServerError(authResponse.Data.ErrorCode, authResponse.Data.ErrorMessage)); return(true); } log.Write(LogVerbosity.Debug, "Authorization completed"); subscription.SetEventByName(AuthenticationEvent, true, null); return(true); }
protected override bool HandleSubscriptionResponse(SocketConnection s, SocketSubscription subscription, object request, JToken message, out CallResult <object> callResult) { callResult = null; if (message.Type == JTokenType.String && message.ToString() == "pong") { return(false); } if (message["info"] != null && ((string)message["info"]).StartsWith("Welcome")) { log.Write(LogVerbosity.Debug, "skipping welcome message by request"); return(false); } if (message.Type == JTokenType.String && (string)message == "pong") { return(true); } var response = Deserialize <BitmexSubscriptionResponse>(message, false); var bRequest = (BitmexSubscribeRequest)request; if (response) { if (bRequest.Args.Contains(response.Data.Subscribe)) { callResult = new CallResult <object>(response, response.Success ? null : new ServerError("Subscribtion was not success", response)); return(true); } } callResult = new CallResult <object>(response, response.Success ? null : new ServerError("Subscribtion was not success", response)); return(false); }
/// <inheritdoc /> protected override SocketConnection GetWebsocket(string address, bool authenticated) { // Override because signalr puts `/signalr/` add the end of the url var socketResult = sockets.Where(s => s.Value.Socket.Url == address + "/signalr/" && (s.Value.Authenticated == authenticated || !authenticated) && s.Value.Connected).OrderBy(s => s.Value.HandlerCount).FirstOrDefault(); var result = socketResult.Equals(default(KeyValuePair <int, SocketConnection>)) ? null : socketResult.Value; if (result != null) { if (result.HandlerCount < SocketCombineTarget || (sockets.Count >= MaxSocketConnections && sockets.All(s => s.Value.HandlerCount >= SocketCombineTarget))) { // Use existing socket if it has less than target connections OR it has the least connections and we can't make new return(result); } } // Create new socket var socket = CreateSocket(address); var socketWrapper = new SocketConnection(this, socket); foreach (var kvp in genericHandlers) { socketWrapper.AddHandler(SocketSubscription.CreateForIdentifier(kvp.Key, false, kvp.Value)); } return(socketWrapper); }
private bool SubscriptionHandler(SocketSubscription subscription, JToken data) { var evnt = subscription.GetWaitingEvent(SubscriptionEvent); if (evnt == null) { return(false); } if (((int?)data["id"])?.ToString() != evnt.WaitingId) { return(false); } var authResponse = Deserialize <CoinExSocketRequestResponse <CoinExSocketRequestResponseMessage> >(data, false); if (!authResponse.Success) { log.Write(LogVerbosity.Warning, "Subscription failed: " + authResponse.Error); subscription.SetEventById(evnt.WaitingId, false, authResponse.Error); return(true); } if (authResponse.Data.Error != null) { log.Write(LogVerbosity.Debug, $"Failed to subscribe: {authResponse.Data.Error.Code} {authResponse.Data.Error.Message}"); subscription.SetEventById(evnt.WaitingId, false, new ServerError(authResponse.Data.Error.Code, authResponse.Data.Error.Message)); return(true); } log.Write(LogVerbosity.Debug, "Subscription completed"); subscription.SetEventById(evnt.WaitingId, true, null); return(true); }
/// <inheritdoc /> protected override bool HandleSubscriptionResponse(SocketConnection s, SocketSubscription subscription, object request, JToken message, out CallResult <object>?callResult) { callResult = null; if (message.Type != JTokenType.Object) { return(false); } if (message["reqid"] == null) { return(false); } var requestId = (int)message["reqid"]; var kRequest = (KrakenSubscribeRequest)request; if (requestId != kRequest.RequestId) { return(false); } var response = message.ToObject <KrakenSubscriptionEvent>(); kRequest.ChannelId = response.ChannelId; callResult = new CallResult <object>(response, response.Status == "subscribed" ? null: new ServerError(response.ErrorMessage ?? "-")); return(true); }
private bool DataHandlerQuery(SocketSubscription subscription, JToken data, Action <JToken[]> handler) { var evnt = subscription.GetWaitingEvent(DataEvent); if (evnt == null) { return(false); } if (((int?)data["id"])?.ToString() != evnt.WaitingId) { return(false); } if (data["result"].Type == JTokenType.Null) { subscription.SetEventById(evnt.WaitingId, false, new ServerError((int)data["error"]["code"], (string)data["error"]["message"])); } else { handler(new[] { data["result"] }); subscription.SetEventById(evnt.WaitingId, true, null); } return(true); }
public void UnsubscribingAll_Should_CloseAllSockets() { // arrange var client = new TestSocketClient(new SocketClientOptions() { ReconnectInterval = TimeSpan.Zero, LogVerbosity = LogVerbosity.Debug }); var socket1 = client.CreateSocket(); var socket2 = client.CreateSocket(); socket1.CanConnect = true; socket2.CanConnect = true; var sub1 = new SocketSubscription(socket1); var sub2 = new SocketSubscription(socket2); client.ConnectSocketSub(sub1); client.ConnectSocketSub(sub2); // act client.UnsubscribeAll().Wait(); // assert Assert.IsTrue(socket1.Connected == false); Assert.IsTrue(socket2.Connected == false); }
private bool SubscriptionHandlerV2(SocketSubscription subscription, JToken data) { var v2Sub = (string)data["op"] == "sub"; if (!v2Sub) { return(false); } var subResponse = Deserialize <HuobiSocketAuthResponse>(data, false); if (!subResponse.Success) { log.Write(LogVerbosity.Warning, "Subscription failed: " + subResponse.Error); subscription.SetEventByName(SubscriptionEvent, false, subResponse.Error); return(true); } if (!subResponse.Data.IsSuccessful) { log.Write(LogVerbosity.Warning, "Subscription failed: " + subResponse.Data.ErrorMessage); subscription.SetEventByName(SubscriptionEvent, false, new ServerError(subResponse.Data.ErrorCode, subResponse.Data.ErrorMessage)); return(true); } log.Write(LogVerbosity.Debug, "Subscription completed"); subscription.SetEventByName(SubscriptionEvent, true, null); return(true); }
public void SocketMessages_Should_ContainOriginalDataIfEnabled(bool enabled) { // arrange var client = new TestSocketClient(new SocketClientOptions("") { ReconnectInterval = TimeSpan.Zero, LogLevel = LogLevel.Debug, OutputOriginalData = enabled }); var socket = client.CreateSocket(); socket.ShouldReconnect = true; socket.CanConnect = true; socket.DisconnectTime = DateTime.UtcNow; var sub = new SocketConnection(client, socket); var rstEvent = new ManualResetEvent(false); string original = null; sub.AddSubscription(SocketSubscription.CreateForIdentifier(10, "TestHandler", true, (messageEvent) => { original = messageEvent.OriginalData; rstEvent.Set(); })); client.ConnectSocketSub(sub); // act socket.InvokeMessage("{\"property\": 123}"); rstEvent.WaitOne(1000); // assert Assert.IsTrue(original == (enabled ? "{\"property\": 123}" : null)); }
private async Task <CallResult <SocketSubscription> > CreateAndConnectSocket <T>(bool authenticated, bool subscribing, Action <T> onData) { var socket = CreateSocket(BaseAddress); var subscription = new SocketSubscription(socket); if (subscribing) { subscription.MessageHandlers.Add(DataHandlerName, (subs, data) => UpdateHandler(data, onData)); } var connectResult = await ConnectSocket(subscription).ConfigureAwait(false); if (!connectResult.Success) { return(new CallResult <SocketSubscription>(null, connectResult.Error)); } if (authenticated) { var authResult = await Authenticate(subscription).ConfigureAwait(false); if (!authResult.Success) { return(new CallResult <SocketSubscription>(null, authResult.Error)); } } return(new CallResult <SocketSubscription>(subscription, null)); }
protected virtual SocketConnection BitMaxGetWebsocket(string address, bool authenticated) { address = address.TrimEnd('/'); var socketResult = sockets.Where(s => s.Value.Socket.Url.TrimEnd('/') == address.TrimEnd('/') && (s.Value.Authenticated == authenticated || !authenticated) && s.Value.Connected).OrderBy(s => s.Value.HandlerCount).FirstOrDefault(); var result = socketResult.Equals(default(KeyValuePair <int, SocketConnection>)) ? null : socketResult.Value; if (result != null) { if (result.HandlerCount < SocketCombineTarget || (sockets.Count >= MaxSocketConnections && sockets.All(s => s.Value.HandlerCount >= SocketCombineTarget))) { // Use existing socket if it has less than target connections OR it has the least connections and we can't make new return(result); } } // Create new socket var socket = CreateSocket(address); var socketWrapper = new SocketConnection(this, socket); foreach (var kvp in genericHandlers) { var handler = SocketSubscription.CreateForIdentifier(kvp.Key, false, kvp.Value); socketWrapper.AddHandler(handler); } return(socketWrapper); }
private async Task <CallResult <bool> > Authenticate(SocketSubscription subscription) { if (authProvider == null) { return(new CallResult <bool>(false, new NoApiCredentialsError())); } var authParams = authProvider.AddAuthenticationToParameters(baseAddressAuthenticated, Constants.GetMethod, new Dictionary <string, object>(), true); var authObjects = new HuobiAuthenticationRequest { AccessKeyId = authProvider.Credentials.Key.GetString(), Operation = "auth", SignatureMethod = (string)authParams["SignatureMethod"], SignatureVersion = authParams["SignatureVersion"].ToString(), Timestamp = (string)authParams["Timestamp"], Signature = (string)authParams["Signature"] }; Send(subscription.Socket, authObjects); var authResult = await subscription.WaitForEvent(AuthenticationEvent, socketResponseTimeout).ConfigureAwait(false); if (!authResult.Success) { await subscription.Close().ConfigureAwait(false); return(new CallResult <bool>(false, authResult.Error)); } return(new CallResult <bool>(true, null)); }
protected override bool HandleSubscriptionResponse(SocketConnection s, SocketSubscription subscription, object request, JToken message, out CallResult <object> callResult) { var error = message["error"]; callResult = new CallResult <object>(request, error == null?null:new ServerError(error["message"].ToString(), error)); return(message["result"] != null && (bool)message["result"] == true); }
private bool SubscriptionHandlerV1(SocketSubscription subscription, JToken data) { var v1Sub = data["subbed"] != null; var v1Error = data["status"] != null && (string)data["status"] == "error"; if (v1Sub || v1Error) { var subResponse = Deserialize <HuobiSubscribeResponse>(data, false); if (!subResponse.Success) { log.Write(LogVerbosity.Warning, "Subscription failed: " + subResponse.Error); subscription.SetEventByName(SubscriptionEvent, false, subResponse.Error); return(true); } if (!subResponse.Data.IsSuccessful) { log.Write(LogVerbosity.Warning, "Subscription failed: " + subResponse.Data.ErrorMessage); subscription.SetEventByName(SubscriptionEvent, false, new ServerError($"{subResponse.Data.ErrorCode}, {subResponse.Data.ErrorMessage}")); return(true); } log.Write(LogVerbosity.Debug, "Subscription completed"); subscription.SetEventByName(SubscriptionEvent, true, null); return(true); } return(false); }
public void WhenResubscribeFails_Socket_ShouldReconnect() { // arrange int reconnected = 0; var client = new TestSocketClient(new SocketClientOptions() { ReconnectInterval = TimeSpan.FromMilliseconds(1), LogVerbosity = LogVerbosity.Debug }); var socket = client.CreateSocket(); socket.ShouldReconnect = true; socket.CanConnect = true; socket.DisconnectTime = DateTime.UtcNow; var sub = new SocketSubscription(socket); client.ConnectSocketSub(sub); var rstEvent = new ManualResetEvent(false); client.OnReconnect += () => { reconnected++; rstEvent.Set(); return(reconnected == 2); }; // act socket.InvokeClose(); rstEvent.WaitOne(1000); Thread.Sleep(100); // assert Assert.IsTrue(reconnected == 2); }
/// <summary> /// The message handler. Normally distributes the received data to all data handlers /// </summary> /// <param name="subscription">The subscription that received the data</param> /// <param name="data">The data received</param> protected virtual void ProcessMessage(SocketSubscription subscription, string data) { log.Write(LogVerbosity.Debug, $"Socket {subscription.Socket.Id} received data: " + data); string currentHandlerName = null; try { var sw = Stopwatch.StartNew(); foreach (var handler in subscription.MessageHandlers) { currentHandlerName = handler.Key; if (handler.Value(subscription, JToken.Parse(data))) { break; } } sw.Stop(); if (sw.ElapsedMilliseconds > 500) { log.Write(LogVerbosity.Warning, $"Socket {subscription.Socket.Id} message processing slow ({sw.ElapsedMilliseconds}ms), consider offloading data handling to another thread. " + "Data from this socket may arrive late or not at all if message processing is continuously slow."); } } catch (Exception ex) { log.Write(LogVerbosity.Error, $"Socket {subscription.Socket.Id} Exception during message processing\r\nProcessor: {currentHandlerName}\r\nException: {ex}\r\nData: {data}"); } }
public void DisconnectedSocket_Should_Reconnect() { // arrange bool reconnected = false; var client = new TestSocketClient(new SocketClientOptions() { ReconnectInterval = TimeSpan.Zero, LogVerbosity = LogVerbosity.Debug }); var socket = client.CreateSocket(); socket.ShouldReconnect = true; socket.CanConnect = true; socket.DisconnectTime = DateTime.UtcNow; var sub = new SocketSubscription(socket); client.ConnectSocketSub(sub); var rstEvent = new ManualResetEvent(false); client.OnReconnect += () => { reconnected = true; rstEvent.Set(); return(true); }; // act socket.InvokeClose(); rstEvent.WaitOne(1000); // assert Assert.IsTrue(reconnected); }
private bool DataHandlerV1 <T>(SocketSubscription subscription, JToken data, Action <T> handler) where T : class { var v1Data = (data["data"] != null || data["tick"] != null) && (data["rep"] != null || data["ch"] != null); var v1Error = data["status"] != null && (string)data["status"] == "error"; if (!v1Data && !v1Error) { return(false); } if (!v1Data && subscription.GetWaitingEvent(DataEvent) == null) { return(false); } var desResult = Deserialize <T>(data, false); if (!desResult.Success) { log.Write(LogVerbosity.Warning, $"Failed to deserialize data: {desResult.Error}. Data: {data}"); return(false); } handler(desResult.Data); subscription.SetEventByName(DataEvent, true, null); return(true); }
public void SocketMessages_Should_BeProcessedInDataHandlers() { // arrange var client = new TestSocketClient(new SocketClientOptions("") { ReconnectInterval = TimeSpan.Zero, LogVerbosity = LogVerbosity.Debug }); var socket = client.CreateSocket(); socket.ShouldReconnect = true; socket.CanConnect = true; socket.DisconnectTime = DateTime.UtcNow; var sub = new SocketConnection(client, socket); var rstEvent = new ManualResetEvent(false); JToken result = null; sub.AddHandler(SocketSubscription.CreateForIdentifier("TestHandler", true, (connection, data) => { result = data; rstEvent.Set(); })); client.ConnectSocketSub(sub); // act socket.InvokeMessage("{\"property\": 123}"); rstEvent.WaitOne(1000); // assert Assert.IsTrue((int)result["property"] == 123); }
public void SocketMessages_Should_BeProcessedInSubsequentHandlersIfHandlerReturnsFalse() { // arrange var client = new TestSocketClient(new SocketClientOptions() { ReconnectInterval = TimeSpan.Zero, LogVerbosity = LogVerbosity.Debug }); var socket = client.CreateSocket(); socket.ShouldReconnect = true; socket.CanConnect = true; socket.DisconnectTime = DateTime.UtcNow; var sub = new SocketSubscription(socket); var rstEvent = new ManualResetEvent(false); JToken result = null; sub.MessageHandlers.Add("TestHandlerNotProcessing", (subs, data) => { return(false); }); sub.MessageHandlers.Add("TestHandler", (subs, data) => { result = data; rstEvent.Set(); return(true); }); client.ConnectSocketSub(sub); // act socket.InvokeMessage("{\"property\": 123}"); rstEvent.WaitOne(100); // assert Assert.IsTrue((int)result["property"] == 123); }
private async Task <CallResult <bool> > Authenticate(SocketSubscription subscription) { if (authProvider == null) { return(new CallResult <bool>(false, new NoApiCredentialsError())); } var request = new CoinExSocketRequest(ServerSubject, AuthenticateAction, true, GetAuthParameters()) { Id = NextId() }; var waitTask = subscription.WaitForEvent(AuthenticationEvent, request.Id.ToString(), subResponseTimeout); Send(subscription.Socket, request); var authResult = await waitTask.ConfigureAwait(false); if (!authResult.Success) { var closeTask = subscription.Close(); return(new CallResult <bool>(false, authResult.Error)); } return(new CallResult <bool>(true, null)); }
protected virtual void OnJoinPresentation(Presentation presentation, SocketSubscription sender) { presentation.Join(new Attendee(sender)); sender.Connection.SendEvent(new JoinedPresentation { Name = presentation.Name, CurrentSlide = presentation.CurrentSlide }); }
public virtual void StartOrJoinPresentation(SocketSubscription sender, TextMessage message) { var cmd = message.ToCommand<StartOrJoinPresentation>(); var presentation = Presentations.GetPresentationByName(cmd.Name); if(presentation == null) OnStartPresentation(cmd, sender); else OnJoinPresentation(presentation, sender); }
private bool PingHandlerV2(SocketSubscription subscription, JToken data) { var v2Ping = (string)data["op"] == "ping"; if (v2Ping) { Send(subscription.Socket, new HuobiPingAuthResponse((long)data["ts"])); } return(v2Ping); }
private bool PingHandlerV1(SocketSubscription subscription, JToken data) { var v1Ping = data["ping"] != null; if (v1Ping) { Send(subscription.Socket, new HuobiPingResponse((long)data["ping"])); } return(v1Ping); }
protected override bool HandleSubscriptionResponse(SocketConnection s, SocketSubscription subscription, object request, JToken data, out CallResult <object> callResult) { callResult = null; if (data.Type != JTokenType.Object) { return(false); } var infoEvent = (string)data["event"] == "subscribed"; var errorEvent = (string)data["event"] == "error"; if (!infoEvent && !errorEvent) { return(false); } if (infoEvent) { var subResponse = Deserialize <BitfinexSubscribeResponse>(data, false); if (!subResponse.Success) { callResult = new CallResult <object>(null, subResponse.Error); log.Write(LogVerbosity.Warning, $"Socket {s.Socket.Id} subscription failed: " + subResponse.Error); return(false); } var bRequest = (BitfinexSubscriptionRequest)request; if (bRequest.Channel != subResponse.Data.Channel) { return(false); } log.Write(LogVerbosity.Debug, $"Socket {s.Socket.Id} subscription completed"); bRequest.ChannelId = subResponse.Data.ChannelId; callResult = new CallResult <object>(subResponse.Data, subResponse.Error); return(true); } else { var subResponse = Deserialize <BitfinexErrorResponse>(data, false); if (!subResponse.Success) { callResult = new CallResult <object>(null, subResponse.Error); log.Write(LogVerbosity.Warning, $"Socket {s.Socket.Id} subscription failed: " + subResponse.Error); return(false); } var error = new ServerError(subResponse.Data.Code, subResponse.Data.Message); callResult = new CallResult <object>(null, error); log.Write(LogVerbosity.Debug, $"Socket {s.Socket.Id} subscription failed: " + error); return(true); } }
/// <summary> /// Connect a socket /// </summary> /// <param name="socketSubscription">The subscription to connect</param> /// <returns></returns> protected virtual async Task <CallResult <bool> > ConnectSocket(SocketSubscription socketSubscription) { socketSubscription.Socket.OnMessage += data => ProcessMessage(socketSubscription, data); if (await socketSubscription.Socket.Connect().ConfigureAwait(false)) { lock (sockets) sockets.Add(socketSubscription); return(new CallResult <bool>(true, null)); } socketSubscription.Socket.Dispose(); return(new CallResult <bool>(false, new CantConnectError())); }
protected override bool SocketReconnect(SocketSubscription subscription, TimeSpan disconnectedTime) { var request = (CoinExSocketRequest)subscription.Request; if (request.Signed) { if (!Authenticate(subscription).Result.Success) { return(false); } } return(Subscribe(subscription, request).Result.Success); }
public virtual void ChangeSlide(SocketSubscription sender, TextMessage message) { var cmd = message.ToCommand<ChangeSlide>(); var presentation = Presentations.GetPresentationIfPresenter(sender); if (presentation == null) return; if(presentation.Presenter.ChangeSlide(cmd.NewSlide)) sender.Server.BroadCastEvent( presentation.GetAttendees().Select(a => a.Subscription), new SlideChanged { NewSlide = cmd.NewSlide }); }
protected override bool SocketReconnect(SocketSubscription subscription, TimeSpan disconnectedTime) { var request = (HuobiRequest)subscription.Request; if (request.Signed) { if (!Authenticate(subscription).Result.Success) { return(false); } } Send(subscription.Socket, request); return(subscription.WaitForEvent(SubscriptionEvent, socketResponseTimeout).Result.Success); }
private async Task <CallResult <UpdateSubscription> > Subscribe(SocketSubscription subscription, ConnectionRequest request) { if (request.RequestName != null) { var subResult = await((ISignalRSocket)subscription.Socket).InvokeProxy <bool>(request.RequestName, request.Parameters).ConfigureAwait(false); if (!subResult.Success || !subResult.Data) { var closeTask = subscription.Close(); return(new CallResult <UpdateSubscription>(null, subResult.Error ?? new ServerError("Subscribe returned false"))); } } subscription.Request = request; subscription.Socket.ShouldReconnect = true; return(new CallResult <UpdateSubscription>(new UpdateSubscription(subscription), null)); }
protected virtual void OnStartPresentation(StartOrJoinPresentation cmd, SocketSubscription sender) { var presentation = new Presentation(cmd.Name, new Presenter(sender)); if (Presentations.AddIfNew(presentation)) { presentation.Presenter.Subscription.OnDesubscribe = () => { Presentations.Remove(presentation); presentation.End(); }; sender.Connection.SendEvent(new PresentationStarted { Name = presentation.Name }); } }
public Presenter(SocketSubscription subscription) : base(subscription) { }
protected virtual void OnRecieved(SocketSubscription subscription, BinaryMessage message) { Parallel.ForEach(Routes.GetMathingBinaryMessageRoutes(subscription), r => r.Handler(subscription, message)); }
protected virtual void OnRecieved(SocketSubscription subscription, TextMessage message) { if(message.Action.Equals("Ping", StringComparison.OrdinalIgnoreCase)) { OnPing(subscription, message); return; } Parallel.ForEach(Routes.GetMathingTextMessageRoutes(message.Action, subscription), r => r.Handler(subscription, message)); }
protected virtual void OnPing(SocketSubscription subscription, TextMessage message) { subscription.Connection.SendResponse("OnPinged", "Echo: '{0}'.".Inject(message.Data)); }
public Attendee(SocketSubscription subscription) : base(subscription) { }
public static Presentation GetPresentationIfPresenter(SocketSubscription subscription) { return State.SingleOrDefault(p => p.Presenter.Subscription.Equals(subscription)); }
public virtual IEnumerable<BinaryMessageRoute> GetMathingBinaryMessageRoutes(SocketSubscription subscription) { return BinaryMessageRoutes.Where(r => r.Predicate(subscription)); }
public virtual IEnumerable<TextMessageRoute> GetMathingTextMessageRoutes(string action, SocketSubscription subscription) { return TextMessageRoutes.Where(r => r.Predicate(subscription, action)); }