/// <summary> /// Close broken sockets /// </summary> /// <remarks> /// This function is called regularly to clean up the list of /// connected sockets. /// </remarks> void CheckSockets(object eventState) { try { lock (ConnectedSockets) { foreach (var kv in ConnectedSockets) { try { int id = kv.Key; HttpSocket state = kv.Value; if (state == null || state.IsSocketDead()) { ConnectedSockets.Remove(id); } } catch (Exception e) { log.Error(e); } } } } catch { } }
/// <summary> /// Close broken sockets /// </summary> /// <remarks> /// This function is called regularly to clean up the list of /// connected sockets. /// </remarks> void CheckSockets(object eventState) { Console.WriteLine("Starting Clean Sockets: {0}", ConnectedSockets.Count); try { lock (ConnectedSockets) { var toRemove = new List <int>(); foreach (var kv in ConnectedSockets) { try { int id = kv.Key; HttpSocket state = kv.Value; if (DateTime.Now - state.CreationTime > TimeSpan.FromMinutes(10)) { //Console.WriteLine("Closing Old Socket: {0} {1}", id, state.CreationTime); state.CloseSocket(); } if (state == null || state.IsSocketDead()) { toRemove.Add(id); } } catch (Exception e) { log.Error(e); } } foreach (var id in toRemove) { ConnectedSockets.Remove(id); } } } catch { } Console.WriteLine("Finished Clean Sockets: {0}", ConnectedSockets.Count); }
/// <summary> /// If necessary, connect the remote <c>SocketPS</c> socket /// to the given host and port /// </summary> /// <param name="hostname">Remote host name</param> /// <param name="port">Remote port</param> /// <remarks> /// If SocketPS is already connected to the right host and port, /// the socket is reused as is. /// </remarks> protected void Connect(string hostname, int port, bool secure) { System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(hostname)); System.Diagnostics.Debug.Assert(port > 0); if (DestinationHostName != null && DestinationHostName.Equals(hostname) && DestinationPort == port && (SocketPS != null && !SocketPS.IsSocketDead())) { // Nothing to do, just reuse the socket return; } if (SocketPS != null) { log.Debug("Changing hostname/port from " + DestinationHostName + ":" + DestinationPort + " to " + hostname + ":" + port); // We have a socket connected to the wrong host (or port) SocketPS.CloseSocket(); SocketPS = null; } IPAddress[] ips = Resolve(hostname); Socket socket = null; Exception e = null; foreach (var ip in ips) { try { socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socket.Connect(ip, port); break; } catch (Exception ee) { if (ip.Equals(IPAddress.IPv6Loopback)) { // Do not log that continue; } if (e == null) { e = ee; } if (socket != null) { socket.Close(); socket = null; } log.Error(ee); } } if (socket == null) { throw e; } // Checked up, and good to go SocketPS = new HttpSocket(socket); if (secure) { SocketPS.MakeSecureClient(hostname); } DestinationHostName = hostname; DestinationPort = port; log.Debug("SocketPS connected to " + hostname + ":" + port); }
/// <summary> /// Callback method for accepting new connections /// </summary> void AcceptCallback(IAsyncResult ar) { // Have we really changed thread? if (ListeningThread.ManagedThreadId == System.Threading.Thread.CurrentThread.ManagedThreadId) { // No! Give me a new thread! new Thread(() => AcceptCallback(ar)).Start(); return; } if (IsShuttingDown) return; // Get the socket that handles the client request Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // Signal the main thread to continue ListenThreadSwitch.Set(); #if DEBUG_ACCEPT_CONNECTION log.Debug("\tAcceptCallback sent signal"); #endif // Create the state object HttpSocket state = new HttpSocket(handler); state.id = ++LastClientId; log.DebugFormat("Accepted connection: [S{0}] {1} -> {2}", state.id, handler.RemoteEndPoint, handler.LocalEndPoint); lock (ConnectedSockets) ConnectedSockets[state.id] = state; AbstractProxyLogic proxy = null; try { proxy = OnClientStart(state); } catch (Exception e) { log.Error(e); } if (proxy == null) { CloseSocket(state); return; } // No need for asynchronous I/O from now on try { while (proxy.LogicLoop()) if (IsShuttingDown || state.IsSocketDead()) break; log.Debug("Shutting down socket"); } catch (System.Net.Sockets.SocketException) { /* ignore */ } catch (TrotiNet.IoBroken) { /* ignore */ } catch (Exception e) { log.Error(e); log.Debug("Closing socket on error"); } CloseSocket(state); }
/// <summary> /// Callback method for accepting new connections /// </summary> void AcceptCallback(IAsyncResult ar) { if (IsShuttingDown) return; // Have we really changed thread? if (ListeningThread.ManagedThreadId == System.Threading.Thread.CurrentThread.ManagedThreadId) { // No! Give me a new thread! new Thread(() => AcceptCallback(ar)).Start(); return; } // Get the socket that handles the client request Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // Signal the main thread to continue ListenThreadSwitch.Set(); #if DEBUG_ACCEPT_CONNECTION log.Debug("\tAcceptCallback sent signal"); #endif // Create the state object HttpSocket state = new HttpSocket(handler); state.id = ++LastClientId; lock (ConnectedSockets) ConnectedSockets[state.id] = state; AbstractProxyLogic proxy = null; try { proxy = OnClientStart(state); } catch (Exception e) { log.Error(e); } if (proxy == null) { CloseSocket(state); return; } // No need for asynchronous I/O from now on try { while (proxy.LogicLoop()) if (IsShuttingDown || state.IsSocketDead()) break; log.Debug("Shutting down socket"); } catch (System.Net.Sockets.SocketException) { /* ignore */ } catch (TrotiNet.IoBroken) { /* ignore */ } catch (Exception e) { log.Error(e); log.Debug("Closing socket on error"); } CloseSocket(state); }