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); }
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); }
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)); }
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; }
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)); }
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)); }
public bool TryCompleteAcceptSocket(Ring ring, int result, out LinuxSocket socket) { socket = default; if (result < 0) { HandleCompleteAcceptSocketError(ring, result); return(false); } socket = result; return(true); }
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); }
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); } }
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; }
public InboundConnectionContext(LinuxSocket socket, EndPoint local, EndPoint remote, TransportThreadContext threadContext) : base(socket, local, remote, threadContext) { }
public InboundConnection(LinuxSocket socket, EndPoint local, EndPoint remote, MemoryPool <byte> memoryPool, IoUringOptions options, TransportThreadScheduler scheduler) : base(socket, local, remote, memoryPool, options, scheduler) { }
public AcceptSocketContext(LinuxSocket socket, IPEndPoint endPoint, ChannelWriter <ConnectionContext> acceptQueue) { EndPoint = endPoint; AcceptQueue = acceptQueue; Socket = socket; }