Example #1
0
        public void MainLoop()
        {
            // Init socket
            // var socketFileDescriptorFlags = Check(Fcntl(UdpSocket, F_GETFL, 0));
            // Check(Fcntl(socketFileDescriptor, F_SETFL, socketFileDescriptorFlags | O_NONBLOCK));
            _logger.LogInformation("Start listening on {bindAddress}:{bindPort}", ListenEndPoint.Address, ListenEndPoint.Port);

            // Register to server
            Register();

            // Create epoll
            const int maxEvents = 64;

            using var epollFileDescriptor = EpollCreate();

            // Add tun to epoll
            var tunEpollEvent = new EpollEvent();

            tunEpollEvent.events = EpollEvents.EPOLLIN | EpollEvents.EPOLLOUT;
            tunEpollEvent.fd     = (int)Tun.TunFileDescriptor.DangerousGetHandle().ToInt64();
            Check(EpollCtl(epollFileDescriptor, EPOLL_CTL_ADD, Tun.TunFileDescriptor, ref tunEpollEvent));
            // Add UDP socket to epoll
            var socketEpollEvent = new EpollEvent();

            socketEpollEvent.events = EpollEvents.EPOLLIN | EpollEvents.EPOLLOUT;
            tunEpollEvent.fd        = (int)UdpSocket.SocketFileDescriptor.DangerousGetHandle().ToInt64();
            Check(EpollCtl(epollFileDescriptor, EPOLL_CTL_ADD, UdpSocket.SocketFileDescriptor, ref socketEpollEvent));

            // main loop
            Message    message;
            IPEndPoint remote;
            TunFrame   tunFrame;
            var        epollReceivedEvents = new EpollEvent[maxEvents];

            while (true)
            {
                var epollWaitRet = Check(EpollWait(epollFileDescriptor, epollReceivedEvents, maxEvents, -1));
                for (var i = 0; i < epollWaitRet; i++)
                {
                    var fd = epollReceivedEvents[i].fd;
                    if (epollReceivedEvents[i].events == EpollEvents.EPOLLIN)
                    {
                        if (fd == Tun.TunFileDescriptor)
                        {
                            var data = Tun.Read(BufferSize);
                            TunnelSendQueue.Enqueue(new TunFrame(data));
                        }
                        else if (fd == UdpSocket.SocketFileDescriptor)
                        {
                            var data = UdpSocket.Recv(BufferSize, out remote);
                            message = DeserializeMessage(data);
                            ListenDispatch(message, remote);
                        }
                        else
                        {
                            throw new AliceException("Unexpected file descriptor");
                        }
                    }
                    else if (epollReceivedEvents[i].events == EpollEvents.EPOLLOUT)
                    {
                        if (fd == Tun.TunFileDescriptor)
                        {
                            if (TunnelReceiveQueue.TryDequeue(out tunFrame))
                            {
                                Tun.Write(tunFrame.FrameData);
                            }
                        }
                        else if (fd == UdpSocket.SocketFileDescriptor)
                        {
                            if (TunnelSendQueue.TryDequeue(out tunFrame))
                            {
                                SendTunnel(tunFrame);
                            }
                        }
                    }
                }
            }
        }