void IManager.TryToReconnect() { if (this.State == SocketManager.States.Reconnecting || this.State == SocketManager.States.Closed) { return; } if (!this.Options.Reconnection) { ((IManager)this).EmitAll(EventNames.GetNameFor(SocketIOEventTypes.Disconnect), new object[0]); this.Close(); return; } if (++this.ReconnectAttempts >= this.Options.ReconnectionAttempts) { ((IManager)this).EmitEvent("reconnect_failed", new object[0]); this.Close(); return; } Random random = new Random(); int num = (int)this.Options.ReconnectionDelay.TotalMilliseconds * this.ReconnectAttempts; this.ReconnectAt = DateTime.UtcNow + TimeSpan.FromMilliseconds((double)Math.Min(random.Next((int)((float)num - (float)num * this.Options.RandomizationFactor), (int)((float)num + (float)num * this.Options.RandomizationFactor)), (int)this.Options.ReconnectionDelayMax.TotalMilliseconds)); ((IManager)this).Close(false); this.State = SocketManager.States.Reconnecting; for (int i = 0; i < this.Sockets.Count; i++) { ((ISocket)this.Sockets[i]).Open(); } HTTPManager.Heartbeats.Subscribe(this); HTTPManager.Logger.Information("SocketManager", "Reconnecting"); }
void IHeartbeat.OnHeartbeatUpdate(TimeSpan dif) { switch (this.State) { case SocketManager.States.Opening: if (DateTime.UtcNow - this.ConnectionStarted >= this.Options.Timeout) { ((IManager)this).EmitEvent("connect_error", new object[0]); ((IManager)this).EmitEvent("connect_timeout", new object[0]); ((IManager)this).TryToReconnect(); } break; case SocketManager.States.Open: { ITransport transport; if (this.Transport != null && this.Transport.State == TransportStates.Open) { transport = this.Transport; } else { transport = this.Poller; } if (transport == null || transport.State != TransportStates.Open) { return; } transport.Poll(); this.SendOfflinePackets(); if (this.LastHeartbeat == DateTime.MinValue) { this.LastHeartbeat = DateTime.UtcNow; return; } if (DateTime.UtcNow - this.LastHeartbeat > this.Handshake.PingInterval) { ((IManager)this).SendPacket(new Packet(TransportEventTypes.Ping, SocketIOEventTypes.Unknown, "/", string.Empty, 0, 0)); this.LastHeartbeat = DateTime.UtcNow; } if (DateTime.UtcNow - this.LastPongReceived > this.Handshake.PingTimeout) { ((IManager)this).EmitAll(EventNames.GetNameFor(SocketIOEventTypes.Disconnect), new object[0]); ((IManager)this).TryToReconnect(); } break; } case SocketManager.States.Reconnecting: if (this.ReconnectAt != DateTime.MinValue && DateTime.UtcNow >= this.ReconnectAt) { ((IManager)this).EmitEvent("reconnect_attempt", new object[0]); ((IManager)this).EmitEvent("reconnecting", new object[0]); this.Open(); } break; } }
/// <summary> /// Internal constructor. /// </summary> internal Socket(string nsp, SocketManager manager) { this.Context = new LoggingContext(this); this.Context.Add("nsp", nsp); this.Namespace = nsp; this.Manager = manager; this.IsOpen = false; this.TypedEventTable = new TypedEventTable(this); this.On <ConnectResponse>(EventNames.GetNameFor(SocketIOEventTypes.Connect), OnConnected); }
/// <summary> /// Last call of the OnPacket chain(Transport -> Manager -> Socket), we will dispatch the event if there is any callback /// </summary> void ISocket.OnPacket(Packet packet) { // Some preprocessing of the the packet switch (packet.SocketIOEvent) { case SocketIOEventTypes.Disconnect: if (IsOpen) { IsOpen = false; EventCallbacks.Call(EventNames.GetNameFor(SocketIOEventTypes.Disconnect), packet); Disconnect(); } break; // Create an Error object from the server-sent json string case SocketIOEventTypes.Error: bool success = false; var errDict = JSON.Json.Decode(packet.Payload, ref success) as Dictionary <string, object>; if (success) { Error err = new Error((SocketIOErrors)Convert.ToInt32(errDict["code"]), errDict["message"] as string); EventCallbacks.Call(EventNames.GetNameFor(SocketIOEventTypes.Error), packet, err); return; } break; } // Dispatch the event to all subscriber EventCallbacks.Call(packet); // call Ack callbacks if ((packet.SocketIOEvent == SocketIOEventTypes.Ack || packet.SocketIOEvent == SocketIOEventTypes.BinaryAck) && AckCallbacks != null) { SocketIOAckCallback ackCallback = null; if (AckCallbacks.TryGetValue(packet.Id, out ackCallback) && ackCallback != null) { try { ackCallback(this, packet, packet.Decode(Manager.Encoder)); } catch (Exception ex) { HTTPManager.Logger.Exception("Socket", "ackCallback", ex); } } AckCallbacks.Remove(packet.Id); } }
/// <summary> /// Called from a ITransport implemetation when an error occures and we may have to try to reconnect. /// </summary> void IManager.TryToReconnect() { if (State == States.Reconnecting || State == States.Closed) { return; } if (!Options.Reconnection) { (this as IManager).EmitAll(EventNames.GetNameFor(SocketIOEventTypes.Disconnect)); Close(); return; } if (++ReconnectAttempts >= Options.ReconnectionAttempts) { (this as IManager).EmitEvent("reconnect_failed"); Close(); return; } Random rand = new Random(); int delay = (int)Options.ReconnectionDelay.TotalMilliseconds * ReconnectAttempts; ReconnectAt = DateTime.UtcNow + TimeSpan.FromMilliseconds(Math.Min(rand.Next(/*rand min:*/ (int)(delay - (delay * Options.RandomizationFactor)), /*rand max:*/ (int)(delay + (delay * Options.RandomizationFactor))), (int)Options.ReconnectionDelayMax.TotalMilliseconds)); (this as IManager).Close(false); State = States.Reconnecting; for (int i = 0; i < Sockets.Count; ++i) { (Sockets[i] as ISocket).Open(); } // In the Close() function we unregistered HTTPManager.Heartbeats.Subscribe(this); HTTPManager.Logger.Information("SocketManager", "Reconnecting"); }
void ISocket.OnPacket(Packet packet) { switch (packet.SocketIOEvent) { case SocketIOEventTypes.Disconnect: if (this.IsOpen) { this.IsOpen = false; this.Disconnect(); } break; case SocketIOEventTypes.Error: { bool flag = false; Dictionary <string, object> dictionary = Json.Decode(packet.Payload, ref flag) as Dictionary <string, object>; if (flag) { Error error = new Error((SocketIOErrors)Convert.ToInt32(dictionary["code"]), dictionary["message"] as string); this.EventCallbacks.Call(EventNames.GetNameFor(SocketIOEventTypes.Error), packet, new object[] { error }); return; } break; } } this.EventCallbacks.Call(packet); if ((packet.SocketIOEvent == SocketIOEventTypes.Ack || packet.SocketIOEvent == SocketIOEventTypes.BinaryAck) && this.AckCallbacks != null) { SocketIOAckCallback socketIOAckCallback = null; if (this.AckCallbacks.TryGetValue(packet.Id, out socketIOAckCallback) && socketIOAckCallback != null) { try { socketIOAckCallback(this, packet, packet.Decode(this.Manager.Encoder)); } catch (Exception ex) { HTTPManager.Logger.Exception("Socket", "ackCallback", ex); } } this.AckCallbacks.Remove(packet.Id); } }
void ISocket.OnPacket(Packet packet) { switch (packet.SocketIOEvent) { case SocketIOEventTypes.Disconnect: if (IsOpen) { IsOpen = false; EventCallbacks.Call(EventNames.GetNameFor(SocketIOEventTypes.Disconnect), packet); Disconnect(); } break; case SocketIOEventTypes.Error: { bool success = false; Dictionary <string, object> dictionary = Json.Decode(packet.Payload, ref success) as Dictionary <string, object>; if (success) { Error error = new Error((SocketIOErrors)Convert.ToInt32(dictionary["code"]), dictionary["message"] as string); EventCallbacks.Call(EventNames.GetNameFor(SocketIOEventTypes.Error), packet, error); return; } break; } } EventCallbacks.Call(packet); if ((packet.SocketIOEvent == SocketIOEventTypes.Ack || packet.SocketIOEvent == SocketIOEventTypes.BinaryAck) && AckCallbacks != null) { SocketIOAckCallback value = null; if (AckCallbacks.TryGetValue(packet.Id, out value) && value != null) { try { value(this, packet, packet.Decode(Manager.Encoder)); } catch (Exception ex) { HTTPManager.Logger.Exception("Socket", "ackCallback", ex); } } AckCallbacks.Remove(packet.Id); } }
public IncomingPacket(TransportEventTypes transportEvent, SocketIOEventTypes packetType, string nsp, int id) { this.TransportEvent = transportEvent; this.SocketIOEvent = packetType; this.Namespace = nsp; this.Id = id; this.AttachementCount = 0; //this.ReceivedAttachements = 0; this.Attachements = null; if (this.SocketIOEvent != SocketIOEventTypes.Unknown) { this.EventName = EventNames.GetNameFor(this.SocketIOEvent); } else { this.EventName = EventNames.GetNameFor(this.TransportEvent); } this.DecodedArg = this.DecodedArgs = null; }
public void On(SocketIOEventTypes type, SocketIOCallback callback, bool autoDecodePayload) { string nameFor = EventNames.GetNameFor(type); EventCallbacks.Register(nameFor, callback, onlyOnce: false, autoDecodePayload); }
/// <summary> /// Last call of the OnPacket chain(Transport -> Manager -> Socket), we will dispatch the event if there is any callback /// </summary> void ISocket.OnPacket(Packet packet) { // Some preprocessing of the packet switch (packet.SocketIOEvent) { case SocketIOEventTypes.Connect: this.Id = this.Namespace != "/" ? this.Namespace + "#" + this.Manager.Handshake.Sid : this.Manager.Handshake.Sid; break; case SocketIOEventTypes.Disconnect: if (IsOpen) { IsOpen = false; EventCallbacks.Call(EventNames.GetNameFor(SocketIOEventTypes.Disconnect), packet); Disconnect(); } break; // Create an Error object from the server-sent json string case SocketIOEventTypes.Error: bool success = false; object result = JSON.Json.Decode(packet.Payload, ref success); if (success) { var errDict = result as Dictionary <string, object>; Error err; if (errDict != null && errDict.ContainsKey("code")) { err = new Error((SocketIOErrors)Convert.ToInt32(errDict["code"]), errDict["message"] as string); } else { err = new Error(SocketIOErrors.Custom, packet.Payload); } EventCallbacks.Call(EventNames.GetNameFor(SocketIOEventTypes.Error), packet, err); return; } break; } // Dispatch the event to all subscriber EventCallbacks.Call(packet); // call Ack callbacks if ((packet.SocketIOEvent == SocketIOEventTypes.Ack || packet.SocketIOEvent == SocketIOEventTypes.BinaryAck) && AckCallbacks != null) { SocketIOAckCallback ackCallback = null; if (AckCallbacks.TryGetValue(packet.Id, out ackCallback) && ackCallback != null) { try { ackCallback(this, packet, this.AutoDecodePayload ? packet.Decode(Manager.Encoder) : null); } catch (Exception ex) { HTTPManager.Logger.Exception("Socket", "ackCallback", ex); } } AckCallbacks.Remove(packet.Id); } }
/// <summary> /// Remove the specified callback. /// </summary> public void Off(SocketIOEventTypes type, SocketIOCallback callback) { EventCallbacks.Unregister(EventNames.GetNameFor(type), callback); }
/// <summary> /// Removes all callbacks to the given event. /// </summary> public void Off(SocketIOEventTypes type) { Off(EventNames.GetNameFor(type)); }
public void Once(SocketIOEventTypes type, SocketIOCallback callback, bool autoDecodePayload) { EventCallbacks.Register(EventNames.GetNameFor(type), callback, true, autoDecodePayload); }
public void On(SocketIOEventTypes type, SocketIOCallback callback, bool autoDecodePayload) { string eventName = EventNames.GetNameFor(type); EventCallbacks.Register(eventName, callback, false, autoDecodePayload); }
/// <summary> /// Last call of the OnPacket chain(Transport -> Manager -> Socket), we will dispatch the event if there is any callback /// </summary> void ISocket.OnPacket(Packet packet) { // Some preprocessing of the packet switch (packet.SocketIOEvent) { case SocketIOEventTypes.Connect: if (this.Manager.Options.ServerVersion != SupportedSocketIOVersions.v3) { this.Id = this.Namespace != "/" ? this.Namespace + "#" + this.Manager.Handshake.Sid : this.Manager.Handshake.Sid; } else { var data = JSON.Json.Decode(packet.Payload) as Dictionary <string, object>; this.Id = data["sid"].ToString(); } this.IsOpen = true; break; case SocketIOEventTypes.Disconnect: if (IsOpen) { IsOpen = false; EventCallbacks.Call(EventNames.GetNameFor(SocketIOEventTypes.Disconnect), packet); Disconnect(); } break; // Create an Error object from the server-sent json string case SocketIOEventTypes.Error: bool success = false; object result = JSON.Json.Decode(packet.Payload, ref success); if (success) { var errDict = result as Dictionary <string, object>; Error err = null; if (errDict != null) { object tmpObject = null; string code = null; if (errDict.TryGetValue("code", out tmpObject)) { code = tmpObject.ToString(); } int errorCode; if (code != null && int.TryParse(code, out errorCode) && errorCode >= 0 && errorCode <= 7) { errDict.TryGetValue("message", out tmpObject); err = new Error((SocketIOErrors)errorCode, tmpObject != null ? tmpObject.ToString() : string.Empty); } } if (err == null) { err = new Error(SocketIOErrors.Custom, packet.Payload); } EventCallbacks.Call(EventNames.GetNameFor(SocketIOEventTypes.Error), packet, err); return; } break; } // Dispatch the event to all subscriber EventCallbacks.Call(packet); // call Ack callbacks if ((packet.SocketIOEvent == SocketIOEventTypes.Ack || packet.SocketIOEvent == SocketIOEventTypes.BinaryAck) && AckCallbacks != null) { SocketIOAckCallback ackCallback = null; if (AckCallbacks.TryGetValue(packet.Id, out ackCallback) && ackCallback != null) { try { ackCallback(this, packet, this.AutoDecodePayload ? packet.Decode(Manager.Encoder) : null); } catch (Exception ex) { HTTPManager.Logger.Exception("Socket", "ackCallback", ex); } } AckCallbacks.Remove(packet.Id); } }
public void On(SocketIOEventTypes eventType, Action callback) { this.TypedEventTable.Register(EventNames.GetNameFor(eventType), null, _ => callback()); }
/// <summary> /// Called from the HTTPManager's OnUpdate function every frame. It's main function is to send out heartbeat messages. /// </summary> void IHeartbeat.OnHeartbeatUpdate(TimeSpan dif) { switch (State) { case States.Opening: if (DateTime.UtcNow - ConnectionStarted >= Options.Timeout) { (this as IManager).EmitEvent("connect_error"); (this as IManager).EmitEvent("connect_timeout"); (this as IManager).TryToReconnect(); } break; case States.Reconnecting: if (ReconnectAt != DateTime.MinValue && DateTime.UtcNow >= ReconnectAt) { (this as IManager).EmitEvent("reconnect_attempt"); (this as IManager).EmitEvent("reconnecting"); Open(); } break; case States.Open: ITransport trans = null; // Select transport to use if (Transport != null && Transport.State == TransportStates.Open) { trans = Transport; } else { trans = Poller; } // not yet open? if (trans == null || trans.State != TransportStates.Open) { return; } // Start to poll the server for events trans.Poll(); // Start to send out unsent packets SendOfflinePackets(); // First time we reached this point. Set the LastHeartbeat to the current time, 'cause we are just opened. if (LastHeartbeat == DateTime.MinValue) { LastHeartbeat = DateTime.UtcNow; return; } // It's time to send out a ping event to the server if (DateTime.UtcNow - LastHeartbeat > Handshake.PingInterval) { (this as IManager).SendPacket(new Packet(TransportEventTypes.Ping, SocketIOEventTypes.Unknown, "/", string.Empty)); LastHeartbeat = DateTime.UtcNow; } // No pong event received in the given time, we are disconnected. if (DateTime.UtcNow - LastPongReceived > Handshake.PingTimeout) { (this as IManager).EmitAll(EventNames.GetNameFor(SocketIOEventTypes.Disconnect)); (this as IManager).TryToReconnect(); } break; // case States.Open: } }
void ISocket.EmitEvent(SocketIOEventTypes type, params object[] args) { ((ISocket)this).EmitEvent(EventNames.GetNameFor(type), args); }
public void On <T>(SocketIOEventTypes eventType, Action <T> callback) { this.TypedEventTable.Register(EventNames.GetNameFor(eventType), new Type[] { typeof(T) }, (args) => callback((T)args[0])); }
/// <summary> /// Emits an internal packet-less event to the root namespace without creating it if it isn't exists yet. /// </summary> void IManager.EmitEvent(SocketIOEventTypes type, params object[] args) { (this as IManager).EmitEvent(EventNames.GetNameFor(type), args); }
public void On(SocketIOEventTypes type, SocketIOCallback callback) { string nameFor = EventNames.GetNameFor(type); this.EventCallbacks.Register(nameFor, callback, false, this.AutoDecodePayload); }