From 06d1b10cbefaa7c54c73e09df746ae79b7f14e14 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 Aug 2013 19:23:08 +0200 Subject: [PATCH] tftpd: support "writedelay" within --- tests/FILEFORMAT | 4 +++ tests/server/tftpd.c | 83 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/tests/FILEFORMAT b/tests/FILEFORMAT index 97afa967f..afb959edd 100644 --- a/tests/FILEFORMAT +++ b/tests/FILEFORMAT @@ -144,6 +144,10 @@ rtp: part [num] channel [num] size [num] connection-monitor When used, this will log [DISCONNECT] to the server.input log when the connection is disconnected. + +For TFTP: +writedelay: [secs] delay this amount between reply packets (each packet being + 512 bytes payload) diff --git a/tests/server/tftpd.c b/tests/server/tftpd.c index 8ce363939..c4a21a645 100644 --- a/tests/server/tftpd.c +++ b/tests/server/tftpd.c @@ -107,8 +107,10 @@ struct testcase { size_t bufsize; /* size of the data in buffer */ char *rptr; /* read pointer into the buffer */ size_t rcount; /* amount of data left to read of the file */ - long num; /* test case number */ + long testno; /* test case number */ int ofile; /* file descriptor for output file when uploading to us */ + + int writedelay; /* number of seconds between each packet */ }; struct formats { @@ -571,7 +573,7 @@ static ssize_t write_behind(struct testcase *test, int convert) if(!test->ofile) { char outfile[256]; - snprintf(outfile, sizeof(outfile), "log/upload.%ld", test->num); + snprintf(outfile, sizeof(outfile), "log/upload.%ld", test->testno); test->ofile=open(outfile, O_CREAT|O_RDWR, 0777); if(test->ofile == -1) { logmsg("Couldn't create and/or open file %s for upload!", outfile); @@ -1037,6 +1039,73 @@ again: return 0; } +/* Based on the testno, parse the correct server commands. */ +static int parse_servercmd(struct testcase *req) +{ + FILE *stream; + char *filename; + int error; + + filename = test2file(req->testno); + + stream=fopen(filename, "rb"); + if(!stream) { + error = errno; + logmsg("fopen() failed with error: %d %s", error, strerror(error)); + logmsg(" [1] Error opening file: %s", filename); + logmsg(" Couldn't open test file %ld", req->testno); + return 1; /* done */ + } + else { + char *orgcmd = NULL; + char *cmd = NULL; + size_t cmdsize = 0; + int num=0; + + /* get the custom server control "commands" */ + error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream); + fclose(stream); + if(error) { + logmsg("getpart() failed with error: %d", error); + return 1; /* done */ + } + + cmd = orgcmd; + while(cmd && cmdsize) { + char *check; + if(1 == sscanf(cmd, "writedelay: %d", &num)) { + logmsg("instructed to delay %d secs between packets", num); + req->writedelay = num; + } + else { + logmsg("Unknown instruction found: %s", cmd); + } + /* try to deal with CRLF or just LF */ + check = strchr(cmd, '\r'); + if(!check) + check = strchr(cmd, '\n'); + + if(check) { + /* get to the letter following the newline */ + while((*check == '\r') || (*check == '\n')) + check++; + + if(!*check) + /* if we reached a zero, get out */ + break; + cmd = check; + } + else + break; + } + if(orgcmd) + free(orgcmd); + } + + return 0; /* OK! */ +} + + /* * Validate file access. */ @@ -1087,7 +1156,9 @@ static int validate_access(struct testcase *test, logmsg("requested test number %ld part %ld", testno, partno); - test->num = testno; + test->testno = testno; + + (void)parse_servercmd(test); file = test2file(testno); @@ -1162,6 +1233,12 @@ static void sendtftp(struct testcase *test, struct formats *pf) #ifdef HAVE_SIGSETJMP (void) sigsetjmp(timeoutbuf, 1); #endif + if(test->writedelay) { + logmsg("Pausing %d seconds before %d bytes", test->writedelay, + size); + wait_ms(1000*test->writedelay); + } + send_data: if (swrite(peer, sdp, size + 4) != size + 4) { logmsg("write");