Commit 01eb3f57 authored by jan.koester's avatar jan.koester
Browse files

chunked transfer now working

parent f0ae8dda
Loading
Loading
Loading
Loading
+66 −13
Changes for examples/httpclient.cpp: 66 added lines, 13 removed lines.
Original line number Diff line number Diff line
@@ -36,6 +36,47 @@

#include <cstring>

template<typename T = size_t>
T Hex2Int(const char* const hexstr, bool* overflow=nullptr)
{
    if (!hexstr)
        return false;
    if (overflow)
        *overflow = false;

    auto between = [](char val, char c1, char c2) { return val >= c1 && val <= c2; };
    size_t len = strlen(hexstr);
    T result = 0;

    for (size_t i = 0, offset = sizeof(T) << 3; i < len && (int)offset > 0; i++)
    {
        if (between(hexstr[i], '0', '9'))
            result = result << 4 ^ (hexstr[i] - '0');
        else if (between(tolower(hexstr[i]), 'a', 'f'))
            result = result << 4 ^ (tolower(hexstr[i]) - ('a' - 10)); // Remove the decimal part;
        offset -= 4;
    }
    if (((len + ((len % 2) != 0)) << 2) > (sizeof(T) << 3) && overflow)
        *overflow = true;
    return result;
}

size_t readchunk(const char *data,size_t datasize,size_t &pos){
  size_t start=pos;
  while( (pos < datasize || pos < 512)&& data[pos++]!='\r');
  char value[512];

  if(pos-start > 512){
      return 0;
  }

  memcpy(value,data+start,pos-start);

  ++pos;

  return Hex2Int(value,nullptr);
}

int main(int argc, char** argv){
  signal(SIGPIPE, SIG_IGN);
  netplus::socket *cltsock=nullptr;
@@ -63,30 +104,42 @@ int main(int argc, char** argv){

    std::string html;
    libhttppp::HttpResponse res;
    size_t amount = 0,rlen=0,len=recv;

    try {
      size_t hsize=res.parse(data,len);
      amount = len-hsize;
    size_t len=recv,chunklen=0,hsize=0;

      if(amount>0)
        html.assign(data+hsize,amount);
    int rlen=0;

    try {
      hsize=res.parse(data,len);
      if(strcmp(res.getTransferEncoding(),"chunked")==0){
          chunklen=readchunk(data,recv,--hsize);
      }else{
         rlen=res.getContentLength();
         html.resize(rlen);
      }catch(...){}
      }
    }catch(libhttppp::HTTPException &e){
      std::cerr << e.what() << std::endl;
    };
    while(amount<rlen){

    if(chunklen==0){
        do{
            html.append(data+hsize,recv-hsize);
            rlen-=recv-hsize;
            if(rlen>0){
              recv=cltsock->recvData(&srvsock,data,16384);
        if(recv!=0){
          amount+=recv;
          html.append(data,recv);
              hsize=0;
            }
        }while(rlen>0);
    }else{
        size_t cpos=hsize;
        do{
            html.append(data+cpos,chunklen);
            cpos+=chunklen;
            if(recv<chunklen){
              recv=cltsock->recvData(&srvsock,data,16384);
              cpos=0;
            }
        }while((chunklen=readchunk(data,recv,cpos))!=0);
    }

    delete cltsock;
    if(!html.empty())
      std::cout << html << std::endl;
+18 −3
Changes for src/http.cpp: 18 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -199,6 +199,7 @@ libhttppp::HttpResponse::HttpResponse() : HttpHeader(){
  _ContentLength=nullptr;
  _Connection=setData("connection");
  *_Connection<<"keep-alive";
  _TransferEncoding=nullptr;
}

void libhttppp::HttpResponse::setState(const char* httpstate){
@@ -288,8 +289,6 @@ void libhttppp::HttpResponse::send(netplus::con* curconnection,const char* data,
  curconnection->sending(true);
}

#include <iostream>

size_t libhttppp::HttpResponse::parse(const char *data,size_t inlen){
  if(inlen <9){
      HTTPException excep;
@@ -354,10 +353,13 @@ size_t libhttppp::HttpResponse::parse(const char *data,size_t inlen){
            if(isalpha(key[it]))
              key[it] = (char)tolower(key[it]);
          }
          ++delimeter;
          while(data[delimeter]==' '){
            ++delimeter;
          };
          size_t valuelen=pos-delimeter;
          if(pos > 0 && valuelen <=helen){
            std::string value;
            ++delimeter;
            value.resize(valuelen);
            std::copy(data+delimeter,data+pos,std::begin(value));
            for (size_t it = 0; it < valuelen; ++it) {
@@ -379,11 +381,24 @@ size_t libhttppp::HttpResponse::parse(const char *data,size_t inlen){
 _ContentLength=getData("content-length");
 _Connection=getData("connection");
 _ContentType=getData("content-type");
 _TransferEncoding=getData("transfer-encoding");

  return helen;
}

void libhttppp::HttpResponse::setTransferEncoding(const char* enc){
  if(!_TransferEncoding)
    _TransferEncoding=setData("transfer-encoding");
  *_TransferEncoding << enc;
}

const char * libhttppp::HttpResponse::getTransferEncoding(){
  return getData(_TransferEncoding);
}


libhttppp::HttpResponse::~HttpResponse() {

}

libhttppp::HttpRequest::HttpRequest(){
+5 −3
Changes for src/http.h: 5 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ namespace libhttppp {
    size_t      getHeaderSize();
  protected:
    HttpHeader();
    ~HttpHeader();
    virtual ~HttpHeader();
    HeaderData *_firstHeaderData;
    HeaderData *_lastHeaderData;
  };
@@ -83,7 +83,7 @@ namespace libhttppp {
  class HttpResponse : public HttpHeader {
  public:
    HttpResponse();
    virtual ~HttpResponse();
    ~HttpResponse();

    /*server methods*/
    void   setState(const char *httpstate);
@@ -91,6 +91,7 @@ namespace libhttppp {
    void   setContentLength(size_t len);
    void   setConnection(const char *type);
    void   setVersion(const char* version);
    void   setTransferEncoding(const char *enc);

    /*client methods*/
    const char *getState();
@@ -98,6 +99,7 @@ namespace libhttppp {
    size_t      getContentLength();
    const char *getConnection();
    const char *getVersion();
    const char *getTransferEncoding();

    size_t printHeader(std::string &buffer);

@@ -110,7 +112,7 @@ namespace libhttppp {
  private:
    std::string      _State;
    std::string      _Version;
    bool             _Chuncked;
    HeaderData      *_TransferEncoding;
    HeaderData      *_Connection;
    HeaderData      *_ContentType;
    HeaderData      *_ContentLength;