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); } }
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); } }