Commit 06d1b10c authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

tftpd: support "writedelay" within <servercmd>

parent 816b6390
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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)
</servercmd>
</reply>

+80 −3
Original line number Diff line number Diff line
@@ -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 <servercmd> 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");