/// <summary> /// Called when a pending server gets dropped. /// </summary> /// <param name="pendingServer">The pending server that has been dropped.</param> internal void HandleServerDroppedBeforeReady(PendingDownstreamRemoteServer pendingServer) { logger.Trace($"Server at [{pendingServer.Connection.RemoteEndPoints.Format()}] did not identifiy itself in time."); lock (pendingDownstreamServers) pendingDownstreamServers.Remove(pendingServer); }
/// <summary> /// Called when a new server connects to this server. /// </summary> /// <param name="connection">The new connection.</param> internal void HandleNewConnection(NetworkServerConnection connection) { //TODO make configurable PendingDownstreamRemoteServer server = new PendingDownstreamRemoteServer(connection, 10000, HandleServerReady, HandleServerDroppedBeforeReady, logger); lock (pendingDownstreamServers) pendingDownstreamServers.Add(server); connection.StartListening(); logger.Trace($"New server connected, awaiting identification [{connection.RemoteEndPoints.Format()}]."); }
/// <summary> /// Sets the connection being used by this remote server. /// </summary> /// <param name="pendingServer">The connection to switch to.</param> internal void SetConnection(PendingDownstreamRemoteServer pendingServer) { if (connection != null) { connection.MessageReceived -= MessageReceivedHandler; connection.Disconnected -= DisconnectedHandler; } connection = pendingServer.Connection; // Switch out message received handler from the pending server connection.MessageReceived = MessageReceivedHandler; connection.Disconnected = DisconnectedHandler; EventHandler <ServerConnectedEventArgs> handler = ServerConnected; if (handler != null) { void DoServerConnectedEvent() { long startTimestamp = Stopwatch.GetTimestamp(); try { handler?.Invoke(this, new ServerConnectedEventArgs(this)); } catch (Exception e) { serverConnectedEventFailuresCounter.Increment(); logger.Error("A plugin encountered an error whilst handling the ServerConnected event. The server will still be connected. (See logs for exception)", e); } double time = (double)(Stopwatch.GetTimestamp() - startTimestamp) / Stopwatch.Frequency; serverConnectedEventTimeHistogram.Report(time); } threadHelper.DispatchIfNeeded(DoServerConnectedEvent); } // Handle all messages that had queued foreach (PendingDownstreamRemoteServer.QueuedMessage queuedMessage in pendingServer.GetQueuedMessages()) { HandleMessage(queuedMessage.Message, queuedMessage.SendMode); queuedMessage.Message.Dispose(); } }
/// <summary> /// Called when a pending server has identified itself. /// </summary> /// <param name="pendingServer">The pending server that has been identified.</param> /// <param name="id">The ID the server has identified with.</param> internal void HandleServerReady(PendingDownstreamRemoteServer pendingServer, ushort id) { logger.Trace($"Server at [{pendingServer.Connection.RemoteEndPoints.Format()}] has identified as server {id}."); try { ((DownstreamRemoteServer)FindServer(id)).SetConnection(pendingServer); } catch (KeyNotFoundException) { pendingServer.Connection.Disconnect(); logger.Trace($"Server at [{pendingServer.Connection.RemoteEndPoints.Format()} connected and identified itself as server {id} however the registry has not yet propgated information about that server. The connection has been dropped."); } finally { lock (pendingDownstreamServers) pendingDownstreamServers.Remove(pendingServer); } }