Commit 86205cec authored by jan.koester's avatar jan.koester
Browse files

test

parent e04b1aec
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -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;
            }
        }
    }
+23 −23
Original line number Diff line number Diff line
@@ -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;
  }

@@ -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){
@@ -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;
  }

@@ -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);
  }
}

@@ -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;
  }

@@ -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) {
@@ -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
@@ -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
@@ -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;
@@ -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;
@@ -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;
  }

@@ -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()){
@@ -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;
            }
          }
@@ -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);
        }
      }
    }
+52 −52
Original line number Diff line number Diff line
@@ -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
@@ -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 &&
@@ -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;
@@ -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) {
@@ -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;
                }
            }

@@ -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);
@@ -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;
@@ -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;
                                }
@@ -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 {
@@ -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
@@ -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]);
@@ -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
        }

@@ -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;
@@ -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
@@ -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 &&
@@ -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;
                }
@@ -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;
@@ -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;
@@ -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();
@@ -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){