Loading src/event/epoll.cpp +130 −41 Original line number Original line Diff line number Diff line Loading @@ -171,11 +171,20 @@ namespace netplus { ev.data.fd = fd; ev.data.fd = fd; if (epoll_ctl(_pollFD, EPOLL_CTL_MOD, fd, &ev) < 0) { if (epoll_ctl(_pollFD, EPOLL_CTL_MOD, fd, &ev) < 0) { // If FD doesn't exist in epoll, add it instead if (errno == ENOENT) { if (epoll_ctl(_pollFD, EPOLL_CTL_ADD, fd, &ev) < 0) { NetException except; except[NetException::Error] << "setpollEventsFd: epoll_ctl ADD failed: " << strerror(errno); throw except; } } else { NetException except; NetException except; except[NetException::Error] << "setpollEventsFd: epoll_ctl MOD failed: " << strerror(errno); except[NetException::Error] << "setpollEventsFd: epoll_ctl MOD failed: " << strerror(errno); throw except; throw except; } } } } } int pollState(int pos) override { int pollState(int pos) override { if (_Events[pos].data.fd == _ServerSocket->fd()) if (_Events[pos].data.fd == _ServerSocket->fd()) Loading Loading @@ -244,8 +253,12 @@ namespace netplus { // IO handling (NO DEADLOCK!) // IO handling (NO DEADLOCK!) // ------------------------------------------------------------ // ------------------------------------------------------------ void IoEventHandler(int fd, int events, const int tid, ULONG_PTR args) override { void IoEventHandler(int fd, int events, const int tid, ULONG_PTR args) override { std::cerr << "[EPOLL] ===== IoEventHandler called! fd=" << fd << " events=" << events << " EPOLLIN=" << (events & EPOLLIN) << std::endl; std::shared_ptr<con> c = getConByFd(fd); std::shared_ptr<con> c = getConByFd(fd); if (!c || !c->csock) return; if (!c || !c->csock) { std::cerr << "[EPOLL] No connection found!" << std::endl; return; } EpollArmGuard rearm(fd, c, this); EpollArmGuard rearm(fd, c, this); Loading @@ -264,20 +277,58 @@ namespace netplus { needClose = true; needClose = true; } } else { else { std::cerr << "[EPOLL] Event: events=" << events << " EPOLLIN=" << (events & EPOLLIN) << " handshakeDone=" << c->csock->getHandshakeDone() << std::endl; // Step 1: If handshake not done and EPOLLIN, read raw TCP data into TLS buffer if ((events & EPOLLIN) && !c->csock->getHandshakeDone() && !needClose) { buffer buf(BLOCKSIZE); size_t rcv = 0; std::cerr << "[EPOLL] Attempting to read raw TCP data..." << std::endl; try { // Read raw TCP data (don't use recvData which tries to decrypt) rcv = ((netplus::tcp&)*c->csock).tcp::recvData(buf, 0); std::cerr << "[EPOLL] Read " << rcv << " bytes from socket" << std::endl; } catch (NetException& e) { if (e.getErrorType() == NetException::Note){ std::cerr << "[EPOLL] tcp::recvData threw Note (EAGAIN/EWOULDBLOCK)" << std::endl; // No data available right now - just continue to handshake // (it will re-arm socket when needed) rcv = 0; } else { throw; } } // 1) TLS handshake - loop until no more buffered data if (rcv == 0) { while (!c->csock->getHandshakeDone()) { std::cerr << "[EPOLL] No TCP data available (would block or EOF)" << std::endl; std::cerr << "[EPOLL] Calling handshake_after_accept()" << std::endl; } else { std::cerr << "[EPOLL] Received " << rcv << " raw TCP bytes for handshake" << std::endl; // Put raw TLS data into _rx_tcp_buf via pushReceivedData() c->csock->pushReceivedData((const uint8_t*)buf.data.buf, rcv); } } // Step 2: Try handshake (with buffered TLS data) if (!c->csock->getHandshakeDone() && !needClose) { std::cerr << "[EPOLL] BEFORE handshake_after_accept: handshakeDone=" << c->csock->getHandshakeDone() << std::endl; try { c->csock->handshake_after_accept(); c->csock->handshake_after_accept(); std::cerr << "[EPOLL] handshake_after_accept() returned" << std::endl; } catch (NetException& e) { if (e.getErrorType() != NetException::Note) throw; std::cerr << "[EPOLL] handshake_after_accept returned Note" << std::endl; } std::cerr << "[EPOLL] AFTER handshake_after_accept: handshakeDone=" << c->csock->getHandshakeDone() << std::endl; // Flush any pending write data if (c->csock->hasPendingWrite()) { if (c->csock->hasPendingWrite()) { std::cerr << "[EPOLL] Flushing pending write data" << std::endl; std::cerr << "[EPOLL] Flushing pending write data" << std::endl; try { try { c->csock->flush_out(); c->csock->flush_out(); } catch (NetException& e) { } catch (NetException& e) { if (e.getErrorType() == NetException::Note) { if (e.getErrorType() == NetException::Note) { std::cerr << "[EPOLL] flush_out threw Note" << std::endl; std::cerr << "[EPOLL] flush_out threw Note, re-arming for write" << std::endl; setpollEventsFd(fd, EPOLLOUT | EPOLLRDHUP | EPOLLONESHOT); setpollEventsFd(fd, EPOLLOUT | EPOLLRDHUP | EPOLLONESHOT); } else { } else { throw; throw; Loading @@ -285,32 +336,67 @@ namespace netplus { } } } } // Process any buffered TLS data left in socket buffer while (!c->csock->getHandshakeDone() && c->csock->hasBufferedData()) { std::cerr << "[EPOLL] Processing buffered TLS data" << std::endl; try { c->csock->handshake_after_accept(); } catch (NetException& e) { if (e.getErrorType() != NetException::Note) throw; } if (c->csock->hasPendingWrite()) { try { c->csock->flush_out(); } catch (NetException& e) { if (e.getErrorType() != NetException::Note) throw; setpollEventsFd(fd, EPOLLOUT | EPOLLRDHUP | EPOLLONESHOT); break; } } } // If handshake still not done, re-arm for more data if (!c->csock->getHandshakeDone()) { if (!c->csock->getHandshakeDone()) { // still waiting std::cerr << "[EPOLL] Handshake not done, re-arming socket" << std::endl; // Check if there's buffered data to process first! if (!c->csock->hasBufferedData()) { // No buffered data, re-arm socket for more events std::cerr << "[EPOLL] Handshake not done, re-arming socket for more events" << std::endl; int ev = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT; int ev = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT; if (c->csock->hasPendingWrite()) if (c->csock->hasPendingWrite()) ev |= EPOLLOUT; ev |= EPOLLOUT; setpollEventsFd(fd, ev); setpollEventsFd(fd, ev); break; // Exit handshake loop, return to event handler } } // else: has buffered data, loop again to process it std::cerr << "[EPOLL] Buffered data available, continuing handshake" << std::endl; } } // Step 3: Handle application data (only after handshake) if ((events & EPOLLIN) && c->csock->getHandshakeDone() && !needClose) { // First, read raw TCP data into TLS buffer std::cerr << "[EPOLL] Application data phase: reading raw TCP data..." << std::endl; try { buffer buf(BLOCKSIZE); size_t rcv = ((netplus::tcp&)*c->csock).tcp::recvData(buf, 0); std::cerr << "[EPOLL] Read " << rcv << " raw TCP bytes for application data" << std::endl; if (rcv > 0) { c->csock->pushReceivedData((const uint8_t*)buf.data.buf, rcv); } } catch (NetException& e) { if (e.getErrorType() != NetException::Note) { throw; } std::cerr << "[EPOLL] No more TCP data available (would block)" << std::endl; } } // 2) EPOLLIN: recv one chunk // Now try to decrypt application data from the TLS buffer if (events & EPOLLIN) { if (c->csock->hasBufferedData()) { buffer buf(BLOCKSIZE); buffer buf(BLOCKSIZE); size_t rcv = 0; size_t rcv = 0; std::cerr << "[EPOLL] Calling recvData for decrypted application data" << std::endl; try { try { rcv = c->csock->recvData(buf, 0); rcv = c->csock->recvData(buf, 0); std::cerr << "[EPOLL] recvData returned " << rcv << " decrypted bytes" << std::endl; } catch (NetException& e) { } catch (NetException& e) { std::cerr << "[EPOLL] recvData threw exception type=" << e.getErrorType() << " msg=" << e.what() << std::endl; if (e.getErrorType() == NetException::Note){ if (e.getErrorType() == NetException::Note){ std::cerr << "[EPOLL] Not ready for data, re-arming" << std::endl; rearm.disarm(); rearm.disarm(); setpollEventsFd(fd, EPOLLIN | EPOLLRDHUP | EPOLLONESHOT); setpollEventsFd(fd, EPOLLIN | EPOLLRDHUP | EPOLLONESHOT); return; return; Loading @@ -319,14 +405,17 @@ namespace netplus { } } if (rcv == 0) { if (rcv == 0) { std::cerr << "[EPOLL] recvData returned 0, peer closed" << std::endl; needClose = true; needClose = true; } else { } else { std::cerr << "[EPOLL] Appending " << rcv << " bytes to RecvData" << std::endl; c->RecvData.append(buf.data.buf, rcv); c->RecvData.append(buf.data.buf, rcv); evconnection->RequestEvent(*c, tid, args); evconnection->RequestEvent(*c, tid, args); } } } } } // 3) EPOLLOUT: flush + send one chunk // Step 4: EPOLLOUT: flush + send one chunk if ((events & EPOLLOUT) && !needClose) { if ((events & EPOLLOUT) && !needClose) { if (c->csock->hasPendingWrite()) { if (c->csock->hasPendingWrite()) { Loading src/event/iocp.cpp +78 −68 Original line number Original line Diff line number Diff line Loading @@ -575,7 +575,11 @@ namespace netplus { std::cerr << "[IOCP] handshakeDone=" << owner->csock->getHandshakeDone() << std::endl; std::cerr << "[IOCP] handshakeDone=" << owner->csock->getHandshakeDone() << std::endl; #endif #endif handshake_continue: // Process handshake with buffered data loop bool continueHandshake = true; while (continueHandshake && !owner->csock->getHandshakeDone()) { continueHandshake = false; // Check if handshake is done // Check if handshake is done if (!owner->csock->getHandshakeDone()) { if (!owner->csock->getHandshakeDone()) { #if IOCP_DEBUG #if IOCP_DEBUG Loading Loading @@ -615,29 +619,30 @@ handshake_continue: try { try { post_recv(st, *owner); post_recv(st, *owner); } catch (...) {} } catch (...) {} continue; continueHandshake = false; // Exit loop, wait for more data } } else { // Real error - disconnect // Real error - disconnect #if IOCP_DEBUG #if IOCP_DEBUG std::cerr << "[IOCP] Non-Note error - disconnecting" << std::endl; std::cerr << "[IOCP] Non-Note error - disconnecting" << std::endl; #endif #endif owner->ReadPending.store(false); owner->ReadPending.store(false); try_cleanup_con(ev, st, owner, cs, tid); try_cleanup_con(ev, st, owner, cs, tid); continue; continueHandshake = false; // Exit loop } } catch (std::exception& e) { } catch (std::exception& e) { #if IOCP_DEBUG #if IOCP_DEBUG std::cerr << "[IOCP] handshake_after_accept threw std::exception: " << e.what() << std::endl; std::cerr << "[IOCP] handshake_after_accept threw std::exception: " << e.what() << std::endl; #endif #endif owner->ReadPending.store(false); owner->ReadPending.store(false); try_cleanup_con(ev, st, owner, cs, tid); try_cleanup_con(ev, st, owner, cs, tid); continue; continueHandshake = false; // Exit loop } catch (...) { } catch (...) { #if IOCP_DEBUG #if IOCP_DEBUG std::cerr << "[IOCP] handshake_after_accept threw unknown exception" << std::endl; std::cerr << "[IOCP] handshake_after_accept threw unknown exception" << std::endl; #endif #endif owner->ReadPending.store(false); owner->ReadPending.store(false); try_cleanup_con(ev, st, owner, cs, tid); try_cleanup_con(ev, st, owner, cs, tid); continue; continueHandshake = false; // Exit loop } } // CRITICAL: handshake_after_accept() has ALREADY called flush_out() internally! // CRITICAL: handshake_after_accept() has ALREADY called flush_out() internally! Loading @@ -657,9 +662,8 @@ handshake_continue: std::cerr << "[IOCP] Buffered data available, continuing handshake loop" << std::endl; std::cerr << "[IOCP] Buffered data available, continuing handshake loop" << std::endl; #endif #endif // Continue processing without reposting recv // Continue processing without reposting recv // We need to call handshake_after_accept again continueHandshake = true; // Loop again goto handshake_continue; } else { } #if IOCP_DEBUG #if IOCP_DEBUG std::cerr << "[IOCP] Handshake not done, no buffered data, reposting recv" << std::endl; std::cerr << "[IOCP] Handshake not done, no buffered data, reposting recv" << std::endl; #endif #endif Loading @@ -667,6 +671,12 @@ handshake_continue: try { try { post_recv(st, *owner); post_recv(st, *owner); } catch (...) {} } catch (...) {} } } } } // Handshake is done or error occurred, continue main loop continue; continue; } } } } Loading src/socket.h +7 −6 Original line number Original line Diff line number Diff line Loading @@ -678,12 +678,7 @@ namespace netplus { IDLE IDLE }; }; HsState _hs_state = HsState::READ_CLIENT_HELLO; HsState _hs_state = HsState::IDLE; std::vector<uint8_t> _masterSecret; std::vector<uint8_t> _tls12_transcript_before_client_finished; // Saved for server Finished PRF std::vector<uint8_t> _handshake_transcript; std::vector<uint8_t> _clientHelloRawBytes; bool _handshakeDone = false; bool _handshakeDone = false; bool _is_server = true; bool _is_server = true; Loading @@ -691,6 +686,12 @@ namespace netplus { bool hasTLS13SV = false; bool hasTLS13SV = false; bool hasTLS13KS = false; bool hasTLS13KS = false; // TLS handshake state members std::vector<uint8_t> _handshake_transcript; std::vector<uint8_t> _masterSecret; std::vector<uint8_t> _clientHelloRawBytes; std::vector<uint8_t> _tls12_transcript_before_client_finished; friend class poll; friend class poll; friend class event; friend class event; friend class EventWorker; friend class EventWorker; Loading src/ssl.cpp +9 −1 Original line number Original line Diff line number Diff line Loading @@ -1628,9 +1628,11 @@ void netplus::ssl::handshake_after_accept(){ // Note: Caller (IOCP layer) must hold con::event_mutex to prevent concurrent access // Note: Caller (IOCP layer) must hold con::event_mutex to prevent concurrent access #if SSL_DEBUG #if SSL_DEBUG std::cerr << "[SSL] ===== handshake_after_accept ENTER state=" << (int)_hs_state << std::endl; std::cerr << "[SSL] ===== handshake_after_accept ENTER state=" << (int)_hs_state << " _handshakeDone=" << _handshakeDone << std::endl; std::cerr.flush(); std::cerr.flush(); #endif #endif std::cerr << "[SSL] ===== handshake_after_accept ENTER state=" << (int)_hs_state << " _handshakeDone=" << _handshakeDone << std::endl; std::cerr.flush(); auto throwSSL = [&](int type, const std::string& msg) { auto throwSSL = [&](int type, const std::string& msg) { netplus::NetException e; netplus::NetException e; Loading Loading @@ -1675,6 +1677,7 @@ void netplus::ssl::handshake_after_accept(){ // If already done -> nothing // If already done -> nothing if (_hs_state == HsState::DONE) { if (_hs_state == HsState::DONE) { std::cerr << "[SSL] handshake_after_accept: state already DONE, setting _handshakeDone=true" << std::endl; // sicherstellen: alles raus // sicherstellen: alles raus if (hasPendingWrite()) { if (hasPendingWrite()) { flush_out(); // darf Note werfen -> caller rearm EPOLLOUT flush_out(); // darf Note werfen -> caller rearm EPOLLOUT Loading Loading @@ -2343,6 +2346,7 @@ void netplus::ssl::handshake_after_accept(){ // 3) erst wenn wirklich alles raus ist -> DONE // 3) erst wenn wirklich alles raus ist -> DONE if (!hasPendingWrite()) { if (!hasPendingWrite()) { std::cerr << "[SSL] SEND_CCS_FIN: all data flushed, setting _handshakeDone=true and state=DONE" << std::endl; _handshakeDone = true; _handshakeDone = true; _hs_state = HsState::DONE; _hs_state = HsState::DONE; return; return; Loading Loading @@ -2528,6 +2532,7 @@ void netplus::ssl::handshake_after_accept(){ // after server Finished was added to transcript (but before client Finished). // after server Finished was added to transcript (but before client Finished). // Calling it again here would use wrong transcript (includes client Finished). // Calling it again here would use wrong transcript (includes client Finished). std::cerr << "[SSL] TLS13_WAIT_CLIENT_FINISHED: client finished verified, setting _handshakeDone=true" << std::endl; _handshakeDone = true; _handshakeDone = true; _hs_state = HsState::ESTABLISHED; _hs_state = HsState::ESTABLISHED; return; return; Loading Loading @@ -4431,6 +4436,7 @@ void netplus::ssl::_tls13_send_record(uint8_t inner_type, } } void netplus::ssl::resetTLS() { void netplus::ssl::resetTLS() { std::cerr << "[SSL] resetTLS ENTER: fd=" << this->fd() << std::endl; // MUST be false so next handshake is treated as fresh // MUST be false so next handshake is treated as fresh _handshakeStarted = false; _handshakeStarted = false; Loading @@ -4450,6 +4456,8 @@ void netplus::ssl::resetTLS() { _recv_seq = 0; _recv_seq = 0; _handshakeDone = false; _handshakeDone = false; std::cerr << "[SSL] resetTLS: after reset, _handshakeDone=" << _handshakeDone << " _hs_state=" << (int)_hs_state << std::endl; _handshake_transcript.clear(); _handshake_transcript.clear(); _clientRandom.clear(); _clientRandom.clear(); _serverRandom.clear(); _serverRandom.clear(); Loading Loading
src/event/epoll.cpp +130 −41 Original line number Original line Diff line number Diff line Loading @@ -171,11 +171,20 @@ namespace netplus { ev.data.fd = fd; ev.data.fd = fd; if (epoll_ctl(_pollFD, EPOLL_CTL_MOD, fd, &ev) < 0) { if (epoll_ctl(_pollFD, EPOLL_CTL_MOD, fd, &ev) < 0) { // If FD doesn't exist in epoll, add it instead if (errno == ENOENT) { if (epoll_ctl(_pollFD, EPOLL_CTL_ADD, fd, &ev) < 0) { NetException except; except[NetException::Error] << "setpollEventsFd: epoll_ctl ADD failed: " << strerror(errno); throw except; } } else { NetException except; NetException except; except[NetException::Error] << "setpollEventsFd: epoll_ctl MOD failed: " << strerror(errno); except[NetException::Error] << "setpollEventsFd: epoll_ctl MOD failed: " << strerror(errno); throw except; throw except; } } } } } int pollState(int pos) override { int pollState(int pos) override { if (_Events[pos].data.fd == _ServerSocket->fd()) if (_Events[pos].data.fd == _ServerSocket->fd()) Loading Loading @@ -244,8 +253,12 @@ namespace netplus { // IO handling (NO DEADLOCK!) // IO handling (NO DEADLOCK!) // ------------------------------------------------------------ // ------------------------------------------------------------ void IoEventHandler(int fd, int events, const int tid, ULONG_PTR args) override { void IoEventHandler(int fd, int events, const int tid, ULONG_PTR args) override { std::cerr << "[EPOLL] ===== IoEventHandler called! fd=" << fd << " events=" << events << " EPOLLIN=" << (events & EPOLLIN) << std::endl; std::shared_ptr<con> c = getConByFd(fd); std::shared_ptr<con> c = getConByFd(fd); if (!c || !c->csock) return; if (!c || !c->csock) { std::cerr << "[EPOLL] No connection found!" << std::endl; return; } EpollArmGuard rearm(fd, c, this); EpollArmGuard rearm(fd, c, this); Loading @@ -264,20 +277,58 @@ namespace netplus { needClose = true; needClose = true; } } else { else { std::cerr << "[EPOLL] Event: events=" << events << " EPOLLIN=" << (events & EPOLLIN) << " handshakeDone=" << c->csock->getHandshakeDone() << std::endl; // Step 1: If handshake not done and EPOLLIN, read raw TCP data into TLS buffer if ((events & EPOLLIN) && !c->csock->getHandshakeDone() && !needClose) { buffer buf(BLOCKSIZE); size_t rcv = 0; std::cerr << "[EPOLL] Attempting to read raw TCP data..." << std::endl; try { // Read raw TCP data (don't use recvData which tries to decrypt) rcv = ((netplus::tcp&)*c->csock).tcp::recvData(buf, 0); std::cerr << "[EPOLL] Read " << rcv << " bytes from socket" << std::endl; } catch (NetException& e) { if (e.getErrorType() == NetException::Note){ std::cerr << "[EPOLL] tcp::recvData threw Note (EAGAIN/EWOULDBLOCK)" << std::endl; // No data available right now - just continue to handshake // (it will re-arm socket when needed) rcv = 0; } else { throw; } } // 1) TLS handshake - loop until no more buffered data if (rcv == 0) { while (!c->csock->getHandshakeDone()) { std::cerr << "[EPOLL] No TCP data available (would block or EOF)" << std::endl; std::cerr << "[EPOLL] Calling handshake_after_accept()" << std::endl; } else { std::cerr << "[EPOLL] Received " << rcv << " raw TCP bytes for handshake" << std::endl; // Put raw TLS data into _rx_tcp_buf via pushReceivedData() c->csock->pushReceivedData((const uint8_t*)buf.data.buf, rcv); } } // Step 2: Try handshake (with buffered TLS data) if (!c->csock->getHandshakeDone() && !needClose) { std::cerr << "[EPOLL] BEFORE handshake_after_accept: handshakeDone=" << c->csock->getHandshakeDone() << std::endl; try { c->csock->handshake_after_accept(); c->csock->handshake_after_accept(); std::cerr << "[EPOLL] handshake_after_accept() returned" << std::endl; } catch (NetException& e) { if (e.getErrorType() != NetException::Note) throw; std::cerr << "[EPOLL] handshake_after_accept returned Note" << std::endl; } std::cerr << "[EPOLL] AFTER handshake_after_accept: handshakeDone=" << c->csock->getHandshakeDone() << std::endl; // Flush any pending write data if (c->csock->hasPendingWrite()) { if (c->csock->hasPendingWrite()) { std::cerr << "[EPOLL] Flushing pending write data" << std::endl; std::cerr << "[EPOLL] Flushing pending write data" << std::endl; try { try { c->csock->flush_out(); c->csock->flush_out(); } catch (NetException& e) { } catch (NetException& e) { if (e.getErrorType() == NetException::Note) { if (e.getErrorType() == NetException::Note) { std::cerr << "[EPOLL] flush_out threw Note" << std::endl; std::cerr << "[EPOLL] flush_out threw Note, re-arming for write" << std::endl; setpollEventsFd(fd, EPOLLOUT | EPOLLRDHUP | EPOLLONESHOT); setpollEventsFd(fd, EPOLLOUT | EPOLLRDHUP | EPOLLONESHOT); } else { } else { throw; throw; Loading @@ -285,32 +336,67 @@ namespace netplus { } } } } // Process any buffered TLS data left in socket buffer while (!c->csock->getHandshakeDone() && c->csock->hasBufferedData()) { std::cerr << "[EPOLL] Processing buffered TLS data" << std::endl; try { c->csock->handshake_after_accept(); } catch (NetException& e) { if (e.getErrorType() != NetException::Note) throw; } if (c->csock->hasPendingWrite()) { try { c->csock->flush_out(); } catch (NetException& e) { if (e.getErrorType() != NetException::Note) throw; setpollEventsFd(fd, EPOLLOUT | EPOLLRDHUP | EPOLLONESHOT); break; } } } // If handshake still not done, re-arm for more data if (!c->csock->getHandshakeDone()) { if (!c->csock->getHandshakeDone()) { // still waiting std::cerr << "[EPOLL] Handshake not done, re-arming socket" << std::endl; // Check if there's buffered data to process first! if (!c->csock->hasBufferedData()) { // No buffered data, re-arm socket for more events std::cerr << "[EPOLL] Handshake not done, re-arming socket for more events" << std::endl; int ev = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT; int ev = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT; if (c->csock->hasPendingWrite()) if (c->csock->hasPendingWrite()) ev |= EPOLLOUT; ev |= EPOLLOUT; setpollEventsFd(fd, ev); setpollEventsFd(fd, ev); break; // Exit handshake loop, return to event handler } } // else: has buffered data, loop again to process it std::cerr << "[EPOLL] Buffered data available, continuing handshake" << std::endl; } } // Step 3: Handle application data (only after handshake) if ((events & EPOLLIN) && c->csock->getHandshakeDone() && !needClose) { // First, read raw TCP data into TLS buffer std::cerr << "[EPOLL] Application data phase: reading raw TCP data..." << std::endl; try { buffer buf(BLOCKSIZE); size_t rcv = ((netplus::tcp&)*c->csock).tcp::recvData(buf, 0); std::cerr << "[EPOLL] Read " << rcv << " raw TCP bytes for application data" << std::endl; if (rcv > 0) { c->csock->pushReceivedData((const uint8_t*)buf.data.buf, rcv); } } catch (NetException& e) { if (e.getErrorType() != NetException::Note) { throw; } std::cerr << "[EPOLL] No more TCP data available (would block)" << std::endl; } } // 2) EPOLLIN: recv one chunk // Now try to decrypt application data from the TLS buffer if (events & EPOLLIN) { if (c->csock->hasBufferedData()) { buffer buf(BLOCKSIZE); buffer buf(BLOCKSIZE); size_t rcv = 0; size_t rcv = 0; std::cerr << "[EPOLL] Calling recvData for decrypted application data" << std::endl; try { try { rcv = c->csock->recvData(buf, 0); rcv = c->csock->recvData(buf, 0); std::cerr << "[EPOLL] recvData returned " << rcv << " decrypted bytes" << std::endl; } catch (NetException& e) { } catch (NetException& e) { std::cerr << "[EPOLL] recvData threw exception type=" << e.getErrorType() << " msg=" << e.what() << std::endl; if (e.getErrorType() == NetException::Note){ if (e.getErrorType() == NetException::Note){ std::cerr << "[EPOLL] Not ready for data, re-arming" << std::endl; rearm.disarm(); rearm.disarm(); setpollEventsFd(fd, EPOLLIN | EPOLLRDHUP | EPOLLONESHOT); setpollEventsFd(fd, EPOLLIN | EPOLLRDHUP | EPOLLONESHOT); return; return; Loading @@ -319,14 +405,17 @@ namespace netplus { } } if (rcv == 0) { if (rcv == 0) { std::cerr << "[EPOLL] recvData returned 0, peer closed" << std::endl; needClose = true; needClose = true; } else { } else { std::cerr << "[EPOLL] Appending " << rcv << " bytes to RecvData" << std::endl; c->RecvData.append(buf.data.buf, rcv); c->RecvData.append(buf.data.buf, rcv); evconnection->RequestEvent(*c, tid, args); evconnection->RequestEvent(*c, tid, args); } } } } } // 3) EPOLLOUT: flush + send one chunk // Step 4: EPOLLOUT: flush + send one chunk if ((events & EPOLLOUT) && !needClose) { if ((events & EPOLLOUT) && !needClose) { if (c->csock->hasPendingWrite()) { if (c->csock->hasPendingWrite()) { Loading
src/event/iocp.cpp +78 −68 Original line number Original line Diff line number Diff line Loading @@ -575,7 +575,11 @@ namespace netplus { std::cerr << "[IOCP] handshakeDone=" << owner->csock->getHandshakeDone() << std::endl; std::cerr << "[IOCP] handshakeDone=" << owner->csock->getHandshakeDone() << std::endl; #endif #endif handshake_continue: // Process handshake with buffered data loop bool continueHandshake = true; while (continueHandshake && !owner->csock->getHandshakeDone()) { continueHandshake = false; // Check if handshake is done // Check if handshake is done if (!owner->csock->getHandshakeDone()) { if (!owner->csock->getHandshakeDone()) { #if IOCP_DEBUG #if IOCP_DEBUG Loading Loading @@ -615,29 +619,30 @@ handshake_continue: try { try { post_recv(st, *owner); post_recv(st, *owner); } catch (...) {} } catch (...) {} continue; continueHandshake = false; // Exit loop, wait for more data } } else { // Real error - disconnect // Real error - disconnect #if IOCP_DEBUG #if IOCP_DEBUG std::cerr << "[IOCP] Non-Note error - disconnecting" << std::endl; std::cerr << "[IOCP] Non-Note error - disconnecting" << std::endl; #endif #endif owner->ReadPending.store(false); owner->ReadPending.store(false); try_cleanup_con(ev, st, owner, cs, tid); try_cleanup_con(ev, st, owner, cs, tid); continue; continueHandshake = false; // Exit loop } } catch (std::exception& e) { } catch (std::exception& e) { #if IOCP_DEBUG #if IOCP_DEBUG std::cerr << "[IOCP] handshake_after_accept threw std::exception: " << e.what() << std::endl; std::cerr << "[IOCP] handshake_after_accept threw std::exception: " << e.what() << std::endl; #endif #endif owner->ReadPending.store(false); owner->ReadPending.store(false); try_cleanup_con(ev, st, owner, cs, tid); try_cleanup_con(ev, st, owner, cs, tid); continue; continueHandshake = false; // Exit loop } catch (...) { } catch (...) { #if IOCP_DEBUG #if IOCP_DEBUG std::cerr << "[IOCP] handshake_after_accept threw unknown exception" << std::endl; std::cerr << "[IOCP] handshake_after_accept threw unknown exception" << std::endl; #endif #endif owner->ReadPending.store(false); owner->ReadPending.store(false); try_cleanup_con(ev, st, owner, cs, tid); try_cleanup_con(ev, st, owner, cs, tid); continue; continueHandshake = false; // Exit loop } } // CRITICAL: handshake_after_accept() has ALREADY called flush_out() internally! // CRITICAL: handshake_after_accept() has ALREADY called flush_out() internally! Loading @@ -657,9 +662,8 @@ handshake_continue: std::cerr << "[IOCP] Buffered data available, continuing handshake loop" << std::endl; std::cerr << "[IOCP] Buffered data available, continuing handshake loop" << std::endl; #endif #endif // Continue processing without reposting recv // Continue processing without reposting recv // We need to call handshake_after_accept again continueHandshake = true; // Loop again goto handshake_continue; } else { } #if IOCP_DEBUG #if IOCP_DEBUG std::cerr << "[IOCP] Handshake not done, no buffered data, reposting recv" << std::endl; std::cerr << "[IOCP] Handshake not done, no buffered data, reposting recv" << std::endl; #endif #endif Loading @@ -667,6 +671,12 @@ handshake_continue: try { try { post_recv(st, *owner); post_recv(st, *owner); } catch (...) {} } catch (...) {} } } } } // Handshake is done or error occurred, continue main loop continue; continue; } } } } Loading
src/socket.h +7 −6 Original line number Original line Diff line number Diff line Loading @@ -678,12 +678,7 @@ namespace netplus { IDLE IDLE }; }; HsState _hs_state = HsState::READ_CLIENT_HELLO; HsState _hs_state = HsState::IDLE; std::vector<uint8_t> _masterSecret; std::vector<uint8_t> _tls12_transcript_before_client_finished; // Saved for server Finished PRF std::vector<uint8_t> _handshake_transcript; std::vector<uint8_t> _clientHelloRawBytes; bool _handshakeDone = false; bool _handshakeDone = false; bool _is_server = true; bool _is_server = true; Loading @@ -691,6 +686,12 @@ namespace netplus { bool hasTLS13SV = false; bool hasTLS13SV = false; bool hasTLS13KS = false; bool hasTLS13KS = false; // TLS handshake state members std::vector<uint8_t> _handshake_transcript; std::vector<uint8_t> _masterSecret; std::vector<uint8_t> _clientHelloRawBytes; std::vector<uint8_t> _tls12_transcript_before_client_finished; friend class poll; friend class poll; friend class event; friend class event; friend class EventWorker; friend class EventWorker; Loading
src/ssl.cpp +9 −1 Original line number Original line Diff line number Diff line Loading @@ -1628,9 +1628,11 @@ void netplus::ssl::handshake_after_accept(){ // Note: Caller (IOCP layer) must hold con::event_mutex to prevent concurrent access // Note: Caller (IOCP layer) must hold con::event_mutex to prevent concurrent access #if SSL_DEBUG #if SSL_DEBUG std::cerr << "[SSL] ===== handshake_after_accept ENTER state=" << (int)_hs_state << std::endl; std::cerr << "[SSL] ===== handshake_after_accept ENTER state=" << (int)_hs_state << " _handshakeDone=" << _handshakeDone << std::endl; std::cerr.flush(); std::cerr.flush(); #endif #endif std::cerr << "[SSL] ===== handshake_after_accept ENTER state=" << (int)_hs_state << " _handshakeDone=" << _handshakeDone << std::endl; std::cerr.flush(); auto throwSSL = [&](int type, const std::string& msg) { auto throwSSL = [&](int type, const std::string& msg) { netplus::NetException e; netplus::NetException e; Loading Loading @@ -1675,6 +1677,7 @@ void netplus::ssl::handshake_after_accept(){ // If already done -> nothing // If already done -> nothing if (_hs_state == HsState::DONE) { if (_hs_state == HsState::DONE) { std::cerr << "[SSL] handshake_after_accept: state already DONE, setting _handshakeDone=true" << std::endl; // sicherstellen: alles raus // sicherstellen: alles raus if (hasPendingWrite()) { if (hasPendingWrite()) { flush_out(); // darf Note werfen -> caller rearm EPOLLOUT flush_out(); // darf Note werfen -> caller rearm EPOLLOUT Loading Loading @@ -2343,6 +2346,7 @@ void netplus::ssl::handshake_after_accept(){ // 3) erst wenn wirklich alles raus ist -> DONE // 3) erst wenn wirklich alles raus ist -> DONE if (!hasPendingWrite()) { if (!hasPendingWrite()) { std::cerr << "[SSL] SEND_CCS_FIN: all data flushed, setting _handshakeDone=true and state=DONE" << std::endl; _handshakeDone = true; _handshakeDone = true; _hs_state = HsState::DONE; _hs_state = HsState::DONE; return; return; Loading Loading @@ -2528,6 +2532,7 @@ void netplus::ssl::handshake_after_accept(){ // after server Finished was added to transcript (but before client Finished). // after server Finished was added to transcript (but before client Finished). // Calling it again here would use wrong transcript (includes client Finished). // Calling it again here would use wrong transcript (includes client Finished). std::cerr << "[SSL] TLS13_WAIT_CLIENT_FINISHED: client finished verified, setting _handshakeDone=true" << std::endl; _handshakeDone = true; _handshakeDone = true; _hs_state = HsState::ESTABLISHED; _hs_state = HsState::ESTABLISHED; return; return; Loading Loading @@ -4431,6 +4436,7 @@ void netplus::ssl::_tls13_send_record(uint8_t inner_type, } } void netplus::ssl::resetTLS() { void netplus::ssl::resetTLS() { std::cerr << "[SSL] resetTLS ENTER: fd=" << this->fd() << std::endl; // MUST be false so next handshake is treated as fresh // MUST be false so next handshake is treated as fresh _handshakeStarted = false; _handshakeStarted = false; Loading @@ -4450,6 +4456,8 @@ void netplus::ssl::resetTLS() { _recv_seq = 0; _recv_seq = 0; _handshakeDone = false; _handshakeDone = false; std::cerr << "[SSL] resetTLS: after reset, _handshakeDone=" << _handshakeDone << " _hs_state=" << (int)_hs_state << std::endl; _handshake_transcript.clear(); _handshake_transcript.clear(); _clientRandom.clear(); _clientRandom.clear(); _serverRandom.clear(); _serverRandom.clear(); Loading