From 7ef9bea5381311ad8b35b503c6998e779c72a857 Mon Sep 17 00:00:00 2001 From: nishi Date: Wed, 24 Jan 2024 13:08:25 +0000 Subject: [PATCH] added chunk support git-svn-id: file:///raid/svn-main/nishi-libw3/trunk@58 d27a3e52-49c5-7645-884c-6793ebffc270 --- .clang-format | 1 + Example/fetch.c | 7 +++-- Library/HTTP.c | 80 ++++++++++++++++++++++++++++++++++++++++++++----- W3Version.h.p | 2 +- 4 files changed, 80 insertions(+), 10 deletions(-) diff --git a/.clang-format b/.clang-format index 4fbff0c..0554a6a 100644 --- a/.clang-format +++ b/.clang-format @@ -7,5 +7,6 @@ IndentWidth: 8 PointerAlignment: Left ColumnLimit: 1024 AllowShortIfStatementsOnASingleLine: Always +AllowShortBlocksOnASingleLine: Never AllowShortLoopsOnASingleLine: True SpaceBeforeParens: Never diff --git a/Example/fetch.c b/Example/fetch.c index 393ff29..2d0d4c7 100644 --- a/Example/fetch.c +++ b/Example/fetch.c @@ -12,7 +12,10 @@ FILE* f; -void fetch_data(struct W3* w3, char* data, size_t size) { fwrite(data, size, 1, f); } +void fetch_data(struct W3* w3, char* data, size_t size) { + fwrite(data, size, 1, f); + printf("Got data, %d bytes\n", size); +} void status(struct W3* w3, int status) { fprintf(stderr, "Response code is %d\n", status); } @@ -34,7 +37,7 @@ int main(int argc, char** argv) { return 1; } W3_Library_Init(); - struct W3* w3 = W3_Create("http", argv[1], 80); + struct W3* w3 = W3_Create("https", argv[1], 443); if(w3 != NULL) { W3_Set_Read_Size(w3, 1024); W3_Set_Method(w3, argv[3] == NULL ? "GET" : argv[3]); diff --git a/Library/HTTP.c b/Library/HTTP.c index 75e0b19..336bcf0 100644 --- a/Library/HTTP.c +++ b/Library/HTTP.c @@ -64,6 +64,13 @@ void __W3_HTTP_Request(struct W3* w3) { char* headerbuf = malloc(1); headerbuf[0] = 0; int phase = 0; + bool chunked = false; + int chunkphase = 0; + char* chunklen = NULL; + int chunkincr = 0; + char* chunk = NULL; + bool breakchunk = false; + int chunksize; while(true) { int l = __W3_Auto_Read(w3, buf, w3->readsize); if(l <= 0) break; @@ -138,6 +145,9 @@ void __W3_HTTP_Request(struct W3* w3) { void (*func)(struct W3*, char*, char*) = (void (*)(struct W3*, char*, char*))funcptr; func(w3, data, data + k + 1); } + if(strcasecmp(data, "transfer-encoding") == 0 && strcasecmp(data + k + 1, "chunked") == 0) { + chunked = true; + } } break; } @@ -157,19 +167,75 @@ void __W3_HTTP_Request(struct W3* w3) { } } } else if(phase == 2) { - void* funcptr = __W3_Get_Event(w3, "data"); - if(funcptr != NULL) { - void (*func)(struct W3*, char*, size_t) = (void (*)(struct W3*, char*, size_t))funcptr; - char* buffer = malloc(l - i); - memcpy(buffer, buf + i, l - i); - func(w3, buffer, l - i); - free(buffer); + if(chunked) { + int j; + for(j = i; j < l; j++) { + char c = buf[j]; + if(chunkphase == 0) { + if(c == '\n') { + if(chunklen != NULL) { + chunkphase = 1; + chunkincr = strtol(chunklen, NULL, 16); + free(chunklen); + chunklen = NULL; + if(chunkincr == 0) { + breakchunk = true; + break; + } else { + chunk = malloc(chunkincr); + chunksize = chunkincr; + } + } + continue; + } else if(c == '\r') + continue; + if(chunklen == NULL) { + chunklen = malloc(1); + chunklen[0] = 0; + } + char* cbuf = malloc(2); + cbuf[0] = c; + cbuf[1] = 0; + char* tmp = chunklen; + chunklen = __W3_Concat(tmp, cbuf); + free(tmp); + free(cbuf); + } else if(chunkphase == 1) { + chunkincr--; + if(chunkincr >= 0) { + chunk[chunksize - chunkincr - 1] = c; + } + if(chunkincr == -2) { + chunkphase = 0; + free(chunk); + chunk = NULL; + } else if(chunkincr == 0) { + void* funcptr = __W3_Get_Event(w3, "data"); + if(funcptr != NULL) { + void (*func)(struct W3*, char*, size_t) = (void (*)(struct W3*, char*, size_t))funcptr; + func(w3, chunk, chunksize); + } + } + } + } + } else { + void* funcptr = __W3_Get_Event(w3, "data"); + if(funcptr != NULL) { + void (*func)(struct W3*, char*, size_t) = (void (*)(struct W3*, char*, size_t))funcptr; + char* buffer = malloc(l - i); + memcpy(buffer, buf + i, l - i); + func(w3, buffer, l - i); + free(buffer); + } } break; } } + if(breakchunk) break; } free(headerbuf); free(statusbuf); free(buf); + if(chunklen != NULL) free(chunklen); + if(chunk != NULL) free(chunk); } diff --git a/W3Version.h.p b/W3Version.h.p index 9bb9cdb..1146e87 100644 --- a/W3Version.h.p +++ b/W3Version.h.p @@ -6,7 +6,7 @@ extern "C" { #endif -#define LIBW3_VERSION "1.2C" \ +#define LIBW3_VERSION "1.3" \ SUFFIX #ifdef __cplusplus -- 2.43.0