private int HandleAccept(TSocket tacceptSocket)
            {
                var         type     = tacceptSocket.Type;
                int         clientFd = -1;
                PosixResult result;

                if (type == SocketFlags.TypeAccept)
                {
                    // TODO: should we handle more than 1 accept? If we do, we shouldn't be to eager
                    //       as that might give the kernel the impression we have nothing to do
                    //       which could interfere with the SO_REUSEPORT load-balancing.
                    result = tacceptSocket.TryAccept(out clientFd, blocking: false);
                }
                else
                {
                    result = tacceptSocket.TryReceiveSocket(out clientFd, blocking: false);
                    if (result.Value == 0)
                    {
                        // The socket passing us file descriptors has closed.
                        // We dispose our end so we get get removed from the epoll.
                        tacceptSocket.Close();
                        return(0);
                    }
                }
                if (result.IsSuccess)
                {
                    TSocket tsocket;
                    try
                    {
                        SocketFlags flags = SocketFlags.TypeClient | (tacceptSocket.IsDeferSend ? SocketFlags.DeferSend : SocketFlags.None);
                        tsocket = new TSocket(this, clientFd, flags)
                        {
                            ZeroCopyThreshold = tacceptSocket.ZeroCopyThreshold
                        };

                        bool ipSocket = !object.ReferenceEquals(tacceptSocket.LocalAddress, NotIPSocket);

                        // Store the last LocalAddress on the tacceptSocket so we might reuse it instead
                        // of allocating a new one for the same address.
                        IPEndPointStruct localAddress  = default(IPEndPointStruct);
                        IPEndPointStruct remoteAddress = default(IPEndPointStruct);
                        if (ipSocket && tsocket.TryGetLocalIPAddress(out localAddress, tacceptSocket.LocalAddress))
                        {
                            tsocket.LocalAddress = localAddress.Address;
                            tsocket.LocalPort    = localAddress.Port;
                            if (tsocket.TryGetPeerIPAddress(out remoteAddress))
                            {
                                tsocket.RemoteAddress = remoteAddress.Address;
                                tsocket.RemotePort    = remoteAddress.Port;
                            }
                        }
                        else
                        {
                            // This is not an IP socket.
                            tacceptSocket.LocalAddress = NotIPSocket;
                            ipSocket = false;
                        }

                        if (ipSocket)
                        {
                            tsocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, 1);
                        }
                    }
                    catch
                    {
                        IOInterop.Close(clientFd);
                        return(0);
                    }

                    tsocket.MiddlewareTask = _connectionDispatcher.OnConnection(tsocket);

                    lock (_sockets)
                    {
                        _sockets.Add(clientFd, tsocket);
                    }

                    bool dataMayBeAvailable = tacceptSocket.IsDeferAccept;
                    tsocket.Start(dataMayBeAvailable);

                    return(1);
                }
                else
                {
                    return(0);
                }
            }
コード例 #2
0
            private int HandleAccept(TSocket tacceptSocket)
            {
                var         type     = tacceptSocket.Type;
                int         clientFd = -1;
                PosixResult result;

                if (type == SocketFlags.TypeAccept)
                {
                    // TODO: should we handle more than 1 accept? If we do, we shouldn't be to eager
                    //       as that might give the kernel the impression we have nothing to do
                    //       which could interfere with the SO_REUSEPORT load-balancing.
                    result = tacceptSocket.TryAccept(out clientFd, blocking: false);
                }
                else
                {
                    result = tacceptSocket.TryReceiveSocket(out clientFd, blocking: false);
                    if (result.Value == 0)
                    {
                        // The socket passing us file descriptors has closed.
                        // We dispose our end so we get get removed from the epoll.
                        tacceptSocket.Close();
                        return(0);
                    }
                }
                if (result.IsSuccess)
                {
                    TSocket tsocket;
                    try
                    {
                        SocketFlags flags = SocketFlags.TypeClient | (tacceptSocket.IsDeferSend ? SocketFlags.DeferSend : SocketFlags.None);
                        tsocket = new TSocket(this, clientFd, flags, _transportOptions)
                        {
                            ZeroCopyThreshold = tacceptSocket.ZeroCopyThreshold
                        };

                        var  localIpEndPoint = tacceptSocket.LocalEndPoint as IPEndPoint;
                        bool ipSocket        = !object.ReferenceEquals(localIpEndPoint?.Address, NotIPSocket);

                        // Store the last LocalAddress on the tacceptSocket so we might reuse it instead
                        // of allocating a new one for the same address.
                        IPEndPointStruct localAddress  = default(IPEndPointStruct);
                        IPEndPointStruct remoteAddress = default(IPEndPointStruct);
                        if (ipSocket && tsocket.TryGetLocalIPAddress(out localAddress, localIpEndPoint?.Address))
                        {
                            tsocket.LocalEndPoint = new IPEndPoint(localAddress.Address, localAddress.Port);

                            if (tsocket.TryGetPeerIPAddress(out remoteAddress))
                            {
                                tsocket.RemoteEndPoint = new IPEndPoint(remoteAddress.Address, remoteAddress.Port);
                            }
                        }
                        else
                        {
                            // This is not an IP socket.
                            // REVIEW: Should LocalEndPoint be null instead? Some other EndPoint type?
                            tacceptSocket.LocalEndPoint = new IPEndPoint(NotIPSocket, 0);
                            ipSocket = false;
                        }

                        if (ipSocket)
                        {
                            tsocket.SetSocketOption(SOL_TCP, TCP_NODELAY, 1);
                        }
                    }
                    catch
                    {
                        IOInterop.Close(clientFd);
                        return(0);
                    }

                    bool accepted = _acceptQueue.Writer.TryWrite(tsocket);
                    Debug.Assert(accepted, "The connection was not written to the channel!");

                    lock (_sockets)
                    {
                        _sockets.Add(clientFd, tsocket);
                    }

                    bool dataMayBeAvailable = tacceptSocket.IsDeferAccept;
                    tsocket.Start(dataMayBeAvailable);

                    return(1);
                }
                else
                {
                    return(0);
                }
            }