Commit 5deefa3c authored by jan.koester's avatar jan.koester
Browse files

test

parent 3f201ab0
Loading
Loading
Loading
Loading
+73 −79
Original line number Diff line number Diff line
@@ -172,21 +172,16 @@ namespace netplus {
        void ConnectEventHandler(int pos, const int tid, ULONG_PTR args) {
            NetException exception;

            // DRAIN THE LISTEN QUEUE: Loop to accept all waiting connections.
            while (true) {
                // The ccon unique_ptr scope is inside the loop, ensuring it is destroyed
                // if setup fails before being released into the CONNECTIONS map.
            // 1) Create connection object (HttpRequest etc.)
            std::unique_ptr<con> ccon;

                // 1. Create the base connection object
            evconnection->CreateConnection(ccon);

            if (!ccon) {
                    // Should not happen, but exit if connection wrapper creation failed
                std::cerr << "ConnectEventHandler: CreateConnection returned null\n";
                return;
            }

                // 2. Initialize the socket wrapper based on server type
            // 2) Create the right socket
            if (_ServerSocket->_Type == sockettype::TCP) {
                ccon->csock = std::make_unique<tcp>(-1);
            } else if (_ServerSocket->_Type == sockettype::UDP) {
@@ -194,74 +189,73 @@ void ConnectEventHandler(int pos, const int tid, ULONG_PTR args) {
            } else if (_ServerSocket->_Type == sockettype::SSL) {
                netplus::ssl* srv = static_cast<netplus::ssl*>(_ServerSocket);
                ccon->csock = std::make_unique<ssl>(srv->_cert, -1);
            } else {
                exception[NetException::Error] << "ConnectEventHandler: unsupported socket type";
                throw exception;
            }

                // If no supported socket type was initialized, skip this iteration/exit function
            if (!ccon->csock) {
                     // Since we don't know how other types are handled, we stop the loop
                     // in a production environment, this should log a critical error.
                     std::cerr << "ConnectEventHandler: Unsupported socket type on server." << std::endl;
                     return;
                exception[NetException::Error] << "ConnectEventHandler: failed to create client socket";
                throw exception;
            }

                try{
                    // 3. Attempt to accept the new connection
            // 3) Accept
            _ServerSocket->accept(ccon->csock);
                }catch(NetException &e){
                    // Check for the non-fatal error (EAGAIN/EWOULDBLOCK) wrapped in NetException::Note.
                    if (e.getErrorType()==NetException::Note) {
                        // This means the listen queue is empty. Break the accept loop.
                        return;
                    }

                    // Handle fatal accept errors (e.g., resource exhaustion)
                    char errstr[255];
                    strerror_r_netplus(errno,errstr,255);
                    std::cerr << "ConnectEventHandler: Failed to accept connection: " << errstr << std::endl;
                    return;
                }

                // --- SETUP ACCEPTED CONNECTION (The rest of the original logic) ---

                // Set accepted socket to non-blocking
            // 4) Nonblocking
            try {
                ccon->csock->setFlag(O_NONBLOCK, 1);
            } catch (NetException& e) {
                // Accept succeeded but nonblock failed -> close immediately
                try { ccon->csock->close(); } catch (...) {}
                throw;
            }

                // Log IP
            // 5) Optional log
            try {
                std::string ip;
                ccon->csock->getAddress(ip);
                std::cout << "Connected: " << ip << std::endl;
            } catch (...) {
                // ignore logging failures
            }

            ccon->lasteventime = time(nullptr);

                std::lock_guard<std::mutex> global_lock(POLL_HANDLER_MUTEX);
                // Register client socket with kqueue for read events
                struct kevent setevent {};
                setevent.udata = ccon.get();

                // EV_ONESHOT is used, so we must re-register after every R/W operation
                EV_SET(&setevent, ccon->csock->fd(), EVFILT_READ, EV_ADD | EV_ONESHOT,0,0,ccon.get());

                int estate = kevent(_pollFD, &setevent, 1, nullptr, 0, nullptr);

                if ( estate < 0 ) {
            // IMPORTANT: kqueue stores the udata pointer; it must remain valid.
            // We'll only release ownership once the socket is registered successfully.
            con* raw = ccon.get();
            int fd = ccon->csock->fd();

            // 6) Register initial READ (oneshot)
            // Use EV_CLEAR if you want edge-trigger-ish behavior.
            // If you prefer level-trigger: omit EV_CLEAR.
            struct kevent kev;
            EV_SET(&kev,
                fd,
                EVFILT_READ,
                EV_ADD | EV_ENABLE | EV_ONESHOT /* | EV_CLEAR */,
                0,
                0,
                raw);

            if (kevent(_pollFD, &kev, 1, nullptr, 0, nullptr) < 0) {
                char errstr[255];
                strerror_r_netplus(errno, errstr, 255);
                exception[NetException::Error] << "ConnectEventHandler: can't add socket to kqueue: " << errstr;
                    // Throw error to close the worker thread
                throw exception;
            }

                // Call user-defined connection event handler
                evconnection ->ConnectEvent(*ccon,tid,args);
            // 7) Inform protocol layer once (do NOT call repeatedly in write handler)
            evconnection->ConnectEvent(*raw, tid, args);

                // Release the unique_ptr and insert the raw pointer into the global map
            // 8) Publish to global map and release ownership
            {
                    std::lock_guard<std::mutex> clock(ccon->event_mutex),global_lock(POLL_HANDLER_MUTEX);
                    CONNECTIONS.emplace(ccon->csock->fd(),ccon.release());
                std::lock_guard<std::mutex> glk(POLL_HANDLER_MUTEX);
                CONNECTIONS.emplace(fd, raw);
            }

                // Loop continues to accept the next connection from the queue
            }
            ccon.release(); // ownership transferred to event loop lifetime management
        }

        void ReadEventHandler(int pos, const int tid, ULONG_PTR args) {