📄 sws.c
字号:
char pipereq[REQBUFSIZ]; int pipereq_length; if(req->pipelining) { pipereq_length = req->offset - req->checkindex; memcpy(pipereq, reqbuf + req->checkindex, pipereq_length); } else pipereq_length = 0; /*** Init the httpreqest structure properly for the upcoming request ***/ memset(req, 0, sizeof(struct httprequest)); /* here's what should not be 0 from the start */ req->testno = DOCNUMBER_NOTHING; /* safe default */ req->open = TRUE; /* connection should remain open and wait for more commands */ req->pipe = 0; /*** end of httprequest init ***/ while (req->offset < REQBUFSIZ) { ssize_t got; if(pipereq_length) { memcpy(reqbuf, pipereq, pipereq_length); got = pipereq_length; pipereq_length = 0; } else got = sread(sock, reqbuf + req->offset, REQBUFSIZ - req->offset); if (got <= 0) { if (got < 0) { logmsg("recv() returned error: %d", SOCKERRNO); return DOCNUMBER_INTERNAL; } logmsg("Connection closed by client"); reqbuf[req->offset]=0; /* dump the request receivied so far to the external file */ storerequest(reqbuf, req->offset); return DOCNUMBER_INTERNAL; } logmsg("Read %d bytes", got); req->offset += got; reqbuf[req->offset] = 0; if(ProcessRequest(req)) { if(req->pipe--) { logmsg("Waiting for another piped request"); continue; } break; } } if (req->offset >= REQBUFSIZ) { logmsg("Request buffer overflow, closing connection"); reqbuf[REQBUFSIZ-1]=0; fail = TRUE; /* dump the request to an external file anyway */ } else reqbuf[req->offset]=0; /* dump the request to an external file */ storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset); return fail; /* success */}/* returns -1 on failure */static int send_doc(curl_socket_t sock, struct httprequest *req){ ssize_t written; size_t count; const char *buffer; char *ptr; FILE *stream; char *cmd=NULL; size_t cmdsize=0; FILE *dump; int persistant = TRUE; size_t responsesize; int error; static char weare[256]; char partbuf[80]="data"; logmsg("Send response number %d part %d", req->testno, req->partno); switch(req->rcmd) { default: case RCMD_NORMALREQ: break; /* continue with business as usual */ case RCMD_STREAM:#define STREAMTHIS "a string to stream 01234567890\n" count = strlen(STREAMTHIS); while(1) { written = swrite(sock, STREAMTHIS, count); if(written != (ssize_t)count) { logmsg("Stopped streaming"); break; } } return -1; case RCMD_IDLE: /* Do nothing. Sit idle. Pretend it rains. */ return 0; } req->open = FALSE; if(req->testno < 0) { size_t msglen; char msgbuf[64]; switch(req->testno) { case DOCNUMBER_QUIT: logmsg("Replying to QUIT"); buffer = docquit; break; case DOCNUMBER_WERULEZ: /* we got a "friends?" question, reply back that we sure are */ logmsg("Identifying ourselves as friends"); sprintf(msgbuf, "WE ROOLZ: %d\r\n", (int)getpid()); msglen = strlen(msgbuf); sprintf(weare, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s", msglen, msgbuf); buffer = weare; break; case DOCNUMBER_INTERNAL: logmsg("Bailing out due to internal error"); return -1; case DOCNUMBER_CONNECT: logmsg("Replying to CONNECT"); buffer = docconnect; break; case DOCNUMBER_BADCONNECT: logmsg("Replying to a bad CONNECT"); buffer = docbadconnect; break; case DOCNUMBER_404: default: logmsg("Replying to with a 404"); buffer = doc404; break; } ptr = NULL; stream=NULL; count = strlen(buffer); } else { char *filename = test2file(req->testno); if(0 != req->partno) sprintf(partbuf, "data%ld", req->partno); stream=fopen(filename, "rb"); if(!stream) { error = ERRNO; logmsg("fopen() failed with error: %d %s", error, strerror(error)); logmsg("Error opening file: %s", filename); logmsg("Couldn't open test file"); return 0; } else { buffer = spitout(stream, "reply", partbuf, &count); ptr = (char *)buffer; fclose(stream); } /* re-open the same file again */ stream=fopen(filename, "rb"); if(!stream) { error = ERRNO; logmsg("fopen() failed with error: %d %s", error, strerror(error)); logmsg("Error opening file: %s", filename); logmsg("Couldn't open test file"); return 0; } else { /* get the custom server control "commands" */ cmd = (char *)spitout(stream, "reply", "postcmd", &cmdsize); fclose(stream); } } dump = fopen(RESPONSE_DUMP, "ab"); /* b is for windows-preparing */ if(!dump) { error = ERRNO; logmsg("fopen() failed with error: %d %s", error, strerror(error)); logmsg("Error opening file: %s", RESPONSE_DUMP); logmsg("couldn't create logfile: " RESPONSE_DUMP); return -1; } /* If the word 'swsclose' is present anywhere in the reply chunk, the connection will be closed after the data has been sent to the requesting client... */ if(strstr(buffer, "swsclose") || !count) { persistant = FALSE; logmsg("connection close instruction \"swsclose\" found in response"); } if(strstr(buffer, "swsbounce")) { prevbounce = TRUE; logmsg("enable \"swsbounce\" in the next request"); } else prevbounce = FALSE; responsesize = count; do { /* Ok, we send no more than 200 bytes at a time, just to make sure that larger chunks are split up so that the client will need to do multiple recv() calls to get it and thus we exercise that code better */ size_t num = count; if(num > 200) num = 200; written = swrite(sock, buffer, num); if (written < 0) { fclose(dump); logmsg("Sending response failed and we bailed out!"); return -1; } else { logmsg("Sent off %d bytes", written); } /* write to file as well */ fwrite(buffer, 1, written, dump); count -= written; buffer += written; } while(count>0); fclose(dump); logmsg("Response sent (%d bytes) and written to " RESPONSE_DUMP, responsesize); if(ptr) free(ptr); if(cmdsize > 0 ) { char command[32]; int num; ptr=cmd; do { if(2 == sscanf(ptr, "%31s %d", command, &num)) { if(!strcmp("wait", command)) { logmsg("Told to sleep for %d seconds", num); sleep(num); /* wait this many seconds */ } else logmsg("Unknown command in reply command section"); } ptr = strchr(ptr, '\n'); if(ptr) ptr++; else ptr = NULL; } while(ptr && *ptr); } if(cmd) free(cmd); req->open = persistant; prevtestno = req->testno; prevpartno = req->partno; return 0;}char use_ipv6=FALSE;int main(int argc, char *argv[]){ struct sockaddr_in me;#ifdef ENABLE_IPV6 struct sockaddr_in6 me6;#endif /* ENABLE_IPV6 */ curl_socket_t sock, msgsock; int flag; unsigned short port = DEFAULT_PORT; FILE *pidfile; char *pidname= (char *)".http.pid"; struct httprequest req; int rc; int error; int arg=1;#ifdef CURL_SWS_FORK_ENABLED bool use_fork = FALSE;#endif while(argc>arg) { if(!strcmp("--version", argv[arg])) { printf("sws IPv4%s"#ifdef CURL_SWS_FORK_ENABLED " FORK"#endif "\n" ,#ifdef ENABLE_IPV6 "/IPv6"#else ""#endif ); return 0; } else if(!strcmp("--pidfile", argv[arg])) { arg++; if(argc>arg) pidname = argv[arg++]; } else if(!strcmp("--ipv6", argv[arg])) {#ifdef ENABLE_IPV6 use_ipv6=TRUE;#endif arg++; }#ifdef CURL_SWS_FORK_ENABLED else if(!strcmp("--fork", argv[arg])) { use_fork=TRUE; arg++; }#endif else if(argc>arg) { if(atoi(argv[arg])) port = (unsigned short)atoi(argv[arg++]); if(argc>arg) path = argv[arg++]; } }#ifdef WIN32 win32_init(); atexit(win32_cleanup);#else#ifdef SIGPIPE#ifdef HAVE_SIGNAL signal(SIGPIPE, sigpipe_handler);#endif#ifdef HAVE_SIGINTERRUPT siginterrupt(SIGPIPE, 1);#endif#endif#endif#ifdef ENABLE_IPV6 if(!use_ipv6)#endif sock = socket(AF_INET, SOCK_STREAM, 0);#ifdef ENABLE_IPV6 else sock = socket(AF_INET6, SOCK_STREAM, 0);#endif if (CURL_SOCKET_BAD == sock) { logmsg("Error opening socket: %d", SOCKERRNO); return 1; } flag = 1; if (0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &flag, sizeof(flag))) { logmsg("setsockopt(SO_REUSEADDR) failed: %d", SOCKERRNO); sclose(sock); return 1; }#ifdef ENABLE_IPV6 if(!use_ipv6) {#endif memset(&me, 0, sizeof(me)); me.sin_family = AF_INET; me.sin_addr.s_addr = INADDR_ANY; me.sin_port = htons(port); rc = bind(sock, (struct sockaddr *) &me, sizeof(me));#ifdef ENABLE_IPV6 } else { memset(&me6, 0, sizeof(me6)); me6.sin6_family = AF_INET6; me6.sin6_addr = in6addr_any; me6.sin6_port = htons(port); rc = bind(sock, (struct sockaddr *) &me6, sizeof(me6)); }#endif /* ENABLE_IPV6 */ if(0 != rc) { logmsg("Error binding socket: %d", SOCKERRNO); sclose(sock); return 1; } pidfile = fopen(pidname, "w"); if(pidfile) { fprintf(pidfile, "%d\n", (int)getpid()); fclose(pidfile); } else { error = ERRNO; logmsg("fopen() failed with error: %d %s", error, strerror(error)); logmsg("Error opening file: %s", pidname); logmsg("Couldn't write pid file"); sclose(sock); return 1; } logmsg("Running IPv%d version on port %d",#ifdef ENABLE_IPV6 (use_ipv6?6:4)#else 4#endif , port ); /* start accepting connections */ rc = listen(sock, 5); if(0 != rc) { logmsg("listen() failed with error: %d", SOCKERRNO); sclose(sock); return 1; } while (1) { msgsock = accept(sock, NULL, NULL); if (CURL_SOCKET_BAD == msgsock) { printf("MAJOR ERROR: accept() failed with error: %d\n", SOCKERRNO); break; }#ifdef CURL_SWS_FORK_ENABLED if(use_fork) { /* The fork enabled version just forks off the child and don't care about it anymore, so don't assume otherwise. Beware and don't do this at home. */ rc = fork(); if(-1 == rc) { printf("MAJOR ERROR: fork() failed!\n"); break; } } else /* not a fork, just set rc so the following proceeds nicely */ rc = 0; /* 0 is returned to the child */ if(0 == rc) {#endif logmsg("====> Client connect");#ifdef TCP_NODELAY /* * Disable the Nagle algorithm to make it easier to send out a large * response in many small segments to torture the clients more. */ flag = 1; if (setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY, (void *)&flag, sizeof(flag)) == -1) { logmsg("====> TCP_NODELAY failed"); }#endif /* full initialization for new request after connection */ memset(&req, 0, sizeof(req)); req.testno = DOCNUMBER_NOTHING; req.open = TRUE; req.auth_req = FALSE; req.auth = FALSE; req.digest = FALSE; req.ntlm = FALSE; req.pipelining = FALSE; do { if(get_request(msgsock, &req)) /* non-zero means error, break out of loop */ break; if(prevbounce) { /* bounce treatment requested */ if((req.testno == prevtestno) && (req.partno == prevpartno)) { req.partno++; logmsg("BOUNCE part number to %ld", req.partno); } } send_doc(msgsock, &req); if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) { logmsg("special request received, no persistancy"); break; } if(!req.open) { logmsg("instructed to close connection after server-reply"); break; } if(req.open) logmsg("=> persistant connection request ended, awaits new request"); /* if we got a CONNECT, loop and get another request as well! */ } while(req.open || (req.testno == DOCNUMBER_CONNECT)); logmsg("====> Client disconnect"); sclose(msgsock); if (req.testno == DOCNUMBER_QUIT) break;#ifdef CURL_SWS_FORK_ENABLED }#endif } sclose(sock); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -