/// <summary> /// It's the handler of the asynchronous reading. /// </summary> /// <param name="asyncResult"> /// It is the result of the asynchronous reading. /// </param> private void AsyncAcceptRequestHandler(IAsyncResult asyncResult) { if (asyncResult.AsyncState == _socket) { Socket socket = null; lock (this) { if (asyncResult.AsyncState == _socket) { if (!_listening) { // Someone called Close over socket. EndAccept and return. try { _socket.EndAccept(asyncResult); } catch { } Monitor.Pulse(this); return; } try { // Accept connection. socket = _socket.EndAccept(asyncResult); } catch (Exception e) { OnError(e); return; } try { // Start an asynchronous accept operation. _socket.BeginAccept(new AsyncCallback(AsyncAcceptRequestHandler), _socket); } catch (Exception e) { Stop(); OnError(e); } } } if (socket == null) { return; } IChannel channel = null; try { if (socket.RemoteEndPoint == null) { NDC.Push(string.Format("{0}<-?", GetNDCName())); } else { NDC.Push(string.Format("{0}<-{1}", GetNDCName(), socket.RemoteEndPoint.ToString())); } if ((_channelPool != null) && OnConnectionRequest(socket.RemoteEndPoint)) { channel = _channelPool.Remove(); if (channel == null) { if (Logger.IsInfoEnabled) { Logger.Info(string.Format( "Connection request from {0}, not accepted because channel pool is empty.", socket.RemoteEndPoint.ToString())); } // Can't get a channel for the new connection, close it. socket.Shutdown(SocketShutdown.Both); socket = null; } else { channel.BeginBind(socket); } } else { if (Logger.IsInfoEnabled) { if (_channelPool == null) { Logger.Info(string.Format( "Connection request from {0}, not accepted because channel pool is null.", socket.RemoteEndPoint.ToString())); } else { Logger.Info(string.Format( "Connection request from {0}, not accepted.", socket.RemoteEndPoint.ToString())); } } // Connection not accepted, close it. socket.Shutdown(SocketShutdown.Both); } } catch (Exception e) { try { OnError(e); socket.Shutdown(SocketShutdown.Both); // Return channel to the pool. if (channel != null) { _channelPool.Add(channel); channel = null; if (Logger.IsInfoEnabled) { Logger.Info(string.Format( "Channel returned to pool, {0} channel/s remaining in channel pool.", _channelPool.Length)); } } } catch { } } finally { NDC.Pop(); } if (channel != null) { try { NDC.Push(string.Format("{0}<-{1}", GetNDCName(), socket.RemoteEndPoint.ToString())); // It is necessary first to raise the event, and soon the EndBind. Doing this // the components that receive the event can initialize before the channel // begins to receive. OnConnected(channel); channel.EndBind(); } catch (Exception e) { try { channel.Close(); OnError(e); // Return channel to the pool. if (channel != null) { _channelPool.Add(channel); channel = null; if (Logger.IsInfoEnabled) { Logger.Info(string.Format( "Channel returned to pool, {0} channel/s remaining in channel pool.", _channelPool.Length)); } } } catch { } } finally { NDC.Pop(); } } } }