Example #1
0
        public bool TryAccept(Ring ring, out LinuxSocket socket)
        {
            if (IsIpSocket)
            {
                _addr.AsSpan().Clear();
                *AddrLen = SizeOf.sockaddr_storage;
            }

            if (!ring.Supports(RingOperation.Accept))
            {
                // pre v5.5
                socket = Socket.Accept4(Addr, AddrLen, SOCK_NONBLOCK | SOCK_CLOEXEC);
                return(true);
            }

            socket = default;
            int acceptSocket = Socket;

            if (!ring.TryPrepareAccept(acceptSocket, Addr, AddrLen, SOCK_NONBLOCK | SOCK_CLOEXEC, AsyncOperation.AcceptFrom(acceptSocket).AsUlong()))
            {
                _scheduler.ScheduleAccept(acceptSocket);
            }

            return(false);
        }
Example #2
0
        private OutboundConnection(LinuxSocket socket, EndPoint remote, MemoryPool <byte> memoryPool, IoUringOptions options, TransportThreadScheduler scheduler, TaskCompletionSource <ConnectionContext> connectCompletion)
            : base(socket, null, remote, memoryPool, options, scheduler)
        {
            unsafe
            {
                switch (remote)
                {
                case IPEndPoint ipEndPoint:
                {
                    ipEndPoint.ToSockAddr((sockaddr_storage *)Addr, out var addrLength);
                    AddrLen = addrLength;
                    break;
                }

                case UnixDomainSocketEndPoint unixDomainSocketEndPoint:
                {
                    unixDomainSocketEndPoint.ToSockAddr((sockaddr_un *)Addr);
                    AddrLen = SizeOf.sockaddr_un;
                    break;
                }
                }
            }

            _connectCompletion = connectCompletion;

            // Add IConnectionInherentKeepAliveFeature to the tcp connection impl since Kestrel doesn't implement
            // the IConnectionHeartbeatFeature
            Features.Set <IConnectionInherentKeepAliveFeature>(this);
        }
Example #3
0
        public static AcceptSocket Bind(FileHandleEndPoint fileHandleEndPoint, ChannelWriter <ConnectionContext> acceptQueue, IoUringOptions options)
        {
            LinuxSocket s        = (int)fileHandleEndPoint.FileHandle;
            var         endPoint = s.GetLocalAddress();

            return(new AcceptSocket(s, endPoint ?? fileHandleEndPoint, acceptQueue, null, options, null));
        }
Example #4
0
        public static OutboundConnection Create(EndPoint endpoint, TaskCompletionSource <ConnectionContext> connectCompletion, MemoryPool <byte> memoryPool, IoUringOptions options, TransportThreadScheduler scheduler)
        {
            LinuxSocket s = default;

            switch (endpoint)
            {
            case IPEndPoint _:
                var domain = endpoint.AddressFamily == AddressFamily.InterNetwork ? AF_INET : AF_INET6;
                s = new LinuxSocket(domain, SOCK_STREAM, IPPROTO_TCP, blocking: false);
                if (options.TcpNoDelay)
                {
                    s.SetOption(SOL_TCP, TCP_NODELAY, 1);
                }
                break;

            case UnixDomainSocketEndPoint _:
                s = new LinuxSocket(AF_UNIX, SOCK_STREAM, 0, blocking: false);
                break;

            case FileHandleEndPoint fileHandleEndPoint:
                s = (int)fileHandleEndPoint.FileHandle;
                break;

            default:
                ThrowHelper.ThrowNewNotSupportedException_EndPointNotSupported();
                break;
            }

            return(new OutboundConnection(s, endpoint, memoryPool, options, scheduler, connectCompletion));
        }
 public OutboundConnectionContext(LinuxSocket socket, EndPoint remote, TransportThreadContext threadContext)
     : base(socket, null, remote, threadContext)
 {
     // Add IConnectionInherentKeepAliveFeature to the tcp connection impl since Kestrel doesn't implement
     // the IConnectionHeartbeatFeature
     Features.Set <IConnectionInherentKeepAliveFeature>(this);
 }
        public bool TryCompleteReceive(Ring ring, int result, [NotNullWhen(true)] out InboundConnection connection)
        {
            // Start work-around for https://github.com/axboe/liburing/issues/128
            _iov.AsSpan().Clear();
            _dummyBuffer.AsSpan().Clear();
            _control.AsSpan().Clear();
            _header.AsSpan().Clear();

            iovec* iov = (iovec*) MemoryHelper.UnsafeGetAddressOfPinnedArrayData(_iov);
            iov->iov_base = (byte*) MemoryHelper.UnsafeGetAddressOfPinnedArrayData(_dummyBuffer);
            iov->iov_len = 1;

            byte* control = (byte*) MemoryHelper.UnsafeGetAddressOfPinnedArrayData(_control);

            msghdr* header = (msghdr*) MemoryHelper.UnsafeGetAddressOfPinnedArrayData(_header);
            header->msg_iov = iov;
            header->msg_iovlen = 1;
            header->msg_control = control;
            header->msg_controllen = _control.Length;

            result = _recipient.RecvMsg(header, (MSG_NOSIGNAL | MSG_CMSG_CLOEXEC));
            // End of work-around for https://github.com/axboe/liburing/issues/128

            connection = default;
            if (result < 0)
            {
                HandleCompleteReceiveError(ring, result);
                return false;
            }

            bool receivedSocket = false;
            LinuxSocket socket = default;
            for (cmsghdr* cmsg = CMSG_FIRSTHDR(header); cmsg != null; cmsg = CMSG_NXTHDR(header, cmsg))
            {
                if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
                {
                    int* fdptr = (int*) CMSG_DATA(cmsg);
                    socket = *fdptr;
                    socket.SetFlag(O_NONBLOCK);

                    receivedSocket = true;
                    break;
                }
            }

            if (!receivedSocket)
            {
                if (result != 0)
                {
                    PollReceive(ring);
                }

                return false;
            }

            connection = new InboundConnection(socket, _endPoint, null, _memoryPool, _options, _scheduler);
            return true;
        }
 public SocketReceiver(LinuxSocket recipient, ChannelWriter<ConnectionContext> acceptQueue, EndPoint endPoint, MemoryPool<byte> memoryPool, IoUringOptions options, TransportThreadScheduler scheduler)
 {
     _recipient = recipient;
     AcceptQueue = acceptQueue;
     _endPoint = endPoint;
     _memoryPool = memoryPool;
     _options = options;
     _scheduler = scheduler;
 }
Example #8
0
        public bool CompleteAcceptPoll(Ring ring, int result, out LinuxSocket socket)
        {
            if (result < 0)
            {
                HandleCompleteAcceptPollError(ring, result);
                socket = default;
                return(false);
            }

            return(TryAccept(ring, out socket));
        }
Example #9
0
        public static AcceptSocket Bind(UnixDomainSocketEndPoint unixDomainSocketEndPoint, ChannelWriter <ConnectionContext> acceptQueue, IoUringOptions options)
        {
            var socketPath = unixDomainSocketEndPoint.ToString();
            var s          = new LinuxSocket(AF_UNIX, SOCK_STREAM, 0, blocking: false);

            File.Delete(socketPath);
            s.Bind(unixDomainSocketEndPoint);
            s.Listen(options.ListenBacklog);

            return(new AcceptSocket(s, unixDomainSocketEndPoint, acceptQueue, null, options, null));
        }
Example #10
0
        public bool TryCompleteAcceptSocket(Ring ring, int result, out LinuxSocket socket)
        {
            socket = default;
            if (result < 0)
            {
                HandleCompleteAcceptSocketError(ring, result);
                return(false);
            }

            socket = result;
            return(true);
        }
Example #11
0
        public static AcceptSocket Bind(IPEndPoint ipEndPoint, ChannelWriter <ConnectionContext> acceptQueue, MemoryPool <byte> memoryPool, IoUringOptions options, TransportThreadScheduler scheduler)
        {
            var         domain = ipEndPoint.AddressFamily == AddressFamily.InterNetwork ? AF_INET : AF_INET6;
            LinuxSocket s      = new LinuxSocket(domain, SOCK_STREAM, IPPROTO_TCP, blocking: false);

            s.SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
            s.SetOption(SOL_SOCKET, SO_REUSEPORT, 1);
            s.Bind(ipEndPoint);
            s.Listen(options.ListenBacklog);

            return(new AcceptSocket(s, s.GetLocalAddress(), acceptQueue, memoryPool, options, scheduler));
        }
        public OutboundConnectionContext(LinuxSocket socket, EndPoint remote, TransportThreadContext threadContext)
            : base(socket, null, remote, threadContext)
        {
            sockaddr_storage addr = default;
            var addrHandle        = GCHandle.Alloc(addr, GCHandleType.Pinned);

            _addr       = (sockaddr_storage *)addrHandle.AddrOfPinnedObject();
            _addrHandle = addrHandle;

            // Add IConnectionInherentKeepAliveFeature to the tcp connection impl since Kestrel doesn't implement
            // the IConnectionHeartbeatFeature
            Features.Set <IConnectionInherentKeepAliveFeature>(this);
        }
Example #13
0
        private AcceptSocket(LinuxSocket socket, EndPoint endPoint, ChannelWriter <ConnectionContext> acceptQueue, MemoryPool <byte> memoryPool, IoUringOptions options, TransportThreadScheduler scheduler)
        {
            Socket      = socket;
            EndPoint    = endPoint;
            AcceptQueue = acceptQueue;
            _memoryPool = memoryPool;
            _options    = options;
            _scheduler  = scheduler;

            _unbindCompletion = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            if (endPoint is IPEndPoint) // _addr is null by intention for the remaining EndPoint types
            {
                _addr    = GC.AllocateUninitializedArray <byte>(SizeOf.sockaddr_storage, pinned: true);
                _addrLen = GC.AllocateUninitializedArray <byte>(SizeOf.socklen_t, pinned: true);
            }
        }
Example #14
0
        private void Bind(AcceptSocket context)
        {
            var threads  = _transportThreads;
            var handlers = new LinuxSocket[threads.Length];

            for (var i = 0; i < threads.Length; i++)
            {
                handlers[i] = threads[i].RegisterHandlerFor(context.AcceptQueue, context.EndPoint);
            }
            context.Handlers = handlers;

            int socket = context.Socket;

            _acceptSockets[socket] = context;
            _acceptSocketsPerEndPoint[context.EndPoint] = context;
            _scheduler.ScheduleAsyncAcceptPoll(socket);
        }
        public AcceptSocketContext(LinuxSocket socket, IPEndPoint endPoint, ChannelWriter <ConnectionContext> acceptQueue)
        {
            EndPoint    = endPoint;
            AcceptQueue = acceptQueue;
            Socket      = socket;

            sockaddr_storage storage = default;
            var addrHandle           = GCHandle.Alloc(storage, GCHandleType.Pinned);

            _addr       = (sockaddr_storage *)addrHandle.AddrOfPinnedObject();
            _addrHandle = addrHandle;

            socklen_t addrLen       = SizeOf.sockaddr_storage;
            var       addrLenHandle = GCHandle.Alloc(addrLen, GCHandleType.Pinned);

            _addLen        = (socklen_t *)addrLenHandle.AddrOfPinnedObject();
            _addrLenHandle = addrLenHandle;
        }
Example #16
0
 public InboundConnectionContext(LinuxSocket socket, EndPoint local, EndPoint remote, TransportThreadContext threadContext)
     : base(socket, local, remote, threadContext)
 {
 }
Example #17
0
 public InboundConnection(LinuxSocket socket, EndPoint local, EndPoint remote, MemoryPool <byte> memoryPool, IoUringOptions options, TransportThreadScheduler scheduler)
     : base(socket, local, remote, memoryPool, options, scheduler)
 {
 }
Example #18
0
 public AcceptSocketContext(LinuxSocket socket, IPEndPoint endPoint, ChannelWriter <ConnectionContext> acceptQueue)
 {
     EndPoint    = endPoint;
     AcceptQueue = acceptQueue;
     Socket      = socket;
 }