Loading examples/httpsysinfo.cpp +7 −7 Original line number Diff line number Diff line Loading @@ -250,15 +250,15 @@ public: void ResponseEvent(libhttppp::HttpRequest& curreq, const int tid,ULONG_PTR args){ if (curreq.getRequestURL()=="/images/header.png") { size_t rem = header_png_size - curreq.slots[0].SendData.pos; size_t rem = header_png_size - curreq.SendData.pos; size_t si = (rem > BLOCKSIZE) ? BLOCKSIZE : rem; curreq.slots[0].SendData.append((const char*)header_png + curreq.slots[0].SendData.pos, si); curreq.slots[0].SendData.pos += si; curreq.SendData.append((const char*)header_png + curreq.SendData.pos, si); curreq.SendData.pos += si; } else if(curreq.getRequestURL()=="/favicon.ico"){ if(curreq.slots[0].SendData.pos < favicon_ico_size){ size_t si = BLOCKSIZE < (favicon_ico_size-curreq.slots[0].SendData.pos) ? BLOCKSIZE : (favicon_ico_size-curreq.slots[0].SendData.pos); curreq.slots[0].SendData.append((const char*)favicon_ico+curreq.slots[0].SendData.pos, si); curreq.slots[0].SendData.pos+=si; if(curreq.SendData.pos < favicon_ico_size){ size_t si = BLOCKSIZE < (favicon_ico_size-curreq.SendData.pos) ? BLOCKSIZE : (favicon_ico_size-curreq.SendData.pos); curreq.SendData.append((const char*)favicon_ico+curreq.SendData.pos, si); curreq.SendData.pos+=si; } } } Loading src/http.cpp +23 −23 Original line number Diff line number Diff line Loading @@ -2933,10 +2933,10 @@ void libhttppp::HttpResponse::send(netplus::con &curconnection,const std::string } // For HTTP/2 and HTTP/3: store structured response info directly, // write only body data to slots[0].SendData (no H1 text round-trip) // write only body data to SendData (no H1 text round-trip) if (_storeResponseInfo(curconnection, datalen)) { if (datalen > 0) curconnection.slots[0].SendData.append(data.data(), datalen); curconnection.SendData.append(data.data(), datalen); return; } Loading @@ -2944,10 +2944,10 @@ void libhttppp::HttpResponse::send(netplus::con &curconnection,const std::string printHeader(header); curconnection.slots[0].SendData.append(header.data(),header.size()); curconnection.SendData.append(header.data(),header.size()); if (datalen > 0) curconnection.slots[0].SendData.append(data.data(),datalen); curconnection.SendData.append(data.data(),datalen); } void libhttppp::HttpResponse::send(netplus::con &curconnection,const unsigned char *data,int datalen){ Loading @@ -2965,7 +2965,7 @@ void libhttppp::HttpResponse::send(netplus::con &curconnection,const unsigned c // For HTTP/2 and HTTP/3: store structured response info directly if (_storeResponseInfo(curconnection, datalen)) { if (datalen > 0 && data) curconnection.slots[0].SendData.append(reinterpret_cast<const char*>(data), datalen); curconnection.SendData.append(reinterpret_cast<const char*>(data), datalen); return; } Loading @@ -2973,10 +2973,10 @@ void libhttppp::HttpResponse::send(netplus::con &curconnection,const unsigned c printHeader(header); curconnection.slots[0].SendData.append(header.data(),header.size()); curconnection.SendData.append(header.data(),header.size()); if (datalen > 0 && data) { curconnection.slots[0].SendData.append(reinterpret_cast<const char*>(data), datalen); curconnection.SendData.append(reinterpret_cast<const char*>(data), datalen); } } Loading @@ -2999,7 +2999,7 @@ void libhttppp::HttpResponse::send(netplus::con &curconnection,const std::vector // For HTTP/2 and HTTP/3: store structured response info directly if (_storeResponseInfo(curconnection, datalen)) { if (datalen > 0) curconnection.slots[0].SendData.append(data.data(), datalen); curconnection.SendData.append(data.data(), datalen); return; } Loading @@ -3007,10 +3007,10 @@ void libhttppp::HttpResponse::send(netplus::con &curconnection,const std::vector printHeader(header); curconnection.slots[0].SendData.append(header.data(),header.size()); curconnection.SendData.append(header.data(),header.size()); if (datalen > 0) curconnection.slots[0].SendData.append(data.data(),datalen); curconnection.SendData.append(data.data(),datalen); } size_t libhttppp::HttpResponse::parse(const char *data, size_t inlen) { Loading Loading @@ -3253,7 +3253,7 @@ size_t libhttppp::HttpRequest::parseH2(const std::vector<hpack::HeaderField> &he h2.streamId = stream_id; h2.headersSent = false; h2.bodyBytesSent = 0; slots[0].SendData.pos = 0; SendData.pos = 0; // Store ALL headers (including pseudo-headers) in _firstHeaderData. // Split values by ';' (matching parseH1 behaviour) so that cookie Loading Loading @@ -3321,7 +3321,7 @@ size_t libhttppp::HttpRequest::parseH2(const std::vector<hpack::HeaderField> &he size_t libhttppp::HttpRequest::parseH3(const std::vector<qpack::HeaderField> &headers) { clear(); _httpProtocol = 2; slots[0].SendData.pos = 0; SendData.pos = 0; // Store ALL headers (including pseudo-headers) in _firstHeaderData. // Split values by ';' (matching parseH1 behaviour) so that cookie Loading Loading @@ -3405,7 +3405,7 @@ size_t libhttppp::HttpRequest::parseH1() { try { // 1) Find end of headers: "\r\n\r\n" size_t endpos = slots[0].RecvData.search("\r\n\r\n"); size_t endpos = RecvData.search("\r\n\r\n"); if (endpos == std::string::npos) { // Not enough data yet _RequestType = PARSEREQUEST; Loading @@ -3414,11 +3414,11 @@ size_t libhttppp::HttpRequest::parseH1() { // 2) Copy header bytes (include the first \r\n of the separator so // every header line, including the last one, ends with \r\n) header.assign(slots[0].RecvData.begin(), slots[0].RecvData.begin() + endpos + 2); header.assign(RecvData.begin(), RecvData.begin() + endpos + 2); // 3) Consume header (and the delimiter) from slots[0].RecvData // 3) Consume header (and the delimiter) from RecvData endpos += 4; // include "\r\n\r\n" slots[0].RecvData.erase(slots[0].RecvData.begin(),slots[0].RecvData.begin()+endpos); RecvData.erase(RecvData.begin(),RecvData.begin()+endpos); // 4) Parse the request line (first line until CRLF) size_t line_end = 0; Loading Loading @@ -3572,13 +3572,13 @@ size_t libhttppp::HttpRequest::parseH1() { } catch (netplus::NetException& e) { if (e.getErrorType() != netplus::NetException::Note) { slots[0].RecvData.clear(); RecvData.clear(); } excep[HTTPException::Error] << "netplus error: " << e.what(); throw excep; } catch (...) { // keep behavior similar to your original: on parse error, clean up input slots[0].RecvData.clear(); RecvData.clear(); throw; } Loading Loading @@ -3759,14 +3759,14 @@ void libhttppp::HttpForm::parse(libhttppp::HttpRequest &request){ throw excep; } // Use content-length if available, otherwise fall back to slots[0].RecvData size // Use content-length if available, otherwise fall back to RecvData size // (HTTP/2 and HTTP/3 may omit Content-Length) size_t bodyLen = request.getContentLength(); if(bodyLen == 0) bodyLen = request.slots[0].RecvData.size(); bodyLen = request.RecvData.size(); for(auto *cval=ctype->getfirstValue(); cval; cval=cval->nextvalue()){ if(bodyLen <= request.slots[0].RecvData.size()){ if(bodyLen <= request.RecvData.size()){ if(cval->getvalue().find("multipart/form-data") != std::string::npos){ _contentType = "multipart/form-data"; for(auto *cbod=ctype->getfirstValue(); cbod; cbod=cbod->nextvalue()){ Loading @@ -3783,7 +3783,7 @@ void libhttppp::HttpForm::parse(libhttppp::HttpRequest &request){ if(bval.size() >= 2 && bval.front() == '"' && bval.back() == '"') bval = bval.substr(1, bval.size() - 2); _boundary = std::move(bval); _parseMultipart(request.slots[0].RecvData.data(), request.slots[0].RecvData.size()); _parseMultipart(request.RecvData.data(), request.RecvData.size()); break; } } Loading @@ -3791,7 +3791,7 @@ void libhttppp::HttpForm::parse(libhttppp::HttpRequest &request){ } if(cval->getvalue().find("application/x-www-form-urlencoded") != std::string::npos){ _contentType = "application/x-www-form-urlencoded"; _parseUrlDecode(request.slots[0].RecvData.data(), bodyLen); _parseUrlDecode(request.RecvData.data(), bodyLen); } } } Loading src/httpd.cpp +52 −52 Original line number Diff line number Diff line Loading @@ -366,7 +366,7 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, // Store POST body in RecvData so HttpForm::parse() can access it if (!reqBody.empty()) { tempreq.slots[0].RecvData.append(reqBody.data(), reqBody.size()); tempreq.RecvData.append(reqBody.data(), reqBody.size()); } // Ensure content-length is set from actual body size (H2 framing Loading Loading @@ -405,9 +405,9 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, std::string body; if (content_length > 0) body.reserve(content_length); if (!tempreq.slots[0].SendData.empty()) { body.assign(tempreq.slots[0].SendData.data(), tempreq.slots[0].SendData.size()); tempreq.slots[0].SendData.clear(); if (!tempreq.SendData.empty()) { body.assign(tempreq.SendData.data(), tempreq.SendData.size()); tempreq.SendData.clear(); } bool is_streaming = (content_length > 0 && Loading @@ -420,7 +420,7 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, // from the upstream backend (via ResponseEvent on tempreq). tempreq.h2state().expectedContentLength = content_length; tempreq.slots[0].SendData.pos = 0; tempreq.SendData.pos = 0; // Collect extra :res-* headers before we start std::vector<libhttppp::hpack::HeaderField> extra; Loading Loading @@ -452,22 +452,22 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, } // Flush to real connection so client starts receiving cureq.slots[0].SendData.append(out.data(), out.size()); cureq.SendData.append(out.data(), out.size()); out.clear(); // Immediately flush HEADERS to the socket so the browser // can start preparing its video player while we stream DATA. if (cureq.slots[0].csock) { while (cureq.slots[0].SendData.pos < cureq.slots[0].SendData.size()) { size_t remaining = cureq.slots[0].SendData.size() - cureq.slots[0].SendData.pos; while (cureq.SendData.pos < cureq.SendData.size()) { size_t remaining = cureq.SendData.size() - cureq.SendData.pos; size_t sendlen = std::min(remaining, (size_t)BLOCKSIZE); netplus::buffer buf(cureq.slots[0].SendData.data() + cureq.slots[0].SendData.pos, sendlen); netplus::buffer buf(cureq.SendData.data() + cureq.SendData.pos, sendlen); try { size_t consumed = cureq.slots[0].csock->sendData(buf, 0); if (cureq.slots[0].csock->hasPendingWrite()) cureq.slots[0].csock->flush_out(); if (consumed > 0) cureq.slots[0].SendData.pos += consumed; cureq.SendData.pos += consumed; else break; } catch (netplus::NetException &e) { Loading @@ -476,9 +476,9 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, throw; } } if (cureq.slots[0].SendData.pos >= cureq.slots[0].SendData.size()) { cureq.slots[0].SendData.clear(); cureq.slots[0].SendData.pos = 0; if (cureq.SendData.pos >= cureq.SendData.size()) { cureq.SendData.clear(); cureq.SendData.pos = 0; } } Loading @@ -493,13 +493,13 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, i < max_iterations && total_sent < content_length; ++i) { ResponseEvent(tempreq, tid, args); size_t sa = tempreq.slots[0].SendData.size(); size_t sa = tempreq.SendData.size(); if (sa > 0) { // Build DATA frames and flush directly to the // real connection so epoll can drain to the client. bool last = (total_sent + sa >= content_length); std::string chunk(tempreq.slots[0].SendData.data(), sa); tempreq.slots[0].SendData.clear(); std::string chunk(tempreq.SendData.data(), sa); tempreq.SendData.clear(); std::string frames; frames.reserve(sa + (sa / H2_MAX_FRAME_SIZE + 1) * H2_FRAME_HEADER_LEN); Loading @@ -513,7 +513,7 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, std::string(chunk.data() + off, frag)); off += frag; } cureq.slots[0].SendData.append(frames.data(), frames.size()); cureq.SendData.append(frames.data(), frames.size()); total_sent += sa; empty_count = 0; backoff_ms = 1; Loading @@ -523,16 +523,16 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, // Without this, the entire video buffers in memory // before the event loop can write any bytes. if (cureq.slots[0].csock) { while (cureq.slots[0].SendData.pos < cureq.slots[0].SendData.size()) { size_t remaining = cureq.slots[0].SendData.size() - cureq.slots[0].SendData.pos; while (cureq.SendData.pos < cureq.SendData.size()) { size_t remaining = cureq.SendData.size() - cureq.SendData.pos; size_t sendlen = std::min(remaining, (size_t)BLOCKSIZE); netplus::buffer buf(cureq.slots[0].SendData.data() + cureq.slots[0].SendData.pos, sendlen); netplus::buffer buf(cureq.SendData.data() + cureq.SendData.pos, sendlen); try { size_t consumed = cureq.slots[0].csock->sendData(buf, 0); if (cureq.slots[0].csock->hasPendingWrite()) cureq.slots[0].csock->flush_out(); if (consumed > 0) { cureq.slots[0].SendData.pos += consumed; cureq.SendData.pos += consumed; } else { break; } Loading @@ -542,13 +542,13 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, throw; } } if (cureq.slots[0].SendData.pos >= cureq.slots[0].SendData.size()) { cureq.slots[0].SendData.clear(); cureq.slots[0].SendData.pos = 0; } else if (cureq.slots[0].SendData.pos > BLOCKSIZE * 4) { cureq.slots[0].SendData.erase(cureq.slots[0].SendData.begin(), cureq.slots[0].SendData.begin() + cureq.slots[0].SendData.pos); cureq.slots[0].SendData.pos = 0; if (cureq.SendData.pos >= cureq.SendData.size()) { cureq.SendData.clear(); cureq.SendData.pos = 0; } else if (cureq.SendData.pos > BLOCKSIZE * 4) { cureq.SendData.erase(cureq.SendData.begin(), cureq.SendData.begin() + cureq.SendData.pos); cureq.SendData.pos = 0; } } } else { Loading @@ -564,7 +564,7 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, // If we exited without finishing, send END_STREAM on an empty DATA frame if (total_sent < content_length) { std::string end_frame = h2BuildFrame(H2_FRAME_DATA, H2_FLAG_END_STREAM, sid, ""); cureq.slots[0].SendData.append(end_frame.data(), end_frame.size()); cureq.SendData.append(end_frame.data(), end_frame.size()); } return; // Already handled — skip the normal encoding below Loading Loading @@ -642,20 +642,20 @@ bool libhttppp::HttpEvent::Http2RequestEvent(netplus::con &curcon, size_t off = 0; // Consume HTTP/2 client connection preface if present if (cureq.slots[0].RecvData.size() >= H2_CLIENT_PREFACE_LEN && std::memcmp(cureq.slots[0].RecvData.data(), H2_CLIENT_PREFACE, H2_CLIENT_PREFACE_LEN) == 0) { if (cureq.RecvData.size() >= H2_CLIENT_PREFACE_LEN && std::memcmp(cureq.RecvData.data(), H2_CLIENT_PREFACE, H2_CLIENT_PREFACE_LEN) == 0) { off += H2_CLIENT_PREFACE_LEN; } // Send server SETTINGS if not already sent (e.g. ConnectEvent already sent it) if (cureq.slots[0].SendData.empty()) { if (cureq.SendData.empty()) { out += h2BuildSettings(); out += h2ConnectionWindowBoost(); } // Process all complete frames in RecvData while (off + H2_FRAME_HEADER_LEN <= cureq.slots[0].RecvData.size()) { const char *data = cureq.slots[0].RecvData.data(); while (off + H2_FRAME_HEADER_LEN <= cureq.RecvData.size()) { const char *data = cureq.RecvData.data(); uint32_t flen = (static_cast<uint8_t>(data[off]) << 16) | (static_cast<uint8_t>(data[off + 1]) << 8) | static_cast<uint8_t>(data[off + 2]); Loading @@ -666,7 +666,7 @@ bool libhttppp::HttpEvent::Http2RequestEvent(netplus::con &curcon, (static_cast<uint8_t>(data[off + 7]) << 8) | static_cast<uint8_t>(data[off + 8]); if (off + H2_FRAME_HEADER_LEN + flen > cureq.slots[0].RecvData.size()) { if (off + H2_FRAME_HEADER_LEN + flen > cureq.RecvData.size()) { break; // Incomplete frame, wait for more data } Loading Loading @@ -824,11 +824,11 @@ bool libhttppp::HttpEvent::Http2RequestEvent(netplus::con &curcon, done: if (!out.empty()) { cureq.slots[0].SendData.append(out.data(), out.size()); cureq.SendData.append(out.data(), out.size()); } if (off > 0) { cureq.slots[0].RecvData.erase(cureq.slots[0].RecvData.begin(), cureq.slots[0].RecvData.begin() + off); cureq.RecvData.erase(cureq.RecvData.begin(), cureq.RecvData.begin() + off); } return true; Loading Loading @@ -960,7 +960,7 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock, // Store POST body in RecvData so HttpForm::parse() can access it if (!bodyData.empty()) { tempreq.slots[0].RecvData.append(bodyData.data(), bodyData.size()); tempreq.RecvData.append(bodyData.data(), bodyData.size()); } // Ensure content-length is set from actual body size (H3 framing Loading Loading @@ -999,9 +999,9 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock, std::string body; if (content_length > 0) body.reserve(content_length); if (!tempreq.slots[0].SendData.empty()) { body.assign(tempreq.slots[0].SendData.data(), tempreq.slots[0].SendData.size()); tempreq.slots[0].SendData.clear(); if (!tempreq.SendData.empty()) { body.assign(tempreq.SendData.data(), tempreq.SendData.size()); tempreq.SendData.clear(); } bool is_streaming = (content_length > 0 && Loading @@ -1009,16 +1009,16 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock, // If streaming, collect all remaining data if (is_streaming) { tempreq.slots[0].SendData.pos = 0; tempreq.SendData.pos = 0; size_t max_iter = content_length / BLOCKSIZE + 4096; for (size_t i = 0; i < max_iter && body.size() < content_length; ++i) { ResponseEvent(tempreq, 0, 0); size_t sa = tempreq.slots[0].SendData.size(); size_t sa = tempreq.SendData.size(); if (sa > 0) { body.append(tempreq.slots[0].SendData.data(), sa); tempreq.slots[0].SendData.clear(); body.append(tempreq.SendData.data(), sa); tempreq.SendData.clear(); } else { break; } Loading Loading @@ -1091,9 +1091,9 @@ REQUESTHANDLING: if(clen == 0){ RequestEvent(cureq,tid,args); cureq._RequestType=PARSEREQUEST; } else if(cureq.slots[0].RecvData.size()>=clen){ } else if(cureq.RecvData.size()>=clen){ RequestEvent(cureq,tid,args); cureq.slots[0].RecvData.erase(cureq.slots[0].RecvData.begin(),cureq.slots[0].RecvData.begin()+clen); cureq.RecvData.erase(cureq.RecvData.begin(),cureq.RecvData.begin()+clen); cureq._RequestType=PARSEREQUEST; } break; Loading @@ -1103,9 +1103,9 @@ REQUESTHANDLING: if(clen == 0){ RequestEvent(cureq,tid,args); cureq._RequestType=PARSEREQUEST; } else if(cureq.slots[0].RecvData.size()>=clen){ } else if(cureq.RecvData.size()>=clen){ RequestEvent(cureq,tid,args); cureq.slots[0].RecvData.erase(cureq.slots[0].RecvData.begin(),cureq.slots[0].RecvData.begin()+clen); cureq.RecvData.erase(cureq.RecvData.begin(),cureq.RecvData.begin()+clen); cureq._RequestType=PARSEREQUEST; } break; Loading Loading @@ -1149,7 +1149,7 @@ void libhttppp::HttpEvent::ResponseEvent(netplus::con &curcon,const int tid,ULON if (last) break; } if (!batch.empty()) { cureq.slots[0].SendData.append(batch.data(), batch.size()); cureq.SendData.append(batch.data(), batch.size()); } if (pending.offset >= pending.body.size()) { cureq._h2->pendingResponses.pop_front(); Loading @@ -1171,8 +1171,8 @@ void libhttppp::HttpEvent::ResponseEvent(netplus::con &curcon,const int tid,ULON } ResponseEvent(cureq,tid,args); if(cureq.slots[0].SendData.empty()){ cureq.slots[0].SendData.pos=0; if(cureq.SendData.empty()){ cureq.SendData.pos=0; cureq.clear(); } }catch(HTTPException &e){ Loading Loading
examples/httpsysinfo.cpp +7 −7 Original line number Diff line number Diff line Loading @@ -250,15 +250,15 @@ public: void ResponseEvent(libhttppp::HttpRequest& curreq, const int tid,ULONG_PTR args){ if (curreq.getRequestURL()=="/images/header.png") { size_t rem = header_png_size - curreq.slots[0].SendData.pos; size_t rem = header_png_size - curreq.SendData.pos; size_t si = (rem > BLOCKSIZE) ? BLOCKSIZE : rem; curreq.slots[0].SendData.append((const char*)header_png + curreq.slots[0].SendData.pos, si); curreq.slots[0].SendData.pos += si; curreq.SendData.append((const char*)header_png + curreq.SendData.pos, si); curreq.SendData.pos += si; } else if(curreq.getRequestURL()=="/favicon.ico"){ if(curreq.slots[0].SendData.pos < favicon_ico_size){ size_t si = BLOCKSIZE < (favicon_ico_size-curreq.slots[0].SendData.pos) ? BLOCKSIZE : (favicon_ico_size-curreq.slots[0].SendData.pos); curreq.slots[0].SendData.append((const char*)favicon_ico+curreq.slots[0].SendData.pos, si); curreq.slots[0].SendData.pos+=si; if(curreq.SendData.pos < favicon_ico_size){ size_t si = BLOCKSIZE < (favicon_ico_size-curreq.SendData.pos) ? BLOCKSIZE : (favicon_ico_size-curreq.SendData.pos); curreq.SendData.append((const char*)favicon_ico+curreq.SendData.pos, si); curreq.SendData.pos+=si; } } } Loading
src/http.cpp +23 −23 Original line number Diff line number Diff line Loading @@ -2933,10 +2933,10 @@ void libhttppp::HttpResponse::send(netplus::con &curconnection,const std::string } // For HTTP/2 and HTTP/3: store structured response info directly, // write only body data to slots[0].SendData (no H1 text round-trip) // write only body data to SendData (no H1 text round-trip) if (_storeResponseInfo(curconnection, datalen)) { if (datalen > 0) curconnection.slots[0].SendData.append(data.data(), datalen); curconnection.SendData.append(data.data(), datalen); return; } Loading @@ -2944,10 +2944,10 @@ void libhttppp::HttpResponse::send(netplus::con &curconnection,const std::string printHeader(header); curconnection.slots[0].SendData.append(header.data(),header.size()); curconnection.SendData.append(header.data(),header.size()); if (datalen > 0) curconnection.slots[0].SendData.append(data.data(),datalen); curconnection.SendData.append(data.data(),datalen); } void libhttppp::HttpResponse::send(netplus::con &curconnection,const unsigned char *data,int datalen){ Loading @@ -2965,7 +2965,7 @@ void libhttppp::HttpResponse::send(netplus::con &curconnection,const unsigned c // For HTTP/2 and HTTP/3: store structured response info directly if (_storeResponseInfo(curconnection, datalen)) { if (datalen > 0 && data) curconnection.slots[0].SendData.append(reinterpret_cast<const char*>(data), datalen); curconnection.SendData.append(reinterpret_cast<const char*>(data), datalen); return; } Loading @@ -2973,10 +2973,10 @@ void libhttppp::HttpResponse::send(netplus::con &curconnection,const unsigned c printHeader(header); curconnection.slots[0].SendData.append(header.data(),header.size()); curconnection.SendData.append(header.data(),header.size()); if (datalen > 0 && data) { curconnection.slots[0].SendData.append(reinterpret_cast<const char*>(data), datalen); curconnection.SendData.append(reinterpret_cast<const char*>(data), datalen); } } Loading @@ -2999,7 +2999,7 @@ void libhttppp::HttpResponse::send(netplus::con &curconnection,const std::vector // For HTTP/2 and HTTP/3: store structured response info directly if (_storeResponseInfo(curconnection, datalen)) { if (datalen > 0) curconnection.slots[0].SendData.append(data.data(), datalen); curconnection.SendData.append(data.data(), datalen); return; } Loading @@ -3007,10 +3007,10 @@ void libhttppp::HttpResponse::send(netplus::con &curconnection,const std::vector printHeader(header); curconnection.slots[0].SendData.append(header.data(),header.size()); curconnection.SendData.append(header.data(),header.size()); if (datalen > 0) curconnection.slots[0].SendData.append(data.data(),datalen); curconnection.SendData.append(data.data(),datalen); } size_t libhttppp::HttpResponse::parse(const char *data, size_t inlen) { Loading Loading @@ -3253,7 +3253,7 @@ size_t libhttppp::HttpRequest::parseH2(const std::vector<hpack::HeaderField> &he h2.streamId = stream_id; h2.headersSent = false; h2.bodyBytesSent = 0; slots[0].SendData.pos = 0; SendData.pos = 0; // Store ALL headers (including pseudo-headers) in _firstHeaderData. // Split values by ';' (matching parseH1 behaviour) so that cookie Loading Loading @@ -3321,7 +3321,7 @@ size_t libhttppp::HttpRequest::parseH2(const std::vector<hpack::HeaderField> &he size_t libhttppp::HttpRequest::parseH3(const std::vector<qpack::HeaderField> &headers) { clear(); _httpProtocol = 2; slots[0].SendData.pos = 0; SendData.pos = 0; // Store ALL headers (including pseudo-headers) in _firstHeaderData. // Split values by ';' (matching parseH1 behaviour) so that cookie Loading Loading @@ -3405,7 +3405,7 @@ size_t libhttppp::HttpRequest::parseH1() { try { // 1) Find end of headers: "\r\n\r\n" size_t endpos = slots[0].RecvData.search("\r\n\r\n"); size_t endpos = RecvData.search("\r\n\r\n"); if (endpos == std::string::npos) { // Not enough data yet _RequestType = PARSEREQUEST; Loading @@ -3414,11 +3414,11 @@ size_t libhttppp::HttpRequest::parseH1() { // 2) Copy header bytes (include the first \r\n of the separator so // every header line, including the last one, ends with \r\n) header.assign(slots[0].RecvData.begin(), slots[0].RecvData.begin() + endpos + 2); header.assign(RecvData.begin(), RecvData.begin() + endpos + 2); // 3) Consume header (and the delimiter) from slots[0].RecvData // 3) Consume header (and the delimiter) from RecvData endpos += 4; // include "\r\n\r\n" slots[0].RecvData.erase(slots[0].RecvData.begin(),slots[0].RecvData.begin()+endpos); RecvData.erase(RecvData.begin(),RecvData.begin()+endpos); // 4) Parse the request line (first line until CRLF) size_t line_end = 0; Loading Loading @@ -3572,13 +3572,13 @@ size_t libhttppp::HttpRequest::parseH1() { } catch (netplus::NetException& e) { if (e.getErrorType() != netplus::NetException::Note) { slots[0].RecvData.clear(); RecvData.clear(); } excep[HTTPException::Error] << "netplus error: " << e.what(); throw excep; } catch (...) { // keep behavior similar to your original: on parse error, clean up input slots[0].RecvData.clear(); RecvData.clear(); throw; } Loading Loading @@ -3759,14 +3759,14 @@ void libhttppp::HttpForm::parse(libhttppp::HttpRequest &request){ throw excep; } // Use content-length if available, otherwise fall back to slots[0].RecvData size // Use content-length if available, otherwise fall back to RecvData size // (HTTP/2 and HTTP/3 may omit Content-Length) size_t bodyLen = request.getContentLength(); if(bodyLen == 0) bodyLen = request.slots[0].RecvData.size(); bodyLen = request.RecvData.size(); for(auto *cval=ctype->getfirstValue(); cval; cval=cval->nextvalue()){ if(bodyLen <= request.slots[0].RecvData.size()){ if(bodyLen <= request.RecvData.size()){ if(cval->getvalue().find("multipart/form-data") != std::string::npos){ _contentType = "multipart/form-data"; for(auto *cbod=ctype->getfirstValue(); cbod; cbod=cbod->nextvalue()){ Loading @@ -3783,7 +3783,7 @@ void libhttppp::HttpForm::parse(libhttppp::HttpRequest &request){ if(bval.size() >= 2 && bval.front() == '"' && bval.back() == '"') bval = bval.substr(1, bval.size() - 2); _boundary = std::move(bval); _parseMultipart(request.slots[0].RecvData.data(), request.slots[0].RecvData.size()); _parseMultipart(request.RecvData.data(), request.RecvData.size()); break; } } Loading @@ -3791,7 +3791,7 @@ void libhttppp::HttpForm::parse(libhttppp::HttpRequest &request){ } if(cval->getvalue().find("application/x-www-form-urlencoded") != std::string::npos){ _contentType = "application/x-www-form-urlencoded"; _parseUrlDecode(request.slots[0].RecvData.data(), bodyLen); _parseUrlDecode(request.RecvData.data(), bodyLen); } } } Loading
src/httpd.cpp +52 −52 Original line number Diff line number Diff line Loading @@ -366,7 +366,7 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, // Store POST body in RecvData so HttpForm::parse() can access it if (!reqBody.empty()) { tempreq.slots[0].RecvData.append(reqBody.data(), reqBody.size()); tempreq.RecvData.append(reqBody.data(), reqBody.size()); } // Ensure content-length is set from actual body size (H2 framing Loading Loading @@ -405,9 +405,9 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, std::string body; if (content_length > 0) body.reserve(content_length); if (!tempreq.slots[0].SendData.empty()) { body.assign(tempreq.slots[0].SendData.data(), tempreq.slots[0].SendData.size()); tempreq.slots[0].SendData.clear(); if (!tempreq.SendData.empty()) { body.assign(tempreq.SendData.data(), tempreq.SendData.size()); tempreq.SendData.clear(); } bool is_streaming = (content_length > 0 && Loading @@ -420,7 +420,7 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, // from the upstream backend (via ResponseEvent on tempreq). tempreq.h2state().expectedContentLength = content_length; tempreq.slots[0].SendData.pos = 0; tempreq.SendData.pos = 0; // Collect extra :res-* headers before we start std::vector<libhttppp::hpack::HeaderField> extra; Loading Loading @@ -452,22 +452,22 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, } // Flush to real connection so client starts receiving cureq.slots[0].SendData.append(out.data(), out.size()); cureq.SendData.append(out.data(), out.size()); out.clear(); // Immediately flush HEADERS to the socket so the browser // can start preparing its video player while we stream DATA. if (cureq.slots[0].csock) { while (cureq.slots[0].SendData.pos < cureq.slots[0].SendData.size()) { size_t remaining = cureq.slots[0].SendData.size() - cureq.slots[0].SendData.pos; while (cureq.SendData.pos < cureq.SendData.size()) { size_t remaining = cureq.SendData.size() - cureq.SendData.pos; size_t sendlen = std::min(remaining, (size_t)BLOCKSIZE); netplus::buffer buf(cureq.slots[0].SendData.data() + cureq.slots[0].SendData.pos, sendlen); netplus::buffer buf(cureq.SendData.data() + cureq.SendData.pos, sendlen); try { size_t consumed = cureq.slots[0].csock->sendData(buf, 0); if (cureq.slots[0].csock->hasPendingWrite()) cureq.slots[0].csock->flush_out(); if (consumed > 0) cureq.slots[0].SendData.pos += consumed; cureq.SendData.pos += consumed; else break; } catch (netplus::NetException &e) { Loading @@ -476,9 +476,9 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, throw; } } if (cureq.slots[0].SendData.pos >= cureq.slots[0].SendData.size()) { cureq.slots[0].SendData.clear(); cureq.slots[0].SendData.pos = 0; if (cureq.SendData.pos >= cureq.SendData.size()) { cureq.SendData.clear(); cureq.SendData.pos = 0; } } Loading @@ -493,13 +493,13 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, i < max_iterations && total_sent < content_length; ++i) { ResponseEvent(tempreq, tid, args); size_t sa = tempreq.slots[0].SendData.size(); size_t sa = tempreq.SendData.size(); if (sa > 0) { // Build DATA frames and flush directly to the // real connection so epoll can drain to the client. bool last = (total_sent + sa >= content_length); std::string chunk(tempreq.slots[0].SendData.data(), sa); tempreq.slots[0].SendData.clear(); std::string chunk(tempreq.SendData.data(), sa); tempreq.SendData.clear(); std::string frames; frames.reserve(sa + (sa / H2_MAX_FRAME_SIZE + 1) * H2_FRAME_HEADER_LEN); Loading @@ -513,7 +513,7 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, std::string(chunk.data() + off, frag)); off += frag; } cureq.slots[0].SendData.append(frames.data(), frames.size()); cureq.SendData.append(frames.data(), frames.size()); total_sent += sa; empty_count = 0; backoff_ms = 1; Loading @@ -523,16 +523,16 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, // Without this, the entire video buffers in memory // before the event loop can write any bytes. if (cureq.slots[0].csock) { while (cureq.slots[0].SendData.pos < cureq.slots[0].SendData.size()) { size_t remaining = cureq.slots[0].SendData.size() - cureq.slots[0].SendData.pos; while (cureq.SendData.pos < cureq.SendData.size()) { size_t remaining = cureq.SendData.size() - cureq.SendData.pos; size_t sendlen = std::min(remaining, (size_t)BLOCKSIZE); netplus::buffer buf(cureq.slots[0].SendData.data() + cureq.slots[0].SendData.pos, sendlen); netplus::buffer buf(cureq.SendData.data() + cureq.SendData.pos, sendlen); try { size_t consumed = cureq.slots[0].csock->sendData(buf, 0); if (cureq.slots[0].csock->hasPendingWrite()) cureq.slots[0].csock->flush_out(); if (consumed > 0) { cureq.slots[0].SendData.pos += consumed; cureq.SendData.pos += consumed; } else { break; } Loading @@ -542,13 +542,13 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, throw; } } if (cureq.slots[0].SendData.pos >= cureq.slots[0].SendData.size()) { cureq.slots[0].SendData.clear(); cureq.slots[0].SendData.pos = 0; } else if (cureq.slots[0].SendData.pos > BLOCKSIZE * 4) { cureq.slots[0].SendData.erase(cureq.slots[0].SendData.begin(), cureq.slots[0].SendData.begin() + cureq.slots[0].SendData.pos); cureq.slots[0].SendData.pos = 0; if (cureq.SendData.pos >= cureq.SendData.size()) { cureq.SendData.clear(); cureq.SendData.pos = 0; } else if (cureq.SendData.pos > BLOCKSIZE * 4) { cureq.SendData.erase(cureq.SendData.begin(), cureq.SendData.begin() + cureq.SendData.pos); cureq.SendData.pos = 0; } } } else { Loading @@ -564,7 +564,7 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, // If we exited without finishing, send END_STREAM on an empty DATA frame if (total_sent < content_length) { std::string end_frame = h2BuildFrame(H2_FRAME_DATA, H2_FLAG_END_STREAM, sid, ""); cureq.slots[0].SendData.append(end_frame.data(), end_frame.size()); cureq.SendData.append(end_frame.data(), end_frame.size()); } return; // Already handled — skip the normal encoding below Loading Loading @@ -642,20 +642,20 @@ bool libhttppp::HttpEvent::Http2RequestEvent(netplus::con &curcon, size_t off = 0; // Consume HTTP/2 client connection preface if present if (cureq.slots[0].RecvData.size() >= H2_CLIENT_PREFACE_LEN && std::memcmp(cureq.slots[0].RecvData.data(), H2_CLIENT_PREFACE, H2_CLIENT_PREFACE_LEN) == 0) { if (cureq.RecvData.size() >= H2_CLIENT_PREFACE_LEN && std::memcmp(cureq.RecvData.data(), H2_CLIENT_PREFACE, H2_CLIENT_PREFACE_LEN) == 0) { off += H2_CLIENT_PREFACE_LEN; } // Send server SETTINGS if not already sent (e.g. ConnectEvent already sent it) if (cureq.slots[0].SendData.empty()) { if (cureq.SendData.empty()) { out += h2BuildSettings(); out += h2ConnectionWindowBoost(); } // Process all complete frames in RecvData while (off + H2_FRAME_HEADER_LEN <= cureq.slots[0].RecvData.size()) { const char *data = cureq.slots[0].RecvData.data(); while (off + H2_FRAME_HEADER_LEN <= cureq.RecvData.size()) { const char *data = cureq.RecvData.data(); uint32_t flen = (static_cast<uint8_t>(data[off]) << 16) | (static_cast<uint8_t>(data[off + 1]) << 8) | static_cast<uint8_t>(data[off + 2]); Loading @@ -666,7 +666,7 @@ bool libhttppp::HttpEvent::Http2RequestEvent(netplus::con &curcon, (static_cast<uint8_t>(data[off + 7]) << 8) | static_cast<uint8_t>(data[off + 8]); if (off + H2_FRAME_HEADER_LEN + flen > cureq.slots[0].RecvData.size()) { if (off + H2_FRAME_HEADER_LEN + flen > cureq.RecvData.size()) { break; // Incomplete frame, wait for more data } Loading Loading @@ -824,11 +824,11 @@ bool libhttppp::HttpEvent::Http2RequestEvent(netplus::con &curcon, done: if (!out.empty()) { cureq.slots[0].SendData.append(out.data(), out.size()); cureq.SendData.append(out.data(), out.size()); } if (off > 0) { cureq.slots[0].RecvData.erase(cureq.slots[0].RecvData.begin(), cureq.slots[0].RecvData.begin() + off); cureq.RecvData.erase(cureq.RecvData.begin(), cureq.RecvData.begin() + off); } return true; Loading Loading @@ -960,7 +960,7 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock, // Store POST body in RecvData so HttpForm::parse() can access it if (!bodyData.empty()) { tempreq.slots[0].RecvData.append(bodyData.data(), bodyData.size()); tempreq.RecvData.append(bodyData.data(), bodyData.size()); } // Ensure content-length is set from actual body size (H3 framing Loading Loading @@ -999,9 +999,9 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock, std::string body; if (content_length > 0) body.reserve(content_length); if (!tempreq.slots[0].SendData.empty()) { body.assign(tempreq.slots[0].SendData.data(), tempreq.slots[0].SendData.size()); tempreq.slots[0].SendData.clear(); if (!tempreq.SendData.empty()) { body.assign(tempreq.SendData.data(), tempreq.SendData.size()); tempreq.SendData.clear(); } bool is_streaming = (content_length > 0 && Loading @@ -1009,16 +1009,16 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock, // If streaming, collect all remaining data if (is_streaming) { tempreq.slots[0].SendData.pos = 0; tempreq.SendData.pos = 0; size_t max_iter = content_length / BLOCKSIZE + 4096; for (size_t i = 0; i < max_iter && body.size() < content_length; ++i) { ResponseEvent(tempreq, 0, 0); size_t sa = tempreq.slots[0].SendData.size(); size_t sa = tempreq.SendData.size(); if (sa > 0) { body.append(tempreq.slots[0].SendData.data(), sa); tempreq.slots[0].SendData.clear(); body.append(tempreq.SendData.data(), sa); tempreq.SendData.clear(); } else { break; } Loading Loading @@ -1091,9 +1091,9 @@ REQUESTHANDLING: if(clen == 0){ RequestEvent(cureq,tid,args); cureq._RequestType=PARSEREQUEST; } else if(cureq.slots[0].RecvData.size()>=clen){ } else if(cureq.RecvData.size()>=clen){ RequestEvent(cureq,tid,args); cureq.slots[0].RecvData.erase(cureq.slots[0].RecvData.begin(),cureq.slots[0].RecvData.begin()+clen); cureq.RecvData.erase(cureq.RecvData.begin(),cureq.RecvData.begin()+clen); cureq._RequestType=PARSEREQUEST; } break; Loading @@ -1103,9 +1103,9 @@ REQUESTHANDLING: if(clen == 0){ RequestEvent(cureq,tid,args); cureq._RequestType=PARSEREQUEST; } else if(cureq.slots[0].RecvData.size()>=clen){ } else if(cureq.RecvData.size()>=clen){ RequestEvent(cureq,tid,args); cureq.slots[0].RecvData.erase(cureq.slots[0].RecvData.begin(),cureq.slots[0].RecvData.begin()+clen); cureq.RecvData.erase(cureq.RecvData.begin(),cureq.RecvData.begin()+clen); cureq._RequestType=PARSEREQUEST; } break; Loading Loading @@ -1149,7 +1149,7 @@ void libhttppp::HttpEvent::ResponseEvent(netplus::con &curcon,const int tid,ULON if (last) break; } if (!batch.empty()) { cureq.slots[0].SendData.append(batch.data(), batch.size()); cureq.SendData.append(batch.data(), batch.size()); } if (pending.offset >= pending.body.size()) { cureq._h2->pendingResponses.pop_front(); Loading @@ -1171,8 +1171,8 @@ void libhttppp::HttpEvent::ResponseEvent(netplus::con &curcon,const int tid,ULON } ResponseEvent(cureq,tid,args); if(cureq.slots[0].SendData.empty()){ cureq.slots[0].SendData.pos=0; if(cureq.SendData.empty()){ cureq.SendData.pos=0; cureq.clear(); } }catch(HTTPException &e){ Loading