public Transport(IPEndPoint listenEndPoint, IConnectionHandler connectionHandler, LinuxTransportOptions transportOptions, ILoggerFactory loggerFactory) { if (connectionHandler == null) { throw new ArgumentNullException(nameof(connectionHandler)); } if (transportOptions == null) { throw new ArgumentException(nameof(transportOptions)); } if (loggerFactory == null) { throw new ArgumentException(nameof(loggerFactory)); } if (listenEndPoint == null) { throw new ArgumentException(nameof(listenEndPoint)); } _endPoint = listenEndPoint; _connectionHandler = connectionHandler; _transportOptions = transportOptions; _loggerFactory = loggerFactory; _logger = loggerFactory.CreateLogger <Transport>(); }
public Transport(IEndPointInformation ipEndPointInformation, IConnectionDispatcher connectionDispatcher, LinuxTransportOptions transportOptions, ILoggerFactory loggerFactory) { if (connectionDispatcher == null) { throw new ArgumentNullException(nameof(connectionDispatcher)); } if (transportOptions == null) { throw new ArgumentException(nameof(transportOptions)); } if (loggerFactory == null) { throw new ArgumentException(nameof(loggerFactory)); } if (ipEndPointInformation == null) { throw new ArgumentException(nameof(ipEndPointInformation)); } _endPoint = ipEndPointInformation; _connectionDispatcher = connectionDispatcher; _transportOptions = transportOptions; _loggerFactory = loggerFactory; _logger = loggerFactory.CreateLogger <Transport>(); _threads = Array.Empty <TransportThread>(); }
public TransportThread(IPEndPoint endPoint, IConnectionHandler connectionHandler, LinuxTransportOptions options, int threadId, int cpuId, ILoggerFactory loggerFactory) { if (connectionHandler == null) { throw new ArgumentNullException(nameof(connectionHandler)); } _connectionHandler = connectionHandler; _threadId = threadId; _cpuId = cpuId; _endPoint = endPoint; _transportOptions = options; _loggerFactory = loggerFactory; }
public LinuxTransportFactory(IOptions <LinuxTransportOptions> options, ILoggerFactory loggerFactory) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (loggerFactory == null) { throw new ArgumentNullException(nameof(loggerFactory)); } _options = options.Value; _loggerFactory = loggerFactory; }
public ThreadContext(TransportThread transportThread, LinuxTransportOptions transportOptions, IConnectionHandler connectionHandler, ILogger logger) { TransportThread = transportThread; ConnectionHandler = connectionHandler; Sockets = new Dictionary <int, TSocket>(); Logger = logger; AcceptSockets = new List <TSocket>(); _schedulerAdding = new Queue <ScheduledAction>(1024); _schedulerRunning = new Queue <ScheduledAction>(1024); _epollState = EPollBlocked; SendScheduler = transportOptions.DeferSend ? this as IScheduler : InlineScheduler.Default; }
public TransportThread(IPEndPoint endPoint, IConnectionDispatcher connectionDispatcher, LinuxTransportOptions options, AcceptThread acceptThread, int threadId, int cpuId, ILoggerFactory loggerFactory) { if (connectionDispatcher == null) { throw new ArgumentNullException(nameof(connectionDispatcher)); } ConnectionDispatcher = connectionDispatcher; ThreadId = threadId; CpuId = cpuId; EndPoint = endPoint; TransportOptions = options; AcceptThread = acceptThread; LoggerFactory = loggerFactory; }
public unsafe ThreadContext(TransportThread transportThread) { _transportThread = transportThread; _connectionDispatcher = transportThread.ConnectionDispatcher; _sockets = new Dictionary <int, TSocket>(); _logger = _transportThread.LoggerFactory.CreateLogger($"{nameof(RedHatX)}.{nameof(TransportThread)}.{_transportThread.ThreadId}"); _acceptSockets = new List <TSocket>(); _transportOptions = transportThread.TransportOptions; _scheduledSendAdding = new List <ScheduledSend>(1024); _scheduledSendRunning = new List <ScheduledSend>(1024); _epollState = EPollBlocked; if (_transportOptions.AioReceive | _transportOptions.AioSend) { _aioEventsMemory = AllocMemory(sizeof(AioEvent) * EventBufferLength); _aioCbsMemory = AllocMemory(sizeof(AioCb) * EventBufferLength); _aioCbsTableMemory = AllocMemory(sizeof(AioCb *) * EventBufferLength); _ioVectorTableMemory = AllocMemory(sizeof(IOVector) * IoVectorsPerAioSocket * EventBufferLength); for (int i = 0; i < EventBufferLength; i++) { AioCbsTable[i] = &AioCbs[i]; } if (_transportOptions.AioSend) { _aioSendBuffers = new ReadOnlySequence <byte> [EventBufferLength]; } } int maxMemoryHandleCount = TSocket.MaxIOVectorReceiveLength; if (_transportOptions.AioReceive || _transportOptions.AioSend) { maxMemoryHandleCount = Math.Max(maxMemoryHandleCount, EventBufferLength); } if (_transportOptions.DeferSend) { maxMemoryHandleCount = Math.Max(maxMemoryHandleCount, TSocket.MaxIOVectorSendLength); } MemoryHandles = new MemoryHandle[maxMemoryHandleCount]; // These members need to be Disposed _epoll = EPoll.Create(); _epollFd = _epoll.DangerousGetHandle().ToInt32(); MemoryPool = CreateMemoryPool(); _pipeEnds = PipeEnd.CreatePair(blocking: false); if (_aioEventsMemory != IntPtr.Zero) { AioInterop.IoSetup(EventBufferLength, out _aioContext).ThrowOnError(); } }
private static void AcceptOn(IPEndPoint endPoint, int cpuId, LinuxTransportOptions transportOptions, ThreadContext threadContext) { Socket acceptSocket = null; int fd = 0; int port = endPoint.Port; SocketFlags flags = SocketFlags.TypeAccept; try { bool ipv4 = endPoint.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork; acceptSocket = Socket.Create(ipv4 ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp, blocking: false); fd = acceptSocket.DangerousGetHandle().ToInt32(); if (!ipv4) { // Don't do mapped ipv4 acceptSocket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 1); } if (transportOptions.ReceiveOnIncomingCpu) { if (cpuId != -1) { if (!acceptSocket.TrySetSocketOption(SocketOptionLevel.Socket, SocketOptionName.IncomingCpu, cpuId)) { threadContext.Logger.LogWarning($"Cannot enable nameof{SocketOptionName.IncomingCpu} for {endPoint}"); } } } // Linux: allow bind during linger time acceptSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); // Linux: allow concurrent binds and let the kernel do load-balancing acceptSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReusePort, 1); if (transportOptions.DeferAccept) { // Linux: wait up to 1 sec for data to arrive before accepting socket acceptSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.DeferAccept, 1); flags |= SocketFlags.DeferAccept; } acceptSocket.Bind(endPoint); if (port == 0) { // When testing we want the OS to select a free port port = acceptSocket.GetLocalIPAddress().Port; } acceptSocket.Listen(ListenBacklog); } catch { acceptSocket?.Dispose(); throw; } TSocket tsocket = null; var sockets = threadContext.Sockets; try { tsocket = new TSocket(threadContext) { Flags = flags, Fd = fd, Socket = acceptSocket }; threadContext.AcceptSockets.Add(tsocket); lock (sockets) { sockets.Add(tsocket.Fd, tsocket); } EPollInterop.EPollControl(threadContext.EPollFd, EPollOperation.Add, fd, EPollEvents.Readable, EPollData(fd)); } catch { acceptSocket.Dispose(); threadContext.AcceptSockets.Remove(tsocket); lock (sockets) { sockets.Remove(fd); } throw; } endPoint.Port = port; }
public Transport(IEndPointInformation IEndPointInformation, IConnectionHandler connectionHandler, LinuxTransportOptions transportOptions, ILoggerFactory loggerFactory) : this(CreateEndPointFromIEndPointInformation(IEndPointInformation), connectionHandler, transportOptions, loggerFactory) { }