예제 #1
0
        /// <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();
                    }
                }
            }
        }