public void Connect() { if (!MsgCenter.Running) { if (Log.IsVerbose) { Log.Verbose(ErrorCode.ProxyClient_MsgCtrNotRunning, "Ignoring connection attempt to gateway {0} because the proxy message center is not running", Address); } return; } // Yes, we take the lock around a Sleep. The point is to ensure that no more than one thread can try this at a time. // There's still a minor problem as written -- if the sending thread and receiving thread both get here, the first one // will try to reconnect. eventually do so, and then the other will try to reconnect even though it doesn't have to... // Hopefully the initial "if" statement will prevent that. lock (Lockable) { if (!IsLive) { if (Log.IsVerbose) { Log.Verbose(ErrorCode.ProxyClient_DeadGateway, "Ignoring connection attempt to gateway {0} because this gateway connection is already marked as non live", Address); } return; // if the connection is already marked as dead, don't try to reconnect. It has been doomed. } for (var i = 0; i < ProxiedMessageCenter.CONNECT_RETRY_COUNT; i++) { try { if (Socket != null) { if (Socket.Connected) { return; } MarkAsDisconnected(Socket); // clean up the socket before reconnecting. } if (lastConnect != new DateTime()) { // We already tried at least once in the past to connect to this GW. // If we are no longer connected to this GW and it is no longer in the list returned // from the GatewayProvider, consider directly this connection dead. if (!MsgCenter.GatewayManager.GetLiveGateways().Contains(Address)) { break; } // Wait at least ProxiedMessageCenter.MINIMUM_INTERCONNECT_DELAY before reconnection tries var millisecondsSinceLastAttempt = DateTime.UtcNow - lastConnect; if (millisecondsSinceLastAttempt < ProxiedMessageCenter.MINIMUM_INTERCONNECT_DELAY) { var wait = ProxiedMessageCenter.MINIMUM_INTERCONNECT_DELAY - millisecondsSinceLastAttempt; if (Log.IsVerbose) { Log.Verbose(ErrorCode.ProxyClient_PauseBeforeRetry, "Pausing for {0} before trying to connect to gateway {1} on trial {2}", wait, Address, i); } Thread.Sleep(wait); } } lastConnect = DateTime.UtcNow; Socket = new Socket(Silo.Endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); SocketManager.Connect(Socket, Silo.Endpoint, MsgCenter.MessagingConfiguration.OpenConnectionTimeout); NetworkingStatisticsGroup.OnOpenedGatewayDuplexSocket(); MsgCenter.OnGatewayConnectionOpen(); SocketManager.WriteConnectionPreamble(Socket, MsgCenter.ClientId); // Identifies this client Log.Info(ErrorCode.ProxyClient_Connected, "Connected to gateway at address {0} on trial {1}.", Address, i); return; } catch (Exception ex) { Log.Warn(ErrorCode.ProxyClient_CannotConnect, $"Unable to connect to gateway at address {Address} on trial {i} (Exception: {ex.Message})"); MarkAsDisconnected(Socket); } } // Failed too many times -- give up MarkAsDead(); } }