protected IoUringConnectionContext(LinuxSocket socket, EndPoint local, EndPoint remote, TransportThreadContext threadContext) { Socket = socket; LocalEndPoint = local; RemoteEndPoint = remote; MemoryPool = threadContext.MemoryPool; _threadContext = threadContext; var appScheduler = threadContext.Options.ApplicationSchedulingMode; var inputOptions = new PipeOptions(MemoryPool, appScheduler, PipeScheduler.Inline, PauseInputWriterThreshold, PauseInputWriterThreshold / 2, useSynchronizationContext: false); var outputOptions = new PipeOptions(MemoryPool, PipeScheduler.Inline, appScheduler, PauseOutputWriterThreshold, PauseOutputWriterThreshold / 2, useSynchronizationContext: false); var pair = DuplexPipe.CreateConnectionPair(inputOptions, outputOptions); Transport = pair.Transport; Application = pair.Application; _onOnFlushedToApp = FlushedToAppAsynchronously; _onReadFromApp = ReadFromAppAsynchronously; iovec[] vecs = new iovec[ReadIOVecCount + WriteIOVecCount]; var handle = GCHandle.Alloc(vecs, GCHandleType.Pinned); _iovec = (iovec *)handle.AddrOfPinnedObject(); _iovecHandle = handle; }
protected IoUringConnection(LinuxSocket socket, EndPoint local, EndPoint remote, MemoryPool <byte> memoryPool, IoUringOptions options, TransportThreadScheduler scheduler) { Socket = socket; LocalEndPoint = local; RemoteEndPoint = remote; MemoryPool = memoryPool; Debug.Assert(MaxBufferSize == MemoryPool.MaxBufferSize); _scheduler = scheduler; _connectionClosedTokenSource = new CancellationTokenSource(); ConnectionClosed = _connectionClosedTokenSource.Token; _waitForConnectionClosedTcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); var appScheduler = options.ApplicationSchedulingMode; var inputOptions = new PipeOptions(memoryPool, appScheduler, PipeScheduler.Inline, PauseInputWriterThreshold, PauseInputWriterThreshold / 2, useSynchronizationContext: false); var outputOptions = new PipeOptions(memoryPool, PipeScheduler.Inline, appScheduler, PauseOutputWriterThreshold, PauseOutputWriterThreshold / 2, useSynchronizationContext: false); var pair = DuplexPipe.CreateConnectionPair(inputOptions, outputOptions); Transport = pair.Transport; Application = pair.Application; _onOnFlushedToApp = () => HandleFlushedToApp(); _onReadFromApp = () => HandleReadFromApp(); _ioVecBytes = GC.AllocateUninitializedArray <byte>(SizeOf.iovec * (ReadIOVecCount + WriteIOVecCount), pinned: true); unsafe { _iovec = (iovec *)MemoryHelper.UnsafeGetAddressOfPinnedArrayData(_ioVecBytes); } }
public RingUnblockHandle(Ring ring) { _supportsRead = ring.Supports(RingOperation.Read); _supportsFastPoll = ring.SupportsFastPoll; int eventfdFlags = EFD_CLOEXEC; if (!_supportsFastPoll) { // Work-around for https://bugzilla.kernel.org/show_bug.cgi?id=208039 eventfdFlags |= EFD_NONBLOCK; } int res = eventfd(0, eventfdFlags); if (res == -1) { ThrowHelper.ThrowNewErrnoException(); } _eventfd = res; if (!_supportsRead) { _eventfdIoVecBytes = GC.AllocateUninitializedArray <byte>(SizeOf.iovec, pinned: true); IoVec->iov_base = Buffer; IoVec->iov_len = BufferLen; } }
public ValueTask <ConnectionContext> Connect(IPEndPoint endpoint) { var domain = endpoint.AddressFamily == AddressFamily.InterNetwork ? AF_INET : AF_INET6; LinuxSocket s = socket(domain, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP); if (_threadContext.Options.TcpNoDelay) { s.SetOption(SOL_TCP, TCP_NODELAY, 1); } var context = new OutboundConnectionContext(s, endpoint, _threadContext); var tcs = new TaskCompletionSource <ConnectionContext>(TaskCreationOptions.RunContinuationsAsynchronously); // Ensure the transport thread doesn't run continuations context.ConnectCompletion = tcs; endpoint.ToSockAddr(context.Addr, out var addrLength); context.AddrLen = addrLength; _connections[s] = context; Connect(context); _threadContext.Notify(); return(new ValueTask <ConnectionContext>(tcs.Task)); }
private void CompleteAccept(AcceptSocketContext acceptContext, int result) { if (result < 0) { var err = -result; if (err == EAGAIN || err == EINTR || err == EMFILE) { Debug.WriteLine($"accept completed with EAGAIN on {(int)acceptContext.Socket}"); Accept(acceptContext); return; } throw new ErrnoException(err); } LinuxSocket socket = result; Debug.WriteLine($"Accepted {(int)socket} from {(int)acceptContext.Socket}"); if (_threadContext.Options.TcpNoDelay) { socket.SetOption(SOL_TCP, TCP_NODELAY, 1); } var remoteEndpoint = IPEndPointFormatter.AddrToIpEndPoint(acceptContext.Addr); var context = new InboundConnectionContext(socket, acceptContext.EndPoint, remoteEndpoint, _threadContext); _connections[socket] = context; acceptContext.AcceptQueue.TryWrite(context); Accept(acceptContext); Read(context); ReadFromApp(context); }
public void Bind(IPEndPoint endpoint, ChannelWriter <ConnectionContext> acceptQueue) { var domain = endpoint.AddressFamily == AddressFamily.InterNetwork ? AF_INET : AF_INET6; LinuxSocket s = socket(domain, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP); s.SetOption(SOL_SOCKET, SO_REUSEADDR, 1); s.SetOption(SOL_SOCKET, SO_REUSEPORT, 1); s.Bind(endpoint); s.Listen(ListenBacklog); var context = new AcceptSocketContext(s, endpoint, acceptQueue); _acceptSocketQueue.Enqueue(context); _threadContext.Notify(); }
public RingUnblockHandle(Ring ring) { _supportsRead = ring.Supports(RingOperation.Read); _supportsFastPoll = ring.SupportsFastPoll; int res = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); if (res == -1) { ThrowHelper.ThrowNewErrnoException(); } _eventfd = res; if (!_supportsRead) { _eventfdIoVecBytes = GC.AllocateUninitializedArray <byte>(SizeOf.iovec, pinned: true); IoVec->iov_base = Buffer; IoVec->iov_len = BufferLen; } }
public ValueTask <ConnectionContext> Connect(IPEndPoint endpoint) { var domain = endpoint.AddressFamily == AddressFamily.InterNetwork ? AF_INET : AF_INET6; LinuxSocket s = socket(domain, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP); if (_threadContext.Options.TcpNoDelay) { s.SetOption(SOL_TCP, TCP_NODELAY, 1); } var context = new OutboundConnectionContext(s, endpoint, _threadContext); bool connectedSynchronously; try { connectedSynchronously = s.TryConnectNonBlocking(endpoint); } catch (ErrnoException ex) { return(new ValueTask <ConnectionContext>(Task.FromException <ConnectionContext>(ex))); } if (connectedSynchronously) { context.LocalEndPoint = s.GetLocalAddress(); return(new ValueTask <ConnectionContext>(context)); } var tcs = new TaskCompletionSource <ConnectionContext>(); context.ConnectCompletion = tcs; // Socket will become writable, once connect completed _clientSocketQueue.Enqueue(context); _threadContext.Notify(); return(new ValueTask <ConnectionContext>(tcs.Task)); }