/// <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> /// 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 (GhostLib.Network.Proxy.IoBroken) { /* ignore */ } catch (Exception e) { // log.Error(e); // log.Debug("Closing socket on error"); } CloseSocket(state); }
/// <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) { 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); DestinationHostName = hostname; DestinationPort = port; //log.Debug("SocketPS connected to " + hostname + ":" + port); }