/// <summary> /// Closes the connection and shuts down the transport. /// </summary> public void Close() { if (this.State == ConnectionStates.Closed) return; this.State = ConnectionStates.Closed; ReconnectStartedAt = null; TransportConnectionStartedAt = null; if (Transport != null) { Transport.Abort(); Transport = null; } NegotiationResult = null; HTTPManager.Heartbeats.Unsubscribe(this); LastReceivedMessage = null; if (Hubs != null) for (int i = 0; i < Hubs.Length; ++i) (Hubs[i] as IHub).Close(); if (BufferedMessages != null) { BufferedMessages.Clear(); BufferedMessages = null; } if (OnClosed != null) { try { OnClosed(this); } catch (Exception ex) { HTTPManager.Logger.Exception("SignalR Connection", "OnClosed", ex); } } }
/// <summary> /// Called when we receive a message from the server /// </summary> void IConnection.OnMessage(IServerMessage msg) { if (this.State == ConnectionStates.Closed) return; // Store messages that we receive while we are connecting if (this.State == ConnectionStates.Connecting) { if (BufferedMessages == null) BufferedMessages = new List<IServerMessage>(); BufferedMessages.Add(msg); return; } LastMessageReceivedAt = DateTime.UtcNow; switch(msg.Type) { case MessageTypes.Multiple: LastReceivedMessage = msg as MultiMessage; // Not received in the reconnect process, so we can't rely on it if (LastReceivedMessage.IsInitialization) HTTPManager.Logger.Information("SignalR Connection", "OnMessage - Init"); if (LastReceivedMessage.GroupsToken != null) GroupsToken = LastReceivedMessage.GroupsToken; if (LastReceivedMessage.ShouldReconnect) { HTTPManager.Logger.Information("SignalR Connection", "OnMessage - Should Reconnect"); Reconnect(); // Should we return here not processing the messages that may come with it? //return; } if (LastReceivedMessage.Data != null) for (int i = 0; i < LastReceivedMessage.Data.Count; ++i) (this as IConnection).OnMessage(LastReceivedMessage.Data[i]); break; case MessageTypes.MethodCall: MethodCallMessage methodCall = msg as MethodCallMessage; Hub hub = this[methodCall.Hub]; if (hub != null) (hub as IHub).OnMethod(methodCall); else HTTPManager.Logger.Warning("SignalR Connection", string.Format("Hub \"{0}\" not found!", methodCall.Hub)); break; case MessageTypes.Result: case MessageTypes.Failure: case MessageTypes.Progress: UInt64 id = (msg as IHubMessage).InvocationId; hub = FindHub(id); if (hub != null) (hub as IHub).OnMessage(msg); else HTTPManager.Logger.Warning("SignalR Connection", string.Format("No Hub found for Progress message! Id: {0}", id.ToString())); break; case MessageTypes.Data: if (OnNonHubMessage != null) OnNonHubMessage(this, (msg as DataMessage).Data); break; case MessageTypes.KeepAlive: break; default: HTTPManager.Logger.Warning("SignalR Connection", "Unknown message type received: " + msg.Type.ToString()); break; } }
/// <summary> /// When the json string is successfully parsed will return with an IServerMessage implementation. /// </summary> public static IServerMessage Parse(IJsonEncoder encoder, string json) { // Nothing to parse? if (string.IsNullOrEmpty(json)) { HTTPManager.Logger.Error("MessageFactory", "Parse - called with empty or null string!"); return null; } // We don't have to do further decoding, if it's an empty json object, then it's a KeepAlive message from the server if (json.Length == 2 && json == "{}") return new KeepAliveMessage(); IDictionary<string, object> msg = null; try { // try to decode the json message with the encoder msg = encoder.DecodeMessage(json); } catch(Exception ex) { HTTPManager.Logger.Exception("MessageFactory", "Parse - encoder.DecodeMessage", ex); return null; } if (msg == null) { HTTPManager.Logger.Error("MessageFactory", "Parse - Json Decode failed for json string: \"" + json + "\""); return null; } // "C" is for message id IServerMessage result = null; if (!msg.ContainsKey("C")) { // If there are no ErrorMessage in the object, then it was a success if (!msg.ContainsKey("E")) result = new ResultMessage(); else result = new FailureMessage(); } else result = new MultiMessage(); result.Parse(msg); return result; }