From da5c8d66836d377d789e3f1a57ed4db273ae5b9c Mon Sep 17 00:00:00 2001 From: bel2125 Date: Sat, 18 Apr 2015 11:05:03 +0200 Subject: [PATCH] Quick and dirty test client to check chunked transfer encoding A quick hack to check chunked transfer encoding for Linux (see converation to issue #98, chunked transfer encoding has been added with #95 but there are merge errors). Can be used this way: Compile civetweb 'make WITH_LUA=1'. Set environment variable 'export resource_script_demo_storage=/tmp/' Start it with 'civetweb -document_root /path/to/civetweb/test'. Compile this example directly with 'gcc testclient.c' from the command line. Start the resulting file './a.out' A file /tmp/r1.txt with 1024 bytes will be created ('ls -l /tmp/'). Delete this file ('rm /tmp/r1.txt'). This was NOT chunked transfer encoding. Now enable chunked tranfer encoding: Change to chunked=1 in line 38. Rebuild 'gcc testclient.c' and run './a.out' again. Currently a 0 byte file will be created in /tmp/. This file has to be deleted after every test. Hope this helps fixing the merge errors. --- .../testclient_chunked_linux/testclient.c | 225 ++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 testutils/testclient_chunked_linux/testclient.c diff --git a/testutils/testclient_chunked_linux/testclient.c b/testutils/testclient_chunked_linux/testclient.c new file mode 100644 index 00000000..9f90a879 --- /dev/null +++ b/testutils/testclient_chunked_linux/testclient.c @@ -0,0 +1,225 @@ +/* quick and dirty test for chunked encoding */ + +#ifdef WIN32 +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +typedef int SOCKET; +typedef struct sockaddr SOCKADDR; +typedef struct hostent HOSTENT; +const int INVALID_SOCKET = -1; +const int SD_SEND = SHUT_WR; +const int SD_BOTH = SHUT_RDWR; +#define closesocket(x) close(x) +#define Sleep(x) usleep((x)*1000) +#define ioctlsocket(a,b,c) ioctl(a,b,c) +#endif +#include +#include +#include + +char * HOST = "127.0.0.1"; +unsigned short PORT = 8080; +const char * RESOURCE = "/resource_script_demo.lua/r1.txt"; +const char * METHOD = "PUT"; + +unsigned postSize = 1024; +unsigned extraHeadSize = 0; +int keep_alive = 0; +int chunked = 0; + + +int sockvprintf(SOCKET soc, const char * fmt, va_list vl) { + + char buf[1024*8]; +#ifdef WIN32 + int len = vsprintf_s(buf, sizeof(buf), fmt, vl); +#else + int len = vsprintf(buf, fmt, vl); +#endif + int ret = send(soc, buf, len, 0); + return ret; +} + + +int sockprintf(SOCKET soc, const char * fmt, ...) { + + int ret = -1; + va_list vl; + va_start(vl, fmt); + ret = sockvprintf(soc, fmt, vl); + va_end(vl); + return ret; +} + + +static struct sockaddr_in target = {0}; + + +int TestClient(unsigned clientNo) { + + SOCKET soc; + time_t lastData; + size_t totalData = 0; + size_t bodyData = 0; + int isBody = 0; + int isTest = (clientNo == 0); + int cpu = ((int)clientNo) % 100; + int timeOut = 10; + unsigned long i, j; + + // TCP + soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (soc==INVALID_SOCKET) { + printf("\r\nClient %u: cannot create socket\a\r\n", (int)clientNo); + return 3; + } + + // comment in to disable Nagle: + {int disable_Nagle = 1; setsockopt(soc, IPPROTO_TCP, TCP_NODELAY, (char *) &disable_Nagle, sizeof(disable_Nagle));} + + if (connect(soc, (SOCKADDR*)&target, sizeof(target))) { + printf("\r\nClient %u: cannot connect to server %s:%u\a\r\n", (int)clientNo, HOST, PORT); + return 4; + } + + sockprintf(soc, "%s %s", METHOD, RESOURCE); + // could send query string here + sockprintf(soc, " HTTP/1.1\r\nHost: %s\r\n", HOST); + + if (keep_alive) { + sockprintf(soc, "Connection: Keep-Alive\r\n"); + } else { + sockprintf(soc, "Connection: Close\r\n"); + } + + for (i=0;i<(extraHeadSize/25);i++) { + sockprintf(soc, "Comment%04u: 1234567890\r\n", i % 10000); + } + + if (!strcmp(METHOD, "GET")) { + sockprintf(soc, "\r\n"); + + } else if (chunked) { + + sockprintf(soc, "Transfer-Encoding: chunked\r\n\r\n", postSize); + + for (i=0;i<(postSize/10);i++) {sockprintf(soc, "A\r\n1234567890\r\n");} + if ((postSize%10)>0) { + sockprintf(soc, "%x\r\n", postSize%10); + for (i=0;i<(postSize%10);i++) {sockprintf(soc, "_");} + sockprintf(soc, "\r\n"); + } + + } else { + + sockprintf(soc, "Content-Length: %u\r\n\r\n", postSize); + + for (i=0;i0) { + //fwrite(headEnd,1,got,STORE); + bodyData += chunkSize; + } + isBody=1; + } + } else { + //fwrite(buf,1,got,STORE); + bodyData += chunkSize; + } + lastData = time(0); + totalData += chunkSize; + } else { + time_t current = time(0); + if (difftime(current, lastData) > timeOut) { + break; + } + Sleep(10); + } + } + + shutdown(soc, SD_BOTH); + closesocket(soc); + + return 0; +} + + + +int main(int argc, char * argv[]) { + + HOSTENT * lpHost = 0; + +#ifdef WIN32 + WSADATA wsaData = {0}; + + if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) { + printf("\r\nCannot init WinSock\a\r\n"); + return 1; + } +#endif + + lpHost = gethostbyname(HOST); + if (lpHost == NULL) { + printf("\r\nCannot find host %s\a\r\n",HOST); + return 2; + } + + target.sin_family = AF_INET; +#ifdef WIN32 + target.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr)); +#else + target.sin_addr.s_addr = htonl(0x7F000001); +#endif + target.sin_port = htons(PORT); + printf("\r\nConnect to %s\r\n", inet_ntoa(target.sin_addr)); + + TestClient(1); + +#ifdef WIN32 + WSACleanup(); +#endif + + return 0; +}