Diff for /embedaddon/iperf/src/iperf_api.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2016/10/18 13:28:18 version 1.1.1.2, 2021/03/17 00:36:46
Line 1 Line 1
 /*  /*
 * iperf, Copyright (c) 2014, 2015, 2016, The Regents of the University of * iperf, Copyright (c) 2014-2020, The Regents of the University of
  * California, through Lawrence Berkeley National Laboratory (subject   * California, through Lawrence Berkeley National Laboratory (subject
  * to receipt of any required approvals from the U.S. Dept. of   * to receipt of any required approvals from the U.S. Dept. of
  * Energy).  All rights reserved.   * Energy).  All rights reserved.
Line 24 Line 24
  * This code is distributed under a BSD style license, see the LICENSE file   * This code is distributed under a BSD style license, see the LICENSE file
  * for complete information.   * for complete information.
  */   */
#define _GNU_SOURCE#ifndef _GNU_SOURCE
 # define _GNU_SOURCE
 #endif
 #define __USE_GNU  #define __USE_GNU
   
 #include "iperf_config.h"  #include "iperf_config.h"
Line 32 Line 34
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
   #include <time.h>
 #include <getopt.h>  #include <getopt.h>
 #include <errno.h>  #include <errno.h>
 #include <signal.h>  #include <signal.h>
Line 43 Line 46
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <arpa/inet.h>  #include <arpa/inet.h>
 #include <netdb.h>  #include <netdb.h>
 #include <pthread.h>  
 #ifdef HAVE_STDINT_H  #ifdef HAVE_STDINT_H
 #include <stdint.h>  #include <stdint.h>
 #endif  #endif
Line 55 Line 57
 #include <sched.h>  #include <sched.h>
 #include <setjmp.h>  #include <setjmp.h>
 #include <stdarg.h>  #include <stdarg.h>
   #include <math.h>
   
 #if defined(HAVE_CPUSET_SETAFFINITY)  #if defined(HAVE_CPUSET_SETAFFINITY)
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/cpuset.h>  #include <sys/cpuset.h>
 #endif /* HAVE_CPUSET_SETAFFINITY */  #endif /* HAVE_CPUSET_SETAFFINITY */
   
   #if defined(__CYGWIN__) || defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__)
   #define CPU_SETSIZE __CPU_SETSIZE
   #endif /* __CYGWIN__, _WIN32, _WIN64, __WINDOWS__ */
   
   #if defined(HAVE_SETPROCESSAFFINITYMASK)
   #include <Windows.h>
   #endif /* HAVE_SETPROCESSAFFINITYMASK */
   
 #include "net.h"  #include "net.h"
 #include "iperf.h"  #include "iperf.h"
 #include "iperf_api.h"  #include "iperf_api.h"
 #include "iperf_udp.h"  #include "iperf_udp.h"
 #include "iperf_tcp.h"  #include "iperf_tcp.h"
#if defined(HAVE_SCTP)#if defined(HAVE_SCTP_H)
 #include "iperf_sctp.h"  #include "iperf_sctp.h"
#endif /* HAVE_SCTP */#endif /* HAVE_SCTP_H */
 #include "timer.h"  #include "timer.h"
   
 #include "cjson.h"  #include "cjson.h"
 #include "units.h"  #include "units.h"
 #include "tcp_window_size.h"  
 #include "iperf_util.h"  #include "iperf_util.h"
 #include "iperf_locale.h"  #include "iperf_locale.h"
 #include "version.h"  #include "version.h"
   #if defined(HAVE_SSL)
   #include <openssl/bio.h>
   #include "iperf_auth.h"
   #endif /* HAVE_SSL */
   
 /* Forwards. */  /* Forwards. */
 static int send_parameters(struct iperf_test *test);  static int send_parameters(struct iperf_test *test);
Line 100  usage() Line 114  usage()
   
   
 void  void
usage_long()usage_long(FILE *f)
 {  {
    fprintf(stderr, usage_longstr, UDP_RATE / (1024*1024), DURATION, DEFAULT_TCP_BLKSIZE / 1024, DEFAULT_UDP_BLKSIZE / 1024);    fprintf(f, usage_longstr, UDP_RATE / (1024*1024), DURATION, DEFAULT_TCP_BLKSIZE / 1024, DEFAULT_UDP_BLKSIZE);
 }  }
   
   
void warning(char *str)void warning(const char *str)
 {  {
     fprintf(stderr, "warning: %s\n", str);      fprintf(stderr, "warning: %s\n", str);
 }  }
Line 127  iperf_get_control_socket(struct iperf_test *ipt) Line 141  iperf_get_control_socket(struct iperf_test *ipt)
 }  }
   
 int  int
   iperf_get_control_socket_mss(struct iperf_test *ipt)
   {
       return ipt->ctrl_sck_mss;
   }
   
   int
 iperf_get_test_omit(struct iperf_test *ipt)  iperf_get_test_omit(struct iperf_test *ipt)
 {  {
     return ipt->omit;      return ipt->omit;
Line 144  iperf_get_test_rate(struct iperf_test *ipt) Line 164  iperf_get_test_rate(struct iperf_test *ipt)
     return ipt->settings->rate;      return ipt->settings->rate;
 }  }
   
   uint64_t
   iperf_get_test_bitrate_limit(struct iperf_test *ipt)
   {
       return ipt->settings->bitrate_limit;
   }
   
   double
   iperf_get_test_bitrate_limit_interval(struct iperf_test *ipt)
   {
       return ipt->settings->bitrate_limit_interval;
   }
   
 int  int
   iperf_get_test_bitrate_limit_stats_per_interval(struct iperf_test *ipt)
   {
       return ipt->settings->bitrate_limit_stats_per_interval;
   }
   
   uint64_t
   iperf_get_test_fqrate(struct iperf_test *ipt)
   {
       return ipt->settings->fqrate;
   }
   
   int
   iperf_get_test_pacing_timer(struct iperf_test *ipt)
   {
       return ipt->settings->pacing_timer;
   }
   
   uint64_t
   iperf_get_test_bytes(struct iperf_test *ipt)
   {
       return (uint64_t) ipt->settings->bytes;
   }
   
   uint64_t
   iperf_get_test_blocks(struct iperf_test *ipt)
   {
       return (uint64_t) ipt->settings->blocks;
   }
   
   int
 iperf_get_test_burst(struct iperf_test *ipt)  iperf_get_test_burst(struct iperf_test *ipt)
 {  {
     return ipt->settings->burst;      return ipt->settings->burst;
Line 199  iperf_get_test_num_streams(struct iperf_test *ipt) Line 261  iperf_get_test_num_streams(struct iperf_test *ipt)
 }  }
   
 int  int
   iperf_get_test_timestamps(struct iperf_test *ipt)
   {
       return ipt->timestamps;
   }
   
   const char *
   iperf_get_test_timestamp_format(struct iperf_test *ipt)
   {
       return ipt->timestamp_format;
   }
   
   int
   iperf_get_test_repeating_payload(struct iperf_test *ipt)
   {
       return ipt->repeating_payload;
   }
   
   int
 iperf_get_test_server_port(struct iperf_test *ipt)  iperf_get_test_server_port(struct iperf_test *ipt)
 {  {
     return ipt->server_port;      return ipt->server_port;
Line 271  iperf_get_test_one_off(struct iperf_test *ipt) Line 351  iperf_get_test_one_off(struct iperf_test *ipt)
 }  }
   
 int  int
iperf_get_no_fq_socket_pacing(struct iperf_test *ipt)iperf_get_test_tos(struct iperf_test *ipt)
 {  {
    return ipt->no_fq_socket_pacing;    return ipt->settings->tos;
 }  }
   
   char *
   iperf_get_test_extra_data(struct iperf_test *ipt)
   {
       return ipt->extra_data;
   }
   
   static const char iperf_version[] = IPERF_VERSION;
   char *
   iperf_get_iperf_version(void)
   {
       return (char*)iperf_version;
   }
   
   int
   iperf_get_test_no_delay(struct iperf_test *ipt)
   {
       return ipt->no_delay;
   }
   
   int
   iperf_get_test_connect_timeout(struct iperf_test *ipt)
   {
       return ipt->settings->connect_timeout;
   }
   
 /************** Setter routines for some fields inside iperf_test *************/  /************** Setter routines for some fields inside iperf_test *************/
   
 void  void
Line 327  iperf_set_test_blksize(struct iperf_test *ipt, int blk Line 432  iperf_set_test_blksize(struct iperf_test *ipt, int blk
 }  }
   
 void  void
   iperf_set_test_logfile(struct iperf_test *ipt, const char *logfile)
   {
       ipt->logfile = strdup(logfile);
   }
   
   void
 iperf_set_test_rate(struct iperf_test *ipt, uint64_t rate)  iperf_set_test_rate(struct iperf_test *ipt, uint64_t rate)
 {  {
     ipt->settings->rate = rate;      ipt->settings->rate = rate;
 }  }
   
 void  void
   iperf_set_test_bitrate_limit_maximum(struct iperf_test *ipt, uint64_t total_rate)
   {
       ipt->settings->bitrate_limit = total_rate;
   }
   
   void
   iperf_set_test_bitrate_limit_interval(struct iperf_test *ipt, uint64_t bitrate_limit_interval)
   {
       ipt->settings->bitrate_limit_interval = bitrate_limit_interval;
   }
   
   void
   iperf_set_test_bitrate_limit_stats_per_interval(struct iperf_test *ipt, uint64_t bitrate_limit_stats_per_interval)
   {
       ipt->settings->bitrate_limit_stats_per_interval = bitrate_limit_stats_per_interval;
   }
   
   void
   iperf_set_test_fqrate(struct iperf_test *ipt, uint64_t fqrate)
   {
       ipt->settings->fqrate = fqrate;
   }
   
   void
   iperf_set_test_pacing_timer(struct iperf_test *ipt, int pacing_timer)
   {
       ipt->settings->pacing_timer = pacing_timer;
   }
   
   void
   iperf_set_test_bytes(struct iperf_test *ipt, uint64_t bytes)
   {
       ipt->settings->bytes = (iperf_size_t) bytes;
   }
   
   void
   iperf_set_test_blocks(struct iperf_test *ipt, uint64_t blocks)
   {
       ipt->settings->blocks = (iperf_size_t) blocks;
   }
   
   void
 iperf_set_test_burst(struct iperf_test *ipt, int burst)  iperf_set_test_burst(struct iperf_test *ipt, int burst)
 {  {
     ipt->settings->burst = burst;      ipt->settings->burst = burst;
 }  }
   
 void  void
iperf_set_test_server_port(struct iperf_test *ipt, int server_port)iperf_set_test_server_port(struct iperf_test *ipt, int srv_port)
 {  {
    ipt->server_port = server_port;    ipt->server_port = srv_port;
 }  }
   
 void  void
Line 356  iperf_set_test_num_streams(struct iperf_test *ipt, int Line 509  iperf_set_test_num_streams(struct iperf_test *ipt, int
     ipt->num_streams = num_streams;      ipt->num_streams = num_streams;
 }  }
   
   void
   iperf_set_test_repeating_payload(struct iperf_test *ipt, int repeating_payload)
   {
       ipt->repeating_payload = repeating_payload;
   }
   
   void
   iperf_set_test_timestamps(struct iperf_test *ipt, int timestamps)
   {
       ipt->timestamps = timestamps;
   }
   
   void
   iperf_set_test_timestamp_format(struct iperf_test *ipt, const char *tf)
   {
       ipt->timestamp_format = strdup(tf);
   }
   
 static void  static void
 check_sender_has_retransmits(struct iperf_test *ipt)  check_sender_has_retransmits(struct iperf_test *ipt)
 {  {
    if (ipt->sender && ipt->protocol->id == Ptcp && has_tcpinfo_retransmits())    if (ipt->mode != RECEIVER && ipt->protocol->id == Ptcp && has_tcpinfo_retransmits())
         ipt->sender_has_retransmits = 1;          ipt->sender_has_retransmits = 1;
     else      else
         ipt->sender_has_retransmits = 0;          ipt->sender_has_retransmits = 0;
Line 369  void Line 540  void
 iperf_set_test_role(struct iperf_test *ipt, char role)  iperf_set_test_role(struct iperf_test *ipt, char role)
 {  {
     ipt->role = role;      ipt->role = role;
    if (role == 'c')    if (!ipt->reverse) {
        ipt->sender = 1;        if (ipt->bidirectional)
    else if (role == 's')            ipt->mode = BIDIRECTIONAL;
        ipt->sender = 0;        else if (role == 'c')
    if (ipt->reverse)            ipt->mode = SENDER;
        ipt->sender = ! ipt->sender;        else if (role == 's')
             ipt->mode = RECEIVER;
     } else {
         if (role == 'c')
             ipt->mode = RECEIVER;
         else if (role == 's')
             ipt->mode = SENDER;
     }
     check_sender_has_retransmits(ipt);      check_sender_has_retransmits(ipt);
 }  }
   
 void  void
iperf_set_test_server_hostname(struct iperf_test *ipt, char *server_hostname)iperf_set_test_server_hostname(struct iperf_test *ipt, const char *server_hostname)
 {  {
     ipt->server_hostname = strdup(server_hostname);      ipt->server_hostname = strdup(server_hostname);
 }  }
   
 void  void
iperf_set_test_template(struct iperf_test *ipt, char *tmp_template)iperf_set_test_template(struct iperf_test *ipt, const char *tmp_template)
 {  {
     ipt->tmp_template = strdup(tmp_template);      ipt->tmp_template = strdup(tmp_template);
 }  }
Line 394  void Line 572  void
 iperf_set_test_reverse(struct iperf_test *ipt, int reverse)  iperf_set_test_reverse(struct iperf_test *ipt, int reverse)
 {  {
     ipt->reverse = reverse;      ipt->reverse = reverse;
    if (ipt->reverse)    if (!ipt->reverse) {
        ipt->sender = ! ipt->sender;        if (ipt->role == 'c')
             ipt->mode = SENDER;
         else if (ipt->role == 's')
             ipt->mode = RECEIVER;
     } else {
         if (ipt->role == 'c')
             ipt->mode = RECEIVER;
         else if (ipt->role == 's')
             ipt->mode = SENDER;
     }
     check_sender_has_retransmits(ipt);      check_sender_has_retransmits(ipt);
 }  }
   
Line 429  iperf_set_test_unit_format(struct iperf_test *ipt, cha Line 616  iperf_set_test_unit_format(struct iperf_test *ipt, cha
     ipt->settings->unit_format = unit_format;      ipt->settings->unit_format = unit_format;
 }  }
   
   #if defined(HAVE_SSL)
 void  void
iperf_set_test_bind_address(struct iperf_test *ipt, char *bind_address)iperf_set_test_client_username(struct iperf_test *ipt, const char *client_username)
 {  {
    ipt->bind_address = strdup(bind_address);    ipt->settings->client_username = strdup(client_username);
 }  }
   
 void  void
   iperf_set_test_client_password(struct iperf_test *ipt, const char *client_password)
   {
       ipt->settings->client_password = strdup(client_password);
   }
   
   void
   iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, const char *client_rsa_pubkey_base64)
   {
       ipt->settings->client_rsa_pubkey = load_pubkey_from_base64(client_rsa_pubkey_base64);
   }
   
   void
   iperf_set_test_server_authorized_users(struct iperf_test *ipt, const char *server_authorized_users)
   {
       ipt->server_authorized_users = strdup(server_authorized_users);
   }
   
   void
   iperf_set_test_server_rsa_privkey(struct iperf_test *ipt, const char *server_rsa_privkey_base64)
   {
       ipt->server_rsa_private_key = load_privkey_from_base64(server_rsa_privkey_base64);
   }
   #endif // HAVE_SSL
   
   void
   iperf_set_test_bind_address(struct iperf_test *ipt, const char *bnd_address)
   {
       ipt->bind_address = strdup(bnd_address);
   }
   
   void
 iperf_set_test_udp_counters_64bit(struct iperf_test *ipt, int udp_counters_64bit)  iperf_set_test_udp_counters_64bit(struct iperf_test *ipt, int udp_counters_64bit)
 {  {
     ipt->udp_counters_64bit = udp_counters_64bit;      ipt->udp_counters_64bit = udp_counters_64bit;
Line 448  iperf_set_test_one_off(struct iperf_test *ipt, int one Line 667  iperf_set_test_one_off(struct iperf_test *ipt, int one
 }  }
   
 void  void
iperf_set_no_fq_socket_pacing(struct iperf_test *ipt, int no_pacing)iperf_set_test_tos(struct iperf_test *ipt, int tos)
 {  {
    ipt->no_fq_socket_pacing = no_pacing;    ipt->settings->tos = tos;
 }  }
   
   void
   iperf_set_test_extra_data(struct iperf_test *ipt, const char *dat)
   {
       ipt->extra_data = strdup(dat);
   }
   
   void
   iperf_set_test_bidirectional(struct iperf_test* ipt, int bidirectional)
   {
       ipt->bidirectional = bidirectional;
       if (bidirectional)
           ipt->mode = BIDIRECTIONAL;
       else
           iperf_set_test_reverse(ipt, ipt->reverse);
   }
   
   void
   iperf_set_test_no_delay(struct iperf_test* ipt, int no_delay)
   {
       ipt->no_delay = no_delay;
   }
   
   void
   iperf_set_test_connect_timeout(struct iperf_test* ipt, int ct)
   {
       ipt->settings->connect_timeout = ct;
   }
   
   
 /********************** Get/set test protocol structure ***********************/  /********************** Get/set test protocol structure ***********************/
   
 struct protocol *  struct protocol *
Line 501  void Line 749  void
 iperf_on_test_start(struct iperf_test *test)  iperf_on_test_start(struct iperf_test *test)
 {  {
     if (test->json_output) {      if (test->json_output) {
        cJSON_AddItemToObject(test->json_start, "test_start", iperf_json_printf("protocol: %s  num_streams: %d  blksize: %d  omit: %d  duration: %d  bytes: %d  blocks: %d  reverse: %d", test->protocol->name, (int64_t) test->num_streams, (int64_t) test->settings->blksize, (int64_t) test->omit, (int64_t) test->duration, (int64_t) test->settings->bytes, (int64_t) test->settings->blocks, test->reverse?(int64_t)1:(int64_t)0));        cJSON_AddItemToObject(test->json_start, "test_start", iperf_json_printf("protocol: %s  num_streams: %d  blksize: %d  omit: %d  duration: %d  bytes: %d  blocks: %d  reverse: %d  tos: %d", test->protocol->name, (int64_t) test->num_streams, (int64_t) test->settings->blksize, (int64_t) test->omit, (int64_t) test->duration, (int64_t) test->settings->bytes, (int64_t) test->settings->blocks, test->reverse?(int64_t)1:(int64_t)0, (int64_t) test->settings->tos));
     } else {      } else {
         if (test->verbose) {          if (test->verbose) {
             if (test->settings->bytes)              if (test->settings->bytes)
                iprintf(test, test_start_bytes, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->bytes);                iperf_printf(test, test_start_bytes, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->bytes, test->settings->tos);
             else if (test->settings->blocks)              else if (test->settings->blocks)
                iprintf(test, test_start_blocks, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->blocks);                iperf_printf(test, test_start_blocks, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->blocks, test->settings->tos);
             else              else
                iprintf(test, test_start_time, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->duration);                iperf_printf(test, test_start_time, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->duration, test->settings->tos);
         }          }
     }      }
 }  }
Line 536  void Line 784  void
 iperf_on_connect(struct iperf_test *test)  iperf_on_connect(struct iperf_test *test)
 {  {
     time_t now_secs;      time_t now_secs;
    const char* rfc1123_fmt = "%a, %d %b %Y %H:%M:%S GMT";    const char* rfc1123_fmt = "%a, %d %b %Y %H:%M:%S %Z";
     char now_str[100];      char now_str[100];
     char ipr[INET6_ADDRSTRLEN];      char ipr[INET6_ADDRSTRLEN];
     int port;      int port;
Line 544  iperf_on_connect(struct iperf_test *test) Line 792  iperf_on_connect(struct iperf_test *test)
     struct sockaddr_in *sa_inP;      struct sockaddr_in *sa_inP;
     struct sockaddr_in6 *sa_in6P;      struct sockaddr_in6 *sa_in6P;
     socklen_t len;      socklen_t len;
     int opt;  
   
     now_secs = time((time_t*) 0);      now_secs = time((time_t*) 0);
     (void) strftime(now_str, sizeof(now_str), rfc1123_fmt, gmtime(&now_secs));      (void) strftime(now_str, sizeof(now_str), rfc1123_fmt, gmtime(&now_secs));
     if (test->json_output)      if (test->json_output)
         cJSON_AddItemToObject(test->json_start, "timestamp", iperf_json_printf("time: %s  timesecs: %d", now_str, (int64_t) now_secs));          cJSON_AddItemToObject(test->json_start, "timestamp", iperf_json_printf("time: %s  timesecs: %d", now_str, (int64_t) now_secs));
     else if (test->verbose)      else if (test->verbose)
        iprintf(test, report_time, now_str);        iperf_printf(test, report_time, now_str);
   
     if (test->role == 'c') {      if (test->role == 'c') {
         if (test->json_output)          if (test->json_output)
             cJSON_AddItemToObject(test->json_start, "connecting_to", iperf_json_printf("host: %s  port: %d", test->server_hostname, (int64_t) test->server_port));              cJSON_AddItemToObject(test->json_start, "connecting_to", iperf_json_printf("host: %s  port: %d", test->server_hostname, (int64_t) test->server_port));
         else {          else {
            iprintf(test, report_connecting, test->server_hostname, test->server_port);            iperf_printf(test, report_connecting, test->server_hostname, test->server_port);
             if (test->reverse)              if (test->reverse)
                iprintf(test, report_reverse, test->server_hostname);                iperf_printf(test, report_reverse, test->server_hostname);
         }          }
     } else {      } else {
         len = sizeof(sa);          len = sizeof(sa);
Line 577  iperf_on_connect(struct iperf_test *test) Line 824  iperf_on_connect(struct iperf_test *test)
         if (test->json_output)          if (test->json_output)
             cJSON_AddItemToObject(test->json_start, "accepted_connection", iperf_json_printf("host: %s  port: %d", ipr, (int64_t) port));              cJSON_AddItemToObject(test->json_start, "accepted_connection", iperf_json_printf("host: %s  port: %d", ipr, (int64_t) port));
         else          else
            iprintf(test, report_accepted, ipr, port);            iperf_printf(test, report_accepted, ipr, port);
     }      }
     if (test->json_output) {      if (test->json_output) {
         cJSON_AddStringToObject(test->json_start, "cookie", test->cookie);          cJSON_AddStringToObject(test->json_start, "cookie", test->cookie);
Line 585  iperf_on_connect(struct iperf_test *test) Line 832  iperf_on_connect(struct iperf_test *test)
             if (test->settings->mss)              if (test->settings->mss)
                 cJSON_AddNumberToObject(test->json_start, "tcp_mss", test->settings->mss);                  cJSON_AddNumberToObject(test->json_start, "tcp_mss", test->settings->mss);
             else {              else {
                len = sizeof(opt);                cJSON_AddNumberToObject(test->json_start, "tcp_mss_default", test->ctrl_sck_mss);
                getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len); 
                cJSON_AddNumberToObject(test->json_start, "tcp_mss_default", opt); 
             }              }
        }        if (test->settings->rate)
             cJSON_AddNumberToObject(test->json_start, "target_bitrate", test->settings->rate);
         }
     } else if (test->verbose) {      } else if (test->verbose) {
        iprintf(test, report_cookie, test->cookie);        iperf_printf(test, report_cookie, test->cookie);
         if (test->protocol->id == SOCK_STREAM) {          if (test->protocol->id == SOCK_STREAM) {
             if (test->settings->mss)              if (test->settings->mss)
                iprintf(test, "      TCP MSS: %d\n", test->settings->mss);                iperf_printf(test, "      TCP MSS: %d\n", test->settings->mss);
             else {              else {
                len = sizeof(opt);                iperf_printf(test, "      TCP MSS: %d (default)\n", test->ctrl_sck_mss);
                getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len); 
                iprintf(test, "      TCP MSS: %d (default)\n", opt); 
             }              }
         }          }
        if (test->settings->rate)
             iperf_printf(test, "      Target Bitrate: %"PRIu64"\n", test->settings->rate);
     }      }
 }  }
   
Line 629  iperf_parse_arguments(struct iperf_test *test, int arg Line 875  iperf_parse_arguments(struct iperf_test *test, int arg
         {"server", no_argument, NULL, 's'},          {"server", no_argument, NULL, 's'},
         {"client", required_argument, NULL, 'c'},          {"client", required_argument, NULL, 'c'},
         {"udp", no_argument, NULL, 'u'},          {"udp", no_argument, NULL, 'u'},
           {"bitrate", required_argument, NULL, 'b'},
         {"bandwidth", required_argument, NULL, 'b'},          {"bandwidth", required_argument, NULL, 'b'},
           {"server-bitrate-limit", required_argument, NULL, OPT_SERVER_BITRATE_LIMIT},
         {"time", required_argument, NULL, 't'},          {"time", required_argument, NULL, 't'},
         {"bytes", required_argument, NULL, 'n'},          {"bytes", required_argument, NULL, 'n'},
         {"blockcount", required_argument, NULL, 'k'},          {"blockcount", required_argument, NULL, 'k'},
         {"length", required_argument, NULL, 'l'},          {"length", required_argument, NULL, 'l'},
         {"parallel", required_argument, NULL, 'P'},          {"parallel", required_argument, NULL, 'P'},
         {"reverse", no_argument, NULL, 'R'},          {"reverse", no_argument, NULL, 'R'},
           {"bidir", no_argument, NULL, OPT_BIDIRECTIONAL},
         {"window", required_argument, NULL, 'w'},          {"window", required_argument, NULL, 'w'},
         {"bind", required_argument, NULL, 'B'},          {"bind", required_argument, NULL, 'B'},
         {"cport", required_argument, NULL, OPT_CLIENT_PORT},          {"cport", required_argument, NULL, OPT_CLIENT_PORT},
Line 644  iperf_parse_arguments(struct iperf_test *test, int arg Line 893  iperf_parse_arguments(struct iperf_test *test, int arg
         {"version4", no_argument, NULL, '4'},          {"version4", no_argument, NULL, '4'},
         {"version6", no_argument, NULL, '6'},          {"version6", no_argument, NULL, '6'},
         {"tos", required_argument, NULL, 'S'},          {"tos", required_argument, NULL, 'S'},
           {"dscp", required_argument, NULL, OPT_DSCP},
           {"extra-data", required_argument, NULL, OPT_EXTRA_DATA},
 #if defined(HAVE_FLOWLABEL)  #if defined(HAVE_FLOWLABEL)
         {"flowlabel", required_argument, NULL, 'L'},          {"flowlabel", required_argument, NULL, 'L'},
 #endif /* HAVE_FLOWLABEL */  #endif /* HAVE_FLOWLABEL */
         {"zerocopy", no_argument, NULL, 'Z'},          {"zerocopy", no_argument, NULL, 'Z'},
         {"omit", required_argument, NULL, 'O'},          {"omit", required_argument, NULL, 'O'},
         {"file", required_argument, NULL, 'F'},          {"file", required_argument, NULL, 'F'},
           {"repeating-payload", no_argument, NULL, OPT_REPEATING_PAYLOAD},
           {"timestamps", optional_argument, NULL, OPT_TIMESTAMPS},
 #if defined(HAVE_CPU_AFFINITY)  #if defined(HAVE_CPU_AFFINITY)
         {"affinity", required_argument, NULL, 'A'},          {"affinity", required_argument, NULL, 'A'},
 #endif /* HAVE_CPU_AFFINITY */  #endif /* HAVE_CPU_AFFINITY */
Line 658  iperf_parse_arguments(struct iperf_test *test, int arg Line 911  iperf_parse_arguments(struct iperf_test *test, int arg
         {"congestion", required_argument, NULL, 'C'},          {"congestion", required_argument, NULL, 'C'},
         {"linux-congestion", required_argument, NULL, 'C'},          {"linux-congestion", required_argument, NULL, 'C'},
 #endif /* HAVE_TCP_CONGESTION */  #endif /* HAVE_TCP_CONGESTION */
#if defined(HAVE_SCTP)#if defined(HAVE_SCTP_H)
         {"sctp", no_argument, NULL, OPT_SCTP},          {"sctp", no_argument, NULL, OPT_SCTP},
         {"nstreams", required_argument, NULL, OPT_NUMSTREAMS},          {"nstreams", required_argument, NULL, OPT_NUMSTREAMS},
         {"xbind", required_argument, NULL, 'X'},          {"xbind", required_argument, NULL, 'X'},
 #endif  #endif
         {"pidfile", required_argument, NULL, 'I'},          {"pidfile", required_argument, NULL, 'I'},
         {"logfile", required_argument, NULL, OPT_LOGFILE},          {"logfile", required_argument, NULL, OPT_LOGFILE},
           {"forceflush", no_argument, NULL, OPT_FORCEFLUSH},
         {"get-server-output", no_argument, NULL, OPT_GET_SERVER_OUTPUT},          {"get-server-output", no_argument, NULL, OPT_GET_SERVER_OUTPUT},
         {"udp-counters-64bit", no_argument, NULL, OPT_UDP_COUNTERS_64BIT},          {"udp-counters-64bit", no_argument, NULL, OPT_UDP_COUNTERS_64BIT},
        {"no-fq-socket-pacing", no_argument, NULL, OPT_NO_FQ_SOCKET_PACING},        {"no-fq-socket-pacing", no_argument, NULL, OPT_NO_FQ_SOCKET_PACING},
 #if defined(HAVE_SSL)
     {"username", required_argument, NULL, OPT_CLIENT_USERNAME},
     {"rsa-public-key-path", required_argument, NULL, OPT_CLIENT_RSA_PUBLIC_KEY},
     {"rsa-private-key-path", required_argument, NULL, OPT_SERVER_RSA_PRIVATE_KEY},
     {"authorized-users-path", required_argument, NULL, OPT_SERVER_AUTHORIZED_USERS},
 #endif /* HAVE_SSL */
         {"fq-rate", required_argument, NULL, OPT_FQ_RATE},
         {"pacing-timer", required_argument, NULL, OPT_PACING_TIMER},
         {"connect-timeout", required_argument, NULL, OPT_CONNECT_TIMEOUT},
         {"debug", no_argument, NULL, 'd'},          {"debug", no_argument, NULL, 'd'},
         {"help", no_argument, NULL, 'h'},          {"help", no_argument, NULL, 'h'},
         {NULL, 0, NULL, 0}          {NULL, 0, NULL, 0}
     };      };
     int flag;      int flag;
       int portno;
     int blksize;      int blksize;
     int server_flag, client_flag, rate_flag, duration_flag;      int server_flag, client_flag, rate_flag, duration_flag;
     char *endptr;      char *endptr;
Line 681  iperf_parse_arguments(struct iperf_test *test, int arg Line 945  iperf_parse_arguments(struct iperf_test *test, int arg
 #endif /* HAVE_CPU_AFFINITY */  #endif /* HAVE_CPU_AFFINITY */
     char* slash;      char* slash;
     struct xbind_entry *xbe;      struct xbind_entry *xbe;
       double farg;
   
     blksize = 0;      blksize = 0;
     server_flag = client_flag = rate_flag = duration_flag = 0;      server_flag = client_flag = rate_flag = duration_flag = 0;
   #if defined(HAVE_SSL)
       char *client_username = NULL, *client_rsa_public_key = NULL, *server_rsa_private_key = NULL;
   #endif /* HAVE_SSL */
   
     while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) {      while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) {
         switch (flag) {          switch (flag) {
             case 'p':              case 'p':
                test->server_port = atoi(optarg);                portno = atoi(optarg);
                 if (portno < 1 || portno > 65535) {
                     i_errno = IEBADPORT;
                     return -1;
                 }
                 test->server_port = portno;
                 break;                  break;
             case 'f':              case 'f':
                test->settings->unit_format = *optarg;                if (!optarg) {
                     i_errno = IEBADFORMAT;
                     return -1;
                 }
                 test->settings->unit_format = *optarg;
                 if (test->settings->unit_format == 'k' ||
                     test->settings->unit_format == 'K' ||
                     test->settings->unit_format == 'm' ||
                     test->settings->unit_format == 'M' ||
                     test->settings->unit_format == 'g' ||
                     test->settings->unit_format == 'G' ||
                     test->settings->unit_format == 't' ||
                     test->settings->unit_format == 'T') {
                         break;
                 }
                 else {
                     i_errno = IEBADFORMAT;
                     return -1;
                 }
                 break;                  break;
             case 'i':              case 'i':
                 /* XXX: could potentially want separate stat collection and reporting intervals,                  /* XXX: could potentially want separate stat collection and reporting intervals,
Line 716  iperf_parse_arguments(struct iperf_test *test, int arg Line 1008  iperf_parse_arguments(struct iperf_test *test, int arg
                 test->json_output = 1;                  test->json_output = 1;
                 break;                  break;
             case 'v':              case 'v':
                printf("%s\n%s\n%s\n", version, get_system_info(),                 printf("%s (cJSON %s)\n%s\n%s\n", version, cJSON_Version(), get_system_info(),
                        get_optional_features());                         get_optional_features());
                 exit(0);                  exit(0);
             case 's':              case 's':
Line 739  iperf_parse_arguments(struct iperf_test *test, int arg Line 1031  iperf_parse_arguments(struct iperf_test *test, int arg
                 client_flag = 1;                  client_flag = 1;
                 break;                  break;
             case OPT_SCTP:              case OPT_SCTP:
#if defined(HAVE_SCTP)#if defined(HAVE_SCTP_H)
                 set_protocol(test, Psctp);                  set_protocol(test, Psctp);
                 client_flag = 1;                  client_flag = 1;
#else /* HAVE_SCTP */                break;
 #else /* HAVE_SCTP_H */
                 i_errno = IEUNIMP;                  i_errno = IEUNIMP;
                 return -1;                  return -1;
#endif /* HAVE_SCTP */#endif /* HAVE_SCTP_H */
            break; 
   
             case OPT_NUMSTREAMS:              case OPT_NUMSTREAMS:
 #if defined(linux) || defined(__FreeBSD__)  #if defined(linux) || defined(__FreeBSD__)
Line 772  iperf_parse_arguments(struct iperf_test *test, int arg Line 1064  iperf_parse_arguments(struct iperf_test *test, int arg
                 rate_flag = 1;                  rate_flag = 1;
                 client_flag = 1;                  client_flag = 1;
                 break;                  break;
               case OPT_SERVER_BITRATE_LIMIT:
                   slash = strchr(optarg, '/');
                   if (slash) {
                       *slash = '\0';
                       ++slash;
                       test->settings->bitrate_limit_interval = atof(slash);
                       if (test->settings->bitrate_limit_interval != 0 &&  /* Using same Max/Min limits as for Stats Interval */
                           (test->settings->bitrate_limit_interval < MIN_INTERVAL || test->settings->bitrate_limit_interval > MAX_INTERVAL) ) {
                           i_errno = IETOTALINTERVAL;
                           return -1;
                       }
                   }
                   test->settings->bitrate_limit = unit_atof_rate(optarg);
                   server_flag = 1;
                   break;
             case 't':              case 't':
                 test->duration = atoi(optarg);                  test->duration = atoi(optarg);
                 if (test->duration > MAX_TIME) {                  if (test->duration > MAX_TIME) {
Line 802  iperf_parse_arguments(struct iperf_test *test, int arg Line 1109  iperf_parse_arguments(struct iperf_test *test, int arg
                 client_flag = 1;                  client_flag = 1;
                 break;                  break;
             case 'R':              case 'R':
                   if (test->bidirectional) {
                       i_errno = IEREVERSEBIDIR;
                       return -1;
                   }
                 iperf_set_test_reverse(test, 1);                  iperf_set_test_reverse(test, 1);
                 client_flag = 1;                  client_flag = 1;
                 break;                  break;
               case OPT_BIDIRECTIONAL:
                   if (test->reverse) {
                       i_errno = IEREVERSEBIDIR;
                       return -1;
                   }
                   iperf_set_test_bidirectional(test, 1);
                   client_flag = 1;
                   break;
             case 'w':              case 'w':
                 // XXX: This is a socket buffer, not specific to TCP                  // XXX: This is a socket buffer, not specific to TCP
                test->settings->socket_bufsize = unit_atof(optarg);                // Do sanity checks as double-precision floating point 
                if (test->settings->socket_bufsize > MAX_TCP_BUFFER) {                // to avoid possible integer overflows.
                 farg = unit_atof(optarg);
                 if (farg > (double) MAX_TCP_BUFFER) {
                     i_errno = IEBUFSIZE;                      i_errno = IEBUFSIZE;
                     return -1;                      return -1;
                 }                  }
                   test->settings->socket_bufsize = (int) farg;
                 client_flag = 1;                  client_flag = 1;
                 break;                  break;
             case 'B':              case 'B':
                 test->bind_address = strdup(optarg);                  test->bind_address = strdup(optarg);
                 break;                  break;
             case OPT_CLIENT_PORT:              case OPT_CLIENT_PORT:
                test->bind_port = atoi(optarg);                portno = atoi(optarg);
                 if (portno < 1 || portno > 65535) {
                     i_errno = IEBADPORT;
                     return -1;
                 }
                 test->bind_port = portno;
                 break;                  break;
             case 'M':              case 'M':
                 test->settings->mss = atoi(optarg);                  test->settings->mss = atoi(optarg);
Line 848  iperf_parse_arguments(struct iperf_test *test, int arg Line 1175  iperf_parse_arguments(struct iperf_test *test, int arg
                 }                  }
                 client_flag = 1;                  client_flag = 1;
                 break;                  break;
               case OPT_DSCP:
                   test->settings->tos = parse_qos(optarg);
                   if(test->settings->tos < 0) {
                           i_errno = IEBADTOS;
                           return -1;
                   }
                   client_flag = 1;
                   break;
               case OPT_EXTRA_DATA:
                   test->extra_data = strdup(optarg);
                   client_flag = 1;
                   break;
             case 'L':              case 'L':
 #if defined(HAVE_FLOWLABEL)  #if defined(HAVE_FLOWLABEL)
                 test->settings->flowlabel = strtol(optarg, &endptr, 0);                  test->settings->flowlabel = strtol(optarg, &endptr, 0);
Line 884  iperf_parse_arguments(struct iperf_test *test, int arg Line 1223  iperf_parse_arguments(struct iperf_test *test, int arg
                 test->zerocopy = 1;                  test->zerocopy = 1;
                 client_flag = 1;                  client_flag = 1;
                 break;                  break;
               case OPT_REPEATING_PAYLOAD:
                   test->repeating_payload = 1;
                   client_flag = 1;
                   break;
               case OPT_TIMESTAMPS:
                   iperf_set_test_timestamps(test, 1);
                   if (optarg) {
                       iperf_set_test_timestamp_format(test, optarg);
                   }
                   else {
                       iperf_set_test_timestamp_format(test, TIMESTAMP_FORMAT);
                   }
                   break;
             case 'O':              case 'O':
                 test->omit = atoi(optarg);                  test->omit = atoi(optarg);
                 if (test->omit < 0 || test->omit > 60) {                  if (test->omit < 0 || test->omit > 60) {
Line 940  iperf_parse_arguments(struct iperf_test *test, int arg Line 1292  iperf_parse_arguments(struct iperf_test *test, int arg
             case OPT_LOGFILE:              case OPT_LOGFILE:
                 test->logfile = strdup(optarg);                  test->logfile = strdup(optarg);
                 break;                  break;
               case OPT_FORCEFLUSH:
                   test->forceflush = 1;
                   break;
             case OPT_GET_SERVER_OUTPUT:              case OPT_GET_SERVER_OUTPUT:
                 test->get_server_output = 1;                  test->get_server_output = 1;
                 client_flag = 1;                  client_flag = 1;
Line 949  iperf_parse_arguments(struct iperf_test *test, int arg Line 1304  iperf_parse_arguments(struct iperf_test *test, int arg
                 break;                  break;
             case OPT_NO_FQ_SOCKET_PACING:              case OPT_NO_FQ_SOCKET_PACING:
 #if defined(HAVE_SO_MAX_PACING_RATE)  #if defined(HAVE_SO_MAX_PACING_RATE)
                test->no_fq_socket_pacing = 1;                printf("Warning:  --no-fq-socket-pacing is deprecated\n");
                 test->settings->fqrate = 0;
                 client_flag = 1;
 #else /* HAVE_SO_MAX_PACING_RATE */  #else /* HAVE_SO_MAX_PACING_RATE */
                 i_errno = IEUNIMP;                  i_errno = IEUNIMP;
                 return -1;                  return -1;
 #endif  #endif
                 break;                  break;
            case 'h':            case OPT_FQ_RATE:
 #if defined(HAVE_SO_MAX_PACING_RATE)
                 test->settings->fqrate = unit_atof_rate(optarg);
                 client_flag = 1;
 #else /* HAVE_SO_MAX_PACING_RATE */
                 i_errno = IEUNIMP;
                 return -1;
 #endif
                 break;
 #if defined(HAVE_SSL)
         case OPT_CLIENT_USERNAME:
             client_username = strdup(optarg);
             break;
         case OPT_CLIENT_RSA_PUBLIC_KEY:
             client_rsa_public_key = strdup(optarg);
             break;
         case OPT_SERVER_RSA_PRIVATE_KEY:
             server_rsa_private_key = strdup(optarg);
             break;
         case OPT_SERVER_AUTHORIZED_USERS:
             test->server_authorized_users = strdup(optarg);
             break;
 #endif /* HAVE_SSL */
             case OPT_PACING_TIMER:
                 test->settings->pacing_timer = unit_atoi(optarg);
                 client_flag = 1;
                 break;
             case OPT_CONNECT_TIMEOUT:
                 test->settings->connect_timeout = unit_atoi(optarg);
                 client_flag = 1;
                 break;
             case 'h':
                 usage_long(stdout);
                 exit(0);
             default:              default:
                usage_long();                usage_long(stderr);
                 exit(1);                  exit(1);
         }          }
     }      }
   
     /* Set logging to a file if specified, otherwise use the default (stdout) */  
     if (test->logfile) {  
         test->outfile = fopen(test->logfile, "a+");  
         if (test->outfile == NULL) {  
             i_errno = IELOGFILE;  
             return -1;  
         }  
     }  
   
     /* Check flag / role compatibility. */      /* Check flag / role compatibility. */
     if (test->role == 'c' && server_flag) {      if (test->role == 'c' && server_flag) {
        i_errno = IESERVERONLY;        i_errno = IESERVERONLY;
        return -1;        return -1;
     }      }
     if (test->role == 's' && client_flag) {      if (test->role == 's' && client_flag) {
        i_errno = IECLIENTONLY;        i_errno = IECLIENTONLY;
        return -1;        return -1;
     }      }
   
    if (!test->bind_address && test->bind_port) {#if defined(HAVE_SSL)
        i_errno = IEBIND;
     if (test->role == 's' && (client_username || client_rsa_public_key)){
         i_errno = IECLIENTONLY;
         return -1;          return -1;
       } else if (test->role == 'c' && (client_username || client_rsa_public_key) && 
           !(client_username && client_rsa_public_key)) {
           i_errno = IESETCLIENTAUTH;
           return -1;
       } else if (test->role == 'c' && (client_username && client_rsa_public_key)){
   
           char *client_password = NULL;
           size_t s;
           /* Need to copy env var, so we can do a common free */
           if ((client_password = getenv("IPERF3_PASSWORD")) != NULL)
                client_password = strdup(client_password);
           else if (iperf_getpass(&client_password, &s, stdin) < 0){
               i_errno = IESETCLIENTAUTH;
               return -1;
           } 
           if (test_load_pubkey_from_file(client_rsa_public_key) < 0){
               i_errno = IESETCLIENTAUTH;
               return -1;
           }
   
           test->settings->client_username = client_username;
           test->settings->client_password = client_password;
           test->settings->client_rsa_pubkey = load_pubkey_from_file(client_rsa_public_key);
           free(client_rsa_public_key);
           client_rsa_public_key = NULL;
     }      }
   
       if (test->role == 'c' && (server_rsa_private_key || test->server_authorized_users)){
           i_errno = IESERVERONLY;
           return -1;
       } else if (test->role == 's' && (server_rsa_private_key || test->server_authorized_users) && 
           !(server_rsa_private_key && test->server_authorized_users)) {
            i_errno = IESETSERVERAUTH;
           return -1;
       } else if (test->role == 's' && server_rsa_private_key) {
           test->server_rsa_private_key = load_privkey_from_file(server_rsa_private_key);
           if (test->server_rsa_private_key == NULL){
               i_errno = IESETSERVERAUTH;
               return -1;
           }
           free(server_rsa_private_key);
           server_rsa_private_key = NULL;
       }
   
   #endif //HAVE_SSL
     if (blksize == 0) {      if (blksize == 0) {
         if (test->protocol->id == Pudp)          if (test->protocol->id == Pudp)
            blksize = DEFAULT_UDP_BLKSIZE;            blksize = 0;      /* try to dynamically determine from MSS */
         else if (test->protocol->id == Psctp)          else if (test->protocol->id == Psctp)
             blksize = DEFAULT_SCTP_BLKSIZE;              blksize = DEFAULT_SCTP_BLKSIZE;
         else          else
             blksize = DEFAULT_TCP_BLKSIZE;              blksize = DEFAULT_TCP_BLKSIZE;
     }      }
    if (blksize <= 0 || blksize > MAX_BLOCKSIZE) {    if ((test->protocol->id != Pudp && blksize <= 0) 
         || blksize > MAX_BLOCKSIZE) {
         i_errno = IEBLOCKSIZE;          i_errno = IEBLOCKSIZE;
         return -1;          return -1;
     }      }
     if (test->protocol->id == Pudp &&      if (test->protocol->id == Pudp &&
        blksize > MAX_UDP_BLOCKSIZE) {        (blksize > 0 &&
             (blksize < MIN_UDP_BLOCKSIZE || blksize > MAX_UDP_BLOCKSIZE))) {
         i_errno = IEUDPBLOCKSIZE;          i_errno = IEUDPBLOCKSIZE;
         return -1;          return -1;
     }      }
Line 1033  iperf_parse_arguments(struct iperf_test *test, int arg Line 1462  iperf_parse_arguments(struct iperf_test *test, int arg
         return -1;          return -1;
     }      }
   
       /* Set Total-rate average interval to multiplicity of State interval */
       if (test->settings->bitrate_limit_interval != 0) {
           test->settings->bitrate_limit_stats_per_interval =
               (test->settings->bitrate_limit_interval <= test->stats_interval ?
               1 : round(test->settings->bitrate_limit_interval/test->stats_interval) );
       }
   
       /* Show warning if JSON output is used with explicit report format */
       if ((test->json_output) && (test->settings->unit_format != 'a')) {
           warning("Report format (-f) flag ignored with JSON output (-J)");
       }
   
       /* Show warning if JSON output is used with verbose or debug flags */
       if (test->json_output && test->verbose) {
           warning("Verbose output (-v) may interfere with JSON output (-J)");
       }
       if (test->json_output && test->debug) {
           warning("Debug output (-d) may interfere with JSON output (-J)");
       }
   
     return 0;      return 0;
 }  }
   
   /*
    * Open the file specified by test->logfile and set test->outfile to its' FD.
    */
   int iperf_open_logfile(struct iperf_test *test)
   {
       test->outfile = fopen(test->logfile, "a+");
       if (test->outfile == NULL) {
           i_errno = IELOGFILE;
           return -1;
       }
   
       return 0;
   }
   
 int  int
 iperf_set_send_state(struct iperf_test *test, signed char state)  iperf_set_send_state(struct iperf_test *test, signed char state)
 {  {
Line 1048  iperf_set_send_state(struct iperf_test *test, signed c Line 1511  iperf_set_send_state(struct iperf_test *test, signed c
 }  }
   
 void  void
iperf_check_throttle(struct iperf_stream *sp, struct timeval *nowP)iperf_check_throttle(struct iperf_stream *sp, struct iperf_time *nowP)
 {  {
       struct iperf_time temp_time;
     double seconds;      double seconds;
     uint64_t bits_per_second;      uint64_t bits_per_second;
   
    if (sp->test->done)    if (sp->test->done || sp->test->settings->rate == 0 || sp->test->settings->burst != 0)
         return;          return;
    seconds = timeval_diff(&sp->result->start_time_fixed, nowP);    iperf_time_diff(&sp->result->start_time_fixed, nowP, &temp_time);
     seconds = iperf_time_in_secs(&temp_time);
     bits_per_second = sp->result->bytes_sent * 8 / seconds;      bits_per_second = sp->result->bytes_sent * 8 / seconds;
     if (bits_per_second < sp->test->settings->rate) {      if (bits_per_second < sp->test->settings->rate) {
         sp->green_light = 1;          sp->green_light = 1;
Line 1066  iperf_check_throttle(struct iperf_stream *sp, struct t Line 1531  iperf_check_throttle(struct iperf_stream *sp, struct t
     }      }
 }  }
   
   /* Verify that average traffic is not greater than the specifid limit */
   void
   iperf_check_total_rate(struct iperf_test *test, iperf_size_t last_interval_bytes_transferred)
   {
       double seconds;
       uint64_t bits_per_second;
       iperf_size_t total_bytes;
       int i;
   
       if (test->done || test->settings->bitrate_limit == 0)    // Continue only if check should be done
           return;
       
       /* Add last inetrval's transffered bytes to the array */
       if (++test->bitrate_limit_last_interval_index >= test->settings->bitrate_limit_stats_per_interval)
           test->bitrate_limit_last_interval_index = 0;
       test->bitrate_limit_intervals_traffic_bytes[test->bitrate_limit_last_interval_index] = last_interval_bytes_transferred;
   
       /* Ensure that enough stats periods passed to allow averaging throughput */
       test->bitrate_limit_stats_count += 1;
       if (test->bitrate_limit_stats_count < test->settings->bitrate_limit_stats_per_interval)
           return;
    
        /* Calculating total bytes traffic to be averaged */
       for (total_bytes = 0, i = 0; i < test->settings->bitrate_limit_stats_per_interval; i++) {
           total_bytes += test->bitrate_limit_intervals_traffic_bytes[i];
       }
   
       seconds = test->stats_interval * test->settings->bitrate_limit_stats_per_interval;
       bits_per_second = total_bytes * 8 / seconds;
       if (test->debug) {
           iperf_printf(test,"Interval %" PRIu64 " - throughput %" PRIu64 " bps (limit %" PRIu64 ")\n", test->bitrate_limit_stats_count, bits_per_second, test->settings->bitrate_limit);
       }
   
       if (bits_per_second  > test->settings->bitrate_limit) {
           iperf_err(test, "Total throughput of %" PRIu64 " bps exceeded %" PRIu64 " bps limit", bits_per_second, test->settings->bitrate_limit);
           test->bitrate_limit_exceeded = 1;
       }
   }
   
 int  int
 iperf_send(struct iperf_test *test, fd_set *write_setP)  iperf_send(struct iperf_test *test, fd_set *write_setP)
 {  {
     register int multisend, r, streams_active;      register int multisend, r, streams_active;
     register struct iperf_stream *sp;      register struct iperf_stream *sp;
    struct timeval now;    struct iperf_time now;
   
     /* Can we do multisend mode? */      /* Can we do multisend mode? */
     if (test->settings->burst != 0)      if (test->settings->burst != 0)
Line 1083  iperf_send(struct iperf_test *test, fd_set *write_setP Line 1587  iperf_send(struct iperf_test *test, fd_set *write_setP
   
     for (; multisend > 0; --multisend) {      for (; multisend > 0; --multisend) {
         if (test->settings->rate != 0 && test->settings->burst == 0)          if (test->settings->rate != 0 && test->settings->burst == 0)
            gettimeofday(&now, NULL);            iperf_time_now(&now);
         streams_active = 0;          streams_active = 0;
         SLIST_FOREACH(sp, &test->streams, streams) {          SLIST_FOREACH(sp, &test->streams, streams) {
            if (! test->no_fq_socket_pacing ||            if ((sp->green_light && sp->sender &&
                (sp->green_light && 
                  (write_setP == NULL || FD_ISSET(sp->socket, write_setP)))) {                   (write_setP == NULL || FD_ISSET(sp->socket, write_setP)))) {
                 if ((r = sp->snd(sp)) < 0) {                  if ((r = sp->snd(sp)) < 0) {
                     if (r == NET_SOFTERROR)                      if (r == NET_SOFTERROR)
Line 1098  iperf_send(struct iperf_test *test, fd_set *write_setP Line 1601  iperf_send(struct iperf_test *test, fd_set *write_setP
                 streams_active = 1;                  streams_active = 1;
                 test->bytes_sent += r;                  test->bytes_sent += r;
                 ++test->blocks_sent;                  ++test->blocks_sent;
                if (test->settings->rate != 0 && test->settings->burst == 0)                iperf_check_throttle(sp, &now);
                    iperf_check_throttle(sp, &now); 
                 if (multisend > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes)                  if (multisend > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes)
                     break;                      break;
                 if (multisend > 1 && test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks)                  if (multisend > 1 && test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks)
Line 1110  iperf_send(struct iperf_test *test, fd_set *write_setP Line 1612  iperf_send(struct iperf_test *test, fd_set *write_setP
             break;              break;
     }      }
     if (test->settings->burst != 0) {      if (test->settings->burst != 0) {
        gettimeofday(&now, NULL);        iperf_time_now(&now);
         SLIST_FOREACH(sp, &test->streams, streams)          SLIST_FOREACH(sp, &test->streams, streams)
            iperf_check_throttle(sp, &now);            if (sp->sender)
                 iperf_check_throttle(sp, &now);
     }      }
     if (write_setP != NULL)      if (write_setP != NULL)
         SLIST_FOREACH(sp, &test->streams, streams)          SLIST_FOREACH(sp, &test->streams, streams)
Line 1129  iperf_recv(struct iperf_test *test, fd_set *read_setP) Line 1632  iperf_recv(struct iperf_test *test, fd_set *read_setP)
     struct iperf_stream *sp;      struct iperf_stream *sp;
   
     SLIST_FOREACH(sp, &test->streams, streams) {      SLIST_FOREACH(sp, &test->streams, streams) {
        if (FD_ISSET(sp->socket, read_setP)) {        if (FD_ISSET(sp->socket, read_setP) && !sp->sender) {
             if ((r = sp->rcv(sp)) < 0) {              if ((r = sp->rcv(sp)) < 0) {
                 i_errno = IESTREAMREAD;                  i_errno = IESTREAMREAD;
                 return r;                  return r;
             }              }
            test->bytes_sent += r;            test->bytes_received += r;
            ++test->blocks_sent;            ++test->blocks_received;
             FD_CLR(sp->socket, read_setP);              FD_CLR(sp->socket, read_setP);
         }          }
     }      }
Line 1146  iperf_recv(struct iperf_test *test, fd_set *read_setP) Line 1649  iperf_recv(struct iperf_test *test, fd_set *read_setP)
 int  int
 iperf_init_test(struct iperf_test *test)  iperf_init_test(struct iperf_test *test)
 {  {
    struct timeval now;    struct iperf_time now;
     struct iperf_stream *sp;      struct iperf_stream *sp;
   
     if (test->protocol->init) {      if (test->protocol->init) {
Line 1155  iperf_init_test(struct iperf_test *test) Line 1658  iperf_init_test(struct iperf_test *test)
     }      }
   
     /* Init each stream. */      /* Init each stream. */
    if (gettimeofday(&now, NULL) < 0) {    if (iperf_time_now(&now) < 0) {
         i_errno = IEINITTEST;          i_errno = IEINITTEST;
         return -1;          return -1;
     }      }
Line 1170  iperf_init_test(struct iperf_test *test) Line 1673  iperf_init_test(struct iperf_test *test)
 }  }
   
 static void  static void
send_timer_proc(TimerClientData client_data, struct timeval *nowP)send_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
 {  {
     struct iperf_stream *sp = client_data.p;      struct iperf_stream *sp = client_data.p;
   
Line 1184  send_timer_proc(TimerClientData client_data, struct ti Line 1687  send_timer_proc(TimerClientData client_data, struct ti
 int  int
 iperf_create_send_timers(struct iperf_test * test)  iperf_create_send_timers(struct iperf_test * test)
 {  {
    struct timeval now;    struct iperf_time now;
     struct iperf_stream *sp;      struct iperf_stream *sp;
     TimerClientData cd;      TimerClientData cd;
   
    if (gettimeofday(&now, NULL) < 0) {    if (iperf_time_now(&now) < 0) {
         i_errno = IEINITTEST;          i_errno = IEINITTEST;
         return -1;          return -1;
     }      }
     SLIST_FOREACH(sp, &test->streams, streams) {      SLIST_FOREACH(sp, &test->streams, streams) {
         sp->green_light = 1;          sp->green_light = 1;
        if (test->settings->rate != 0) {        if (test->settings->rate != 0 && sp->sender) {
             cd.p = sp;              cd.p = sp;
            sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, 100000L, 1);            sp->send_timer = tmr_create(NULL, send_timer_proc, cd, test->settings->pacing_timer, 1);
            /* (Repeat every tenth second - arbitrary often value.) */ 
             if (sp->send_timer == NULL) {              if (sp->send_timer == NULL) {
                 i_errno = IEINITTEST;                  i_errno = IEINITTEST;
                 return -1;                  return -1;
Line 1207  iperf_create_send_timers(struct iperf_test * test) Line 1709  iperf_create_send_timers(struct iperf_test * test)
     return 0;      return 0;
 }  }
   
   #if defined(HAVE_SSL)
   int test_is_authorized(struct iperf_test *test){
       if ( !(test->server_rsa_private_key && test->server_authorized_users)) {
           return 0;
       }
   
       if (test->settings->authtoken){
           char *username = NULL, *password = NULL;
           time_t ts;
           int rc = decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts);
           if (rc) {
               return -1;
           }
           int ret = check_authentication(username, password, ts, test->server_authorized_users);
           if (ret == 0){
               iperf_printf(test, report_authentication_succeeded, username, ts);
               free(username);
               free(password);
               return 0;
           } else {
               iperf_printf(test, report_authentication_failed, username, ts);
               free(username);
               free(password);
               return -1;
           }
       }
       return -1;
   }
   #endif //HAVE_SSL
   
 /**  /**
  * iperf_exchange_parameters - handles the param_Exchange part for client   * iperf_exchange_parameters - handles the param_Exchange part for client
  *   *
Line 1228  iperf_exchange_parameters(struct iperf_test *test) Line 1760  iperf_exchange_parameters(struct iperf_test *test)
         if (get_parameters(test) < 0)          if (get_parameters(test) < 0)
             return -1;              return -1;
   
   #if defined(HAVE_SSL)
           if (test_is_authorized(test) < 0){
               if (iperf_set_send_state(test, SERVER_ERROR) != 0)
                   return -1;
               i_errno = IEAUTHTEST;
               err = htonl(i_errno);
               if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
                   i_errno = IECTRLWRITE;
                   return -1;
               }
               return -1;
           }
   #endif //HAVE_SSL
   
         if ((s = test->protocol->listen(test)) < 0) {          if ((s = test->protocol->listen(test)) < 0) {
            if (iperf_set_send_state(test, SERVER_ERROR) != 0)                if (iperf_set_send_state(test, SERVER_ERROR) != 0)
                 return -1;                  return -1;
             err = htonl(i_errno);              err = htonl(i_errno);
             if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {              if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
Line 1243  iperf_exchange_parameters(struct iperf_test *test) Line 1789  iperf_exchange_parameters(struct iperf_test *test)
             }              }
             return -1;              return -1;
         }          }
   
         FD_SET(s, &test->read_set);          FD_SET(s, &test->read_set);
         test->max_fd = (s > test->max_fd) ? s : test->max_fd;          test->max_fd = (s > test->max_fd) ? s : test->max_fd;
         test->prot_listener = s;          test->prot_listener = s;
Line 1301  send_parameters(struct iperf_test *test) Line 1848  send_parameters(struct iperf_test *test)
         cJSON_AddNumberToObject(j, "omit", test->omit);          cJSON_AddNumberToObject(j, "omit", test->omit);
         if (test->server_affinity != -1)          if (test->server_affinity != -1)
             cJSON_AddNumberToObject(j, "server_affinity", test->server_affinity);              cJSON_AddNumberToObject(j, "server_affinity", test->server_affinity);
        if (test->duration)        cJSON_AddNumberToObject(j, "time", test->duration);
            cJSON_AddNumberToObject(j, "time", test->duration); 
         if (test->settings->bytes)          if (test->settings->bytes)
             cJSON_AddNumberToObject(j, "num", test->settings->bytes);              cJSON_AddNumberToObject(j, "num", test->settings->bytes);
         if (test->settings->blocks)          if (test->settings->blocks)
Line 1314  send_parameters(struct iperf_test *test) Line 1860  send_parameters(struct iperf_test *test)
         cJSON_AddNumberToObject(j, "parallel", test->num_streams);          cJSON_AddNumberToObject(j, "parallel", test->num_streams);
         if (test->reverse)          if (test->reverse)
             cJSON_AddTrueToObject(j, "reverse");              cJSON_AddTrueToObject(j, "reverse");
           if (test->bidirectional)
                       cJSON_AddTrueToObject(j, "bidirectional");
         if (test->settings->socket_bufsize)          if (test->settings->socket_bufsize)
             cJSON_AddNumberToObject(j, "window", test->settings->socket_bufsize);              cJSON_AddNumberToObject(j, "window", test->settings->socket_bufsize);
         if (test->settings->blksize)          if (test->settings->blksize)
             cJSON_AddNumberToObject(j, "len", test->settings->blksize);              cJSON_AddNumberToObject(j, "len", test->settings->blksize);
         if (test->settings->rate)          if (test->settings->rate)
             cJSON_AddNumberToObject(j, "bandwidth", test->settings->rate);              cJSON_AddNumberToObject(j, "bandwidth", test->settings->rate);
           if (test->settings->fqrate)
               cJSON_AddNumberToObject(j, "fqrate", test->settings->fqrate);
           if (test->settings->pacing_timer)
               cJSON_AddNumberToObject(j, "pacing_timer", test->settings->pacing_timer);
         if (test->settings->burst)          if (test->settings->burst)
             cJSON_AddNumberToObject(j, "burst", test->settings->burst);              cJSON_AddNumberToObject(j, "burst", test->settings->burst);
         if (test->settings->tos)          if (test->settings->tos)
Line 1328  send_parameters(struct iperf_test *test) Line 1880  send_parameters(struct iperf_test *test)
             cJSON_AddNumberToObject(j, "flowlabel", test->settings->flowlabel);              cJSON_AddNumberToObject(j, "flowlabel", test->settings->flowlabel);
         if (test->title)          if (test->title)
             cJSON_AddStringToObject(j, "title", test->title);              cJSON_AddStringToObject(j, "title", test->title);
           if (test->extra_data)
               cJSON_AddStringToObject(j, "extra_data", test->extra_data);
         if (test->congestion)          if (test->congestion)
             cJSON_AddStringToObject(j, "congestion", test->congestion);              cJSON_AddStringToObject(j, "congestion", test->congestion);
           if (test->congestion_used)
               cJSON_AddStringToObject(j, "congestion_used", test->congestion_used);
         if (test->get_server_output)          if (test->get_server_output)
             cJSON_AddNumberToObject(j, "get_server_output", iperf_get_test_get_server_output(test));              cJSON_AddNumberToObject(j, "get_server_output", iperf_get_test_get_server_output(test));
         if (test->udp_counters_64bit)          if (test->udp_counters_64bit)
             cJSON_AddNumberToObject(j, "udp_counters_64bit", iperf_get_test_udp_counters_64bit(test));              cJSON_AddNumberToObject(j, "udp_counters_64bit", iperf_get_test_udp_counters_64bit(test));
        if (test->no_fq_socket_pacing)        if (test->repeating_payload)
            cJSON_AddNumberToObject(j, "no_fq_socket_pacing", iperf_get_no_fq_socket_pacing(test));            cJSON_AddNumberToObject(j, "repeating_payload", test->repeating_payload);
 #if defined(HAVE_SSL)
         /* Send authentication parameters */
         if (test->settings->client_username && test->settings->client_password && test->settings->client_rsa_pubkey){
             int rc = encode_auth_setting(test->settings->client_username, test->settings->client_password, test->settings->client_rsa_pubkey, &test->settings->authtoken);
   
               if (rc) {
                   cJSON_Delete(j);
                   i_errno = IESENDPARAMS;
                   return -1;
               }
               
               cJSON_AddStringToObject(j, "authtoken", test->settings->authtoken);
           }
   #endif // HAVE_SSL
         cJSON_AddStringToObject(j, "client_version", IPERF_VERSION);          cJSON_AddStringToObject(j, "client_version", IPERF_VERSION);
   
         if (test->debug) {          if (test->debug) {
            printf("send_parameters:\n%s\n", cJSON_Print(j));            char *str = cJSON_Print(j);
             printf("send_parameters:\n%s\n", str);
             cJSON_free(str);
         }          }
   
         if (JSON_write(test->ctrl_sck, j) < 0) {          if (JSON_write(test->ctrl_sck, j) < 0) {
Line 1367  get_parameters(struct iperf_test *test) Line 1938  get_parameters(struct iperf_test *test)
         r = -1;          r = -1;
     } else {      } else {
         if (test->debug) {          if (test->debug) {
            printf("get_parameters:\n%s\n", cJSON_Print(j));            char *str;
             str = cJSON_Print(j);
             printf("get_parameters:\n%s\n", str );
             cJSON_free(str);
         }          }
   
         if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL)          if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL)
Line 1394  get_parameters(struct iperf_test *test) Line 1968  get_parameters(struct iperf_test *test)
             test->num_streams = j_p->valueint;              test->num_streams = j_p->valueint;
         if ((j_p = cJSON_GetObjectItem(j, "reverse")) != NULL)          if ((j_p = cJSON_GetObjectItem(j, "reverse")) != NULL)
             iperf_set_test_reverse(test, 1);              iperf_set_test_reverse(test, 1);
           if ((j_p = cJSON_GetObjectItem(j, "bidirectional")) != NULL)
               iperf_set_test_bidirectional(test, 1);
         if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL)          if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL)
             test->settings->socket_bufsize = j_p->valueint;              test->settings->socket_bufsize = j_p->valueint;
         if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL)          if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL)
             test->settings->blksize = j_p->valueint;              test->settings->blksize = j_p->valueint;
         if ((j_p = cJSON_GetObjectItem(j, "bandwidth")) != NULL)          if ((j_p = cJSON_GetObjectItem(j, "bandwidth")) != NULL)
             test->settings->rate = j_p->valueint;              test->settings->rate = j_p->valueint;
           if ((j_p = cJSON_GetObjectItem(j, "fqrate")) != NULL)
               test->settings->fqrate = j_p->valueint;
           if ((j_p = cJSON_GetObjectItem(j, "pacing_timer")) != NULL)
               test->settings->pacing_timer = j_p->valueint;
         if ((j_p = cJSON_GetObjectItem(j, "burst")) != NULL)          if ((j_p = cJSON_GetObjectItem(j, "burst")) != NULL)
             test->settings->burst = j_p->valueint;              test->settings->burst = j_p->valueint;
         if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL)          if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL)
Line 1408  get_parameters(struct iperf_test *test) Line 1988  get_parameters(struct iperf_test *test)
             test->settings->flowlabel = j_p->valueint;              test->settings->flowlabel = j_p->valueint;
         if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL)          if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL)
             test->title = strdup(j_p->valuestring);              test->title = strdup(j_p->valuestring);
           if ((j_p = cJSON_GetObjectItem(j, "extra_data")) != NULL)
               test->extra_data = strdup(j_p->valuestring);
         if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL)          if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL)
             test->congestion = strdup(j_p->valuestring);              test->congestion = strdup(j_p->valuestring);
           if ((j_p = cJSON_GetObjectItem(j, "congestion_used")) != NULL)
               test->congestion_used = strdup(j_p->valuestring);
         if ((j_p = cJSON_GetObjectItem(j, "get_server_output")) != NULL)          if ((j_p = cJSON_GetObjectItem(j, "get_server_output")) != NULL)
             iperf_set_test_get_server_output(test, 1);              iperf_set_test_get_server_output(test, 1);
         if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL)          if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL)
             iperf_set_test_udp_counters_64bit(test, 1);              iperf_set_test_udp_counters_64bit(test, 1);
        if ((j_p = cJSON_GetObjectItem(j, "no_fq_socket_pacing")) != NULL)        if ((j_p = cJSON_GetObjectItem(j, "repeating_payload")) != NULL)
            iperf_set_no_fq_socket_pacing(test, 1);            test->repeating_payload = 1;
        #if defined(HAVE_SSL)
        if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits())        if ((j_p = cJSON_GetObjectItem(j, "authtoken")) != NULL)
         test->settings->authtoken = strdup(j_p->valuestring);
 #endif //HAVE_SSL
         if (test->mode && test->protocol->id == Ptcp && has_tcpinfo_retransmits())
             test->sender_has_retransmits = 1;              test->sender_has_retransmits = 1;
           if (test->settings->rate)
               cJSON_AddNumberToObject(test->json_start, "target_bitrate", test->settings->rate);
         cJSON_Delete(j);          cJSON_Delete(j);
     }      }
     return r;      return r;
Line 1437  send_results(struct iperf_test *test) Line 2026  send_results(struct iperf_test *test)
     int sender_has_retransmits;      int sender_has_retransmits;
     iperf_size_t bytes_transferred;      iperf_size_t bytes_transferred;
     int retransmits;      int retransmits;
       struct iperf_time temp_time;
       double start_time, end_time;
   
     j = cJSON_CreateObject();      j = cJSON_CreateObject();
     if (j == NULL) {      if (j == NULL) {
Line 1446  send_results(struct iperf_test *test) Line 2037  send_results(struct iperf_test *test)
         cJSON_AddNumberToObject(j, "cpu_util_total", test->cpu_util[0]);          cJSON_AddNumberToObject(j, "cpu_util_total", test->cpu_util[0]);
         cJSON_AddNumberToObject(j, "cpu_util_user", test->cpu_util[1]);          cJSON_AddNumberToObject(j, "cpu_util_user", test->cpu_util[1]);
         cJSON_AddNumberToObject(j, "cpu_util_system", test->cpu_util[2]);          cJSON_AddNumberToObject(j, "cpu_util_system", test->cpu_util[2]);
        if ( ! test->sender )        if ( test->mode == RECEIVER )
             sender_has_retransmits = -1;              sender_has_retransmits = -1;
         else          else
             sender_has_retransmits = test->sender_has_retransmits;              sender_has_retransmits = test->sender_has_retransmits;
         cJSON_AddNumberToObject(j, "sender_has_retransmits", sender_has_retransmits);          cJSON_AddNumberToObject(j, "sender_has_retransmits", sender_has_retransmits);
           if ( test->congestion_used ) {
               cJSON_AddStringToObject(j, "congestion_used", test->congestion_used);
           }
   
         /* If on the server and sending server output, then do this */          /* If on the server and sending server output, then do this */
         if (test->role == 's' && test->get_server_output) {          if (test->role == 's' && test->get_server_output) {
Line 1476  send_results(struct iperf_test *test) Line 2070  send_results(struct iperf_test *test)
                 }                  }
   
                 cJSON_AddStringToObject(j, "server_output_text", output);                  cJSON_AddStringToObject(j, "server_output_text", output);
           free(output);
             }              }
         }          }
   
Line 1492  send_results(struct iperf_test *test) Line 2087  send_results(struct iperf_test *test)
                     r = -1;                      r = -1;
                 } else {                  } else {
                     cJSON_AddItemToArray(j_streams, j_stream);                      cJSON_AddItemToArray(j_streams, j_stream);
                    bytes_transferred = test->sender ? (sp->result->bytes_sent - sp->result->bytes_sent_omit) : sp->result->bytes_received;                    bytes_transferred = sp->sender ? (sp->result->bytes_sent - sp->result->bytes_sent_omit) : sp->result->bytes_received;
                    retransmits = (test->sender && test->sender_has_retransmits) ? sp->result->stream_retrans : -1;                    retransmits = (sp->sender && test->sender_has_retransmits) ? sp->result->stream_retrans : -1;
                     cJSON_AddNumberToObject(j_stream, "id", sp->id);                      cJSON_AddNumberToObject(j_stream, "id", sp->id);
                     cJSON_AddNumberToObject(j_stream, "bytes", bytes_transferred);                      cJSON_AddNumberToObject(j_stream, "bytes", bytes_transferred);
                     cJSON_AddNumberToObject(j_stream, "retransmits", retransmits);                      cJSON_AddNumberToObject(j_stream, "retransmits", retransmits);
                     cJSON_AddNumberToObject(j_stream, "jitter", sp->jitter);                      cJSON_AddNumberToObject(j_stream, "jitter", sp->jitter);
                     cJSON_AddNumberToObject(j_stream, "errors", sp->cnt_error);                      cJSON_AddNumberToObject(j_stream, "errors", sp->cnt_error);
                     cJSON_AddNumberToObject(j_stream, "packets", sp->packet_count);                      cJSON_AddNumberToObject(j_stream, "packets", sp->packet_count);
   
                       iperf_time_diff(&sp->result->start_time, &sp->result->start_time, &temp_time);
                       start_time = iperf_time_in_secs(&temp_time);
                       iperf_time_diff(&sp->result->start_time, &sp->result->end_time, &temp_time);
                       end_time = iperf_time_in_secs(&temp_time);
                       cJSON_AddNumberToObject(j_stream, "start_time", start_time);
                       cJSON_AddNumberToObject(j_stream, "end_time", end_time);
   
                 }                  }
             }              }
             if (r == 0 && test->debug) {              if (r == 0 && test->debug) {
                printf("send_results\n%s\n", cJSON_Print(j));                char *str = cJSON_Print(j);
                 printf("send_results\n%s\n", str);
                 cJSON_free(str);
             }              }
             if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) {              if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) {
                 i_errno = IESENDRESULTS;                  i_errno = IESENDRESULTS;
Line 1525  get_results(struct iperf_test *test) Line 2130  get_results(struct iperf_test *test)
     cJSON *j_cpu_util_total;      cJSON *j_cpu_util_total;
     cJSON *j_cpu_util_user;      cJSON *j_cpu_util_user;
     cJSON *j_cpu_util_system;      cJSON *j_cpu_util_system;
       cJSON *j_remote_congestion_used;
     cJSON *j_sender_has_retransmits;      cJSON *j_sender_has_retransmits;
     int result_has_retransmits;      int result_has_retransmits;
     cJSON *j_streams;      cJSON *j_streams;
Line 1537  get_results(struct iperf_test *test) Line 2143  get_results(struct iperf_test *test)
     cJSON *j_errors;      cJSON *j_errors;
     cJSON *j_packets;      cJSON *j_packets;
     cJSON *j_server_output;      cJSON *j_server_output;
       cJSON *j_start_time, *j_end_time;
     int sid, cerror, pcount;      int sid, cerror, pcount;
     double jitter;      double jitter;
     iperf_size_t bytes_transferred;      iperf_size_t bytes_transferred;
Line 1557  get_results(struct iperf_test *test) Line 2164  get_results(struct iperf_test *test)
             r = -1;              r = -1;
         } else {          } else {
             if (test->debug) {              if (test->debug) {
                printf("get_results\n%s\n", cJSON_Print(j));                char *str = cJSON_Print(j);
                 printf("get_results\n%s\n", str);
                 cJSON_free(str);
             }              }
   
             test->remote_cpu_util[0] = j_cpu_util_total->valuedouble;              test->remote_cpu_util[0] = j_cpu_util_total->valuedouble;
             test->remote_cpu_util[1] = j_cpu_util_user->valuedouble;              test->remote_cpu_util[1] = j_cpu_util_user->valuedouble;
             test->remote_cpu_util[2] = j_cpu_util_system->valuedouble;              test->remote_cpu_util[2] = j_cpu_util_system->valuedouble;
             result_has_retransmits = j_sender_has_retransmits->valueint;              result_has_retransmits = j_sender_has_retransmits->valueint;
            if (! test->sender)            if ( test->mode == RECEIVER ) {
                test->sender_has_retransmits = result_has_retransmits;                test->sender_has_retransmits = result_has_retransmits;
                 test->other_side_has_retransmits = 0;
             }
             else if ( test->mode == BIDIRECTIONAL )
                 test->other_side_has_retransmits = result_has_retransmits;
 
             j_streams = cJSON_GetObjectItem(j, "streams");              j_streams = cJSON_GetObjectItem(j, "streams");
             if (j_streams == NULL) {              if (j_streams == NULL) {
                 i_errno = IERECVRESULTS;                  i_errno = IERECVRESULTS;
Line 1584  get_results(struct iperf_test *test) Line 2198  get_results(struct iperf_test *test)
                         j_jitter = cJSON_GetObjectItem(j_stream, "jitter");                          j_jitter = cJSON_GetObjectItem(j_stream, "jitter");
                         j_errors = cJSON_GetObjectItem(j_stream, "errors");                          j_errors = cJSON_GetObjectItem(j_stream, "errors");
                         j_packets = cJSON_GetObjectItem(j_stream, "packets");                          j_packets = cJSON_GetObjectItem(j_stream, "packets");
                           j_start_time = cJSON_GetObjectItem(j_stream, "start_time");
                           j_end_time = cJSON_GetObjectItem(j_stream, "end_time");
                         if (j_id == NULL || j_bytes == NULL || j_retransmits == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) {                          if (j_id == NULL || j_bytes == NULL || j_retransmits == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) {
                             i_errno = IERECVRESULTS;                              i_errno = IERECVRESULTS;
                             r = -1;                              r = -1;
Line 1600  get_results(struct iperf_test *test) Line 2216  get_results(struct iperf_test *test)
                                 i_errno = IESTREAMID;                                  i_errno = IESTREAMID;
                                 r = -1;                                  r = -1;
                             } else {                              } else {
                                if (test->sender) {                                if (sp->sender) {
                                     sp->jitter = jitter;                                      sp->jitter = jitter;
                                     sp->cnt_error = cerror;                                      sp->cnt_error = cerror;
                                    sp->packet_count = pcount;                                    sp->peer_packet_count = pcount;
                                     sp->result->bytes_received = bytes_transferred;                                      sp->result->bytes_received = bytes_transferred;
                                       /*
                                        * We have to handle the possibilty that
                                        * start_time and end_time might not be
                                        * available; this is the case for older (pre-3.2)
                                        * servers.
                                        *
                                        * We need to have result structure members to hold
                                        * the both sides' start_time and end_time.
                                        */
                                       if (j_start_time && j_end_time) {
                                           sp->result->receiver_time = j_end_time->valuedouble - j_start_time->valuedouble;
                                       }
                                       else {
                                           sp->result->receiver_time = 0.0;
                                       }
                                 } else {                                  } else {
                                       sp->peer_packet_count = pcount;
                                     sp->result->bytes_sent = bytes_transferred;                                      sp->result->bytes_sent = bytes_transferred;
                                     sp->result->stream_retrans = retransmits;                                      sp->result->stream_retrans = retransmits;
                                       if (j_start_time && j_end_time) {
                                           sp->result->sender_time = j_end_time->valuedouble - j_start_time->valuedouble;
                                       }
                                       else {
                                           sp->result->sender_time = 0.0;
                                       }
                                 }                                  }
                             }                              }
                         }                          }
Line 1633  get_results(struct iperf_test *test) Line 2271  get_results(struct iperf_test *test)
                 }                  }
             }              }
         }          }
   
           j_remote_congestion_used = cJSON_GetObjectItem(j, "congestion_used");
           if (j_remote_congestion_used != NULL) {
               test->remote_congestion_used = strdup(j_remote_congestion_used->valuestring);
           }
   
         cJSON_Delete(j);          cJSON_Delete(j);
     }      }
     return r;      return r;
Line 1659  JSON_write(int fd, cJSON *json) Line 2303  JSON_write(int fd, cJSON *json)
             if (Nwrite(fd, str, hsize, Ptcp) < 0)              if (Nwrite(fd, str, hsize, Ptcp) < 0)
                 r = -1;                  r = -1;
         }          }
        free(str);        cJSON_free(str);
     }      }
     return r;      return r;
 }  }
Line 1754  connect_msg(struct iperf_stream *sp) Line 2398  connect_msg(struct iperf_stream *sp)
     if (sp->test->json_output)      if (sp->test->json_output)
         cJSON_AddItemToArray(sp->test->json_connected, iperf_json_printf("socket: %d  local_host: %s  local_port: %d  remote_host: %s  remote_port: %d", (int64_t) sp->socket, ipl, (int64_t) lport, ipr, (int64_t) rport));          cJSON_AddItemToArray(sp->test->json_connected, iperf_json_printf("socket: %d  local_host: %s  local_port: %d  remote_host: %s  remote_port: %d", (int64_t) sp->socket, ipl, (int64_t) lport, ipr, (int64_t) rport));
     else      else
        iprintf(sp->test, report_connected, sp->socket, ipl, lport, ipr, rport);        iperf_printf(sp->test, report_connected, sp->socket, ipl, lport, ipr, rport);
 }  }
   
   
Line 1781  iperf_new_test() Line 2425  iperf_new_test()
     }      }
     memset(test->settings, 0, sizeof(struct iperf_settings));      memset(test->settings, 0, sizeof(struct iperf_settings));
   
       test->bitrate_limit_intervals_traffic_bytes = (iperf_size_t *) malloc(sizeof(iperf_size_t) * MAX_INTERVAL);
       if (!test->bitrate_limit_intervals_traffic_bytes) {
           free(test);
           i_errno = IENEWTEST;
           return NULL;
       }
       memset(test->bitrate_limit_intervals_traffic_bytes, 0, sizeof(sizeof(iperf_size_t) * MAX_INTERVAL));   
   
     /* By default all output goes to stdout */      /* By default all output goes to stdout */
     test->outfile = stdout;      test->outfile = stdout;
   
Line 1814  int Line 2466  int
 iperf_defaults(struct iperf_test *testp)  iperf_defaults(struct iperf_test *testp)
 {  {
     struct protocol *tcp, *udp;      struct protocol *tcp, *udp;
#if defined(HAVE_SCTP)#if defined(HAVE_SCTP_H)
     struct protocol *sctp;      struct protocol *sctp;
#endif /* HAVE_SCTP */#endif /* HAVE_SCTP_H */
   
     testp->omit = OMIT;      testp->omit = OMIT;
     testp->duration = DURATION;      testp->duration = DURATION;
Line 1828  iperf_defaults(struct iperf_test *testp) Line 2480  iperf_defaults(struct iperf_test *testp)
     CPU_ZERO(&testp->cpumask);      CPU_ZERO(&testp->cpumask);
 #endif /* HAVE_CPUSET_SETAFFINITY */  #endif /* HAVE_CPUSET_SETAFFINITY */
     testp->title = NULL;      testp->title = NULL;
       testp->extra_data = NULL;
     testp->congestion = NULL;      testp->congestion = NULL;
       testp->congestion_used = NULL;
       testp->remote_congestion_used = NULL;
     testp->server_port = PORT;      testp->server_port = PORT;
     testp->ctrl_sck = -1;      testp->ctrl_sck = -1;
     testp->prot_listener = -1;      testp->prot_listener = -1;
       testp->other_side_has_retransmits = 0;
   
     testp->stats_callback = iperf_stats_callback;      testp->stats_callback = iperf_stats_callback;
     testp->reporter_callback = iperf_reporter_callback;      testp->reporter_callback = iperf_reporter_callback;
Line 1844  iperf_defaults(struct iperf_test *testp) Line 2500  iperf_defaults(struct iperf_test *testp)
     testp->settings->socket_bufsize = 0;    /* use autotuning */      testp->settings->socket_bufsize = 0;    /* use autotuning */
     testp->settings->blksize = DEFAULT_TCP_BLKSIZE;      testp->settings->blksize = DEFAULT_TCP_BLKSIZE;
     testp->settings->rate = 0;      testp->settings->rate = 0;
       testp->settings->bitrate_limit = 0;
       testp->settings->bitrate_limit_interval = 5;
       testp->settings->bitrate_limit_stats_per_interval = 0;
       testp->settings->fqrate = 0;
       testp->settings->pacing_timer = 1000;
     testp->settings->burst = 0;      testp->settings->burst = 0;
     testp->settings->mss = 0;      testp->settings->mss = 0;
     testp->settings->bytes = 0;      testp->settings->bytes = 0;
     testp->settings->blocks = 0;      testp->settings->blocks = 0;
       testp->settings->connect_timeout = -1;
     memset(testp->cookie, 0, COOKIE_SIZE);      memset(testp->cookie, 0, COOKIE_SIZE);
   
     testp->multisend = 10;      /* arbitrary */      testp->multisend = 10;      /* arbitrary */
Line 1888  iperf_defaults(struct iperf_test *testp) Line 2550  iperf_defaults(struct iperf_test *testp)
   
     set_protocol(testp, Ptcp);      set_protocol(testp, Ptcp);
   
#if defined(HAVE_SCTP)#if defined(HAVE_SCTP_H)
     sctp = protocol_new();      sctp = protocol_new();
     if (!sctp) {      if (!sctp) {
         protocol_free(tcp);          protocol_free(tcp);
Line 1906  iperf_defaults(struct iperf_test *testp) Line 2568  iperf_defaults(struct iperf_test *testp)
     sctp->init = iperf_sctp_init;      sctp->init = iperf_sctp_init;
   
     SLIST_INSERT_AFTER(udp, sctp, protocols);      SLIST_INSERT_AFTER(udp, sctp, protocols);
#endif /* HAVE_SCTP */#endif /* HAVE_SCTP_H */
   
     testp->on_new_stream = iperf_on_new_stream;      testp->on_new_stream = iperf_on_new_stream;
     testp->on_test_start = iperf_on_test_start;      testp->on_test_start = iperf_on_test_start;
Line 1932  iperf_free_test(struct iperf_test *test) Line 2594  iperf_free_test(struct iperf_test *test)
         SLIST_REMOVE_HEAD(&test->streams, streams);          SLIST_REMOVE_HEAD(&test->streams, streams);
         iperf_free_stream(sp);          iperf_free_stream(sp);
     }      }
   
     if (test->server_hostname)      if (test->server_hostname)
         free(test->server_hostname);          free(test->server_hostname);
     if (test->tmp_template)      if (test->tmp_template)
Line 1951  iperf_free_test(struct iperf_test *test) Line 2612  iperf_free_test(struct iperf_test *test)
             free(xbe);              free(xbe);
         }          }
     }      }
   #if defined(HAVE_SSL)
   
       if (test->server_rsa_private_key)
         EVP_PKEY_free(test->server_rsa_private_key);
       test->server_rsa_private_key = NULL;
   
       free(test->settings->authtoken);
       test->settings->authtoken = NULL;
   
       free(test->settings->client_username);
       test->settings->client_username = NULL;
   
       free(test->settings->client_password);
       test->settings->client_password = NULL;
   
       if (test->settings->client_rsa_pubkey)
         EVP_PKEY_free(test->settings->client_rsa_pubkey);
       test->settings->client_rsa_pubkey = NULL;
   #endif /* HAVE_SSL */
   
     if (test->settings)      if (test->settings)
     free(test->settings);      free(test->settings);
     if (test->title)      if (test->title)
         free(test->title);          free(test->title);
       if (test->extra_data)
           free(test->extra_data);
     if (test->congestion)      if (test->congestion)
         free(test->congestion);          free(test->congestion);
       if (test->congestion_used)
           free(test->congestion_used);
       if (test->remote_congestion_used)
           free(test->remote_congestion_used);
       if (test->timestamp_format)
           free(test->timestamp_format);
     if (test->omit_timer != NULL)      if (test->omit_timer != NULL)
         tmr_cancel(test->omit_timer);          tmr_cancel(test->omit_timer);
     if (test->timer != NULL)      if (test->timer != NULL)
Line 1973  iperf_free_test(struct iperf_test *test) Line 2662  iperf_free_test(struct iperf_test *test)
         free(prot);          free(prot);
     }      }
   
       if (test->logfile) {
           free(test->logfile);
           test->logfile = NULL;
           if (test->outfile) {
               fclose(test->outfile);
               test->outfile = NULL;
           }
       }
   
     if (test->server_output_text) {      if (test->server_output_text) {
         free(test->server_output_text);          free(test->server_output_text);
         test->server_output_text = NULL;          test->server_output_text = NULL;
Line 2004  iperf_free_test(struct iperf_test *test) Line 2702  iperf_free_test(struct iperf_test *test)
         }          }
     }      }
   
       /* Free interval's traffic array for avrage rate calculations */
       if (test->bitrate_limit_intervals_traffic_bytes != NULL)
           free(test->bitrate_limit_intervals_traffic_bytes);
   
     /* XXX: Why are we setting these values to NULL? */      /* XXX: Why are we setting these values to NULL? */
     // test->streams = NULL;      // test->streams = NULL;
     test->stats_callback = NULL;      test->stats_callback = NULL;
Line 2016  void Line 2718  void
 iperf_reset_test(struct iperf_test *test)  iperf_reset_test(struct iperf_test *test)
 {  {
     struct iperf_stream *sp;      struct iperf_stream *sp;
       int i;
   
     /* Free streams */      /* Free streams */
     while (!SLIST_EMPTY(&test->streams)) {      while (!SLIST_EMPTY(&test->streams)) {
Line 2043  iperf_reset_test(struct iperf_test *test) Line 2746  iperf_reset_test(struct iperf_test *test)
   
     SLIST_INIT(&test->streams);      SLIST_INIT(&test->streams);
   
       if (test->remote_congestion_used)
           free(test->remote_congestion_used);
       test->remote_congestion_used = NULL;
     test->role = 's';      test->role = 's';
    test->sender = 0;    test->mode = RECEIVER;
     test->sender_has_retransmits = 0;      test->sender_has_retransmits = 0;
     set_protocol(test, Ptcp);      set_protocol(test, Ptcp);
     test->omit = OMIT;      test->omit = OMIT;
Line 2061  iperf_reset_test(struct iperf_test *test) Line 2767  iperf_reset_test(struct iperf_test *test)
     test->bytes_sent = 0;      test->bytes_sent = 0;
     test->blocks_sent = 0;      test->blocks_sent = 0;
   
       test->bytes_received = 0;
       test->blocks_received = 0;
   
       test->other_side_has_retransmits = 0;
   
       test->bitrate_limit_stats_count = 0;
       test->bitrate_limit_last_interval_index = 0;
       test->bitrate_limit_exceeded = 0;
   
       for (i = 0; i < MAX_INTERVAL; i++)
           test->bitrate_limit_intervals_traffic_bytes[i] = 0;
   
     test->reverse = 0;      test->reverse = 0;
       test->bidirectional = 0;
     test->no_delay = 0;      test->no_delay = 0;
   
     FD_ZERO(&test->read_set);      FD_ZERO(&test->read_set);
Line 2073  iperf_reset_test(struct iperf_test *test) Line 2792  iperf_reset_test(struct iperf_test *test)
     test->settings->rate = 0;      test->settings->rate = 0;
     test->settings->burst = 0;      test->settings->burst = 0;
     test->settings->mss = 0;      test->settings->mss = 0;
       test->settings->tos = 0;
   
   #if defined(HAVE_SSL)
       if (test->settings->authtoken) {
           free(test->settings->authtoken);
           test->settings->authtoken = NULL;
       }
       if (test->settings->client_username) {
           free(test->settings->client_username);
           test->settings->client_username = NULL;
       }
       if (test->settings->client_password) {
           free(test->settings->client_password);
           test->settings->client_password = NULL;
       }
       if (test->settings->client_rsa_pubkey) {
           EVP_PKEY_free(test->settings->client_rsa_pubkey);
           test->settings->client_rsa_pubkey = NULL;
       }
   #endif /* HAVE_SSL */
   
     memset(test->cookie, 0, COOKIE_SIZE);      memset(test->cookie, 0, COOKIE_SIZE);
     test->multisend = 10;       /* arbitrary */      test->multisend = 10;       /* arbitrary */
     test->udp_counters_64bit = 0;      test->udp_counters_64bit = 0;
       if (test->title) {
           free(test->title);
           test->title = NULL;
       }
       if (test->extra_data) {
           free(test->extra_data);
           test->extra_data = NULL;
       }
   
     /* Free output line buffers, if any (on the server only) */      /* Free output line buffers, if any (on the server only) */
     struct iperf_textline *t;      struct iperf_textline *t;
Line 2094  iperf_reset_test(struct iperf_test *test) Line 2842  iperf_reset_test(struct iperf_test *test)
 void  void
 iperf_reset_stats(struct iperf_test *test)  iperf_reset_stats(struct iperf_test *test)
 {  {
    struct timeval now;    struct iperf_time now;
     struct iperf_stream *sp;      struct iperf_stream *sp;
     struct iperf_stream_result *rp;      struct iperf_stream_result *rp;
   
     test->bytes_sent = 0;      test->bytes_sent = 0;
     test->blocks_sent = 0;      test->blocks_sent = 0;
    gettimeofday(&now, NULL);    iperf_time_now(&now);
     SLIST_FOREACH(sp, &test->streams, streams) {      SLIST_FOREACH(sp, &test->streams, streams) {
         sp->omitted_packet_count = sp->packet_count;          sp->omitted_packet_count = sp->packet_count;
         sp->omitted_cnt_error = sp->cnt_error;          sp->omitted_cnt_error = sp->cnt_error;
Line 2110  iperf_reset_stats(struct iperf_test *test) Line 2858  iperf_reset_stats(struct iperf_test *test)
         rp->bytes_sent_omit = rp->bytes_sent;          rp->bytes_sent_omit = rp->bytes_sent;
         rp->bytes_received = 0;          rp->bytes_received = 0;
         rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;          rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
        if (test->sender && test->sender_has_retransmits) {        if (test->sender_has_retransmits == 1) {
             struct iperf_interval_results ir; /* temporary results structure */              struct iperf_interval_results ir; /* temporary results structure */
             save_tcpinfo(sp, &ir);              save_tcpinfo(sp, &ir);
             rp->stream_prev_total_retrans = get_total_retransmits(&ir);              rp->stream_prev_total_retrans = get_total_retransmits(&ir);
Line 2133  iperf_stats_callback(struct iperf_test *test) Line 2881  iperf_stats_callback(struct iperf_test *test)
     struct iperf_stream *sp;      struct iperf_stream *sp;
     struct iperf_stream_result *rp = NULL;      struct iperf_stream_result *rp = NULL;
     struct iperf_interval_results *irp, temp;      struct iperf_interval_results *irp, temp;
       struct iperf_time temp_time;
       iperf_size_t total_interval_bytes_transferred = 0;
   
     temp.omitted = test->omitting;      temp.omitted = test->omitting;
     SLIST_FOREACH(sp, &test->streams, streams) {      SLIST_FOREACH(sp, &test->streams, streams) {
         rp = sp->result;          rp = sp->result;
           temp.bytes_transferred = sp->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval;
   
        temp.bytes_transferred = test->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval;        // Total bytes transferred this interval
             total_interval_bytes_transferred += rp->bytes_sent_this_interval + rp->bytes_received_this_interval;
     
         irp = TAILQ_LAST(&rp->interval_results, irlisthead);          irp = TAILQ_LAST(&rp->interval_results, irlisthead);
         /* result->end_time contains timestamp of previous interval */          /* result->end_time contains timestamp of previous interval */
         if ( irp != NULL ) /* not the 1st interval */          if ( irp != NULL ) /* not the 1st interval */
            memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct timeval));            memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct iperf_time));
         else /* or use timestamp from beginning */          else /* or use timestamp from beginning */
            memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct timeval));            memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct iperf_time));
         /* now save time of end of this interval */          /* now save time of end of this interval */
        gettimeofday(&rp->end_time, NULL);        iperf_time_now(&rp->end_time);
        memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct timeval));        memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct iperf_time));
        temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);        iperf_time_diff(&temp.interval_start_time, &temp.interval_end_time, &temp_time);
        //temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);        temp.interval_duration = iperf_time_in_secs(&temp_time);
         if (test->protocol->id == Ptcp) {          if (test->protocol->id == Ptcp) {
             if ( has_tcpinfo()) {              if ( has_tcpinfo()) {
                 save_tcpinfo(sp, &temp);                  save_tcpinfo(sp, &temp);
                if (test->sender && test->sender_has_retransmits) {                if (test->sender_has_retransmits == 1) {
                     long total_retrans = get_total_retransmits(&temp);                      long total_retrans = get_total_retransmits(&temp);
                     temp.interval_retrans = total_retrans - rp->stream_prev_total_retrans;                      temp.interval_retrans = total_retrans - rp->stream_prev_total_retrans;
                     rp->stream_retrans += temp.interval_retrans;                      rp->stream_retrans += temp.interval_retrans;
Line 2175  iperf_stats_callback(struct iperf_test *test) Line 2927  iperf_stats_callback(struct iperf_test *test)
                     }                      }
                     rp->stream_sum_rtt += temp.rtt;                      rp->stream_sum_rtt += temp.rtt;
                     rp->stream_count_rtt++;                      rp->stream_count_rtt++;
   
                       temp.rttvar = get_rttvar(&temp);
                       temp.pmtu = get_pmtu(&temp);
                 }                  }
             }              }
         } else {          } else {
Line 2195  iperf_stats_callback(struct iperf_test *test) Line 2950  iperf_stats_callback(struct iperf_test *test)
         add_to_interval_list(rp, &temp);          add_to_interval_list(rp, &temp);
         rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;          rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
     }      }
   
       /* Verify that total server's throughput is not above specified limit */
       if (test->role == 's') {
           iperf_check_total_rate(test, total_interval_bytes_transferred);
       }
 }  }
   
 /**  /**
Line 2206  iperf_stats_callback(struct iperf_test *test) Line 2966  iperf_stats_callback(struct iperf_test *test)
 static void  static void
 iperf_print_intermediate(struct iperf_test *test)  iperf_print_intermediate(struct iperf_test *test)
 {  {
     char ubuf[UNIT_LEN];  
     char nbuf[UNIT_LEN];  
     struct iperf_stream *sp = NULL;      struct iperf_stream *sp = NULL;
     struct iperf_interval_results *irp;      struct iperf_interval_results *irp;
    iperf_size_t bytes = 0;    struct iperf_time temp_time;
    double bandwidth; 
    int retransmits = 0; 
    double start_time, end_time; 
     cJSON *json_interval;      cJSON *json_interval;
     cJSON *json_interval_streams;      cJSON *json_interval_streams;
     int total_packets = 0, lost_packets = 0;  
     double avg_jitter = 0.0, lost_percent;  
   
       int lower_mode, upper_mode;
       int current_mode;
   
       /*
        * Due to timing oddities, there can be cases, especially on the
        * server side, where at the end of a test there is a fairly short
        * interval with no data transferred.  This could caused by
        * the control and data flows sharing the same path in the network,
        * and having the control messages for stopping the test being
        * queued behind the data packets.
        *
        * We'd like to try to omit that last interval when it happens, to
        * avoid cluttering data and output with useless stuff.
        * So we're going to try to ignore very short intervals (less than
        * 10% of the interval time) that have no data.
        */
       int interval_ok = 0;
       SLIST_FOREACH(sp, &test->streams, streams) {
           irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
           if (irp) {
               iperf_time_diff(&irp->interval_start_time, &irp->interval_end_time, &temp_time);
               double interval_len = iperf_time_in_secs(&temp_time);
               if (test->debug) {
                   printf("interval_len %f bytes_transferred %" PRIu64 "\n", interval_len, irp->bytes_transferred);
               }
   
               /*
                * If the interval is at least 10% the normal interval
                * length, or if there were actual bytes transferrred,
                * then we want to keep this interval.
                */
               if (interval_len >= test->stats_interval * 0.10 ||
                   irp->bytes_transferred > 0) {
                   interval_ok = 1;
                   if (test->debug) {
                       printf("interval forces keep\n");
                   }
               }
           }
       }
       if (!interval_ok) {
           if (test->debug) {
               printf("ignoring short interval with no data\n");
           }
           return;
       }
   
     if (test->json_output) {      if (test->json_output) {
         json_interval = cJSON_CreateObject();          json_interval = cJSON_CreateObject();
         if (json_interval == NULL)          if (json_interval == NULL)
Line 2233  iperf_print_intermediate(struct iperf_test *test) Line 3033  iperf_print_intermediate(struct iperf_test *test)
         json_interval_streams = NULL;          json_interval_streams = NULL;
     }      }
   
    SLIST_FOREACH(sp, &test->streams, streams) {    /*
        print_interval_results(test, sp, json_interval_streams);     * We must to sum streams separately.
        /* sum up all streams */     * For bidirectional mode we must to display
        irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);     * information about sender and receiver streams.
        if (irp == NULL) {     * For client side we must handle sender streams
            iperf_err(test, "iperf_print_intermediate error: interval_results is NULL");     * firstly and receiver streams for server side.
            return;     * The following design allows us to do this.
        }     */
        bytes += irp->bytes_transferred;
        if (test->protocol->id == Ptcp) {    if (test->mode == BIDIRECTIONAL) {
            if (test->sender && test->sender_has_retransmits) {        if (test->role == 'c') {
                retransmits += irp->interval_retrans;            lower_mode = -1;
            }            upper_mode = 0;
        } else {        } else {
            total_packets += irp->interval_packet_count;            lower_mode = 0;
            lost_packets += irp->interval_cnt_error;            upper_mode = 1;
            avg_jitter += irp->jitter;        }
        }    } else {
         lower_mode = test->mode;
         upper_mode = lower_mode;
     }      }
   
     /* next build string with sum of all streams */  
     if (test->num_streams > 1 || test->json_output) {  
         sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */  
         /* Only do this of course if there was a first stream */  
         if (sp) {  
         irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);    /* use 1st stream for timing info */  
   
        unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A');    for (current_mode = lower_mode; current_mode <= upper_mode; ++current_mode) {
        bandwidth = (double) bytes / (double) irp->interval_duration;        char ubuf[UNIT_LEN];
        unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);        char nbuf[UNIT_LEN];
         char mbuf[UNIT_LEN];
         char zbuf[] = "          ";
   
        start_time = timeval_diff(&sp->result->start_time,&irp->interval_start_time);        iperf_size_t bytes = 0;
        end_time = timeval_diff(&sp->result->start_time,&irp->interval_end_time);        double bandwidth;
        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {        int retransmits = 0;
            if (test->sender && test->sender_has_retransmits) {        double start_time, end_time;
                /* Interval sum, TCP with retransmits. */
                if (test->json_output)        int total_packets = 0, lost_packets = 0;
                    cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d  omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) retransmits, irp->omitted)); /* XXX irp->omitted or test->omitting? */        double avg_jitter = 0.0, lost_percent;
                else        int stream_must_be_sender = current_mode * current_mode;
                    iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits, irp->omitted?report_omitted:""); /* XXX irp->omitted or test->omitting? */
            } else {        /*  Print stream role just for bidirectional mode. */
                /* Interval sum, TCP without retransmits. */
                if (test->json_output)        if (test->mode == BIDIRECTIONAL) {
                    cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, test->omitting));            sprintf(mbuf, "[%s-%s]", stream_must_be_sender?"TX":"RX", test->role == 'c'?"C":"S");
                else        } else {
                    iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, test->omitting?report_omitted:"");            mbuf[0] = '\0';
            }            zbuf[0] = '\0';
        } else {        }
            /* Interval sum, UDP. */
            if (test->sender) {        SLIST_FOREACH(sp, &test->streams, streams) {
                if (test->json_output)            if (sp->sender == stream_must_be_sender) {
                    cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  packets: %d  omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) total_packets, test->omitting));                print_interval_results(test, sp, json_interval_streams);
                else                /* sum up all streams */
                    iprintf(test, report_sum_bw_udp_sender_format, start_time, end_time, ubuf, nbuf, total_packets, test->omitting?report_omitted:"");                irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
            } else {                if (irp == NULL) {
                avg_jitter /= test->num_streams;                    iperf_err(test,
                if (total_packets > 0) {                            "iperf_print_intermediate error: interval_results is NULL");
                    lost_percent = 100.0 * lost_packets / total_packets;                    return;
                }                }
                else {                bytes += irp->bytes_transferred;
                    lost_percent = 0.0;                if (test->protocol->id == Ptcp) {
                }                    if (test->sender_has_retransmits == 1) {
                if (test->json_output)                        retransmits += irp->interval_retrans;
                    cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  jitter_ms: %f  lost_packets: %d  packets: %d  lost_percent: %f  omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) total_packets, (double) lost_percent, test->omitting));                    }
                else                } else {
                    iprintf(test, report_sum_bw_udp_format, start_time, end_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, total_packets, lost_percent, test->omitting?report_omitted:"");                    total_packets += irp->interval_packet_count;
            }                    lost_packets += irp->interval_cnt_error;
        }                    avg_jitter += irp->jitter;
        }                }
             }
         }
 
         /* next build string with sum of all streams */
         if (test->num_streams > 1 || test->json_output) {
             sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */
             /* Only do this of course if there was a first stream */
             if (sp) {
             irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);    /* use 1st stream for timing info */
 
             unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A');
             bandwidth = (double) bytes / (double) irp->interval_duration;
             unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
 
             iperf_time_diff(&sp->result->start_time,&irp->interval_start_time, &temp_time);
             start_time = iperf_time_in_secs(&temp_time);
             iperf_time_diff(&sp->result->start_time,&irp->interval_end_time, &temp_time);
             end_time = iperf_time_in_secs(&temp_time);
                 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                     if (test->sender_has_retransmits == 1 && stream_must_be_sender) {
                         /* Interval sum, TCP with retransmits. */
                         if (test->json_output)
                             cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d  omitted: %b sender: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) retransmits, irp->omitted, stream_must_be_sender)); /* XXX irp->omitted or test->omitting? */
                         else
                             iperf_printf(test, report_sum_bw_retrans_format, mbuf, start_time, end_time, ubuf, nbuf, retransmits, irp->omitted?report_omitted:""); /* XXX irp->omitted or test->omitting? */
                     } else {
                         /* Interval sum, TCP without retransmits. */
                         if (test->json_output)
                             cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  omitted: %b sender: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, test->omitting, stream_must_be_sender));
                         else
                             iperf_printf(test, report_sum_bw_format, mbuf, start_time, end_time, ubuf, nbuf, test->omitting?report_omitted:"");
                     }
                 } else {
                     /* Interval sum, UDP. */
                     if (stream_must_be_sender) {
                         if (test->json_output)
                             cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  packets: %d  omitted: %b sender: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) total_packets, test->omitting, stream_must_be_sender));
                         else
                             iperf_printf(test, report_sum_bw_udp_sender_format, mbuf, start_time, end_time, ubuf, nbuf, zbuf, total_packets, test->omitting?report_omitted:"");
                     } else {
                         avg_jitter /= test->num_streams;
                         if (total_packets > 0) {
                             lost_percent = 100.0 * lost_packets / total_packets;
                         }
                         else {
                             lost_percent = 0.0;
                         }
                         if (test->json_output)
                             cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  jitter_ms: %f  lost_packets: %d  packets: %d  lost_percent: %f  omitted: %b sender: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) total_packets, (double) lost_percent, test->omitting, stream_must_be_sender));
                         else
                             iperf_printf(test, report_sum_bw_udp_format, mbuf, start_time, end_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, total_packets, lost_percent, test->omitting?report_omitted:"");
                     }
                 }
             }
         }
     }      }
 }  }
   
Line 2313  iperf_print_results(struct iperf_test *test) Line 3166  iperf_print_results(struct iperf_test *test)
 {  {
   
     cJSON *json_summary_streams = NULL;      cJSON *json_summary_streams = NULL;
     cJSON *json_summary_stream = NULL;  
     int total_retransmits = 0;  
     int total_packets = 0, lost_packets = 0;  
     char ubuf[UNIT_LEN];  
     char nbuf[UNIT_LEN];  
     struct stat sb;  
     char sbuf[UNIT_LEN];  
     struct iperf_stream *sp = NULL;  
     iperf_size_t bytes_sent, total_sent = 0;  
     iperf_size_t bytes_received, total_received = 0;  
     double start_time, end_time, avg_jitter = 0.0, lost_percent;  
     double bandwidth;  
   
       int lower_mode, upper_mode;
       int current_mode;
   
       int tmp_sender_has_retransmits = test->sender_has_retransmits;
   
     /* print final summary for all intervals */      /* print final summary for all intervals */
   
     if (test->json_output) {      if (test->json_output) {
Line 2334  iperf_print_results(struct iperf_test *test) Line 3180  iperf_print_results(struct iperf_test *test)
             return;              return;
         cJSON_AddItemToObject(test->json_end, "streams", json_summary_streams);          cJSON_AddItemToObject(test->json_end, "streams", json_summary_streams);
     } else {      } else {
        iprintf(test, "%s", report_bw_separator);        iperf_printf(test, "%s", report_bw_separator);
         if (test->verbose)          if (test->verbose)
            iprintf(test, "%s", report_summary);            iperf_printf(test, "%s", report_summary);
         if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {          if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
            if (test->sender_has_retransmits)            if (test->sender_has_retransmits || test->other_side_has_retransmits) {
                iprintf(test, "%s", report_bw_retrans_header);                if (test->bidirectional)
                     iperf_printf(test, "%s", report_bw_retrans_header_bidir);
                 else
                     iperf_printf(test, "%s", report_bw_retrans_header);
             }
             else {
                 if (test->bidirectional)
                     iperf_printf(test, "%s", report_bw_header_bidir);
                 else
                     iperf_printf(test, "%s", report_bw_header);
             }
         } else {
             if (test->bidirectional)
                 iperf_printf(test, "%s", report_bw_udp_header_bidir);
             else              else
                iprintf(test, "%s", report_bw_header);                iperf_printf(test, "%s", report_bw_udp_header);
        } else        }
            iprintf(test, "%s", report_bw_udp_header); 
     }      }
   
    start_time = 0.;    /*
    sp = SLIST_FIRST(&test->streams);     * We must to sum streams separately.
    /*      * For bidirectional mode we must to display
     * If there is at least one stream, then figure out the length of time     * information about sender and receiver streams.
     * we were running the tests and print out some statistics about     * For client side we must handle sender streams
     * the streams.  It's possible to not have any streams at all     * firstly and receiver streams for server side.
     * if the client got interrupted before it got to do anything.     * The following design allows us to do this.
      */       */
     if (sp) {  
     end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time);  
     SLIST_FOREACH(sp, &test->streams, streams) {  
         if (test->json_output) {  
             json_summary_stream = cJSON_CreateObject();  
             if (json_summary_stream == NULL)  
                 return;  
             cJSON_AddItemToArray(json_summary_streams, json_summary_stream);  
         }  
   
        bytes_sent = sp->result->bytes_sent - sp->result->bytes_sent_omit;    if (test->mode == BIDIRECTIONAL) {
        bytes_received = sp->result->bytes_received;        if (test->role == 'c') {
        total_sent += bytes_sent;            lower_mode = -1;
        total_received += bytes_received;            upper_mode = 0;
         } else {
             lower_mode = 0;
             upper_mode = 1;
         }
     } else {
         lower_mode = test->mode;
         upper_mode = lower_mode;
     }
   
        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
            if (test->sender_has_retransmits) {    for (current_mode = lower_mode; current_mode <= upper_mode; ++current_mode) {
                total_retransmits += sp->result->stream_retrans;        cJSON *json_summary_stream = NULL;
            }        int total_retransmits = 0;
        } else {        int total_packets = 0, lost_packets = 0;
            total_packets += (sp->packet_count - sp->omitted_packet_count);        int sender_packet_count = 0, receiver_packet_count = 0; /* for this stream, this interval */
            lost_packets += (sp->cnt_error - sp->omitted_cnt_error);        int sender_total_packets = 0, receiver_total_packets = 0; /* running total */
            avg_jitter += sp->jitter;        char ubuf[UNIT_LEN];
         char nbuf[UNIT_LEN];
         struct stat sb;
         char sbuf[UNIT_LEN];
         struct iperf_stream *sp = NULL;
         iperf_size_t bytes_sent, total_sent = 0;
         iperf_size_t bytes_received, total_received = 0;
         double start_time, end_time = 0.0, avg_jitter = 0.0, lost_percent = 0.0;
         double sender_time = 0.0, receiver_time = 0.0;
     struct iperf_time temp_time;
         double bandwidth;
 
         char mbuf[UNIT_LEN];
         int stream_must_be_sender = current_mode * current_mode;
 
 
         /*  Print stream role just for bidirectional mode. */
 
         if (test->mode == BIDIRECTIONAL) {
             sprintf(mbuf, "[%s-%s]", stream_must_be_sender?"TX":"RX", test->role == 'c'?"C":"S");
         } else {
             mbuf[0] = '\0';
         }          }
   
        unit_snprintf(ubuf, UNIT_LEN, (double) bytes_sent, 'A');        /* Get sender_has_retransmits for each sender side (client and server) */
        bandwidth = (double) bytes_sent / (double) end_time;        if (test->mode == BIDIRECTIONAL && stream_must_be_sender)
        unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);            test->sender_has_retransmits = tmp_sender_has_retransmits;
        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {        else if (test->mode == BIDIRECTIONAL && !stream_must_be_sender)
            if (test->sender_has_retransmits) {            test->sender_has_retransmits = test->other_side_has_retransmits;
                /* Summary, TCP with retransmits. */ 
                if (test->json_output) 
                    cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d  max_snd_cwnd:  %d  max_rtt:  %d  min_rtt:  %d  mean_rtt:  %d", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) sp->result->stream_retrans, (int64_t) sp->result->stream_max_snd_cwnd, (int64_t) sp->result->stream_max_rtt, (int64_t) sp->result->stream_min_rtt, (int64_t) ((sp->result->stream_count_rtt == 0) ? 0 : sp->result->stream_sum_rtt / sp->result->stream_count_rtt))); 
                else 
                    iprintf(test, report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->result->stream_retrans, report_sender); 
            } else { 
                /* Summary, TCP without retransmits. */ 
                if (test->json_output) 
                    cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8)); 
                else 
                    iprintf(test, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf, report_sender); 
            } 
        } else { 
            /* Summary, UDP. */ 
            if (sp->packet_count - sp->omitted_packet_count > 0) { 
              lost_percent = 100.0 * (sp->cnt_error - sp->omitted_cnt_error) / (sp->packet_count - sp->omitted_packet_count); 
            } 
            else { 
                lost_percent = 0.0; 
            } 
            if (test->json_output) 
              cJSON_AddItemToObject(json_summary_stream, "udp", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  jitter_ms: %f  lost_packets: %d  packets: %d  lost_percent: %f  out_of_order: %d", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8, (double) sp->jitter * 1000.0, (int64_t) (sp->cnt_error - sp->omitted_cnt_error), (int64_t) (sp->packet_count - sp->omitted_packet_count), (double) lost_percent, (int64_t) (sp->outoforder_packets - sp->omitted_outoforder_packets))); 
            else { 
              iprintf(test, report_bw_udp_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->jitter * 1000.0, (sp->cnt_error - sp->omitted_cnt_error), (sp->packet_count - sp->omitted_packet_count), lost_percent, ""); 
                if (test->role == 'c') 
                    iprintf(test, report_datagrams, sp->socket, (sp->packet_count - sp->omitted_packet_count)); 
                if ((sp->outoforder_packets - sp->omitted_outoforder_packets) > 0) 
                  iprintf(test, report_sum_outoforder, start_time, end_time, (sp->outoforder_packets - sp->omitted_outoforder_packets)); 
            } 
        } 
   
        if (sp->diskfile_fd >= 0) {        start_time = 0.;
            if (fstat(sp->diskfile_fd, &sb) == 0) {        sp = SLIST_FIRST(&test->streams);
                int percent = (int) ( ( (double) bytes_sent / (double) sb.st_size ) * 100.0 ); 
                unit_snprintf(sbuf, UNIT_LEN, (double) sb.st_size, 'A'); 
                if (test->json_output) 
                    cJSON_AddItemToObject(json_summary_stream, "diskfile", iperf_json_printf("sent: %d  size: %d  percent: %d  filename: %s", (int64_t) bytes_sent, (int64_t) sb.st_size, (int64_t) percent, test->diskfile_name)); 
                else 
                    iprintf(test, report_diskfile, ubuf, sbuf, percent, test->diskfile_name); 
            } 
        } 
   
        unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');        /*
        bandwidth = (double) bytes_received / (double) end_time;         * If there is at least one stream, then figure out the length of time
        unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);         * we were running the tests and print out some statistics about
        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {         * the streams.  It's possible to not have any streams at all
            if (test->json_output)         * if the client got interrupted before it got to do anything.
                cJSON_AddItemToObject(json_summary_stream, "receiver", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_received, bandwidth * 8));         *
            else         * Also note that we try to keep seperate values for the sender
                iprintf(test, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf, report_receiver);         * and receiver ending times.  Earlier iperf (3.1 and earlier)
        }         * servers didn't send that to the clients, so in this case we fall
    }         * back to using the client's ending timestamp.  The fallback is
    }         * basically emulating what iperf 3.1 did.
          */
   
    if (test->num_streams > 1 || test->json_output) {        if (sp) {
        unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');    iperf_time_diff(&sp->result->start_time, &sp->result->end_time, &temp_time);
        /* If no tests were run, arbitrariliy set bandwidth to 0. */    end_time = iperf_time_in_secs(&temp_time);
        if (end_time > 0.0) {        if (sp->sender) {
            bandwidth = (double) total_sent / (double) end_time;            sp->result->sender_time = end_time;
        }            if (sp->result->receiver_time == 0.0) {
        else {                sp->result->receiver_time = sp->result->sender_time;
            bandwidth = 0.0;            }
        }        }
        unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);        else {
        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {            sp->result->receiver_time = end_time;
            if (test->sender_has_retransmits) {            if (sp->result->sender_time == 0.0) {
                /* Summary sum, TCP with retransmits. */                sp->result->sender_time = sp->result->receiver_time;
                if (test->json_output)            }
                    cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8, (int64_t) total_retransmits));        }
                else        sender_time = sp->result->sender_time;
                    iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, total_retransmits, report_sender);        receiver_time = sp->result->receiver_time;
            } else {        SLIST_FOREACH(sp, &test->streams, streams) {
                /* Summary sum, TCP without retransmits. */            if (sp->sender == stream_must_be_sender) {
                if (test->json_output)                if (test->json_output) {
                    cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8));                    json_summary_stream = cJSON_CreateObject();
                else                    if (json_summary_stream == NULL)
                    iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, report_sender);                        return;
            }                    cJSON_AddItemToArray(json_summary_streams, json_summary_stream);
            unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A');                }
            /* If no tests were run, set received bandwidth to 0 */
            if (end_time > 0.0) {                bytes_sent = sp->result->bytes_sent - sp->result->bytes_sent_omit;
                bandwidth = (double) total_received / (double) end_time;                bytes_received = sp->result->bytes_received;
            }                total_sent += bytes_sent;
            else {                total_received += bytes_received;
                bandwidth = 0.0;
            }                if (sp->sender) {
                     sender_packet_count = sp->packet_count;
                     receiver_packet_count = sp->peer_packet_count;
                 }
                 else {
                     sender_packet_count = sp->peer_packet_count;
                     receiver_packet_count = sp->packet_count;
                 }
 
                 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                     if (test->sender_has_retransmits) {
                         total_retransmits += sp->result->stream_retrans;
                     }
                 } else {
                     /*
                      * Running total of the total number of packets.  Use the sender packet count if we
                      * have it, otherwise use the receiver packet count.
                      */
                     int packet_count = sender_packet_count ? sender_packet_count : receiver_packet_count;
                     total_packets += (packet_count - sp->omitted_packet_count);
                     sender_total_packets += (sender_packet_count - sp->omitted_packet_count);
                     receiver_total_packets += (receiver_packet_count - sp->omitted_packet_count);
                     lost_packets += (sp->cnt_error - sp->omitted_cnt_error);
                     avg_jitter += sp->jitter;
                 }
 
                 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_sent, 'A');
                 if (sender_time > 0.0) {
                     bandwidth = (double) bytes_sent / (double) sender_time;
                 }
                 else {
                     bandwidth = 0.0;
                 }
                 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
                 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                     if (test->sender_has_retransmits) {
                         /* Sender summary, TCP and SCTP with retransmits. */
                         if (test->json_output)
                             cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d  max_snd_cwnd:  %d  max_rtt:  %d  min_rtt:  %d  mean_rtt:  %d sender: %b", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) sp->result->stream_retrans, (int64_t) sp->result->stream_max_snd_cwnd, (int64_t) sp->result->stream_max_rtt, (int64_t) sp->result->stream_min_rtt, (int64_t) ((sp->result->stream_count_rtt == 0) ? 0 : sp->result->stream_sum_rtt / sp->result->stream_count_rtt), stream_must_be_sender));
                         else
                             if (test->role == 's' && !sp->sender) {
                                 if (test->verbose)
                                     iperf_printf(test, report_sender_not_available_format, sp->socket);
                             }
                             else {
                                 iperf_printf(test, report_bw_retrans_format, sp->socket, mbuf, start_time, sender_time, ubuf, nbuf, sp->result->stream_retrans, report_sender);
                             }
                     } else {
                         /* Sender summary, TCP and SCTP without retransmits. */
                         if (test->json_output)
                             cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f sender: %b", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8,  stream_must_be_sender));
                         else
                             if (test->role == 's' && !sp->sender) {
                                 if (test->verbose)
                                     iperf_printf(test, report_sender_not_available_format, sp->socket);
                             }
                             else {
                                 iperf_printf(test, report_bw_format, sp->socket, mbuf, start_time, sender_time, ubuf, nbuf, report_sender);
                             }
                     }
                 } else {
                     /* Sender summary, UDP. */
                     if (sender_packet_count - sp->omitted_packet_count > 0) {
                         lost_percent = 100.0 * (sp->cnt_error - sp->omitted_cnt_error) / (sender_packet_count - sp->omitted_packet_count);
                     }
                     else {
                         lost_percent = 0.0;
                     }
                     if (test->json_output) {
                         /*
                          * For hysterical raisins, we only emit one JSON
                          * object for the UDP summary, and it contains
                          * information for both the sender and receiver
                          * side.
                          *
                          * The JSON format as currently defined only includes one
                          * value for the number of packets.  We usually want that
                          * to be the sender's value (how many packets were sent
                          * by the sender).  However this value might not be
                          * available on the receiver in certain circumstances
                          * specifically on the server side for a normal test or
                          * the client side for a reverse-mode test.  If this
                          * is the case, then use the receiver's count of packets
                          * instead.
                          */
                         int packet_count = sender_packet_count ? sender_packet_count : receiver_packet_count;
                         cJSON_AddItemToObject(json_summary_stream, "udp", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  jitter_ms: %f  lost_packets: %d  packets: %d  lost_percent: %f  out_of_order: %d sender: %b", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, (double) sp->jitter * 1000.0, (int64_t) (sp->cnt_error - sp->omitted_cnt_error), (int64_t) (packet_count - sp->omitted_packet_count), (double) lost_percent, (int64_t) (sp->outoforder_packets - sp->omitted_outoforder_packets), stream_must_be_sender));
                     }
                     else {
                         /*
                          * Due to ordering of messages on the control channel,
                          * the server cannot report on client-side summary
                          * statistics.  If we're the server, omit one set of
                          * summary statistics to avoid giving meaningless
                          * results.
                          */
                         if (test->role == 's' && !sp->sender) {
                             if (test->verbose)
                                 iperf_printf(test, report_sender_not_available_format, sp->socket);
                         }
                         else {
                             iperf_printf(test, report_bw_udp_format, sp->socket, mbuf, start_time, sender_time, ubuf, nbuf, 0.0, 0, (sender_packet_count - sp->omitted_packet_count), (double) 0, report_sender);
                         }
                         if ((sp->outoforder_packets - sp->omitted_outoforder_packets) > 0)
                           iperf_printf(test, report_sum_outoforder, mbuf, start_time, sender_time, (sp->outoforder_packets - sp->omitted_outoforder_packets));
                     }
                 }
 
                 if (sp->diskfile_fd >= 0) {
                     if (fstat(sp->diskfile_fd, &sb) == 0) {
                         /* In the odd case that it's a zero-sized file, say it was all transferred. */
                         int percent_sent = 100, percent_received = 100;
                         if (sb.st_size > 0) {
                             percent_sent = (int) ( ( (double) bytes_sent / (double) sb.st_size ) * 100.0 );
                             percent_received = (int) ( ( (double) bytes_received / (double) sb.st_size ) * 100.0 );
                         }
                         unit_snprintf(sbuf, UNIT_LEN, (double) sb.st_size, 'A');
                         if (test->json_output)
                             cJSON_AddItemToObject(json_summary_stream, "diskfile", iperf_json_printf("sent: %d  received: %d  size: %d  percent_sent: %d  percent_received: %d  filename: %s", (int64_t) bytes_sent, (int64_t) bytes_received, (int64_t) sb.st_size, (int64_t) percent_sent, (int64_t) percent_received, test->diskfile_name));
                         else
                             if (stream_must_be_sender) {
                                 iperf_printf(test, report_diskfile, ubuf, sbuf, percent_sent, test->diskfile_name);
                             }
                             else {
                                 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
                                 iperf_printf(test, report_diskfile, ubuf, sbuf, percent_received, test->diskfile_name);
                             }
                     }
                 }
 
                 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
                 if (receiver_time > 0) {
                     bandwidth = (double) bytes_received / (double) receiver_time;
                 }
                 else {
                     bandwidth = 0.0;
                 }
                 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
                 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                     /* Receiver summary, TCP and SCTP */
                     if (test->json_output)
                         cJSON_AddItemToObject(json_summary_stream, "receiver", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f sender: %b", (int64_t) sp->socket, (double) start_time, (double) receiver_time, (double) end_time, (int64_t) bytes_received, bandwidth * 8, stream_must_be_sender));
                     else
                         if (test->role == 's' && sp->sender) {
                             if (test->verbose)
                                 iperf_printf(test, report_receiver_not_available_format, sp->socket);
                         }
                         else {
                             iperf_printf(test, report_bw_format, sp->socket, mbuf, start_time, receiver_time, ubuf, nbuf, report_receiver);
                         }
                 }
                 else {
                     /*
                      * Receiver summary, UDP.  Note that JSON was emitted with
                      * the sender summary, so we only deal with human-readable
                      * data here.
                      */
                     if (! test->json_output) {
                         if (receiver_packet_count - sp->omitted_packet_count > 0) {
                             lost_percent = 100.0 * (sp->cnt_error - sp->omitted_cnt_error) / (receiver_packet_count - sp->omitted_packet_count);
                         }
                         else {
                             lost_percent = 0.0;
                         }
 
                         if (test->role == 's' && sp->sender) {
                             if (test->verbose)
                                 iperf_printf(test, report_receiver_not_available_format, sp->socket);
                         }
                         else {
                             iperf_printf(test, report_bw_udp_format, sp->socket, mbuf, start_time, receiver_time, ubuf, nbuf, sp->jitter * 1000.0, (sp->cnt_error - sp->omitted_cnt_error), (receiver_packet_count - sp->omitted_packet_count), lost_percent, report_receiver);
                         }
                     }
                 }
             }
         }
         }
 
         if (test->num_streams > 1 || test->json_output) {
             unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');
             /* If no tests were run, arbitrarily set bandwidth to 0. */
             if (sender_time > 0.0) {
                 bandwidth = (double) total_sent / (double) sender_time;
             }
             else {
                 bandwidth = 0.0;
             }
             unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);              unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
            if (test->json_output)            if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                cJSON_AddItemToObject(test->json_end, "sum_received", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_received, bandwidth * 8));                if (test->sender_has_retransmits) {
            else                    /* Summary sum, TCP with retransmits. */
                iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, report_receiver);                    if (test->json_output)
        } else {                        cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d sender: %b", (double) start_time, (double) sender_time, (double) sender_time, (int64_t) total_sent, bandwidth * 8, (int64_t) total_retransmits, stream_must_be_sender));
            /* Summary sum, UDP. */                    else
            avg_jitter /= test->num_streams;                        if (test->role == 's' && !stream_must_be_sender) {
            /* If no packets were sent, arbitrarily set loss percentage to 0. */                            if (test->verbose)
            if (total_packets > 0) {                                iperf_printf(test, report_sender_not_available_summary_format, "SUM");
                lost_percent = 100.0 * lost_packets / total_packets;                        }
            }                        else {
            else {                          iperf_printf(test, report_sum_bw_retrans_format, mbuf, start_time, sender_time, ubuf, nbuf, total_retransmits, report_sender);
                lost_percent = 0.0;                        }
            }                } else {
            if (test->json_output)                    /* Summary sum, TCP without retransmits. */
                cJSON_AddItemToObject(test->json_end, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  jitter_ms: %f  lost_packets: %d  packets: %d  lost_percent: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) total_packets, (double) lost_percent));                    if (test->json_output)
            else                        cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f sender: %b", (double) start_time, (double) sender_time, (double) sender_time, (int64_t) total_sent, bandwidth * 8, stream_must_be_sender));
                iprintf(test, report_sum_bw_udp_format, start_time, end_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, total_packets, lost_percent, "");                    else
                         if (test->role == 's' && !stream_must_be_sender) {
                             if (test->verbose)
                                 iperf_printf(test, report_sender_not_available_summary_format, "SUM");
                         }
                         else {
                             iperf_printf(test, report_sum_bw_format, mbuf, start_time, sender_time, ubuf, nbuf, report_sender);
                         }
                 }
                 unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A');
                 /* If no tests were run, set received bandwidth to 0 */
                 if (receiver_time > 0.0) {
                     bandwidth = (double) total_received / (double) receiver_time;
                 }
                 else {
                     bandwidth = 0.0;
                 }
                 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
                 if (test->json_output)
                     cJSON_AddItemToObject(test->json_end, "sum_received", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f sender: %b", (double) start_time, (double) receiver_time, (double) receiver_time, (int64_t) total_received, bandwidth * 8, stream_must_be_sender));
                 else
                     if (test->role == 's' && stream_must_be_sender) {
                         if (test->verbose)
                             iperf_printf(test, report_receiver_not_available_summary_format, "SUM");
                     }
                     else {
                         iperf_printf(test, report_sum_bw_format, mbuf, start_time, receiver_time, ubuf, nbuf, report_receiver);
                     }
             } else {
                 /* Summary sum, UDP. */
                 avg_jitter /= test->num_streams;
                 /* If no packets were sent, arbitrarily set loss percentage to 0. */
                 if (total_packets > 0) {
                     lost_percent = 100.0 * lost_packets / total_packets;
                 }
                 else {
                     lost_percent = 0.0;
                 }
                 if (test->json_output)
                     cJSON_AddItemToObject(test->json_end, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  jitter_ms: %f  lost_packets: %d  packets: %d  lost_percent: %f sender: %b", (double) start_time, (double) receiver_time, (double) receiver_time, (int64_t) total_sent, bandwidth * 8, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) total_packets, (double) lost_percent, stream_must_be_sender));
                 else {
                     /*
                      * On the client we have both sender and receiver overall summary
                      * stats.  On the server we have only the side that was on the
                      * server.  Output whatever we have.
                      */
                     if (! (test->role == 's' && !stream_must_be_sender) ) {
                         unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');
                         iperf_printf(test, report_sum_bw_udp_format, mbuf, start_time, sender_time, ubuf, nbuf, 0.0, 0, sender_total_packets, 0.0, "sender");
                     }
                     if (! (test->role == 's' && stream_must_be_sender) ) {
 
                         unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A');
                         /* Compute received bandwidth. */
                         if (end_time > 0.0) {
                             bandwidth = (double) total_received / (double) receiver_time;
                         }
                         else {
                             bandwidth = 0.0;
                         }
                         unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
                         iperf_printf(test, report_sum_bw_udp_format, mbuf, start_time, receiver_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, receiver_total_packets, lost_percent, "receiver");
                     }
                 }
             }
         }          }
     }  
   
    if (test->json_output)        if (test->json_output && current_mode == upper_mode) {
        cJSON_AddItemToObject(test->json_end, "cpu_utilization_percent", iperf_json_printf("host_total: %f  host_user: %f  host_system: %f  remote_total: %f  remote_user: %f  remote_system: %f", (double) test->cpu_util[0], (double) test->cpu_util[1], (double) test->cpu_util[2], (double) test->remote_cpu_util[0], (double) test->remote_cpu_util[1], (double) test->remote_cpu_util[2]));            cJSON_AddItemToObject(test->json_end, "cpu_utilization_percent", iperf_json_printf("host_total: %f  host_user: %f  host_system: %f  remote_total: %f  remote_user: %f  remote_system: %f", (double) test->cpu_util[0], (double) test->cpu_util[1], (double) test->cpu_util[2], (double) test->remote_cpu_util[0], (double) test->remote_cpu_util[1], (double) test->remote_cpu_util[2]));
    else {            if (test->protocol->id == Ptcp) {
        if (test->verbose) {                char *snd_congestion = NULL, *rcv_congestion = NULL;
            iprintf(test, report_cpu, report_local, test->sender?report_sender:report_receiver, test->cpu_util[0], test->cpu_util[1], test->cpu_util[2], report_remote, test->sender?report_receiver:report_sender, test->remote_cpu_util[0], test->remote_cpu_util[1], test->remote_cpu_util[2]);                if (stream_must_be_sender) {
        }                    snd_congestion = test->congestion_used;
                     rcv_congestion = test->remote_congestion_used;
                 }
                 else {
                     snd_congestion = test->remote_congestion_used;
                     rcv_congestion = test->congestion_used;
                 }
                 if (snd_congestion) {
                     cJSON_AddStringToObject(test->json_end, "sender_tcp_congestion", snd_congestion);
                 }
                 if (rcv_congestion) {
                     cJSON_AddStringToObject(test->json_end, "receiver_tcp_congestion", rcv_congestion);
                 }
             }
         }
         else {
             if (test->verbose) {
                 if (stream_must_be_sender) {
                     if (test->bidirectional) {
                         iperf_printf(test, report_cpu, report_local, stream_must_be_sender?report_sender:report_receiver, test->cpu_util[0], test->cpu_util[1], test->cpu_util[2], report_remote, stream_must_be_sender?report_receiver:report_sender, test->remote_cpu_util[0], test->remote_cpu_util[1], test->remote_cpu_util[2]);
                         iperf_printf(test, report_cpu, report_local, !stream_must_be_sender?report_sender:report_receiver, test->cpu_util[0], test->cpu_util[1], test->cpu_util[2], report_remote, !stream_must_be_sender?report_receiver:report_sender, test->remote_cpu_util[0], test->remote_cpu_util[1], test->remote_cpu_util[2]);
                     } else
                         iperf_printf(test, report_cpu, report_local, stream_must_be_sender?report_sender:report_receiver, test->cpu_util[0], test->cpu_util[1], test->cpu_util[2], report_remote, stream_must_be_sender?report_receiver:report_sender, test->remote_cpu_util[0], test->remote_cpu_util[1], test->remote_cpu_util[2]);
                 }
                 if (test->protocol->id == Ptcp) {
                     char *snd_congestion = NULL, *rcv_congestion = NULL;
                     if (stream_must_be_sender) {
                         snd_congestion = test->congestion_used;
                         rcv_congestion = test->remote_congestion_used;
                     }
                     else {
                         snd_congestion = test->remote_congestion_used;
                         rcv_congestion = test->congestion_used;
                     }
                     if (snd_congestion) {
                         iperf_printf(test, "snd_tcp_congestion %s\n", snd_congestion);
                     }
                     if (rcv_congestion) {
                         iperf_printf(test, "rcv_tcp_congestion %s\n", rcv_congestion);
                     }
                 }
             }
   
        /* Print server output if we're on the client and it was requested/provided */            /* Print server output if we're on the client and it was requested/provided */
        if (test->role == 'c' && iperf_get_test_get_server_output(test)) {            if (test->role == 'c' && iperf_get_test_get_server_output(test) && !test->json_output) {
            if (test->json_server_output) {                if (test->json_server_output) {
                iprintf(test, "\nServer JSON output:\n%s\n", cJSON_Print(test->json_server_output));                    char *str = cJSON_Print(test->json_server_output);
                cJSON_Delete(test->json_server_output);                    iperf_printf(test, "\nServer JSON output:\n%s\n", str);
                test->json_server_output = NULL;                    cJSON_free(str);
            }                    cJSON_Delete(test->json_server_output);
            if (test->server_output_text) {                    test->json_server_output = NULL;
                iprintf(test, "\nServer output:\n%s\n", test->server_output_text);                }
                test->server_output_text = NULL;                if (test->server_output_text) {
            }                    iperf_printf(test, "\nServer output:\n%s\n", test->server_output_text);
        }                    test->server_output_text = NULL;
                 }
             }
         }
     }      }
   
       /* Set real sender_has_retransmits for current side */
       if (test->mode == BIDIRECTIONAL)
           test->sender_has_retransmits = tmp_sender_has_retransmits;
 }  }
   
 /**************************************************************************/  /**************************************************************************/
Line 2551  print_interval_results(struct iperf_test *test, struct Line 3689  print_interval_results(struct iperf_test *test, struct
     char ubuf[UNIT_LEN];      char ubuf[UNIT_LEN];
     char nbuf[UNIT_LEN];      char nbuf[UNIT_LEN];
     char cbuf[UNIT_LEN];      char cbuf[UNIT_LEN];
       char mbuf[UNIT_LEN];
       char zbuf[] = "          ";
     double st = 0., et = 0.;      double st = 0., et = 0.;
       struct iperf_time temp_time;
     struct iperf_interval_results *irp = NULL;      struct iperf_interval_results *irp = NULL;
     double bandwidth, lost_percent;      double bandwidth, lost_percent;
   
       if (test->mode == BIDIRECTIONAL) {
           sprintf(mbuf, "[%s-%s]", sp->sender?"TX":"RX", test->role == 'c'?"C":"S");
       } else {
           mbuf[0] = '\0';
           zbuf[0] = '\0';
       }
   
     irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* get last entry in linked list */      irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* get last entry in linked list */
     if (irp == NULL) {      if (irp == NULL) {
         iperf_err(test, "print_interval_results error: interval_results is NULL");          iperf_err(test, "print_interval_results error: interval_results is NULL");
Line 2567  print_interval_results(struct iperf_test *test, struct Line 3715  print_interval_results(struct iperf_test *test, struct
             ** else if there's more than one stream, print the separator;              ** else if there's more than one stream, print the separator;
             ** else nothing.              ** else nothing.
             */              */
            if (timeval_equals(&sp->result->start_time, &irp->interval_start_time)) {            if (iperf_time_compare(&sp->result->start_time, &irp->interval_start_time) == 0) {
                 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {                  if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                    if (test->sender && test->sender_has_retransmits)                    if (test->sender_has_retransmits == 1) {
                        iprintf(test, "%s", report_bw_retrans_cwnd_header);                        if (test->bidirectional)
                    else                            iperf_printf(test, "%s", report_bw_retrans_cwnd_header_bidir);
                        iprintf(test, "%s", report_bw_header);                        else
                             iperf_printf(test, "%s", report_bw_retrans_cwnd_header);
                     }
                     else {
                         if (test->bidirectional)
                             iperf_printf(test, "%s", report_bw_header_bidir);
                         else
                             iperf_printf(test, "%s", report_bw_header);
                     }
                 } else {                  } else {
                    if (test->sender)                    if (test->mode == SENDER) {
                        iprintf(test, "%s", report_bw_udp_sender_header);                        iperf_printf(test, "%s", report_bw_udp_sender_header);
                    else                    } else if (test->mode == RECEIVER){
                        iprintf(test, "%s", report_bw_udp_header);                        iperf_printf(test, "%s", report_bw_udp_header);
                     } else {
                         /* BIDIRECTIONAL */
                         iperf_printf(test, "%s", report_bw_udp_header_bidir);
                     }
                 }                  }
             } else if (test->num_streams > 1)              } else if (test->num_streams > 1)
                iprintf(test, "%s", report_bw_separator);                iperf_printf(test, "%s", report_bw_separator);
         }          }
     }      }
   
     unit_snprintf(ubuf, UNIT_LEN, (double) (irp->bytes_transferred), 'A');      unit_snprintf(ubuf, UNIT_LEN, (double) (irp->bytes_transferred), 'A');
    bandwidth = (double) irp->bytes_transferred / (double) irp->interval_duration;    if (irp->interval_duration > 0.0) {
         bandwidth = (double) irp->bytes_transferred / (double) irp->interval_duration;
     }
     else {
         bandwidth = 0.0;
     }
     unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);      unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
           
    st = timeval_diff(&sp->result->start_time, &irp->interval_start_time);    iperf_time_diff(&sp->result->start_time, &irp->interval_start_time, &temp_time);
    et = timeval_diff(&sp->result->start_time, &irp->interval_end_time);    st = iperf_time_in_secs(&temp_time);
     iperf_time_diff(&sp->result->start_time, &irp->interval_end_time, &temp_time);
     et = iperf_time_in_secs(&temp_time);
           
     if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {      if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
        if (test->sender && test->sender_has_retransmits) {        if (test->sender_has_retransmits == 1 && sp->sender) {
             /* Interval, TCP with retransmits. */              /* Interval, TCP with retransmits. */
             if (test->json_output)              if (test->json_output)
                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d  snd_cwnd:  %d  rtt:  %d  omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_retrans, (int64_t) irp->snd_cwnd, (int64_t) irp->rtt, irp->omitted));                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d  snd_cwnd:  %d  rtt:  %d  rttvar: %d  pmtu: %d  omitted: %b sender: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_retrans, (int64_t) irp->snd_cwnd, (int64_t) irp->rtt, (int64_t) irp->rttvar, (int64_t) irp->pmtu, irp->omitted, sp->sender));
             else {              else {
                 unit_snprintf(cbuf, UNIT_LEN, irp->snd_cwnd, 'A');                  unit_snprintf(cbuf, UNIT_LEN, irp->snd_cwnd, 'A');
                iprintf(test, report_bw_retrans_cwnd_format, sp->socket, st, et, ubuf, nbuf, irp->interval_retrans, cbuf, irp->omitted?report_omitted:"");                iperf_printf(test, report_bw_retrans_cwnd_format, sp->socket, mbuf, st, et, ubuf, nbuf, irp->interval_retrans, cbuf, irp->omitted?report_omitted:"");
             }              }
         } else {          } else {
             /* Interval, TCP without retransmits. */              /* Interval, TCP without retransmits. */
             if (test->json_output)              if (test->json_output)
                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, irp->omitted));                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  omitted: %b sender: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, irp->omitted, sp->sender));
             else              else
                iprintf(test, report_bw_format, sp->socket, st, et, ubuf, nbuf, irp->omitted?report_omitted:"");                iperf_printf(test, report_bw_format, sp->socket, mbuf, st, et, ubuf, nbuf, irp->omitted?report_omitted:"");
         }          }
     } else {      } else {
         /* Interval, UDP. */          /* Interval, UDP. */
        if (test->sender) {        if (sp->sender) {
             if (test->json_output)              if (test->json_output)
                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  packets: %d  omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_packet_count, irp->omitted));                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  packets: %d  omitted: %b sender: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_packet_count, irp->omitted, sp->sender));
             else              else
                iprintf(test, report_bw_udp_sender_format, sp->socket, st, et, ubuf, nbuf, irp->interval_packet_count, irp->omitted?report_omitted:"");                iperf_printf(test, report_bw_udp_sender_format, sp->socket, mbuf, st, et, ubuf, nbuf, zbuf, irp->interval_packet_count, irp->omitted?report_omitted:"");
         } else {          } else {
             if (irp->interval_packet_count > 0) {              if (irp->interval_packet_count > 0) {
                 lost_percent = 100.0 * irp->interval_cnt_error / irp->interval_packet_count;                  lost_percent = 100.0 * irp->interval_cnt_error / irp->interval_packet_count;
Line 2622  print_interval_results(struct iperf_test *test, struct Line 3789  print_interval_results(struct iperf_test *test, struct
                 lost_percent = 0.0;                  lost_percent = 0.0;
             }              }
             if (test->json_output)              if (test->json_output)
                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  jitter_ms: %f  lost_packets: %d  packets: %d  lost_percent: %f  omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (double) irp->jitter * 1000.0, (int64_t) irp->interval_cnt_error, (int64_t) irp->interval_packet_count, (double) lost_percent, irp->omitted));                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  jitter_ms: %f  lost_packets: %d  packets: %d  lost_percent: %f  omitted: %b sender: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (double) irp->jitter * 1000.0, (int64_t) irp->interval_cnt_error, (int64_t) irp->interval_packet_count, (double) lost_percent, irp->omitted, sp->sender));
             else              else
                iprintf(test, report_bw_udp_format, sp->socket, st, et, ubuf, nbuf, irp->jitter * 1000.0, irp->interval_cnt_error, irp->interval_packet_count, lost_percent, irp->omitted?report_omitted:"");                iperf_printf(test, report_bw_udp_format, sp->socket, mbuf, st, et, ubuf, nbuf, irp->jitter * 1000.0, irp->interval_cnt_error, irp->interval_packet_count, lost_percent, irp->omitted?report_omitted:"");
         }          }
     }      }
   
    if (test->logfile)    if (test->logfile || test->forceflush)
         iflush(test);          iflush(test);
 }  }
   
Line 2655  iperf_free_stream(struct iperf_stream *sp) Line 3822  iperf_free_stream(struct iperf_stream *sp)
   
 /**************************************************************************/  /**************************************************************************/
 struct iperf_stream *  struct iperf_stream *
iperf_new_stream(struct iperf_test *test, int s)iperf_new_stream(struct iperf_test *test, int s, int sender)
 {  {
     int i;  
     struct iperf_stream *sp;      struct iperf_stream *sp;
        int ret = 0;
 
     char template[1024];      char template[1024];
     if (test->tmp_template) {      if (test->tmp_template) {
         snprintf(template, sizeof(template) / sizeof(char), "%s", test->tmp_template);          snprintf(template, sizeof(template) / sizeof(char), "%s", test->tmp_template);
     } else {      } else {
        char buf[] = "/tmp/iperf3.XXXXXX";        //find the system temporary dir *unix, windows, cygwin support
        snprintf(template, sizeof(template) / sizeof(char), "%s", buf);        char* tempdir = getenv("TMPDIR");
         if (tempdir == 0){
             tempdir = getenv("TEMP");
         }
         if (tempdir == 0){
             tempdir = getenv("TMP");
         }
         if (tempdir == 0){
             tempdir = "/tmp";
         }
         snprintf(template, sizeof(template) / sizeof(char), "%s/iperf3.XXXXXX", tempdir);
     }      }
   
     h_errno = 0;  
   
     sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream));      sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream));
     if (!sp) {      if (!sp) {
         i_errno = IECREATESTREAM;          i_errno = IECREATESTREAM;
Line 2678  iperf_new_stream(struct iperf_test *test, int s) Line 3853  iperf_new_stream(struct iperf_test *test, int s)
   
     memset(sp, 0, sizeof(struct iperf_stream));      memset(sp, 0, sizeof(struct iperf_stream));
   
       sp->sender = sender;
     sp->test = test;      sp->test = test;
     sp->settings = test->settings;      sp->settings = test->settings;
     sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));      sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));
Line 2717  iperf_new_stream(struct iperf_test *test, int s) Line 3893  iperf_new_stream(struct iperf_test *test, int s)
         free(sp);          free(sp);
         return NULL;          return NULL;
     }      }
     srandom(time(NULL));  
     for (i = 0; i < test->settings->blksize; ++i)  
         sp->buffer[i] = random();  
   
     /* Set socket */      /* Set socket */
     sp->socket = s;      sp->socket = s;
Line 2728  iperf_new_stream(struct iperf_test *test, int s) Line 3901  iperf_new_stream(struct iperf_test *test, int s)
     sp->rcv = test->protocol->recv;      sp->rcv = test->protocol->recv;
   
     if (test->diskfile_name != (char*) 0) {      if (test->diskfile_name != (char*) 0) {
        sp->diskfile_fd = open(test->diskfile_name, test->sender ? O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC), S_IRUSR|S_IWUSR);        sp->diskfile_fd = open(test->diskfile_name, sender ? O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC), S_IRUSR|S_IWUSR);
         if (sp->diskfile_fd == -1) {          if (sp->diskfile_fd == -1) {
             i_errno = IEFILE;              i_errno = IEFILE;
             munmap(sp->buffer, sp->test->settings->blksize);              munmap(sp->buffer, sp->test->settings->blksize);
Line 2744  iperf_new_stream(struct iperf_test *test, int s) Line 3917  iperf_new_stream(struct iperf_test *test, int s)
         sp->diskfile_fd = -1;          sp->diskfile_fd = -1;
   
     /* Initialize stream */      /* Initialize stream */
    if (iperf_init_stream(sp, test) < 0) {    if (test->repeating_payload)
         fill_with_repeating_pattern(sp->buffer, test->settings->blksize);
     else
         ret = readentropy(sp->buffer, test->settings->blksize);
 
     if ((ret < 0) || (iperf_init_stream(sp, test) < 0)) {
         close(sp->buffer_fd);          close(sp->buffer_fd);
         munmap(sp->buffer, sp->test->settings->blksize);          munmap(sp->buffer, sp->test->settings->blksize);
         free(sp->result);          free(sp->result);
Line 2831  static int Line 4009  static int
 diskfile_send(struct iperf_stream *sp)  diskfile_send(struct iperf_stream *sp)
 {  {
     int r;      int r;
       static int rtot;
   
    r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize);    /* if needed, read enough data from the disk to fill up the buffer */
    if (r == 0)    if (sp->diskfile_left < sp->test->settings->blksize && !sp->test->done) {
        sp->test->done = 1;        r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize -
    else                 sp->diskfile_left);
        r = sp->snd2(sp);        rtot += r;
         if (sp->test->debug) {
             printf("read %d bytes from file, %d total\n", r, rtot);
             if (r != sp->test->settings->blksize - sp->diskfile_left)
                 printf("possible eof\n");
         }
         /* If there's no data left in the file or in the buffer, we're done */
         if (r == 0 && sp->diskfile_left == 0) {
             sp->test->done = 1;
             if (sp->test->debug)
                 printf("done\n");
         }
     }
 
     r = sp->snd2(sp);
     if (r < 0) {
         return r;
     }
     /*
      * Compute how much data is in the buffer but didn't get sent.
      * If there are bytes that got left behind, slide them to the
      * front of the buffer so they can hopefully go out on the next
      * pass.
      */
     sp->diskfile_left = sp->test->settings->blksize - r;
     if (sp->diskfile_left && sp->diskfile_left < sp->test->settings->blksize) {
         memcpy(sp->buffer,
                sp->buffer + (sp->test->settings->blksize - sp->diskfile_left),
                sp->diskfile_left);
         if (sp->test->debug)
             printf("Shifting %d bytes by %d\n", sp->diskfile_left, (sp->test->settings->blksize - sp->diskfile_left));
     }
     return r;      return r;
 }  }
   
Line 2857  diskfile_recv(struct iperf_stream *sp) Line 4067  diskfile_recv(struct iperf_stream *sp)
 void  void
 iperf_catch_sigend(void (*handler)(int))  iperf_catch_sigend(void (*handler)(int))
 {  {
   #ifdef SIGINT
     signal(SIGINT, handler);      signal(SIGINT, handler);
   #endif
   #ifdef SIGTERM
     signal(SIGTERM, handler);      signal(SIGTERM, handler);
   #endif
   #ifdef SIGHUP
     signal(SIGHUP, handler);      signal(SIGHUP, handler);
   #endif
 }  }
   
 /**  /**
Line 2902  iperf_create_pidfile(struct iperf_test *test) Line 4118  iperf_create_pidfile(struct iperf_test *test)
     if (test->pidfile) {      if (test->pidfile) {
         int fd;          int fd;
         char buf[8];          char buf[8];
   
           /* See if the file already exists and we can read it. */
           fd = open(test->pidfile, O_RDONLY, 0);
           if (fd >= 0) {
               if (read(fd, buf, sizeof(buf) - 1) >= 0) {
   
                   /* We read some bytes, see if they correspond to a valid PID */
                   pid_t pid;
                   pid = atoi(buf);
                   if (pid > 0) {
   
                       /* See if the process exists. */
                       if (kill(pid, 0) == 0) {
                           /*
                            * Make sure not to try to delete existing PID file by
                            * scribbling over the pathname we'd use to refer to it.
                            * Then exit with an error.
                            */
                           free(test->pidfile);
                           test->pidfile = NULL;
                           iperf_errexit(test, "Another instance of iperf3 appears to be running");
                       }
                   }
               }
           }
           
           /*
            * File didn't exist, we couldn't read it, or it didn't correspond to 
            * a running process.  Try to create it. 
            */
         fd = open(test->pidfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR|S_IWUSR);          fd = open(test->pidfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR|S_IWUSR);
         if (fd < 0) {          if (fd < 0) {
             return -1;              return -1;
Line 2959  iperf_json_finish(struct iperf_test *test) Line 4205  iperf_json_finish(struct iperf_test *test)
 {  {
     if (test->title)      if (test->title)
         cJSON_AddStringToObject(test->json_top, "title", test->title);          cJSON_AddStringToObject(test->json_top, "title", test->title);
       if (test->extra_data)
           cJSON_AddStringToObject(test->json_top, "extra_data", test->extra_data);
     /* Include server output */      /* Include server output */
     if (test->json_server_output) {      if (test->json_server_output) {
         cJSON_AddItemToObject(test->json_top, "server_output_json", test->json_server_output);          cJSON_AddItemToObject(test->json_top, "server_output_json", test->json_server_output);
Line 2971  iperf_json_finish(struct iperf_test *test) Line 4219  iperf_json_finish(struct iperf_test *test)
         return -1;          return -1;
     fprintf(test->outfile, "%s\n", test->json_output_string);      fprintf(test->outfile, "%s\n", test->json_output_string);
     iflush(test);      iflush(test);
       cJSON_free(test->json_output_string);
       test->json_output_string = NULL;
     cJSON_Delete(test->json_top);      cJSON_Delete(test->json_top);
     test->json_top = test->json_start = test->json_connected = test->json_intervals = test->json_server_output = test->json_end = NULL;      test->json_top = test->json_start = test->json_connected = test->json_intervals = test->json_server_output = test->json_end = NULL;
     return 0;      return 0;
 }  }
   
   
/* CPU affinity stuff - Linux and FreeBSD only. *//* CPU affinity stuff - Linux, FreeBSD, and Windows only. */
   
 int  int
 iperf_setaffinity(struct iperf_test *test, int affinity)  iperf_setaffinity(struct iperf_test *test, int affinity)
Line 3010  iperf_setaffinity(struct iperf_test *test, int affinit Line 4260  iperf_setaffinity(struct iperf_test *test, int affinit
         return -1;          return -1;
     }      }
     return 0;      return 0;
#else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */#elif defined(HAVE_SETPROCESSAFFINITYMASK)
         HANDLE process = GetCurrentProcess();
         DWORD_PTR processAffinityMask = 1 << affinity;
 
         if (SetProcessAffinityMask(process, processAffinityMask) == 0) {
                 i_errno = IEAFFINITY;
                 return -1;
         }
         return 0;
 #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
     i_errno = IEAFFINITY;      i_errno = IEAFFINITY;
     return -1;      return -1;
#endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */#endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
 }  }
   
 int  int
Line 3038  iperf_clearaffinity(struct iperf_test *test) Line 4297  iperf_clearaffinity(struct iperf_test *test)
         return -1;          return -1;
     }      }
     return 0;      return 0;
#else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */#elif defined(HAVE_SETPROCESSAFFINITYMASK)
         HANDLE process = GetCurrentProcess();
         DWORD_PTR processAffinityMask;
         DWORD_PTR lpSystemAffinityMask;
 
         if (GetProcessAffinityMask(process, &processAffinityMask, &lpSystemAffinityMask) == 0
                         || SetProcessAffinityMask(process, lpSystemAffinityMask) == 0) {
                 i_errno = IEAFFINITY;
                 return -1;
         }
         return 0;
 #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
     i_errno = IEAFFINITY;      i_errno = IEAFFINITY;
     return -1;      return -1;
#endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */#endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
 }  }
   
   char iperf_timestr[100];
   
 int  int
iprintf(struct iperf_test *test, const char* format, ...)iperf_printf(struct iperf_test *test, const char* format, ...)
 {  {
     va_list argp;      va_list argp;
     int r = -1;      int r = -1;
       time_t now;
       struct tm *ltm = NULL;
       char *ct = NULL;
   
       /* Timestamp if requested */
       if (iperf_get_test_timestamps(test)) {
           time(&now);
           ltm = localtime(&now);
           strftime(iperf_timestr, sizeof(iperf_timestr), iperf_get_test_timestamp_format(test), ltm);
           ct = iperf_timestr;
       }
   
     /*      /*
      * There are roughly two use cases here.  If we're the client,       * There are roughly two use cases here.  If we're the client,
      * want to print stuff directly to the output stream.       * want to print stuff directly to the output stream.
Line 3063  iprintf(struct iperf_test *test, const char* format, . Line 4346  iprintf(struct iperf_test *test, const char* format, .
      * to be buffered up anyway.       * to be buffered up anyway.
      */       */
     if (test->role == 'c') {      if (test->role == 'c') {
           if (ct) {
               fprintf(test->outfile, "%s", ct);
           }
         if (test->title)          if (test->title)
             fprintf(test->outfile, "%s:  ", test->title);              fprintf(test->outfile, "%s:  ", test->title);
         va_start(argp, format);          va_start(argp, format);
Line 3071  iprintf(struct iperf_test *test, const char* format, . Line 4357  iprintf(struct iperf_test *test, const char* format, .
     }      }
     else if (test->role == 's') {      else if (test->role == 's') {
         char linebuffer[1024];          char linebuffer[1024];
           int i = 0;
           if (ct) {
               i = sprintf(linebuffer, "%s", ct);
           }
         va_start(argp, format);          va_start(argp, format);
        r = vsnprintf(linebuffer, sizeof(linebuffer), format, argp);        r = vsnprintf(linebuffer + i, sizeof(linebuffer), format, argp);
         va_end(argp);          va_end(argp);
         fprintf(test->outfile, "%s", linebuffer);          fprintf(test->outfile, "%s", linebuffer);
   

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>