File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / iperf / src / iperf_api.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:14:54 2023 UTC (9 months, 1 week ago) by misho
Branches: iperf, MAIN
CVS tags: v3_15, HEAD
Version 3.15

    1: /*
    2:  * iperf, Copyright (c) 2014-2022, The Regents of the University of
    3:  * California, through Lawrence Berkeley National Laboratory (subject
    4:  * to receipt of any required approvals from the U.S. Dept. of
    5:  * Energy).  All rights reserved.
    6:  *
    7:  * If you have questions about your rights to use or distribute this
    8:  * software, please contact Berkeley Lab's Technology Transfer
    9:  * Department at TTD@lbl.gov.
   10:  *
   11:  * NOTICE.  This software is owned by the U.S. Department of Energy.
   12:  * As such, the U.S. Government has been granted for itself and others
   13:  * acting on its behalf a paid-up, nonexclusive, irrevocable,
   14:  * worldwide license in the Software to reproduce, prepare derivative
   15:  * works, and perform publicly and display publicly.  Beginning five
   16:  * (5) years after the date permission to assert copyright is obtained
   17:  * from the U.S. Department of Energy, and subject to any subsequent
   18:  * five (5) year renewals, the U.S. Government is granted for itself
   19:  * and others acting on its behalf a paid-up, nonexclusive,
   20:  * irrevocable, worldwide license in the Software to reproduce,
   21:  * prepare derivative works, distribute copies to the public, perform
   22:  * publicly and display publicly, and to permit others to do so.
   23:  *
   24:  * This code is distributed under a BSD style license, see the LICENSE file
   25:  * for complete information.
   26:  */
   27: #ifndef _GNU_SOURCE
   28: # define _GNU_SOURCE
   29: #endif
   30: #define __USE_GNU
   31: 
   32: #include "iperf_config.h"
   33: 
   34: #include <stdio.h>
   35: #include <stdlib.h>
   36: #include <string.h>
   37: #include <time.h>
   38: #include <getopt.h>
   39: #include <errno.h>
   40: #include <signal.h>
   41: #include <unistd.h>
   42: #include <assert.h>
   43: #include <fcntl.h>
   44: #include <sys/socket.h>
   45: #include <sys/types.h>
   46: #include <netinet/in.h>
   47: #include <arpa/inet.h>
   48: #include <netdb.h>
   49: #ifdef HAVE_STDINT_H
   50: #include <stdint.h>
   51: #endif
   52: #include <sys/time.h>
   53: #include <sys/resource.h>
   54: #include <sys/mman.h>
   55: #include <sys/stat.h>
   56: #include <sched.h>
   57: #include <setjmp.h>
   58: #include <stdarg.h>
   59: #include <math.h>
   60: 
   61: #if defined(HAVE_CPUSET_SETAFFINITY)
   62: #include <sys/param.h>
   63: #include <sys/cpuset.h>
   64: #endif /* HAVE_CPUSET_SETAFFINITY */
   65: 
   66: #if defined(__CYGWIN__) || defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__)
   67: #define CPU_SETSIZE __CPU_SETSIZE
   68: #endif /* __CYGWIN__, _WIN32, _WIN64, __WINDOWS__ */
   69: 
   70: #if defined(HAVE_SETPROCESSAFFINITYMASK)
   71: #include <Windows.h>
   72: #endif /* HAVE_SETPROCESSAFFINITYMASK */
   73: 
   74: #include "net.h"
   75: #include "iperf.h"
   76: #include "iperf_api.h"
   77: #include "iperf_udp.h"
   78: #include "iperf_tcp.h"
   79: #if defined(HAVE_SCTP_H)
   80: #include "iperf_sctp.h"
   81: #endif /* HAVE_SCTP_H */
   82: #include "timer.h"
   83: 
   84: #include "cjson.h"
   85: #include "units.h"
   86: #include "iperf_util.h"
   87: #include "iperf_locale.h"
   88: #include "version.h"
   89: #if defined(HAVE_SSL)
   90: #include <openssl/bio.h>
   91: #include <openssl/err.h>
   92: #include "iperf_auth.h"
   93: #endif /* HAVE_SSL */
   94: 
   95: /* Forwards. */
   96: static int send_parameters(struct iperf_test *test);
   97: static int get_parameters(struct iperf_test *test);
   98: static int send_results(struct iperf_test *test);
   99: static int get_results(struct iperf_test *test);
  100: static int diskfile_send(struct iperf_stream *sp);
  101: static int diskfile_recv(struct iperf_stream *sp);
  102: static int JSON_write(int fd, cJSON *json);
  103: static void print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams);
  104: static cJSON *JSON_read(int fd);
  105: 
  106: 
  107: /*************************** Print usage functions ****************************/
  108: 
  109: void
  110: usage()
  111: {
  112:     fputs(usage_shortstr, stderr);
  113: }
  114: 
  115: 
  116: void
  117: usage_long(FILE *f)
  118: {
  119:     fprintf(f, usage_longstr, DEFAULT_NO_MSG_RCVD_TIMEOUT, UDP_RATE / (1024*1024), DEFAULT_PACING_TIMER, DURATION, DEFAULT_TCP_BLKSIZE / 1024, DEFAULT_UDP_BLKSIZE);
  120: }
  121: 
  122: 
  123: void warning(const char *str)
  124: {
  125:     fprintf(stderr, "warning: %s\n", str);
  126: }
  127: 
  128: 
  129: /************** Getter routines for some fields inside iperf_test *************/
  130: 
  131: int
  132: iperf_get_verbose(struct iperf_test *ipt)
  133: {
  134:     return ipt->verbose;
  135: }
  136: 
  137: int
  138: iperf_get_control_socket(struct iperf_test *ipt)
  139: {
  140:     return ipt->ctrl_sck;
  141: }
  142: 
  143: int
  144: iperf_get_control_socket_mss(struct iperf_test *ipt)
  145: {
  146:     return ipt->ctrl_sck_mss;
  147: }
  148: 
  149: int
  150: iperf_get_test_omit(struct iperf_test *ipt)
  151: {
  152:     return ipt->omit;
  153: }
  154: 
  155: int
  156: iperf_get_test_duration(struct iperf_test *ipt)
  157: {
  158:     return ipt->duration;
  159: }
  160: 
  161: uint64_t
  162: iperf_get_test_rate(struct iperf_test *ipt)
  163: {
  164:     return ipt->settings->rate;
  165: }
  166: 
  167: uint64_t
  168: iperf_get_test_bitrate_limit(struct iperf_test *ipt)
  169: {
  170:     return ipt->settings->bitrate_limit;
  171: }
  172: 
  173: double
  174: iperf_get_test_bitrate_limit_interval(struct iperf_test *ipt)
  175: {
  176:     return ipt->settings->bitrate_limit_interval;
  177: }
  178: 
  179: int
  180: iperf_get_test_bitrate_limit_stats_per_interval(struct iperf_test *ipt)
  181: {
  182:     return ipt->settings->bitrate_limit_stats_per_interval;
  183: }
  184: 
  185: uint64_t
  186: iperf_get_test_fqrate(struct iperf_test *ipt)
  187: {
  188:     return ipt->settings->fqrate;
  189: }
  190: 
  191: int
  192: iperf_get_test_pacing_timer(struct iperf_test *ipt)
  193: {
  194:     return ipt->settings->pacing_timer;
  195: }
  196: 
  197: uint64_t
  198: iperf_get_test_bytes(struct iperf_test *ipt)
  199: {
  200:     return (uint64_t) ipt->settings->bytes;
  201: }
  202: 
  203: uint64_t
  204: iperf_get_test_blocks(struct iperf_test *ipt)
  205: {
  206:     return (uint64_t) ipt->settings->blocks;
  207: }
  208: 
  209: int
  210: iperf_get_test_burst(struct iperf_test *ipt)
  211: {
  212:     return ipt->settings->burst;
  213: }
  214: 
  215: char
  216: iperf_get_test_role(struct iperf_test *ipt)
  217: {
  218:     return ipt->role;
  219: }
  220: 
  221: int
  222: iperf_get_test_reverse(struct iperf_test *ipt)
  223: {
  224:     return ipt->reverse;
  225: }
  226: 
  227: int
  228: iperf_get_test_bidirectional(struct iperf_test *ipt)
  229: {
  230:     return ipt->bidirectional;
  231: }
  232: 
  233: int
  234: iperf_get_test_blksize(struct iperf_test *ipt)
  235: {
  236:     return ipt->settings->blksize;
  237: }
  238: 
  239: FILE *
  240: iperf_get_test_outfile (struct iperf_test *ipt)
  241: {
  242:     return ipt->outfile;
  243: }
  244: 
  245: int
  246: iperf_get_test_socket_bufsize(struct iperf_test *ipt)
  247: {
  248:     return ipt->settings->socket_bufsize;
  249: }
  250: 
  251: double
  252: iperf_get_test_reporter_interval(struct iperf_test *ipt)
  253: {
  254:     return ipt->reporter_interval;
  255: }
  256: 
  257: double
  258: iperf_get_test_stats_interval(struct iperf_test *ipt)
  259: {
  260:     return ipt->stats_interval;
  261: }
  262: 
  263: int
  264: iperf_get_test_num_streams(struct iperf_test *ipt)
  265: {
  266:     return ipt->num_streams;
  267: }
  268: 
  269: int
  270: iperf_get_test_timestamps(struct iperf_test *ipt)
  271: {
  272:     return ipt->timestamps;
  273: }
  274: 
  275: const char *
  276: iperf_get_test_timestamp_format(struct iperf_test *ipt)
  277: {
  278:     return ipt->timestamp_format;
  279: }
  280: 
  281: int
  282: iperf_get_test_repeating_payload(struct iperf_test *ipt)
  283: {
  284:     return ipt->repeating_payload;
  285: }
  286: 
  287: int
  288: iperf_get_test_bind_port(struct iperf_test *ipt)
  289: {
  290:     return ipt->bind_port;
  291: }
  292: 
  293: int
  294: iperf_get_test_server_port(struct iperf_test *ipt)
  295: {
  296:     return ipt->server_port;
  297: }
  298: 
  299: char*
  300: iperf_get_test_server_hostname(struct iperf_test *ipt)
  301: {
  302:     return ipt->server_hostname;
  303: }
  304: 
  305: char*
  306: iperf_get_test_template(struct iperf_test *ipt)
  307: {
  308:     return ipt->tmp_template;
  309: }
  310: 
  311: int
  312: iperf_get_test_protocol_id(struct iperf_test *ipt)
  313: {
  314:     return ipt->protocol->id;
  315: }
  316: 
  317: int
  318: iperf_get_test_json_output(struct iperf_test *ipt)
  319: {
  320:     return ipt->json_output;
  321: }
  322: 
  323: char *
  324: iperf_get_test_json_output_string(struct iperf_test *ipt)
  325: {
  326:     return ipt->json_output_string;
  327: }
  328: 
  329: int
  330: iperf_get_test_zerocopy(struct iperf_test *ipt)
  331: {
  332:     return ipt->zerocopy;
  333: }
  334: 
  335: int
  336: iperf_get_test_get_server_output(struct iperf_test *ipt)
  337: {
  338:     return ipt->get_server_output;
  339: }
  340: 
  341: char
  342: iperf_get_test_unit_format(struct iperf_test *ipt)
  343: {
  344:     return ipt->settings->unit_format;
  345: }
  346: 
  347: char *
  348: iperf_get_test_bind_address(struct iperf_test *ipt)
  349: {
  350:     return ipt->bind_address;
  351: }
  352: 
  353: char *
  354: iperf_get_test_bind_dev(struct iperf_test *ipt)
  355: {
  356:     return ipt->bind_dev;
  357: }
  358: 
  359: int
  360: iperf_get_test_udp_counters_64bit(struct iperf_test *ipt)
  361: {
  362:     return ipt->udp_counters_64bit;
  363: }
  364: 
  365: int
  366: iperf_get_test_one_off(struct iperf_test *ipt)
  367: {
  368:     return ipt->one_off;
  369: }
  370: 
  371: int
  372: iperf_get_test_tos(struct iperf_test *ipt)
  373: {
  374:     return ipt->settings->tos;
  375: }
  376: 
  377: char *
  378: iperf_get_test_extra_data(struct iperf_test *ipt)
  379: {
  380:     return ipt->extra_data;
  381: }
  382: 
  383: static const char iperf_version[] = IPERF_VERSION;
  384: char *
  385: iperf_get_iperf_version(void)
  386: {
  387:     return (char*)iperf_version;
  388: }
  389: 
  390: int
  391: iperf_get_test_no_delay(struct iperf_test *ipt)
  392: {
  393:     return ipt->no_delay;
  394: }
  395: 
  396: int
  397: iperf_get_test_connect_timeout(struct iperf_test *ipt)
  398: {
  399:     return ipt->settings->connect_timeout;
  400: }
  401: 
  402: int
  403: iperf_get_test_idle_timeout(struct iperf_test *ipt)
  404: {
  405:     return ipt->settings->idle_timeout;
  406: }
  407: 
  408: int
  409: iperf_get_dont_fragment(struct iperf_test *ipt)
  410: {
  411:     return ipt->settings->dont_fragment;
  412: }
  413: 
  414: struct iperf_time*
  415: iperf_get_test_rcv_timeout(struct iperf_test *ipt)
  416: {
  417:     return &ipt->settings->rcv_timeout;
  418: }
  419: 
  420: char*
  421: iperf_get_test_congestion_control(struct iperf_test* ipt)
  422: {
  423:     return ipt->congestion;
  424: }
  425: 
  426: int
  427: iperf_get_test_mss(struct iperf_test *ipt)
  428: {
  429:     return ipt->settings->mss;
  430: }
  431: 
  432: int
  433: iperf_get_mapped_v4(struct iperf_test* ipt)
  434: {
  435:     return ipt->mapped_v4;
  436: }
  437: 
  438: /************** Setter routines for some fields inside iperf_test *************/
  439: 
  440: void
  441: iperf_set_verbose(struct iperf_test *ipt, int verbose)
  442: {
  443:     ipt->verbose = verbose;
  444: }
  445: 
  446: void
  447: iperf_set_control_socket(struct iperf_test *ipt, int ctrl_sck)
  448: {
  449:     ipt->ctrl_sck = ctrl_sck;
  450: }
  451: 
  452: void
  453: iperf_set_test_omit(struct iperf_test *ipt, int omit)
  454: {
  455:     ipt->omit = omit;
  456: }
  457: 
  458: void
  459: iperf_set_test_duration(struct iperf_test *ipt, int duration)
  460: {
  461:     ipt->duration = duration;
  462: }
  463: 
  464: void
  465: iperf_set_test_reporter_interval(struct iperf_test *ipt, double reporter_interval)
  466: {
  467:     ipt->reporter_interval = reporter_interval;
  468: }
  469: 
  470: void
  471: iperf_set_test_stats_interval(struct iperf_test *ipt, double stats_interval)
  472: {
  473:     ipt->stats_interval = stats_interval;
  474: }
  475: 
  476: void
  477: iperf_set_test_state(struct iperf_test *ipt, signed char state)
  478: {
  479:     ipt->state = state;
  480: }
  481: 
  482: void
  483: iperf_set_test_blksize(struct iperf_test *ipt, int blksize)
  484: {
  485:     ipt->settings->blksize = blksize;
  486: }
  487: 
  488: void
  489: iperf_set_test_logfile(struct iperf_test *ipt, const char *logfile)
  490: {
  491:     ipt->logfile = strdup(logfile);
  492: }
  493: 
  494: void
  495: iperf_set_test_rate(struct iperf_test *ipt, uint64_t rate)
  496: {
  497:     ipt->settings->rate = rate;
  498: }
  499: 
  500: void
  501: iperf_set_test_bitrate_limit_maximum(struct iperf_test *ipt, uint64_t total_rate)
  502: {
  503:     ipt->settings->bitrate_limit = total_rate;
  504: }
  505: 
  506: void
  507: iperf_set_test_bitrate_limit_interval(struct iperf_test *ipt, uint64_t bitrate_limit_interval)
  508: {
  509:     ipt->settings->bitrate_limit_interval = bitrate_limit_interval;
  510: }
  511: 
  512: void
  513: iperf_set_test_bitrate_limit_stats_per_interval(struct iperf_test *ipt, uint64_t bitrate_limit_stats_per_interval)
  514: {
  515:     ipt->settings->bitrate_limit_stats_per_interval = bitrate_limit_stats_per_interval;
  516: }
  517: 
  518: void
  519: iperf_set_test_fqrate(struct iperf_test *ipt, uint64_t fqrate)
  520: {
  521:     ipt->settings->fqrate = fqrate;
  522: }
  523: 
  524: void
  525: iperf_set_test_pacing_timer(struct iperf_test *ipt, int pacing_timer)
  526: {
  527:     ipt->settings->pacing_timer = pacing_timer;
  528: }
  529: 
  530: void
  531: iperf_set_test_bytes(struct iperf_test *ipt, uint64_t bytes)
  532: {
  533:     ipt->settings->bytes = (iperf_size_t) bytes;
  534: }
  535: 
  536: void
  537: iperf_set_test_blocks(struct iperf_test *ipt, uint64_t blocks)
  538: {
  539:     ipt->settings->blocks = (iperf_size_t) blocks;
  540: }
  541: 
  542: void
  543: iperf_set_test_burst(struct iperf_test *ipt, int burst)
  544: {
  545:     ipt->settings->burst = burst;
  546: }
  547: 
  548: void
  549: iperf_set_test_bind_port(struct iperf_test *ipt, int bind_port)
  550: {
  551:     ipt->bind_port = bind_port;
  552: }
  553: 
  554: void
  555: iperf_set_test_server_port(struct iperf_test *ipt, int srv_port)
  556: {
  557:     ipt->server_port = srv_port;
  558: }
  559: 
  560: void
  561: iperf_set_test_socket_bufsize(struct iperf_test *ipt, int socket_bufsize)
  562: {
  563:     ipt->settings->socket_bufsize = socket_bufsize;
  564: }
  565: 
  566: void
  567: iperf_set_test_num_streams(struct iperf_test *ipt, int num_streams)
  568: {
  569:     ipt->num_streams = num_streams;
  570: }
  571: 
  572: void
  573: iperf_set_test_repeating_payload(struct iperf_test *ipt, int repeating_payload)
  574: {
  575:     ipt->repeating_payload = repeating_payload;
  576: }
  577: 
  578: void
  579: iperf_set_test_timestamps(struct iperf_test *ipt, int timestamps)
  580: {
  581:     ipt->timestamps = timestamps;
  582: }
  583: 
  584: void
  585: iperf_set_test_timestamp_format(struct iperf_test *ipt, const char *tf)
  586: {
  587:     ipt->timestamp_format = strdup(tf);
  588: }
  589: 
  590: void
  591: iperf_set_mapped_v4(struct iperf_test *ipt, const int val)
  592: {
  593:     ipt->mapped_v4 = val;
  594: }
  595: 
  596: void 
  597: iperf_set_on_new_stream_callback(struct iperf_test* ipt, void (*callback)())
  598: {
  599:         ipt->on_new_stream = callback;
  600: }
  601: 
  602: void 
  603: iperf_set_on_test_start_callback(struct iperf_test* ipt, void (*callback)())
  604: {
  605:         ipt->on_test_start = callback;
  606: }
  607: 
  608: void 
  609: iperf_set_on_test_connect_callback(struct iperf_test* ipt, void (*callback)())
  610: {
  611:         ipt->on_connect = callback;
  612: }
  613: 
  614: void 
  615: iperf_set_on_test_finish_callback(struct iperf_test* ipt, void (*callback)())
  616: {
  617:         ipt->on_test_finish = callback;
  618: }
  619: 
  620: static void
  621: check_sender_has_retransmits(struct iperf_test *ipt)
  622: {
  623:     if (ipt->mode != RECEIVER && ipt->protocol->id == Ptcp && has_tcpinfo_retransmits())
  624: 	ipt->sender_has_retransmits = 1;
  625:     else
  626: 	ipt->sender_has_retransmits = 0;
  627: }
  628: 
  629: void
  630: iperf_set_test_role(struct iperf_test *ipt, char role)
  631: {
  632:     ipt->role = role;
  633:     if (!ipt->reverse) {
  634:         if (ipt->bidirectional)
  635:             ipt->mode = BIDIRECTIONAL;
  636:         else if (role == 'c')
  637:             ipt->mode = SENDER;
  638:         else if (role == 's')
  639:             ipt->mode = RECEIVER;
  640:     } else {
  641:         if (role == 'c')
  642:             ipt->mode = RECEIVER;
  643:         else if (role == 's')
  644:             ipt->mode = SENDER;
  645:     }
  646:     check_sender_has_retransmits(ipt);
  647: }
  648: 
  649: void
  650: iperf_set_test_server_hostname(struct iperf_test *ipt, const char *server_hostname)
  651: {
  652:     ipt->server_hostname = strdup(server_hostname);
  653: }
  654: 
  655: void
  656: iperf_set_test_template(struct iperf_test *ipt, const char *tmp_template)
  657: {
  658:     ipt->tmp_template = strdup(tmp_template);
  659: }
  660: 
  661: void
  662: iperf_set_test_reverse(struct iperf_test *ipt, int reverse)
  663: {
  664:     ipt->reverse = reverse;
  665:     if (!ipt->reverse) {
  666:         if (ipt->role == 'c')
  667:             ipt->mode = SENDER;
  668:         else if (ipt->role == 's')
  669:             ipt->mode = RECEIVER;
  670:     } else {
  671:         if (ipt->role == 'c')
  672:             ipt->mode = RECEIVER;
  673:         else if (ipt->role == 's')
  674:             ipt->mode = SENDER;
  675:     }
  676:     check_sender_has_retransmits(ipt);
  677: }
  678: 
  679: void
  680: iperf_set_test_json_output(struct iperf_test *ipt, int json_output)
  681: {
  682:     ipt->json_output = json_output;
  683: }
  684: 
  685: int
  686: iperf_has_zerocopy( void )
  687: {
  688:     return has_sendfile();
  689: }
  690: 
  691: void
  692: iperf_set_test_zerocopy(struct iperf_test *ipt, int zerocopy)
  693: {
  694:     ipt->zerocopy = (zerocopy && has_sendfile());
  695: }
  696: 
  697: void
  698: iperf_set_test_get_server_output(struct iperf_test *ipt, int get_server_output)
  699: {
  700:     ipt->get_server_output = get_server_output;
  701: }
  702: 
  703: void
  704: iperf_set_test_unit_format(struct iperf_test *ipt, char unit_format)
  705: {
  706:     ipt->settings->unit_format = unit_format;
  707: }
  708: 
  709: #if defined(HAVE_SSL)
  710: void
  711: iperf_set_test_client_username(struct iperf_test *ipt, const char *client_username)
  712: {
  713:     ipt->settings->client_username = strdup(client_username);
  714: }
  715: 
  716: void
  717: iperf_set_test_client_password(struct iperf_test *ipt, const char *client_password)
  718: {
  719:     ipt->settings->client_password = strdup(client_password);
  720: }
  721: 
  722: void
  723: iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, const char *client_rsa_pubkey_base64)
  724: {
  725:     ipt->settings->client_rsa_pubkey = load_pubkey_from_base64(client_rsa_pubkey_base64);
  726: }
  727: 
  728: void
  729: iperf_set_test_server_authorized_users(struct iperf_test *ipt, const char *server_authorized_users)
  730: {
  731:     ipt->server_authorized_users = strdup(server_authorized_users);
  732: }
  733: 
  734: void
  735: iperf_set_test_server_skew_threshold(struct iperf_test *ipt, int server_skew_threshold)
  736: {
  737:     ipt->server_skew_threshold = server_skew_threshold;
  738: }
  739: 
  740: void
  741: iperf_set_test_server_rsa_privkey(struct iperf_test *ipt, const char *server_rsa_privkey_base64)
  742: {
  743:     ipt->server_rsa_private_key = load_privkey_from_base64(server_rsa_privkey_base64);
  744: }
  745: #endif // HAVE_SSL
  746: 
  747: void
  748: iperf_set_test_bind_address(struct iperf_test *ipt, const char *bnd_address)
  749: {
  750:     ipt->bind_address = strdup(bnd_address);
  751: }
  752: 
  753: void
  754: iperf_set_test_bind_dev(struct iperf_test *ipt, const char *bnd_dev)
  755: {
  756:     ipt->bind_dev = strdup(bnd_dev);
  757: }
  758: 
  759: void
  760: iperf_set_test_udp_counters_64bit(struct iperf_test *ipt, int udp_counters_64bit)
  761: {
  762:     ipt->udp_counters_64bit = udp_counters_64bit;
  763: }
  764: 
  765: void
  766: iperf_set_test_one_off(struct iperf_test *ipt, int one_off)
  767: {
  768:     ipt->one_off = one_off;
  769: }
  770: 
  771: void
  772: iperf_set_test_tos(struct iperf_test *ipt, int tos)
  773: {
  774:     ipt->settings->tos = tos;
  775: }
  776: 
  777: void
  778: iperf_set_test_extra_data(struct iperf_test *ipt, const char *dat)
  779: {
  780:     ipt->extra_data = strdup(dat);
  781: }
  782: 
  783: void
  784: iperf_set_test_bidirectional(struct iperf_test* ipt, int bidirectional)
  785: {
  786:     ipt->bidirectional = bidirectional;
  787:     if (bidirectional)
  788:         ipt->mode = BIDIRECTIONAL;
  789:     else
  790:         iperf_set_test_reverse(ipt, ipt->reverse);
  791: }
  792: 
  793: void
  794: iperf_set_test_no_delay(struct iperf_test* ipt, int no_delay)
  795: {
  796:     ipt->no_delay = no_delay;
  797: }
  798: 
  799: void
  800: iperf_set_test_connect_timeout(struct iperf_test* ipt, int ct)
  801: {
  802:     ipt->settings->connect_timeout = ct;
  803: }
  804: 
  805: void
  806: iperf_set_test_idle_timeout(struct iperf_test* ipt, int to)
  807: {
  808:     ipt->settings->idle_timeout = to;
  809: }
  810: 
  811: void
  812: iperf_set_dont_fragment(struct iperf_test* ipt, int dnf)
  813: {
  814:     ipt->settings->dont_fragment = dnf;
  815: }
  816: 
  817: void
  818: iperf_set_test_rcv_timeout(struct iperf_test* ipt, struct iperf_time* to)
  819: {
  820:     ipt->settings->rcv_timeout.secs = to->secs;
  821:     ipt->settings->rcv_timeout.usecs = to->usecs;
  822: }
  823: 
  824: void
  825: iperf_set_test_congestion_control(struct iperf_test* ipt, char* cc)
  826: {
  827:     ipt->congestion = strdup(cc);
  828: }
  829: 
  830: void
  831: iperf_set_test_mss(struct iperf_test *ipt, int mss)
  832: {
  833:     ipt->settings->mss = mss;
  834: }
  835: 
  836: /********************** Get/set test protocol structure ***********************/
  837: 
  838: struct protocol *
  839: get_protocol(struct iperf_test *test, int prot_id)
  840: {
  841:     struct protocol *prot;
  842: 
  843:     SLIST_FOREACH(prot, &test->protocols, protocols) {
  844:         if (prot->id == prot_id)
  845:             break;
  846:     }
  847: 
  848:     if (prot == NULL)
  849:         i_errno = IEPROTOCOL;
  850: 
  851:     return prot;
  852: }
  853: 
  854: int
  855: set_protocol(struct iperf_test *test, int prot_id)
  856: {
  857:     struct protocol *prot = NULL;
  858: 
  859:     SLIST_FOREACH(prot, &test->protocols, protocols) {
  860:         if (prot->id == prot_id) {
  861:             test->protocol = prot;
  862: 	    check_sender_has_retransmits(test);
  863:             return 0;
  864:         }
  865:     }
  866: 
  867:     i_errno = IEPROTOCOL;
  868:     return -1;
  869: }
  870: 
  871: 
  872: /************************** Iperf callback functions **************************/
  873: 
  874: void
  875: iperf_on_new_stream(struct iperf_stream *sp)
  876: {
  877:     connect_msg(sp);
  878: }
  879: 
  880: void
  881: iperf_on_test_start(struct iperf_test *test)
  882: {
  883:     if (test->json_output) {
  884: 	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  target_bitrate: %d bidir: %d fqrate: %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, (int64_t) test->settings->rate, (int64_t) test->bidirectional, (uint64_t) test->settings->fqrate));
  885:     } else {
  886: 	if (test->verbose) {
  887: 	    if (test->settings->bytes)
  888: 		iperf_printf(test, test_start_bytes, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->bytes, test->settings->tos);
  889: 	    else if (test->settings->blocks)
  890: 		iperf_printf(test, test_start_blocks, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->blocks, test->settings->tos);
  891: 	    else
  892: 		iperf_printf(test, test_start_time, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->duration, test->settings->tos);
  893: 	}
  894:     }
  895: }
  896: 
  897: /* This converts an IPv6 string address from IPv4-mapped format into regular
  898: ** old IPv4 format, which is easier on the eyes of network veterans.
  899: **
  900: ** If the v6 address is not v4-mapped it is left alone.
  901: **
  902: ** Returns 1 if the v6 address is v4-mapped, 0 otherwise.
  903: */
  904: static int
  905: mapped_v4_to_regular_v4(char *str)
  906: {
  907:     char *prefix = "::ffff:";
  908:     int prefix_len;
  909: 
  910:     prefix_len = strlen(prefix);
  911:     if (strncmp(str, prefix, prefix_len) == 0) {
  912: 	int str_len = strlen(str);
  913: 	memmove(str, str + prefix_len, str_len - prefix_len + 1);
  914: 	return 1;
  915:     }
  916:     return 0;
  917: }
  918: 
  919: void
  920: iperf_on_connect(struct iperf_test *test)
  921: {
  922:     time_t now_secs;
  923:     const char* rfc1123_fmt = "%a, %d %b %Y %H:%M:%S %Z";
  924:     char now_str[100];
  925:     char ipr[INET6_ADDRSTRLEN];
  926:     int port;
  927:     struct sockaddr_storage sa;
  928:     struct sockaddr_in *sa_inP;
  929:     struct sockaddr_in6 *sa_in6P;
  930:     socklen_t len;
  931: 
  932:     now_secs = time((time_t*) 0);
  933:     (void) strftime(now_str, sizeof(now_str), rfc1123_fmt, gmtime(&now_secs));
  934:     if (test->json_output)
  935: 	cJSON_AddItemToObject(test->json_start, "timestamp", iperf_json_printf("time: %s  timesecs: %d", now_str, (int64_t) now_secs));
  936:     else if (test->verbose)
  937: 	iperf_printf(test, report_time, now_str);
  938: 
  939:     if (test->role == 'c') {
  940: 	if (test->json_output)
  941: 	    cJSON_AddItemToObject(test->json_start, "connecting_to", iperf_json_printf("host: %s  port: %d", test->server_hostname, (int64_t) test->server_port));
  942: 	else {
  943: 	    iperf_printf(test, report_connecting, test->server_hostname, test->server_port);
  944: 	    if (test->reverse)
  945: 		iperf_printf(test, report_reverse, test->server_hostname);
  946: 	}
  947:     } else {
  948:         len = sizeof(sa);
  949:         getpeername(test->ctrl_sck, (struct sockaddr *) &sa, &len);
  950:         if (getsockdomain(test->ctrl_sck) == AF_INET) {
  951: 	    sa_inP = (struct sockaddr_in *) &sa;
  952:             inet_ntop(AF_INET, &sa_inP->sin_addr, ipr, sizeof(ipr));
  953: 	    port = ntohs(sa_inP->sin_port);
  954:         } else {
  955: 	    sa_in6P = (struct sockaddr_in6 *) &sa;
  956:             inet_ntop(AF_INET6, &sa_in6P->sin6_addr, ipr, sizeof(ipr));
  957: 	    port = ntohs(sa_in6P->sin6_port);
  958:         }
  959: 	if (mapped_v4_to_regular_v4(ipr)) {
  960: 	    iperf_set_mapped_v4(test, 1);
  961: 	}
  962: 	if (test->json_output)
  963: 	    cJSON_AddItemToObject(test->json_start, "accepted_connection", iperf_json_printf("host: %s  port: %d", ipr, (int64_t) port));
  964: 	else
  965: 	    iperf_printf(test, report_accepted, ipr, port);
  966:     }
  967:     if (test->json_output) {
  968: 	cJSON_AddStringToObject(test->json_start, "cookie", test->cookie);
  969:         if (test->protocol->id == SOCK_STREAM) {
  970: 	    if (test->settings->mss)
  971: 		cJSON_AddNumberToObject(test->json_start, "tcp_mss", test->settings->mss);
  972: 	    else {
  973: 		cJSON_AddNumberToObject(test->json_start, "tcp_mss_default", test->ctrl_sck_mss);
  974: 	    }
  975:         }
  976: 	// Duplicate to make sure it appears on all output
  977:         cJSON_AddNumberToObject(test->json_start, "target_bitrate", test->settings->rate);
  978:         cJSON_AddNumberToObject(test->json_start, "fq_rate", test->settings->fqrate);
  979:     } else if (test->verbose) {
  980:         iperf_printf(test, report_cookie, test->cookie);
  981:         if (test->protocol->id == SOCK_STREAM) {
  982:             if (test->settings->mss)
  983:                 iperf_printf(test, "      TCP MSS: %d\n", test->settings->mss);
  984:             else {
  985:                 iperf_printf(test, "      TCP MSS: %d (default)\n", test->ctrl_sck_mss);
  986:             }
  987:         }
  988:         if (test->settings->rate)
  989:             iperf_printf(test, "      Target Bitrate: %"PRIu64"\n", test->settings->rate);
  990:     }
  991: }
  992: 
  993: void
  994: iperf_on_test_finish(struct iperf_test *test)
  995: {
  996: }
  997: 
  998: 
  999: /******************************************************************************/
 1000: 
 1001: /*
 1002:  * iperf_parse_hostname tries to split apart a string into hostname %
 1003:  * interface parts, which are returned in **p and **p1, if they
 1004:  * exist. If the %interface part is detected, and it's not an IPv6
 1005:  * link local address, then returns 1, else returns 0.
 1006:  *
 1007:  * Modifies the string pointed to by spec in-place due to the use of
 1008:  * strtok(3). The caller should strdup(3) or otherwise copy the string
 1009:  * if an unmodified copy is needed.
 1010:  */
 1011: int
 1012: iperf_parse_hostname(struct iperf_test *test, char *spec, char **p, char **p1) {
 1013:     struct in6_addr ipv6_addr;
 1014: 
 1015:     // Format is <addr>[%<device>]
 1016:     if ((*p = strtok(spec, "%")) != NULL &&
 1017:         (*p1 = strtok(NULL, "%")) != NULL) {
 1018: 
 1019:         /*
 1020:          * If an IPv6 literal for a link-local address, then
 1021:          * tell the caller to leave the "%" in the hostname.
 1022:          */
 1023:         if (inet_pton(AF_INET6, *p, &ipv6_addr) == 1 &&
 1024:             IN6_IS_ADDR_LINKLOCAL(&ipv6_addr)) {
 1025:             if (test->debug) {
 1026:                 iperf_printf(test, "IPv6 link-local address literal detected\n");
 1027:             }
 1028:             return 0;
 1029:         }
 1030:         /*
 1031:          * Other kind of address or FQDN. The interface name after
 1032:          * "%" is a shorthand for --bind-dev.
 1033:          */
 1034:         else {
 1035:             if (test->debug) {
 1036:                 iperf_printf(test, "p %s p1 %s\n", *p, *p1);
 1037:             }
 1038:             return 1;
 1039:         }
 1040:     }
 1041:     else {
 1042:         if (test->debug) {
 1043:             iperf_printf(test, "noparse\n");
 1044:         }
 1045:         return 0;
 1046:     }
 1047: }
 1048: 
 1049: int
 1050: iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
 1051: {
 1052:     static struct option longopts[] =
 1053:     {
 1054:         {"port", required_argument, NULL, 'p'},
 1055:         {"format", required_argument, NULL, 'f'},
 1056:         {"interval", required_argument, NULL, 'i'},
 1057:         {"daemon", no_argument, NULL, 'D'},
 1058:         {"one-off", no_argument, NULL, '1'},
 1059:         {"verbose", no_argument, NULL, 'V'},
 1060:         {"json", no_argument, NULL, 'J'},
 1061:         {"version", no_argument, NULL, 'v'},
 1062:         {"server", no_argument, NULL, 's'},
 1063:         {"client", required_argument, NULL, 'c'},
 1064:         {"udp", no_argument, NULL, 'u'},
 1065:         {"bitrate", required_argument, NULL, 'b'},
 1066:         {"bandwidth", required_argument, NULL, 'b'},
 1067: 	{"server-bitrate-limit", required_argument, NULL, OPT_SERVER_BITRATE_LIMIT},
 1068:         {"time", required_argument, NULL, 't'},
 1069:         {"bytes", required_argument, NULL, 'n'},
 1070:         {"blockcount", required_argument, NULL, 'k'},
 1071:         {"length", required_argument, NULL, 'l'},
 1072:         {"parallel", required_argument, NULL, 'P'},
 1073:         {"reverse", no_argument, NULL, 'R'},
 1074:         {"bidir", no_argument, NULL, OPT_BIDIRECTIONAL},
 1075:         {"window", required_argument, NULL, 'w'},
 1076:         {"bind", required_argument, NULL, 'B'},
 1077: #if defined(HAVE_SO_BINDTODEVICE)
 1078:         {"bind-dev", required_argument, NULL, OPT_BIND_DEV},
 1079: #endif /* HAVE_SO_BINDTODEVICE */
 1080:         {"cport", required_argument, NULL, OPT_CLIENT_PORT},
 1081:         {"set-mss", required_argument, NULL, 'M'},
 1082:         {"no-delay", no_argument, NULL, 'N'},
 1083:         {"version4", no_argument, NULL, '4'},
 1084:         {"version6", no_argument, NULL, '6'},
 1085:         {"tos", required_argument, NULL, 'S'},
 1086:         {"dscp", required_argument, NULL, OPT_DSCP},
 1087: 	{"extra-data", required_argument, NULL, OPT_EXTRA_DATA},
 1088: #if defined(HAVE_FLOWLABEL)
 1089:         {"flowlabel", required_argument, NULL, 'L'},
 1090: #endif /* HAVE_FLOWLABEL */
 1091:         {"zerocopy", no_argument, NULL, 'Z'},
 1092:         {"omit", required_argument, NULL, 'O'},
 1093:         {"file", required_argument, NULL, 'F'},
 1094:         {"repeating-payload", no_argument, NULL, OPT_REPEATING_PAYLOAD},
 1095:         {"timestamps", optional_argument, NULL, OPT_TIMESTAMPS},
 1096: #if defined(HAVE_CPU_AFFINITY)
 1097:         {"affinity", required_argument, NULL, 'A'},
 1098: #endif /* HAVE_CPU_AFFINITY */
 1099:         {"title", required_argument, NULL, 'T'},
 1100: #if defined(HAVE_TCP_CONGESTION)
 1101:         {"congestion", required_argument, NULL, 'C'},
 1102:         {"linux-congestion", required_argument, NULL, 'C'},
 1103: #endif /* HAVE_TCP_CONGESTION */
 1104: #if defined(HAVE_SCTP_H)
 1105:         {"sctp", no_argument, NULL, OPT_SCTP},
 1106:         {"nstreams", required_argument, NULL, OPT_NUMSTREAMS},
 1107:         {"xbind", required_argument, NULL, 'X'},
 1108: #endif
 1109: 	{"pidfile", required_argument, NULL, 'I'},
 1110: 	{"logfile", required_argument, NULL, OPT_LOGFILE},
 1111: 	{"forceflush", no_argument, NULL, OPT_FORCEFLUSH},
 1112: 	{"get-server-output", no_argument, NULL, OPT_GET_SERVER_OUTPUT},
 1113: 	{"udp-counters-64bit", no_argument, NULL, OPT_UDP_COUNTERS_64BIT},
 1114:  	{"no-fq-socket-pacing", no_argument, NULL, OPT_NO_FQ_SOCKET_PACING},
 1115: #if defined(HAVE_DONT_FRAGMENT)
 1116: 	{"dont-fragment", no_argument, NULL, OPT_DONT_FRAGMENT},
 1117: #endif /* HAVE_DONT_FRAGMENT */
 1118: #if defined(HAVE_SSL)
 1119:     {"username", required_argument, NULL, OPT_CLIENT_USERNAME},
 1120:     {"rsa-public-key-path", required_argument, NULL, OPT_CLIENT_RSA_PUBLIC_KEY},
 1121:     {"rsa-private-key-path", required_argument, NULL, OPT_SERVER_RSA_PRIVATE_KEY},
 1122:     {"authorized-users-path", required_argument, NULL, OPT_SERVER_AUTHORIZED_USERS},
 1123:     {"time-skew-threshold", required_argument, NULL, OPT_SERVER_SKEW_THRESHOLD},
 1124: #endif /* HAVE_SSL */
 1125: 	{"fq-rate", required_argument, NULL, OPT_FQ_RATE},
 1126: 	{"pacing-timer", required_argument, NULL, OPT_PACING_TIMER},
 1127: 	{"connect-timeout", required_argument, NULL, OPT_CONNECT_TIMEOUT},
 1128:         {"idle-timeout", required_argument, NULL, OPT_IDLE_TIMEOUT},
 1129:         {"rcv-timeout", required_argument, NULL, OPT_RCV_TIMEOUT},
 1130:         {"snd-timeout", required_argument, NULL, OPT_SND_TIMEOUT},
 1131:         {"debug", optional_argument, NULL, 'd'},
 1132:         {"help", no_argument, NULL, 'h'},
 1133:         {NULL, 0, NULL, 0}
 1134:     };
 1135:     int flag;
 1136:     int portno;
 1137:     int blksize;
 1138:     int server_flag, client_flag, rate_flag, duration_flag, rcv_timeout_flag, snd_timeout_flag;
 1139:     char *endptr;
 1140: #if defined(HAVE_CPU_AFFINITY)
 1141:     char* comma;
 1142: #endif /* HAVE_CPU_AFFINITY */
 1143:     char* slash;
 1144:     char *p, *p1;
 1145:     struct xbind_entry *xbe;
 1146:     double farg;
 1147:     int rcv_timeout_in = 0;
 1148: 
 1149:     blksize = 0;
 1150:     server_flag = client_flag = rate_flag = duration_flag = rcv_timeout_flag = snd_timeout_flag =0;
 1151: #if defined(HAVE_SSL)
 1152:     char *client_username = NULL, *client_rsa_public_key = NULL, *server_rsa_private_key = NULL;
 1153: #endif /* HAVE_SSL */
 1154: 
 1155:     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) {
 1156:         switch (flag) {
 1157:             case 'p':
 1158: 		portno = atoi(optarg);
 1159: 		if (portno < 1 || portno > 65535) {
 1160: 		    i_errno = IEBADPORT;
 1161: 		    return -1;
 1162: 		}
 1163: 		test->server_port = portno;
 1164:                 break;
 1165:             case 'f':
 1166: 		if (!optarg) {
 1167: 		    i_errno = IEBADFORMAT;
 1168: 		    return -1;
 1169: 		}
 1170: 		test->settings->unit_format = *optarg;
 1171: 		if (test->settings->unit_format == 'k' ||
 1172: 		    test->settings->unit_format == 'K' ||
 1173: 		    test->settings->unit_format == 'm' ||
 1174: 		    test->settings->unit_format == 'M' ||
 1175: 		    test->settings->unit_format == 'g' ||
 1176: 		    test->settings->unit_format == 'G' ||
 1177: 		    test->settings->unit_format == 't' ||
 1178: 		    test->settings->unit_format == 'T') {
 1179: 			break;
 1180: 		}
 1181: 		else {
 1182: 		    i_errno = IEBADFORMAT;
 1183: 		    return -1;
 1184: 		}
 1185:                 break;
 1186:             case 'i':
 1187:                 /* XXX: could potentially want separate stat collection and reporting intervals,
 1188:                    but just set them to be the same for now */
 1189:                 test->stats_interval = test->reporter_interval = atof(optarg);
 1190:                 if ((test->stats_interval < MIN_INTERVAL || test->stats_interval > MAX_INTERVAL) && test->stats_interval != 0) {
 1191:                     i_errno = IEINTERVAL;
 1192:                     return -1;
 1193:                 }
 1194:                 break;
 1195:             case 'D':
 1196: 		test->daemon = 1;
 1197: 		server_flag = 1;
 1198: 	        break;
 1199:             case '1':
 1200: 		test->one_off = 1;
 1201: 		server_flag = 1;
 1202: 	        break;
 1203:             case 'V':
 1204:                 test->verbose = 1;
 1205:                 break;
 1206:             case 'J':
 1207:                 test->json_output = 1;
 1208:                 break;
 1209:             case 'v':
 1210:                 printf("%s (cJSON %s)\n%s\n%s\n", version, cJSON_Version(), get_system_info(),
 1211: 		       get_optional_features());
 1212:                 exit(0);
 1213:             case 's':
 1214:                 if (test->role == 'c') {
 1215:                     i_errno = IESERVCLIENT;
 1216:                     return -1;
 1217:                 }
 1218: 		iperf_set_test_role(test, 's');
 1219:                 break;
 1220:             case 'c':
 1221:                 if (test->role == 's') {
 1222:                     i_errno = IESERVCLIENT;
 1223:                     return -1;
 1224:                 }
 1225: 		iperf_set_test_role(test, 'c');
 1226: 		iperf_set_test_server_hostname(test, optarg);
 1227: 
 1228:                 if (iperf_parse_hostname(test, optarg, &p, &p1)) {
 1229: #if defined(HAVE_SO_BINDTODEVICE)
 1230:                     /* Get rid of the hostname we saved earlier. */
 1231:                     free(iperf_get_test_server_hostname(test));
 1232:                     iperf_set_test_server_hostname(test, p);
 1233:                     iperf_set_test_bind_dev(test, p1);
 1234: #else /* HAVE_SO_BINDTODEVICE */
 1235:                     i_errno = IEBINDDEVNOSUPPORT;
 1236:                     return -1;
 1237: #endif /* HAVE_SO_BINDTODEVICE */
 1238:                 }
 1239:                 break;
 1240:             case 'u':
 1241:                 set_protocol(test, Pudp);
 1242: 		client_flag = 1;
 1243:                 break;
 1244:             case OPT_SCTP:
 1245: #if defined(HAVE_SCTP_H)
 1246:                 set_protocol(test, Psctp);
 1247:                 client_flag = 1;
 1248:                 break;
 1249: #else /* HAVE_SCTP_H */
 1250:                 i_errno = IEUNIMP;
 1251:                 return -1;
 1252: #endif /* HAVE_SCTP_H */
 1253: 
 1254:             case OPT_NUMSTREAMS:
 1255: #if defined(linux) || defined(__FreeBSD__)
 1256:                 test->settings->num_ostreams = unit_atoi(optarg);
 1257:                 client_flag = 1;
 1258: #else /* linux */
 1259:                 i_errno = IEUNIMP;
 1260:                 return -1;
 1261: #endif /* linux */
 1262:             case 'b':
 1263: 		slash = strchr(optarg, '/');
 1264: 		if (slash) {
 1265: 		    *slash = '\0';
 1266: 		    ++slash;
 1267: 		    test->settings->burst = atoi(slash);
 1268: 		    if (test->settings->burst <= 0 ||
 1269: 		        test->settings->burst > MAX_BURST) {
 1270: 			i_errno = IEBURST;
 1271: 			return -1;
 1272: 		    }
 1273: 		}
 1274:                 test->settings->rate = unit_atof_rate(optarg);
 1275: 		rate_flag = 1;
 1276: 		client_flag = 1;
 1277:                 break;
 1278:             case OPT_SERVER_BITRATE_LIMIT:
 1279: 		slash = strchr(optarg, '/');
 1280: 		if (slash) {
 1281: 		    *slash = '\0';
 1282: 		    ++slash;
 1283: 		    test->settings->bitrate_limit_interval = atof(slash);
 1284: 		    if (test->settings->bitrate_limit_interval != 0 &&	/* Using same Max/Min limits as for Stats Interval */
 1285: 		        (test->settings->bitrate_limit_interval < MIN_INTERVAL || test->settings->bitrate_limit_interval > MAX_INTERVAL) ) {
 1286: 			i_errno = IETOTALINTERVAL;
 1287: 			return -1;
 1288: 		    }
 1289: 		}
 1290: 		test->settings->bitrate_limit = unit_atof_rate(optarg);
 1291: 		server_flag = 1;
 1292: 	        break;
 1293:             case 't':
 1294:                 test->duration = atoi(optarg);
 1295:                 if (test->duration > MAX_TIME) {
 1296:                     i_errno = IEDURATION;
 1297:                     return -1;
 1298:                 }
 1299: 		duration_flag = 1;
 1300: 		client_flag = 1;
 1301:                 break;
 1302:             case 'n':
 1303:                 test->settings->bytes = unit_atoi(optarg);
 1304: 		client_flag = 1;
 1305:                 break;
 1306:             case 'k':
 1307:                 test->settings->blocks = unit_atoi(optarg);
 1308: 		client_flag = 1;
 1309:                 break;
 1310:             case 'l':
 1311:                 blksize = unit_atoi(optarg);
 1312: 		client_flag = 1;
 1313:                 break;
 1314:             case 'P':
 1315:                 test->num_streams = atoi(optarg);
 1316:                 if (test->num_streams > MAX_STREAMS) {
 1317:                     i_errno = IENUMSTREAMS;
 1318:                     return -1;
 1319:                 }
 1320: 		client_flag = 1;
 1321:                 break;
 1322:             case 'R':
 1323:                 if (test->bidirectional) {
 1324:                     i_errno = IEREVERSEBIDIR;
 1325:                     return -1;
 1326:                 }
 1327: 		iperf_set_test_reverse(test, 1);
 1328: 		client_flag = 1;
 1329:                 break;
 1330:             case OPT_BIDIRECTIONAL:
 1331:                 if (test->reverse) {
 1332:                     i_errno = IEREVERSEBIDIR;
 1333:                     return -1;
 1334:                 }
 1335:                 iperf_set_test_bidirectional(test, 1);
 1336:                 client_flag = 1;
 1337:                 break;
 1338:             case 'w':
 1339:                 // XXX: This is a socket buffer, not specific to TCP
 1340: 		// Do sanity checks as double-precision floating point
 1341: 		// to avoid possible integer overflows.
 1342:                 farg = unit_atof(optarg);
 1343:                 if (farg > (double) MAX_TCP_BUFFER) {
 1344:                     i_errno = IEBUFSIZE;
 1345:                     return -1;
 1346:                 }
 1347:                 test->settings->socket_bufsize = (int) farg;
 1348: 		client_flag = 1;
 1349:                 break;
 1350: 
 1351:             case 'B':
 1352:                 iperf_set_test_bind_address(test, optarg);
 1353: 
 1354:                 if (iperf_parse_hostname(test, optarg, &p, &p1)) {
 1355: #if defined(HAVE_SO_BINDTODEVICE)
 1356:                     /* Get rid of the hostname we saved earlier. */
 1357:                     free(iperf_get_test_bind_address(test));
 1358:                     iperf_set_test_bind_address(test, p);
 1359:                     iperf_set_test_bind_dev(test, p1);
 1360: #else /* HAVE_SO_BINDTODEVICE */
 1361:                     i_errno = IEBINDDEVNOSUPPORT;
 1362:                     return -1;
 1363: #endif /* HAVE_SO_BINDTODEVICE */
 1364:                 }
 1365:                 break;
 1366: #if defined (HAVE_SO_BINDTODEVICE)
 1367:             case OPT_BIND_DEV:
 1368:                 iperf_set_test_bind_dev(test, optarg);
 1369:                 break;
 1370: #endif /* HAVE_SO_BINDTODEVICE */
 1371:             case OPT_CLIENT_PORT:
 1372: 		portno = atoi(optarg);
 1373: 		if (portno < 1 || portno > 65535) {
 1374: 		    i_errno = IEBADPORT;
 1375: 		    return -1;
 1376: 		}
 1377:                 test->bind_port = portno;
 1378:                 break;
 1379:             case 'M':
 1380:                 test->settings->mss = atoi(optarg);
 1381:                 if (test->settings->mss > MAX_MSS) {
 1382:                     i_errno = IEMSS;
 1383:                     return -1;
 1384:                 }
 1385: 		client_flag = 1;
 1386:                 break;
 1387:             case 'N':
 1388:                 test->no_delay = 1;
 1389: 		client_flag = 1;
 1390:                 break;
 1391:             case '4':
 1392:                 test->settings->domain = AF_INET;
 1393:                 break;
 1394:             case '6':
 1395:                 test->settings->domain = AF_INET6;
 1396:                 break;
 1397:             case 'S':
 1398:                 test->settings->tos = strtol(optarg, &endptr, 0);
 1399: 		if (endptr == optarg ||
 1400: 		    test->settings->tos < 0 ||
 1401: 		    test->settings->tos > 255) {
 1402: 		    i_errno = IEBADTOS;
 1403: 		    return -1;
 1404: 		}
 1405: 		client_flag = 1;
 1406:                 break;
 1407: 	    case OPT_DSCP:
 1408:                 test->settings->tos = parse_qos(optarg);
 1409: 		if(test->settings->tos < 0) {
 1410: 			i_errno = IEBADTOS;
 1411: 			return -1;
 1412: 		}
 1413: 		client_flag = 1;
 1414:                 break;
 1415: 	    case OPT_EXTRA_DATA:
 1416: 		test->extra_data = strdup(optarg);
 1417: 		client_flag = 1;
 1418: 	        break;
 1419:             case 'L':
 1420: #if defined(HAVE_FLOWLABEL)
 1421:                 test->settings->flowlabel = strtol(optarg, &endptr, 0);
 1422: 		if (endptr == optarg ||
 1423: 		    test->settings->flowlabel < 1 || test->settings->flowlabel > 0xfffff) {
 1424:                     i_errno = IESETFLOW;
 1425:                     return -1;
 1426: 		}
 1427: 		client_flag = 1;
 1428: #else /* HAVE_FLOWLABEL */
 1429:                 i_errno = IEUNIMP;
 1430:                 return -1;
 1431: #endif /* HAVE_FLOWLABEL */
 1432:                 break;
 1433:             case 'X':
 1434: 		xbe = (struct xbind_entry *)malloc(sizeof(struct xbind_entry));
 1435:                 if (!xbe) {
 1436: 		    i_errno = IESETSCTPBINDX;
 1437:                     return -1;
 1438:                 }
 1439: 	        memset(xbe, 0, sizeof(*xbe));
 1440:                 xbe->name = strdup(optarg);
 1441:                 if (!xbe->name) {
 1442: 		    i_errno = IESETSCTPBINDX;
 1443:                     return -1;
 1444:                 }
 1445: 		TAILQ_INSERT_TAIL(&test->xbind_addrs, xbe, link);
 1446:                 break;
 1447:             case 'Z':
 1448:                 if (!has_sendfile()) {
 1449:                     i_errno = IENOSENDFILE;
 1450:                     return -1;
 1451:                 }
 1452:                 test->zerocopy = 1;
 1453: 		client_flag = 1;
 1454:                 break;
 1455:             case OPT_REPEATING_PAYLOAD:
 1456:                 test->repeating_payload = 1;
 1457:                 client_flag = 1;
 1458:                 break;
 1459:             case OPT_TIMESTAMPS:
 1460:                 iperf_set_test_timestamps(test, 1);
 1461: 		if (optarg) {
 1462: 		    iperf_set_test_timestamp_format(test, optarg);
 1463: 		}
 1464: 		else {
 1465: 		    iperf_set_test_timestamp_format(test, TIMESTAMP_FORMAT);
 1466: 		}
 1467:                 break;
 1468:             case 'O':
 1469:                 test->omit = atoi(optarg);
 1470:                 if (test->omit < 0 || test->omit > 60) {
 1471:                     i_errno = IEOMIT;
 1472:                     return -1;
 1473:                 }
 1474: 		client_flag = 1;
 1475:                 break;
 1476:             case 'F':
 1477:                 test->diskfile_name = optarg;
 1478:                 break;
 1479:             case OPT_IDLE_TIMEOUT:
 1480:                 test->settings->idle_timeout = atoi(optarg);
 1481:                 if (test->settings->idle_timeout < 1 || test->settings->idle_timeout > MAX_TIME) {
 1482:                     i_errno = IEIDLETIMEOUT;
 1483:                     return -1;
 1484:                 }
 1485: 		server_flag = 1;
 1486: 	        break;
 1487:             case OPT_RCV_TIMEOUT:
 1488:                 rcv_timeout_in = atoi(optarg);
 1489:                 if (rcv_timeout_in < MIN_NO_MSG_RCVD_TIMEOUT || rcv_timeout_in > MAX_TIME * SEC_TO_mS) {
 1490:                     i_errno = IERCVTIMEOUT;
 1491:                     return -1;
 1492:                 }
 1493:                 test->settings->rcv_timeout.secs = rcv_timeout_in / SEC_TO_mS;
 1494:                 test->settings->rcv_timeout.usecs = (rcv_timeout_in % SEC_TO_mS) * mS_TO_US;
 1495:                 rcv_timeout_flag = 1;
 1496: 	        break;
 1497: #if defined(HAVE_TCP_USER_TIMEOUT)
 1498:             case OPT_SND_TIMEOUT:
 1499:                 test->settings->snd_timeout = atoi(optarg);
 1500:                 if (test->settings->snd_timeout < 0 || test->settings->snd_timeout > MAX_TIME * SEC_TO_mS) {
 1501:                     i_errno = IESNDTIMEOUT;
 1502:                     return -1;
 1503:                 }
 1504:                 snd_timeout_flag = 1;
 1505: 	        break;
 1506: #endif /* HAVE_TCP_USER_TIMEOUT */
 1507:             case 'A':
 1508: #if defined(HAVE_CPU_AFFINITY)
 1509:                 test->affinity = strtol(optarg, &endptr, 0);
 1510:                 if (endptr == optarg ||
 1511: 		    test->affinity < 0 || test->affinity > 1024) {
 1512:                     i_errno = IEAFFINITY;
 1513:                     return -1;
 1514:                 }
 1515: 		comma = strchr(optarg, ',');
 1516: 		if (comma != NULL) {
 1517: 		    test->server_affinity = atoi(comma+1);
 1518: 		    if (test->server_affinity < 0 || test->server_affinity > 1024) {
 1519: 			i_errno = IEAFFINITY;
 1520: 			return -1;
 1521: 		    }
 1522: 		    client_flag = 1;
 1523: 		}
 1524: #else /* HAVE_CPU_AFFINITY */
 1525:                 i_errno = IEUNIMP;
 1526:                 return -1;
 1527: #endif /* HAVE_CPU_AFFINITY */
 1528:                 break;
 1529:             case 'T':
 1530:                 test->title = strdup(optarg);
 1531: 		client_flag = 1;
 1532:                 break;
 1533: 	    case 'C':
 1534: #if defined(HAVE_TCP_CONGESTION)
 1535: 		test->congestion = strdup(optarg);
 1536: 		client_flag = 1;
 1537: #else /* HAVE_TCP_CONGESTION */
 1538: 		i_errno = IEUNIMP;
 1539: 		return -1;
 1540: #endif /* HAVE_TCP_CONGESTION */
 1541: 		break;
 1542: 	    case 'd':
 1543: 		test->debug = 1;
 1544:                 test->debug_level = DEBUG_LEVEL_MAX;
 1545:                 if (optarg) {
 1546:                     test->debug_level = atoi(optarg);
 1547:                     if (test->debug_level < 0)
 1548:                         test->debug_level = DEBUG_LEVEL_MAX;
 1549:                 }
 1550: 		break;
 1551: 	    case 'I':
 1552: 		test->pidfile = strdup(optarg);
 1553: 	        break;
 1554: 	    case OPT_LOGFILE:
 1555: 		test->logfile = strdup(optarg);
 1556: 		break;
 1557: 	    case OPT_FORCEFLUSH:
 1558: 		test->forceflush = 1;
 1559: 		break;
 1560: 	    case OPT_GET_SERVER_OUTPUT:
 1561: 		test->get_server_output = 1;
 1562: 		client_flag = 1;
 1563: 		break;
 1564: 	    case OPT_UDP_COUNTERS_64BIT:
 1565: 		test->udp_counters_64bit = 1;
 1566: 		break;
 1567: 	    case OPT_NO_FQ_SOCKET_PACING:
 1568: #if defined(HAVE_SO_MAX_PACING_RATE)
 1569: 		printf("Warning:  --no-fq-socket-pacing is deprecated\n");
 1570: 		test->settings->fqrate = 0;
 1571: 		client_flag = 1;
 1572: #else /* HAVE_SO_MAX_PACING_RATE */
 1573: 		i_errno = IEUNIMP;
 1574: 		return -1;
 1575: #endif
 1576: 		break;
 1577: 	    case OPT_FQ_RATE:
 1578: #if defined(HAVE_SO_MAX_PACING_RATE)
 1579: 		test->settings->fqrate = unit_atof_rate(optarg);
 1580: 		client_flag = 1;
 1581: #else /* HAVE_SO_MAX_PACING_RATE */
 1582: 		i_errno = IEUNIMP;
 1583: 		return -1;
 1584: #endif
 1585: 		break;
 1586: #if defined(HAVE_DONT_FRAGMENT)
 1587:         case OPT_DONT_FRAGMENT:
 1588:             test->settings->dont_fragment = 1;
 1589:             client_flag = 1;
 1590:             break;
 1591: #endif /* HAVE_DONT_FRAGMENT */
 1592: #if defined(HAVE_SSL)
 1593:         case OPT_CLIENT_USERNAME:
 1594:             client_username = strdup(optarg);
 1595:             break;
 1596:         case OPT_CLIENT_RSA_PUBLIC_KEY:
 1597:             client_rsa_public_key = strdup(optarg);
 1598:             break;
 1599:         case OPT_SERVER_RSA_PRIVATE_KEY:
 1600:             server_rsa_private_key = strdup(optarg);
 1601:             break;
 1602:         case OPT_SERVER_AUTHORIZED_USERS:
 1603:             test->server_authorized_users = strdup(optarg);
 1604:             break;
 1605:         case OPT_SERVER_SKEW_THRESHOLD:
 1606:             test->server_skew_threshold = atoi(optarg);
 1607:             if(test->server_skew_threshold <= 0){
 1608:                 i_errno = IESKEWTHRESHOLD;
 1609:                 return -1;
 1610:             }
 1611:             break;
 1612: #endif /* HAVE_SSL */
 1613: 	    case OPT_PACING_TIMER:
 1614: 		test->settings->pacing_timer = unit_atoi(optarg);
 1615: 		client_flag = 1;
 1616: 		break;
 1617: 	    case OPT_CONNECT_TIMEOUT:
 1618: 		test->settings->connect_timeout = unit_atoi(optarg);
 1619: 		client_flag = 1;
 1620: 		break;
 1621: 	    case 'h':
 1622: 		usage_long(stdout);
 1623: 		exit(0);
 1624:             default:
 1625:                 fprintf(stderr, "\n");
 1626:                 usage();
 1627:                 exit(1);
 1628:         }
 1629:     }
 1630: 
 1631:     /* Check flag / role compatibility. */
 1632:     if (test->role == 'c' && server_flag) {
 1633:         i_errno = IESERVERONLY;
 1634:         return -1;
 1635:     }
 1636:     if (test->role == 's' && client_flag) {
 1637:         i_errno = IECLIENTONLY;
 1638:         return -1;
 1639:     }
 1640: 
 1641: #if defined(HAVE_SSL)
 1642: 
 1643:     if (test->role == 's' && (client_username || client_rsa_public_key)){
 1644:         i_errno = IECLIENTONLY;
 1645:         return -1;
 1646:     } else if (test->role == 'c' && (client_username || client_rsa_public_key) &&
 1647:         !(client_username && client_rsa_public_key)) {
 1648:         i_errno = IESETCLIENTAUTH;
 1649:         return -1;
 1650:     } else if (test->role == 'c' && (client_username && client_rsa_public_key)){
 1651: 
 1652:         char *client_password = NULL;
 1653:         size_t s;
 1654:         if (test_load_pubkey_from_file(client_rsa_public_key) < 0){
 1655:             iperf_err(test, "%s\n", ERR_error_string(ERR_get_error(), NULL));
 1656:             i_errno = IESETCLIENTAUTH;
 1657:             return -1;
 1658:         }
 1659:         /* Need to copy env var, so we can do a common free */
 1660:         if ((client_password = getenv("IPERF3_PASSWORD")) != NULL)
 1661:              client_password = strdup(client_password);
 1662:         else if (iperf_getpass(&client_password, &s, stdin) < 0){
 1663:             i_errno = IESETCLIENTAUTH;
 1664:             return -1;
 1665:         }
 1666: 
 1667:         test->settings->client_username = client_username;
 1668:         test->settings->client_password = client_password;
 1669:         test->settings->client_rsa_pubkey = load_pubkey_from_file(client_rsa_public_key);
 1670: 	free(client_rsa_public_key);
 1671: 	client_rsa_public_key = NULL;
 1672:     }
 1673: 
 1674:     if (test->role == 'c' && (server_rsa_private_key || test->server_authorized_users)){
 1675:         i_errno = IESERVERONLY;
 1676:         return -1;
 1677:     } else if (test->role == 'c' && (test->server_skew_threshold != 0)){
 1678:         i_errno = IESERVERONLY;
 1679:         return -1;
 1680:     } else if (test->role == 'c' && rcv_timeout_flag && test->mode == SENDER){
 1681:         i_errno = IERVRSONLYRCVTIMEOUT;
 1682:         return -1;
 1683:     } else if (test->role == 's' && (server_rsa_private_key || test->server_authorized_users) &&
 1684:         !(server_rsa_private_key && test->server_authorized_users)) {
 1685:          i_errno = IESETSERVERAUTH;
 1686:         return -1;
 1687:     } else if (test->role == 's' && server_rsa_private_key) {
 1688:         test->server_rsa_private_key = load_privkey_from_file(server_rsa_private_key);
 1689:         if (test->server_rsa_private_key == NULL){
 1690:             iperf_err(test, "%s\n", ERR_error_string(ERR_get_error(), NULL));
 1691:             i_errno = IESETSERVERAUTH;
 1692:             return -1;
 1693:         }
 1694: 	    free(server_rsa_private_key);
 1695: 	    server_rsa_private_key = NULL;
 1696: 
 1697:         if(test->server_skew_threshold == 0){
 1698:             // Set default value for time skew threshold
 1699:             test->server_skew_threshold=10;
 1700:         }
 1701:     }
 1702: 
 1703: #endif //HAVE_SSL
 1704: 
 1705:     // File cannot be transferred using UDP because of the UDP packets header (packet number, etc.)
 1706:     if(test->role == 'c' && test->diskfile_name != (char*) 0 && test->protocol->id == Pudp) {
 1707:         i_errno = IEUDPFILETRANSFER;
 1708:         return -1;
 1709:     }
 1710: 
 1711:     if (blksize == 0) {
 1712: 	if (test->protocol->id == Pudp)
 1713: 	    blksize = 0;	/* try to dynamically determine from MSS */
 1714: 	else if (test->protocol->id == Psctp)
 1715: 	    blksize = DEFAULT_SCTP_BLKSIZE;
 1716: 	else
 1717: 	    blksize = DEFAULT_TCP_BLKSIZE;
 1718:     }
 1719:     if ((test->protocol->id != Pudp && blksize <= 0)
 1720: 	|| blksize > MAX_BLOCKSIZE) {
 1721: 	i_errno = IEBLOCKSIZE;
 1722: 	return -1;
 1723:     }
 1724:     if (test->protocol->id == Pudp &&
 1725: 	(blksize > 0 &&
 1726: 	    (blksize < MIN_UDP_BLOCKSIZE || blksize > MAX_UDP_BLOCKSIZE))) {
 1727: 	i_errno = IEUDPBLOCKSIZE;
 1728: 	return -1;
 1729:     }
 1730:     test->settings->blksize = blksize;
 1731: 
 1732:     if (!rate_flag)
 1733: 	test->settings->rate = test->protocol->id == Pudp ? UDP_RATE : 0;
 1734: 
 1735:     /* if no bytes or blocks specified, nor a duration_flag, and we have -F,
 1736:     ** get the file-size as the bytes count to be transferred
 1737:     */
 1738:     if (test->settings->bytes == 0 &&
 1739:         test->settings->blocks == 0 &&
 1740:         ! duration_flag &&
 1741:         test->diskfile_name != (char*) 0 &&
 1742:         test->role == 'c'
 1743:         ){
 1744:         struct stat st;
 1745:         if( stat(test->diskfile_name, &st) == 0 ){
 1746:             iperf_size_t file_bytes = st.st_size;
 1747:             test->settings->bytes = file_bytes;
 1748:             if (test->debug)
 1749:                 printf("End condition set to file-size: %"PRIu64" bytes\n", test->settings->bytes);
 1750:         }
 1751:         // if failing to read file stat, it should fallback to default duration mode
 1752:     }
 1753: 
 1754:     if ((test->settings->bytes != 0 || test->settings->blocks != 0) && ! duration_flag)
 1755:         test->duration = 0;
 1756: 
 1757:     /* Disallow specifying multiple test end conditions. The code actually
 1758:     ** works just fine without this prohibition. As soon as any one of the
 1759:     ** three possible end conditions is met, the test ends. So this check
 1760:     ** could be removed if desired.
 1761:     */
 1762:     if ((duration_flag && test->settings->bytes != 0) ||
 1763:         (duration_flag && test->settings->blocks != 0) ||
 1764: 	(test->settings->bytes != 0 && test->settings->blocks != 0)) {
 1765:         i_errno = IEENDCONDITIONS;
 1766:         return -1;
 1767:     }
 1768: 
 1769:     /* For subsequent calls to getopt */
 1770: #ifdef __APPLE__
 1771:     optreset = 1;
 1772: #endif
 1773:     optind = 0;
 1774: 
 1775:     if ((test->role != 'c') && (test->role != 's')) {
 1776:         i_errno = IENOROLE;
 1777:         return -1;
 1778:     }
 1779: 
 1780:     /* Set Total-rate average interval to multiplicity of State interval */
 1781:     if (test->settings->bitrate_limit_interval != 0) {
 1782: 	test->settings->bitrate_limit_stats_per_interval =
 1783: 	    (test->settings->bitrate_limit_interval <= test->stats_interval ?
 1784: 	    1 : round(test->settings->bitrate_limit_interval/test->stats_interval) );
 1785:     }
 1786: 
 1787:     /* Show warning if JSON output is used with explicit report format */
 1788:     if ((test->json_output) && (test->settings->unit_format != 'a')) {
 1789:         warning("Report format (-f) flag ignored with JSON output (-J)");
 1790:     }
 1791: 
 1792:     /* Show warning if JSON output is used with verbose or debug flags */
 1793:     if (test->json_output && test->verbose) {
 1794:         warning("Verbose output (-v) may interfere with JSON output (-J)");
 1795:     }
 1796:     if (test->json_output && test->debug) {
 1797:         warning("Debug output (-d) may interfere with JSON output (-J)");
 1798:     }
 1799: 
 1800:     return 0;
 1801: }
 1802: 
 1803: /*
 1804:  * Open the file specified by test->logfile and set test->outfile to its' FD.
 1805:  */
 1806: int iperf_open_logfile(struct iperf_test *test)
 1807: {
 1808:     test->outfile = fopen(test->logfile, "a+");
 1809:     if (test->outfile == NULL) {
 1810:         i_errno = IELOGFILE;
 1811:         return -1;
 1812:     }
 1813: 
 1814:     return 0;
 1815: }
 1816: 
 1817: void iperf_close_logfile(struct iperf_test *test)
 1818: {
 1819:     if (test->outfile && test->outfile != stdout) {
 1820:         fclose(test->outfile);
 1821:         test->outfile = NULL;
 1822:     }
 1823: }
 1824: 
 1825: int
 1826: iperf_set_send_state(struct iperf_test *test, signed char state)
 1827: {
 1828:     if (test->ctrl_sck >= 0) {
 1829:         test->state = state;
 1830:         if (Nwrite(test->ctrl_sck, (char*) &state, sizeof(state), Ptcp) < 0) {
 1831: 	    i_errno = IESENDMESSAGE;
 1832: 	    return -1;
 1833:         }
 1834:     }
 1835:     return 0;
 1836: }
 1837: 
 1838: void
 1839: iperf_check_throttle(struct iperf_stream *sp, struct iperf_time *nowP)
 1840: {
 1841:     struct iperf_time temp_time;
 1842:     double seconds;
 1843:     uint64_t bits_per_second;
 1844: 
 1845:     if (sp->test->done || sp->test->settings->rate == 0)
 1846:         return;
 1847:     iperf_time_diff(&sp->result->start_time_fixed, nowP, &temp_time);
 1848:     seconds = iperf_time_in_secs(&temp_time);
 1849:     bits_per_second = sp->result->bytes_sent * 8 / seconds;
 1850:     if (bits_per_second < sp->test->settings->rate) {
 1851:         sp->green_light = 1;
 1852:         FD_SET(sp->socket, &sp->test->write_set);
 1853:     } else {
 1854:         sp->green_light = 0;
 1855:         FD_CLR(sp->socket, &sp->test->write_set);
 1856:     }
 1857: }
 1858: 
 1859: /* Verify that average traffic is not greater than the specified limit */
 1860: void
 1861: iperf_check_total_rate(struct iperf_test *test, iperf_size_t last_interval_bytes_transferred)
 1862: {
 1863:     double seconds;
 1864:     uint64_t bits_per_second;
 1865:     iperf_size_t total_bytes;
 1866:     int i;
 1867: 
 1868:     if (test->done || test->settings->bitrate_limit == 0)    // Continue only if check should be done
 1869:         return;
 1870: 
 1871:     /* Add last inetrval's transferred bytes to the array */
 1872:     if (++test->bitrate_limit_last_interval_index >= test->settings->bitrate_limit_stats_per_interval)
 1873:         test->bitrate_limit_last_interval_index = 0;
 1874:     test->bitrate_limit_intervals_traffic_bytes[test->bitrate_limit_last_interval_index] = last_interval_bytes_transferred;
 1875: 
 1876:     /* Ensure that enough stats periods passed to allow averaging throughput */
 1877:     test->bitrate_limit_stats_count += 1;
 1878:     if (test->bitrate_limit_stats_count < test->settings->bitrate_limit_stats_per_interval)
 1879:         return;
 1880: 
 1881:      /* Calculating total bytes traffic to be averaged */
 1882:     for (total_bytes = 0, i = 0; i < test->settings->bitrate_limit_stats_per_interval; i++) {
 1883:         total_bytes += test->bitrate_limit_intervals_traffic_bytes[i];
 1884:     }
 1885: 
 1886:     seconds = test->stats_interval * test->settings->bitrate_limit_stats_per_interval;
 1887:     bits_per_second = total_bytes * 8 / seconds;
 1888:     if (test->debug) {
 1889:         iperf_printf(test,"Interval %" PRIu64 " - throughput %" PRIu64 " bps (limit %" PRIu64 ")\n", test->bitrate_limit_stats_count, bits_per_second, test->settings->bitrate_limit);
 1890:     }
 1891: 
 1892:     if (bits_per_second  > test->settings->bitrate_limit) {
 1893:         if (iperf_get_verbose(test))
 1894:             iperf_err(test, "Total throughput of %" PRIu64 " bps exceeded %" PRIu64 " bps limit", bits_per_second, test->settings->bitrate_limit);
 1895: 	test->bitrate_limit_exceeded = 1;
 1896:     }
 1897: }
 1898: 
 1899: int
 1900: iperf_send(struct iperf_test *test, fd_set *write_setP)
 1901: {
 1902:     register int multisend, r, streams_active;
 1903:     register struct iperf_stream *sp;
 1904:     struct iperf_time now;
 1905:     int no_throttle_check;
 1906: 
 1907:     /* Can we do multisend mode? */
 1908:     if (test->settings->burst != 0)
 1909:         multisend = test->settings->burst;
 1910:     else if (test->settings->rate == 0)
 1911:         multisend = test->multisend;
 1912:     else
 1913:         multisend = 1;	/* nope */
 1914: 
 1915:     /* Should bitrate throttle be checked for every send */
 1916:     no_throttle_check = test->settings->rate != 0 && test->settings->burst == 0;
 1917: 
 1918:     for (; multisend > 0; --multisend) {
 1919: 	if (no_throttle_check)
 1920: 	    iperf_time_now(&now);
 1921: 	streams_active = 0;
 1922: 	SLIST_FOREACH(sp, &test->streams, streams) {
 1923: 	    if ((sp->green_light && sp->sender &&
 1924: 		 (write_setP == NULL || FD_ISSET(sp->socket, write_setP)))) {
 1925:         if (multisend > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes)
 1926:             break;
 1927:         if (multisend > 1 && test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks)
 1928:             break;
 1929: 		if ((r = sp->snd(sp)) < 0) {
 1930: 		    if (r == NET_SOFTERROR)
 1931: 			break;
 1932: 		    i_errno = IESTREAMWRITE;
 1933: 		    return r;
 1934: 		}
 1935: 		streams_active = 1;
 1936: 		test->bytes_sent += r;
 1937: 		if (!sp->pending_size)
 1938: 		    ++test->blocks_sent;
 1939:                 if (no_throttle_check)
 1940: 		    iperf_check_throttle(sp, &now);
 1941: 	    }
 1942: 	}
 1943: 	if (!streams_active)
 1944: 	    break;
 1945:     }
 1946:     if (!no_throttle_check) {   /* Throttle check if was not checked for each send */
 1947: 	iperf_time_now(&now);
 1948: 	SLIST_FOREACH(sp, &test->streams, streams)
 1949: 	    if (sp->sender)
 1950: 	        iperf_check_throttle(sp, &now);
 1951:     }
 1952:     if (write_setP != NULL)
 1953: 	SLIST_FOREACH(sp, &test->streams, streams)
 1954: 	    if (FD_ISSET(sp->socket, write_setP))
 1955: 		FD_CLR(sp->socket, write_setP);
 1956: 
 1957:     return 0;
 1958: }
 1959: 
 1960: int
 1961: iperf_recv(struct iperf_test *test, fd_set *read_setP)
 1962: {
 1963:     int r;
 1964:     struct iperf_stream *sp;
 1965: 
 1966:     SLIST_FOREACH(sp, &test->streams, streams) {
 1967: 	if (FD_ISSET(sp->socket, read_setP) && !sp->sender) {
 1968: 	    if ((r = sp->rcv(sp)) < 0) {
 1969: 		i_errno = IESTREAMREAD;
 1970: 		return r;
 1971: 	    }
 1972: 	    test->bytes_received += r;
 1973: 	    ++test->blocks_received;
 1974: 	    FD_CLR(sp->socket, read_setP);
 1975: 	}
 1976:     }
 1977: 
 1978:     return 0;
 1979: }
 1980: 
 1981: int
 1982: iperf_init_test(struct iperf_test *test)
 1983: {
 1984:     struct iperf_time now;
 1985:     struct iperf_stream *sp;
 1986: 
 1987:     if (test->protocol->init) {
 1988:         if (test->protocol->init(test) < 0)
 1989:             return -1;
 1990:     }
 1991: 
 1992:     /* Init each stream. */
 1993:     if (iperf_time_now(&now) < 0) {
 1994: 	i_errno = IEINITTEST;
 1995: 	return -1;
 1996:     }
 1997:     SLIST_FOREACH(sp, &test->streams, streams) {
 1998: 	sp->result->start_time = sp->result->start_time_fixed = now;
 1999:     }
 2000: 
 2001:     if (test->on_test_start)
 2002:         test->on_test_start(test);
 2003: 
 2004:     return 0;
 2005: }
 2006: 
 2007: static void
 2008: send_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
 2009: {
 2010:     struct iperf_stream *sp = client_data.p;
 2011: 
 2012:     /* All we do here is set or clear the flag saying that this stream may
 2013:     ** be sent to.  The actual sending gets done in the send proc, after
 2014:     ** checking the flag.
 2015:     */
 2016:     iperf_check_throttle(sp, nowP);
 2017: }
 2018: 
 2019: int
 2020: iperf_create_send_timers(struct iperf_test * test)
 2021: {
 2022:     struct iperf_time now;
 2023:     struct iperf_stream *sp;
 2024:     TimerClientData cd;
 2025: 
 2026:     if (iperf_time_now(&now) < 0) {
 2027: 	i_errno = IEINITTEST;
 2028: 	return -1;
 2029:     }
 2030:     SLIST_FOREACH(sp, &test->streams, streams) {
 2031:         sp->green_light = 1;
 2032: 	if (test->settings->rate != 0 && sp->sender) {
 2033: 	    cd.p = sp;
 2034: 	    sp->send_timer = tmr_create(NULL, send_timer_proc, cd, test->settings->pacing_timer, 1);
 2035: 	    if (sp->send_timer == NULL) {
 2036: 		i_errno = IEINITTEST;
 2037: 		return -1;
 2038: 	    }
 2039: 	}
 2040:     }
 2041:     return 0;
 2042: }
 2043: 
 2044: #if defined(HAVE_SSL)
 2045: int test_is_authorized(struct iperf_test *test){
 2046:     if ( !(test->server_rsa_private_key && test->server_authorized_users)) {
 2047:         return 0;
 2048:     }
 2049: 
 2050:     if (test->settings->authtoken){
 2051:         char *username = NULL, *password = NULL;
 2052:         time_t ts;
 2053:         int rc = decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts);
 2054: 	if (rc) {
 2055: 	    return -1;
 2056: 	}
 2057:         int ret = check_authentication(username, password, ts, test->server_authorized_users, test->server_skew_threshold);
 2058:         if (ret == 0){
 2059:             if (test->debug) {
 2060:               iperf_printf(test, report_authentication_succeeded, username, ts);
 2061:             }
 2062:             free(username);
 2063:             free(password);
 2064:             return 0;
 2065:         } else {
 2066:             if (test->debug) {
 2067:                 iperf_printf(test, report_authentication_failed, ret, username, ts);
 2068:             }
 2069:             free(username);
 2070:             free(password);
 2071:             return -1;
 2072:         }
 2073:     }
 2074:     return -1;
 2075: }
 2076: #endif //HAVE_SSL
 2077: 
 2078: /**
 2079:  * iperf_exchange_parameters - handles the param_Exchange part for client
 2080:  *
 2081:  */
 2082: 
 2083: int
 2084: iperf_exchange_parameters(struct iperf_test *test)
 2085: {
 2086:     int s;
 2087:     int32_t err;
 2088: 
 2089:     if (test->role == 'c') {
 2090: 
 2091:         if (send_parameters(test) < 0)
 2092:             return -1;
 2093: 
 2094:     } else {
 2095: 
 2096:         if (get_parameters(test) < 0)
 2097:             return -1;
 2098: 
 2099: #if defined(HAVE_SSL)
 2100:         if (test_is_authorized(test) < 0){
 2101:             if (iperf_set_send_state(test, SERVER_ERROR) != 0)
 2102:                 return -1;
 2103:             i_errno = IEAUTHTEST;
 2104:             err = htonl(i_errno);
 2105:             if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
 2106:                 i_errno = IECTRLWRITE;
 2107:                 return -1;
 2108:             }
 2109:             return -1;
 2110:         }
 2111: #endif //HAVE_SSL
 2112: 
 2113:         if ((s = test->protocol->listen(test)) < 0) {
 2114: 	        if (iperf_set_send_state(test, SERVER_ERROR) != 0)
 2115:                 return -1;
 2116:             err = htonl(i_errno);
 2117:             if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
 2118:                 i_errno = IECTRLWRITE;
 2119:                 return -1;
 2120:             }
 2121:             err = htonl(errno);
 2122:             if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
 2123:                 i_errno = IECTRLWRITE;
 2124:                 return -1;
 2125:             }
 2126:             return -1;
 2127:         }
 2128: 
 2129:         FD_SET(s, &test->read_set);
 2130:         test->max_fd = (s > test->max_fd) ? s : test->max_fd;
 2131:         test->prot_listener = s;
 2132: 
 2133:         // Send the control message to create streams and start the test
 2134: 	if (iperf_set_send_state(test, CREATE_STREAMS) != 0)
 2135:             return -1;
 2136: 
 2137:     }
 2138: 
 2139:     return 0;
 2140: }
 2141: 
 2142: /*************************************************************/
 2143: 
 2144: int
 2145: iperf_exchange_results(struct iperf_test *test)
 2146: {
 2147:     if (test->role == 'c') {
 2148:         /* Send results to server. */
 2149: 	if (send_results(test) < 0)
 2150:             return -1;
 2151:         /* Get server results. */
 2152:         if (get_results(test) < 0)
 2153:             return -1;
 2154:     } else {
 2155:         /* Get client results. */
 2156:         if (get_results(test) < 0)
 2157:             return -1;
 2158:         /* Send results to client. */
 2159: 	if (send_results(test) < 0)
 2160:             return -1;
 2161:     }
 2162:     return 0;
 2163: }
 2164: 
 2165: /*************************************************************/
 2166: 
 2167: static int
 2168: send_parameters(struct iperf_test *test)
 2169: {
 2170:     int r = 0;
 2171:     cJSON *j;
 2172: 
 2173:     j = cJSON_CreateObject();
 2174:     if (j == NULL) {
 2175: 	i_errno = IESENDPARAMS;
 2176: 	r = -1;
 2177:     } else {
 2178: 	if (test->protocol->id == Ptcp)
 2179: 	    cJSON_AddTrueToObject(j, "tcp");
 2180: 	else if (test->protocol->id == Pudp)
 2181: 	    cJSON_AddTrueToObject(j, "udp");
 2182:         else if (test->protocol->id == Psctp)
 2183:             cJSON_AddTrueToObject(j, "sctp");
 2184: 	cJSON_AddNumberToObject(j, "omit", test->omit);
 2185: 	if (test->server_affinity != -1)
 2186: 	    cJSON_AddNumberToObject(j, "server_affinity", test->server_affinity);
 2187: 	cJSON_AddNumberToObject(j, "time", test->duration);
 2188:         cJSON_AddNumberToObject(j, "num", test->settings->bytes);
 2189:         cJSON_AddNumberToObject(j, "blockcount", test->settings->blocks);
 2190: 	if (test->settings->mss)
 2191: 	    cJSON_AddNumberToObject(j, "MSS", test->settings->mss);
 2192: 	if (test->no_delay)
 2193: 	    cJSON_AddTrueToObject(j, "nodelay");
 2194: 	cJSON_AddNumberToObject(j, "parallel", test->num_streams);
 2195: 	if (test->reverse)
 2196: 	    cJSON_AddTrueToObject(j, "reverse");
 2197: 	if (test->bidirectional)
 2198: 	            cJSON_AddTrueToObject(j, "bidirectional");
 2199: 	if (test->settings->socket_bufsize)
 2200: 	    cJSON_AddNumberToObject(j, "window", test->settings->socket_bufsize);
 2201: 	if (test->settings->blksize)
 2202: 	    cJSON_AddNumberToObject(j, "len", test->settings->blksize);
 2203: 	if (test->settings->rate)
 2204: 	    cJSON_AddNumberToObject(j, "bandwidth", test->settings->rate);
 2205: 	if (test->settings->fqrate)
 2206: 	    cJSON_AddNumberToObject(j, "fqrate", test->settings->fqrate);
 2207: 	if (test->settings->pacing_timer)
 2208: 	    cJSON_AddNumberToObject(j, "pacing_timer", test->settings->pacing_timer);
 2209: 	if (test->settings->burst)
 2210: 	    cJSON_AddNumberToObject(j, "burst", test->settings->burst);
 2211: 	if (test->settings->tos)
 2212: 	    cJSON_AddNumberToObject(j, "TOS", test->settings->tos);
 2213: 	if (test->settings->flowlabel)
 2214: 	    cJSON_AddNumberToObject(j, "flowlabel", test->settings->flowlabel);
 2215: 	if (test->title)
 2216: 	    cJSON_AddStringToObject(j, "title", test->title);
 2217: 	if (test->extra_data)
 2218: 	    cJSON_AddStringToObject(j, "extra_data", test->extra_data);
 2219: 	if (test->congestion)
 2220: 	    cJSON_AddStringToObject(j, "congestion", test->congestion);
 2221: 	if (test->congestion_used)
 2222: 	    cJSON_AddStringToObject(j, "congestion_used", test->congestion_used);
 2223: 	if (test->get_server_output)
 2224: 	    cJSON_AddNumberToObject(j, "get_server_output", iperf_get_test_get_server_output(test));
 2225: 	if (test->udp_counters_64bit)
 2226: 	    cJSON_AddNumberToObject(j, "udp_counters_64bit", iperf_get_test_udp_counters_64bit(test));
 2227: 	if (test->repeating_payload)
 2228: 	    cJSON_AddNumberToObject(j, "repeating_payload", test->repeating_payload);
 2229: 	if (test->zerocopy)
 2230: 	    cJSON_AddNumberToObject(j, "zerocopy", test->zerocopy);
 2231: #if defined(HAVE_DONT_FRAGMENT)
 2232: 	if (test->settings->dont_fragment)
 2233: 	    cJSON_AddNumberToObject(j, "dont_fragment", test->settings->dont_fragment);
 2234: #endif /* HAVE_DONT_FRAGMENT */
 2235: #if defined(HAVE_SSL)
 2236: 	/* Send authentication parameters */
 2237: 	if (test->settings->client_username && test->settings->client_password && test->settings->client_rsa_pubkey){
 2238: 	    int rc = encode_auth_setting(test->settings->client_username, test->settings->client_password, test->settings->client_rsa_pubkey, &test->settings->authtoken);
 2239: 
 2240: 	    if (rc) {
 2241: 		cJSON_Delete(j);
 2242: 		i_errno = IESENDPARAMS;
 2243: 		return -1;
 2244: 	    }
 2245: 
 2246: 	    cJSON_AddStringToObject(j, "authtoken", test->settings->authtoken);
 2247: 	}
 2248: #endif // HAVE_SSL
 2249: 	cJSON_AddStringToObject(j, "client_version", IPERF_VERSION);
 2250: 
 2251: 	if (test->debug) {
 2252: 	    char *str = cJSON_Print(j);
 2253: 	    printf("send_parameters:\n%s\n", str);
 2254: 	    cJSON_free(str);
 2255: 	}
 2256: 
 2257: 	if (JSON_write(test->ctrl_sck, j) < 0) {
 2258: 	    i_errno = IESENDPARAMS;
 2259: 	    r = -1;
 2260: 	}
 2261: 	cJSON_Delete(j);
 2262:     }
 2263:     return r;
 2264: }
 2265: 
 2266: /*************************************************************/
 2267: 
 2268: static int
 2269: get_parameters(struct iperf_test *test)
 2270: {
 2271:     int r = 0;
 2272:     cJSON *j;
 2273:     cJSON *j_p;
 2274: 
 2275:     j = JSON_read(test->ctrl_sck);
 2276:     if (j == NULL) {
 2277: 	i_errno = IERECVPARAMS;
 2278:         r = -1;
 2279:     } else {
 2280: 	if (test->debug) {
 2281:             char *str;
 2282:             str = cJSON_Print(j);
 2283:             printf("get_parameters:\n%s\n", str );
 2284:             cJSON_free(str);
 2285: 	}
 2286: 
 2287: 	if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL)
 2288: 	    set_protocol(test, Ptcp);
 2289: 	if ((j_p = cJSON_GetObjectItem(j, "udp")) != NULL)
 2290: 	    set_protocol(test, Pudp);
 2291:         if ((j_p = cJSON_GetObjectItem(j, "sctp")) != NULL)
 2292:             set_protocol(test, Psctp);
 2293: 	if ((j_p = cJSON_GetObjectItem(j, "omit")) != NULL)
 2294: 	    test->omit = j_p->valueint;
 2295: 	if ((j_p = cJSON_GetObjectItem(j, "server_affinity")) != NULL)
 2296: 	    test->server_affinity = j_p->valueint;
 2297: 	if ((j_p = cJSON_GetObjectItem(j, "time")) != NULL)
 2298: 	    test->duration = j_p->valueint;
 2299:         test->settings->bytes = 0;
 2300: 	if ((j_p = cJSON_GetObjectItem(j, "num")) != NULL)
 2301: 	    test->settings->bytes = j_p->valueint;
 2302:         test->settings->blocks = 0;
 2303: 	if ((j_p = cJSON_GetObjectItem(j, "blockcount")) != NULL)
 2304: 	    test->settings->blocks = j_p->valueint;
 2305: 	if ((j_p = cJSON_GetObjectItem(j, "MSS")) != NULL)
 2306: 	    test->settings->mss = j_p->valueint;
 2307: 	if ((j_p = cJSON_GetObjectItem(j, "nodelay")) != NULL)
 2308: 	    test->no_delay = 1;
 2309: 	if ((j_p = cJSON_GetObjectItem(j, "parallel")) != NULL)
 2310: 	    test->num_streams = j_p->valueint;
 2311: 	if ((j_p = cJSON_GetObjectItem(j, "reverse")) != NULL)
 2312: 	    iperf_set_test_reverse(test, 1);
 2313:         if ((j_p = cJSON_GetObjectItem(j, "bidirectional")) != NULL)
 2314:             iperf_set_test_bidirectional(test, 1);
 2315: 	if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL)
 2316: 	    test->settings->socket_bufsize = j_p->valueint;
 2317: 	if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL)
 2318: 	    test->settings->blksize = j_p->valueint;
 2319: 	if ((j_p = cJSON_GetObjectItem(j, "bandwidth")) != NULL)
 2320: 	    test->settings->rate = j_p->valueint;
 2321: 	if ((j_p = cJSON_GetObjectItem(j, "fqrate")) != NULL)
 2322: 	    test->settings->fqrate = j_p->valueint;
 2323: 	if ((j_p = cJSON_GetObjectItem(j, "pacing_timer")) != NULL)
 2324: 	    test->settings->pacing_timer = j_p->valueint;
 2325: 	if ((j_p = cJSON_GetObjectItem(j, "burst")) != NULL)
 2326: 	    test->settings->burst = j_p->valueint;
 2327: 	if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL)
 2328: 	    test->settings->tos = j_p->valueint;
 2329: 	if ((j_p = cJSON_GetObjectItem(j, "flowlabel")) != NULL)
 2330: 	    test->settings->flowlabel = j_p->valueint;
 2331: 	if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL)
 2332: 	    test->title = strdup(j_p->valuestring);
 2333: 	if ((j_p = cJSON_GetObjectItem(j, "extra_data")) != NULL)
 2334: 	    test->extra_data = strdup(j_p->valuestring);
 2335: 	if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL)
 2336: 	    test->congestion = strdup(j_p->valuestring);
 2337: 	if ((j_p = cJSON_GetObjectItem(j, "congestion_used")) != NULL)
 2338: 	    test->congestion_used = strdup(j_p->valuestring);
 2339: 	if ((j_p = cJSON_GetObjectItem(j, "get_server_output")) != NULL)
 2340: 	    iperf_set_test_get_server_output(test, 1);
 2341: 	if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL)
 2342: 	    iperf_set_test_udp_counters_64bit(test, 1);
 2343: 	if ((j_p = cJSON_GetObjectItem(j, "repeating_payload")) != NULL)
 2344: 	    test->repeating_payload = 1;
 2345: 	if ((j_p = cJSON_GetObjectItem(j, "zerocopy")) != NULL)
 2346: 	    test->zerocopy = j_p->valueint;
 2347: #if defined(HAVE_DONT_FRAGMENT)
 2348: 	if ((j_p = cJSON_GetObjectItem(j, "dont_fragment")) != NULL)
 2349: 	    test->settings->dont_fragment = j_p->valueint;
 2350: #endif /* HAVE_DONT_FRAGMENT */
 2351: #if defined(HAVE_SSL)
 2352: 	if ((j_p = cJSON_GetObjectItem(j, "authtoken")) != NULL)
 2353:         test->settings->authtoken = strdup(j_p->valuestring);
 2354: #endif //HAVE_SSL
 2355: 	if (test->mode && test->protocol->id == Ptcp && has_tcpinfo_retransmits())
 2356: 	    test->sender_has_retransmits = 1;
 2357: 	if (test->settings->rate)
 2358: 	    cJSON_AddNumberToObject(test->json_start, "target_bitrate", test->settings->rate);
 2359: 	cJSON_Delete(j);
 2360:     }
 2361:     return r;
 2362: }
 2363: 
 2364: /*************************************************************/
 2365: 
 2366: static int
 2367: send_results(struct iperf_test *test)
 2368: {
 2369:     int r = 0;
 2370:     cJSON *j;
 2371:     cJSON *j_streams;
 2372:     struct iperf_stream *sp;
 2373:     cJSON *j_stream;
 2374:     int sender_has_retransmits;
 2375:     iperf_size_t bytes_transferred;
 2376:     int retransmits;
 2377:     struct iperf_time temp_time;
 2378:     double start_time, end_time;
 2379: 
 2380:     j = cJSON_CreateObject();
 2381:     if (j == NULL) {
 2382: 	i_errno = IEPACKAGERESULTS;
 2383: 	r = -1;
 2384:     } else {
 2385: 	cJSON_AddNumberToObject(j, "cpu_util_total", test->cpu_util[0]);
 2386: 	cJSON_AddNumberToObject(j, "cpu_util_user", test->cpu_util[1]);
 2387: 	cJSON_AddNumberToObject(j, "cpu_util_system", test->cpu_util[2]);
 2388: 	if ( test->mode == RECEIVER )
 2389: 	    sender_has_retransmits = -1;
 2390: 	else
 2391: 	    sender_has_retransmits = test->sender_has_retransmits;
 2392: 	cJSON_AddNumberToObject(j, "sender_has_retransmits", sender_has_retransmits);
 2393: 	if ( test->congestion_used ) {
 2394: 	    cJSON_AddStringToObject(j, "congestion_used", test->congestion_used);
 2395: 	}
 2396: 
 2397: 	/* If on the server and sending server output, then do this */
 2398: 	if (test->role == 's' && test->get_server_output) {
 2399: 	    if (test->json_output) {
 2400: 		/* Add JSON output */
 2401: 		cJSON_AddItemReferenceToObject(j, "server_output_json", test->json_top);
 2402: 	    }
 2403: 	    else {
 2404: 		/* Add textual output */
 2405: 		size_t buflen = 0;
 2406: 
 2407: 		/* Figure out how much room we need to hold the complete output string */
 2408: 		struct iperf_textline *t;
 2409: 		TAILQ_FOREACH(t, &(test->server_output_list), textlineentries) {
 2410: 		    buflen += strlen(t->line);
 2411: 		}
 2412: 
 2413: 		/* Allocate and build it up from the component lines */
 2414: 		char *output = calloc(buflen + 1, 1);
 2415: 		TAILQ_FOREACH(t, &(test->server_output_list), textlineentries) {
 2416: 		    strncat(output, t->line, buflen);
 2417: 		    buflen -= strlen(t->line);
 2418: 		}
 2419: 
 2420: 		cJSON_AddStringToObject(j, "server_output_text", output);
 2421:         free(output);
 2422: 	    }
 2423: 	}
 2424: 
 2425: 	j_streams = cJSON_CreateArray();
 2426: 	if (j_streams == NULL) {
 2427: 	    i_errno = IEPACKAGERESULTS;
 2428: 	    r = -1;
 2429: 	} else {
 2430: 	    cJSON_AddItemToObject(j, "streams", j_streams);
 2431: 	    SLIST_FOREACH(sp, &test->streams, streams) {
 2432: 		j_stream = cJSON_CreateObject();
 2433: 		if (j_stream == NULL) {
 2434: 		    i_errno = IEPACKAGERESULTS;
 2435: 		    r = -1;
 2436: 		} else {
 2437: 		    cJSON_AddItemToArray(j_streams, j_stream);
 2438: 		    bytes_transferred = sp->sender ? (sp->result->bytes_sent - sp->result->bytes_sent_omit) : sp->result->bytes_received;
 2439: 		    retransmits = (sp->sender && test->sender_has_retransmits) ? sp->result->stream_retrans : -1;
 2440: 		    cJSON_AddNumberToObject(j_stream, "id", sp->id);
 2441: 		    cJSON_AddNumberToObject(j_stream, "bytes", bytes_transferred);
 2442: 		    cJSON_AddNumberToObject(j_stream, "retransmits", retransmits);
 2443: 		    cJSON_AddNumberToObject(j_stream, "jitter", sp->jitter);
 2444: 		    cJSON_AddNumberToObject(j_stream, "errors", sp->cnt_error);
 2445:                     cJSON_AddNumberToObject(j_stream, "omitted_errors", sp->omitted_cnt_error);
 2446: 		    cJSON_AddNumberToObject(j_stream, "packets", sp->packet_count);
 2447:                     cJSON_AddNumberToObject(j_stream, "omitted_packets", sp->omitted_packet_count);
 2448: 
 2449: 		    iperf_time_diff(&sp->result->start_time, &sp->result->start_time, &temp_time);
 2450: 		    start_time = iperf_time_in_secs(&temp_time);
 2451: 		    iperf_time_diff(&sp->result->start_time, &sp->result->end_time, &temp_time);
 2452: 		    end_time = iperf_time_in_secs(&temp_time);
 2453: 		    cJSON_AddNumberToObject(j_stream, "start_time", start_time);
 2454: 		    cJSON_AddNumberToObject(j_stream, "end_time", end_time);
 2455: 
 2456: 		}
 2457: 	    }
 2458: 	    if (r == 0 && test->debug) {
 2459:                 char *str = cJSON_Print(j);
 2460: 		printf("send_results\n%s\n", str);
 2461:                 cJSON_free(str);
 2462: 	    }
 2463: 	    if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) {
 2464: 		i_errno = IESENDRESULTS;
 2465: 		r = -1;
 2466: 	    }
 2467: 	}
 2468: 	cJSON_Delete(j);
 2469:     }
 2470:     return r;
 2471: }
 2472: 
 2473: /*************************************************************/
 2474: 
 2475: static int
 2476: get_results(struct iperf_test *test)
 2477: {
 2478:     int r = 0;
 2479:     cJSON *j;
 2480:     cJSON *j_cpu_util_total;
 2481:     cJSON *j_cpu_util_user;
 2482:     cJSON *j_cpu_util_system;
 2483:     cJSON *j_remote_congestion_used;
 2484:     cJSON *j_sender_has_retransmits;
 2485:     int result_has_retransmits;
 2486:     cJSON *j_streams;
 2487:     int n, i;
 2488:     cJSON *j_stream;
 2489:     cJSON *j_id;
 2490:     cJSON *j_bytes;
 2491:     cJSON *j_retransmits;
 2492:     cJSON *j_jitter;
 2493:     cJSON *j_errors;
 2494:     cJSON *j_omitted_errors;
 2495:     cJSON *j_packets;
 2496:     cJSON *j_omitted_packets;
 2497:     cJSON *j_server_output;
 2498:     cJSON *j_start_time, *j_end_time;
 2499:     int sid;
 2500:     int64_t cerror, pcount, omitted_cerror, omitted_pcount;
 2501:     double jitter;
 2502:     iperf_size_t bytes_transferred;
 2503:     int retransmits;
 2504:     struct iperf_stream *sp;
 2505: 
 2506:     j = JSON_read(test->ctrl_sck);
 2507:     if (j == NULL) {
 2508: 	i_errno = IERECVRESULTS;
 2509:         r = -1;
 2510:     } else {
 2511: 	j_cpu_util_total = cJSON_GetObjectItem(j, "cpu_util_total");
 2512: 	j_cpu_util_user = cJSON_GetObjectItem(j, "cpu_util_user");
 2513: 	j_cpu_util_system = cJSON_GetObjectItem(j, "cpu_util_system");
 2514: 	j_sender_has_retransmits = cJSON_GetObjectItem(j, "sender_has_retransmits");
 2515: 	if (j_cpu_util_total == NULL || j_cpu_util_user == NULL || j_cpu_util_system == NULL || j_sender_has_retransmits == NULL) {
 2516: 	    i_errno = IERECVRESULTS;
 2517: 	    r = -1;
 2518: 	} else {
 2519: 	    if (test->debug) {
 2520:                 char *str = cJSON_Print(j);
 2521:                 printf("get_results\n%s\n", str);
 2522:                 cJSON_free(str);
 2523: 	    }
 2524: 
 2525: 	    test->remote_cpu_util[0] = j_cpu_util_total->valuedouble;
 2526: 	    test->remote_cpu_util[1] = j_cpu_util_user->valuedouble;
 2527: 	    test->remote_cpu_util[2] = j_cpu_util_system->valuedouble;
 2528: 	    result_has_retransmits = j_sender_has_retransmits->valueint;
 2529: 	    if ( test->mode == RECEIVER ) {
 2530: 	        test->sender_has_retransmits = result_has_retransmits;
 2531: 	        test->other_side_has_retransmits = 0;
 2532: 	    }
 2533: 	    else if ( test->mode == BIDIRECTIONAL )
 2534: 	        test->other_side_has_retransmits = result_has_retransmits;
 2535: 
 2536: 	    j_streams = cJSON_GetObjectItem(j, "streams");
 2537: 	    if (j_streams == NULL) {
 2538: 		i_errno = IERECVRESULTS;
 2539: 		r = -1;
 2540: 	    } else {
 2541: 	        n = cJSON_GetArraySize(j_streams);
 2542: 		for (i=0; i<n; ++i) {
 2543: 		    j_stream = cJSON_GetArrayItem(j_streams, i);
 2544: 		    if (j_stream == NULL) {
 2545: 			i_errno = IERECVRESULTS;
 2546: 			r = -1;
 2547: 		    } else {
 2548: 			j_id = cJSON_GetObjectItem(j_stream, "id");
 2549: 			j_bytes = cJSON_GetObjectItem(j_stream, "bytes");
 2550: 			j_retransmits = cJSON_GetObjectItem(j_stream, "retransmits");
 2551: 			j_jitter = cJSON_GetObjectItem(j_stream, "jitter");
 2552: 			j_errors = cJSON_GetObjectItem(j_stream, "errors");
 2553:                         j_omitted_errors = cJSON_GetObjectItem(j_stream, "omitted_errors");
 2554: 			j_packets = cJSON_GetObjectItem(j_stream, "packets");
 2555:                         j_omitted_packets = cJSON_GetObjectItem(j_stream, "omitted_packets");
 2556: 			j_start_time = cJSON_GetObjectItem(j_stream, "start_time");
 2557: 			j_end_time = cJSON_GetObjectItem(j_stream, "end_time");
 2558: 			if (j_id == NULL || j_bytes == NULL || j_retransmits == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) {
 2559: 			    i_errno = IERECVRESULTS;
 2560: 			    r = -1;
 2561:                         } else if ( (j_omitted_errors == NULL && j_omitted_packets != NULL) || (j_omitted_errors != NULL && j_omitted_packets == NULL) ) {
 2562:                             /* For backward compatibility allow to not receive "omitted" statistcs */
 2563:                             i_errno = IERECVRESULTS;
 2564: 			    r = -1;
 2565: 			} else {
 2566: 			    sid = j_id->valueint;
 2567: 			    bytes_transferred = j_bytes->valueint;
 2568: 			    retransmits = j_retransmits->valueint;
 2569: 			    jitter = j_jitter->valuedouble;
 2570: 			    cerror = j_errors->valueint;
 2571: 			    pcount = j_packets->valueint;
 2572:                             if (j_omitted_packets != NULL) {
 2573:                                 omitted_cerror = j_omitted_errors->valueint;
 2574:                                 omitted_pcount = j_omitted_packets->valueint;
 2575:                             }
 2576: 			    SLIST_FOREACH(sp, &test->streams, streams)
 2577: 				if (sp->id == sid) break;
 2578: 			    if (sp == NULL) {
 2579: 				i_errno = IESTREAMID;
 2580: 				r = -1;
 2581: 			    } else {
 2582: 				if (sp->sender) {
 2583: 				    sp->jitter = jitter;
 2584: 				    sp->cnt_error = cerror;
 2585: 				    sp->peer_packet_count = pcount;
 2586: 				    sp->result->bytes_received = bytes_transferred;
 2587:                                     if (j_omitted_packets != NULL) {
 2588:                                         sp->omitted_cnt_error = omitted_cerror;
 2589:                                         sp->peer_omitted_packet_count = omitted_pcount;
 2590:                                     } else {
 2591:                                         sp->peer_omitted_packet_count = sp->omitted_packet_count;
 2592:                                         if (sp->peer_omitted_packet_count > 0) {
 2593:                                             /* -1 indicates unknown error count since it includes the omitted count */
 2594:                                             sp->omitted_cnt_error = (sp->cnt_error > 0) ? -1 : 0;
 2595:                                         } else {
 2596:                                             sp->omitted_cnt_error = sp->cnt_error;
 2597:                                         }
 2598:                                     }
 2599: 				    /*
 2600: 				     * We have to handle the possibility that
 2601: 				     * start_time and end_time might not be
 2602: 				     * available; this is the case for older (pre-3.2)
 2603: 				     * servers.
 2604: 				     *
 2605: 				     * We need to have result structure members to hold
 2606: 				     * the both sides' start_time and end_time.
 2607: 				     */
 2608: 				    if (j_start_time && j_end_time) {
 2609: 					sp->result->receiver_time = j_end_time->valuedouble - j_start_time->valuedouble;
 2610: 				    }
 2611: 				    else {
 2612: 					sp->result->receiver_time = 0.0;
 2613: 				    }
 2614: 				} else {
 2615: 				    sp->peer_packet_count = pcount;
 2616: 				    sp->result->bytes_sent = bytes_transferred;
 2617: 				    sp->result->stream_retrans = retransmits;
 2618:                                     if (j_omitted_packets != NULL) {
 2619:                                         sp->peer_omitted_packet_count = omitted_pcount;
 2620:                                     } else {
 2621:                                         sp->peer_omitted_packet_count = sp->peer_packet_count;
 2622:                                     }
 2623: 				    if (j_start_time && j_end_time) {
 2624: 					sp->result->sender_time = j_end_time->valuedouble - j_start_time->valuedouble;
 2625: 				    }
 2626: 				    else {
 2627: 					sp->result->sender_time = 0.0;
 2628: 				    }
 2629: 				}
 2630: 			    }
 2631: 			}
 2632: 		    }
 2633: 		}
 2634: 		/*
 2635: 		 * If we're the client and we're supposed to get remote results,
 2636: 		 * look them up and process accordingly.
 2637: 		 */
 2638: 		if (test->role == 'c' && iperf_get_test_get_server_output(test)) {
 2639: 		    /* Look for JSON.  If we find it, grab the object so it doesn't get deleted. */
 2640: 		    j_server_output = cJSON_DetachItemFromObject(j, "server_output_json");
 2641: 		    if (j_server_output != NULL) {
 2642: 			test->json_server_output = j_server_output;
 2643: 		    }
 2644: 		    else {
 2645: 			/* No JSON, look for textual output.  Make a copy of the text for later. */
 2646: 			j_server_output = cJSON_GetObjectItem(j, "server_output_text");
 2647: 			if (j_server_output != NULL) {
 2648: 			    test->server_output_text = strdup(j_server_output->valuestring);
 2649: 			}
 2650: 		    }
 2651: 		}
 2652: 	    }
 2653: 	}
 2654: 
 2655: 	j_remote_congestion_used = cJSON_GetObjectItem(j, "congestion_used");
 2656: 	if (j_remote_congestion_used != NULL) {
 2657: 	    test->remote_congestion_used = strdup(j_remote_congestion_used->valuestring);
 2658: 	}
 2659: 
 2660: 	cJSON_Delete(j);
 2661:     }
 2662:     return r;
 2663: }
 2664: 
 2665: /*************************************************************/
 2666: 
 2667: static int
 2668: JSON_write(int fd, cJSON *json)
 2669: {
 2670:     uint32_t hsize, nsize;
 2671:     char *str;
 2672:     int r = 0;
 2673: 
 2674:     str = cJSON_PrintUnformatted(json);
 2675:     if (str == NULL)
 2676: 	r = -1;
 2677:     else {
 2678: 	hsize = strlen(str);
 2679: 	nsize = htonl(hsize);
 2680: 	if (Nwrite(fd, (char*) &nsize, sizeof(nsize), Ptcp) < 0)
 2681: 	    r = -1;
 2682: 	else {
 2683: 	    if (Nwrite(fd, str, hsize, Ptcp) < 0)
 2684: 		r = -1;
 2685: 	}
 2686: 	cJSON_free(str);
 2687:     }
 2688:     return r;
 2689: }
 2690: 
 2691: /*************************************************************/
 2692: 
 2693: static cJSON *
 2694: JSON_read(int fd)
 2695: {
 2696:     uint32_t hsize, nsize;
 2697:     size_t strsize;
 2698:     char *str;
 2699:     cJSON *json = NULL;
 2700:     int rc;
 2701: 
 2702:     /*
 2703:      * Read a four-byte integer, which is the length of the JSON to follow.
 2704:      * Then read the JSON into a buffer and parse it.  Return a parsed JSON
 2705:      * structure, NULL if there was an error.
 2706:      */
 2707:     if (Nread(fd, (char*) &nsize, sizeof(nsize), Ptcp) >= 0) {
 2708: 	hsize = ntohl(nsize);
 2709: 	/* Allocate a buffer to hold the JSON */
 2710: 	strsize = hsize + 1;              /* +1 for trailing NULL */
 2711: 	if (strsize) {
 2712: 	str = (char *) calloc(sizeof(char), strsize);
 2713: 	if (str != NULL) {
 2714: 	    rc = Nread(fd, str, hsize, Ptcp);
 2715: 	    if (rc >= 0) {
 2716: 		/*
 2717: 		 * We should be reading in the number of bytes corresponding to the
 2718: 		 * length in that 4-byte integer.  If we don't the socket might have
 2719: 		 * prematurely closed.  Only do the JSON parsing if we got the
 2720: 		 * correct number of bytes.
 2721: 		 */
 2722: 		if (rc == hsize) {
 2723: 		    json = cJSON_Parse(str);
 2724: 		}
 2725: 		else {
 2726: 		    printf("WARNING:  Size of data read does not correspond to offered length\n");
 2727: 		}
 2728: 	    }
 2729: 	}
 2730: 	free(str);
 2731: 	}
 2732: 	else {
 2733: 	    printf("WARNING:  Data length overflow\n");
 2734: 	}
 2735:     }
 2736:     return json;
 2737: }
 2738: 
 2739: /*************************************************************/
 2740: /**
 2741:  * add_to_interval_list -- adds new interval to the interval_list
 2742:  */
 2743: 
 2744: void
 2745: add_to_interval_list(struct iperf_stream_result * rp, struct iperf_interval_results * new)
 2746: {
 2747:     struct iperf_interval_results *irp;
 2748: 
 2749:     irp = (struct iperf_interval_results *) malloc(sizeof(struct iperf_interval_results));
 2750:     memcpy(irp, new, sizeof(struct iperf_interval_results));
 2751:     TAILQ_INSERT_TAIL(&rp->interval_results, irp, irlistentries);
 2752: }
 2753: 
 2754: 
 2755: /************************************************************/
 2756: 
 2757: /**
 2758:  * connect_msg -- displays connection message
 2759:  * denoting sender/receiver details
 2760:  *
 2761:  */
 2762: 
 2763: void
 2764: connect_msg(struct iperf_stream *sp)
 2765: {
 2766:     char ipl[INET6_ADDRSTRLEN], ipr[INET6_ADDRSTRLEN];
 2767:     int lport, rport;
 2768: 
 2769:     if (getsockdomain(sp->socket) == AF_INET) {
 2770:         inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->local_addr)->sin_addr, ipl, sizeof(ipl));
 2771: 	mapped_v4_to_regular_v4(ipl);
 2772:         inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->remote_addr)->sin_addr, ipr, sizeof(ipr));
 2773: 	mapped_v4_to_regular_v4(ipr);
 2774:         lport = ntohs(((struct sockaddr_in *) &sp->local_addr)->sin_port);
 2775:         rport = ntohs(((struct sockaddr_in *) &sp->remote_addr)->sin_port);
 2776:     } else {
 2777:         inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->local_addr)->sin6_addr, ipl, sizeof(ipl));
 2778: 	mapped_v4_to_regular_v4(ipl);
 2779:         inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->remote_addr)->sin6_addr, ipr, sizeof(ipr));
 2780: 	mapped_v4_to_regular_v4(ipr);
 2781:         lport = ntohs(((struct sockaddr_in6 *) &sp->local_addr)->sin6_port);
 2782:         rport = ntohs(((struct sockaddr_in6 *) &sp->remote_addr)->sin6_port);
 2783:     }
 2784: 
 2785:     if (sp->test->json_output)
 2786:         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));
 2787:     else
 2788: 	iperf_printf(sp->test, report_connected, sp->socket, ipl, lport, ipr, rport);
 2789: }
 2790: 
 2791: 
 2792: /**************************************************************************/
 2793: 
 2794: struct iperf_test *
 2795: iperf_new_test()
 2796: {
 2797:     struct iperf_test *test;
 2798: 
 2799:     test = (struct iperf_test *) malloc(sizeof(struct iperf_test));
 2800:     if (!test) {
 2801:         i_errno = IENEWTEST;
 2802:         return NULL;
 2803:     }
 2804:     /* initialize everything to zero */
 2805:     memset(test, 0, sizeof(struct iperf_test));
 2806: 
 2807:     test->settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings));
 2808:     if (!test->settings) {
 2809:         free(test);
 2810: 	i_errno = IENEWTEST;
 2811: 	return NULL;
 2812:     }
 2813:     memset(test->settings, 0, sizeof(struct iperf_settings));
 2814: 
 2815:     test->bitrate_limit_intervals_traffic_bytes = (iperf_size_t *) malloc(sizeof(iperf_size_t) * MAX_INTERVAL);
 2816:     if (!test->bitrate_limit_intervals_traffic_bytes) {
 2817:         free(test->settings);
 2818:         free(test);
 2819: 	i_errno = IENEWTEST;
 2820: 	return NULL;
 2821:     }
 2822:     memset(test->bitrate_limit_intervals_traffic_bytes, 0, sizeof(sizeof(iperf_size_t) * MAX_INTERVAL));
 2823: 
 2824:     /* By default all output goes to stdout */
 2825:     test->outfile = stdout;
 2826: 
 2827:     return test;
 2828: }
 2829: 
 2830: /**************************************************************************/
 2831: 
 2832: struct protocol *
 2833: protocol_new(void)
 2834: {
 2835:     struct protocol *proto;
 2836: 
 2837:     proto = malloc(sizeof(struct protocol));
 2838:     if(!proto) {
 2839:         return NULL;
 2840:     }
 2841:     memset(proto, 0, sizeof(struct protocol));
 2842: 
 2843:     return proto;
 2844: }
 2845: 
 2846: void
 2847: protocol_free(struct protocol *proto)
 2848: {
 2849:     free(proto);
 2850: }
 2851: 
 2852: /**************************************************************************/
 2853: int
 2854: iperf_defaults(struct iperf_test *testp)
 2855: {
 2856:     struct protocol *tcp, *udp;
 2857: #if defined(HAVE_SCTP_H)
 2858:     struct protocol *sctp;
 2859: #endif /* HAVE_SCTP_H */
 2860: 
 2861:     testp->omit = OMIT;
 2862:     testp->duration = DURATION;
 2863:     testp->diskfile_name = (char*) 0;
 2864:     testp->affinity = -1;
 2865:     testp->server_affinity = -1;
 2866:     TAILQ_INIT(&testp->xbind_addrs);
 2867: #if defined(HAVE_CPUSET_SETAFFINITY)
 2868:     CPU_ZERO(&testp->cpumask);
 2869: #endif /* HAVE_CPUSET_SETAFFINITY */
 2870:     testp->title = NULL;
 2871:     testp->extra_data = NULL;
 2872:     testp->congestion = NULL;
 2873:     testp->congestion_used = NULL;
 2874:     testp->remote_congestion_used = NULL;
 2875:     testp->server_port = PORT;
 2876:     testp->ctrl_sck = -1;
 2877:     testp->listener = -1;
 2878:     testp->prot_listener = -1;
 2879:     testp->other_side_has_retransmits = 0;
 2880: 
 2881:     testp->stats_callback = iperf_stats_callback;
 2882:     testp->reporter_callback = iperf_reporter_callback;
 2883: 
 2884:     testp->stats_interval = testp->reporter_interval = 1;
 2885:     testp->num_streams = 1;
 2886: 
 2887:     testp->settings->domain = AF_UNSPEC;
 2888:     testp->settings->unit_format = 'a';
 2889:     testp->settings->socket_bufsize = 0;    /* use autotuning */
 2890:     testp->settings->blksize = DEFAULT_TCP_BLKSIZE;
 2891:     testp->settings->rate = 0;
 2892:     testp->settings->bitrate_limit = 0;
 2893:     testp->settings->bitrate_limit_interval = 5;
 2894:     testp->settings->bitrate_limit_stats_per_interval = 0;
 2895:     testp->settings->fqrate = 0;
 2896:     testp->settings->pacing_timer = DEFAULT_PACING_TIMER;
 2897:     testp->settings->burst = 0;
 2898:     testp->settings->mss = 0;
 2899:     testp->settings->bytes = 0;
 2900:     testp->settings->blocks = 0;
 2901:     testp->settings->connect_timeout = -1;
 2902:     testp->settings->rcv_timeout.secs = DEFAULT_NO_MSG_RCVD_TIMEOUT / SEC_TO_mS;
 2903:     testp->settings->rcv_timeout.usecs = (DEFAULT_NO_MSG_RCVD_TIMEOUT % SEC_TO_mS) * mS_TO_US;
 2904:     testp->zerocopy = 0;
 2905: 
 2906:     memset(testp->cookie, 0, COOKIE_SIZE);
 2907: 
 2908:     testp->multisend = 10;	/* arbitrary */
 2909: 
 2910:     /* Set up protocol list */
 2911:     SLIST_INIT(&testp->streams);
 2912:     SLIST_INIT(&testp->protocols);
 2913: 
 2914:     tcp = protocol_new();
 2915:     if (!tcp)
 2916:         return -1;
 2917: 
 2918:     tcp->id = Ptcp;
 2919:     tcp->name = "TCP";
 2920:     tcp->accept = iperf_tcp_accept;
 2921:     tcp->listen = iperf_tcp_listen;
 2922:     tcp->connect = iperf_tcp_connect;
 2923:     tcp->send = iperf_tcp_send;
 2924:     tcp->recv = iperf_tcp_recv;
 2925:     tcp->init = NULL;
 2926:     SLIST_INSERT_HEAD(&testp->protocols, tcp, protocols);
 2927: 
 2928:     udp = protocol_new();
 2929:     if (!udp) {
 2930:         protocol_free(tcp);
 2931:         return -1;
 2932:     }
 2933: 
 2934:     udp->id = Pudp;
 2935:     udp->name = "UDP";
 2936:     udp->accept = iperf_udp_accept;
 2937:     udp->listen = iperf_udp_listen;
 2938:     udp->connect = iperf_udp_connect;
 2939:     udp->send = iperf_udp_send;
 2940:     udp->recv = iperf_udp_recv;
 2941:     udp->init = iperf_udp_init;
 2942:     SLIST_INSERT_AFTER(tcp, udp, protocols);
 2943: 
 2944:     set_protocol(testp, Ptcp);
 2945: 
 2946: #if defined(HAVE_SCTP_H)
 2947:     sctp = protocol_new();
 2948:     if (!sctp) {
 2949:         protocol_free(tcp);
 2950:         protocol_free(udp);
 2951:         return -1;
 2952:     }
 2953: 
 2954:     sctp->id = Psctp;
 2955:     sctp->name = "SCTP";
 2956:     sctp->accept = iperf_sctp_accept;
 2957:     sctp->listen = iperf_sctp_listen;
 2958:     sctp->connect = iperf_sctp_connect;
 2959:     sctp->send = iperf_sctp_send;
 2960:     sctp->recv = iperf_sctp_recv;
 2961:     sctp->init = iperf_sctp_init;
 2962: 
 2963:     SLIST_INSERT_AFTER(udp, sctp, protocols);
 2964: #endif /* HAVE_SCTP_H */
 2965: 
 2966:     testp->on_new_stream = iperf_on_new_stream;
 2967:     testp->on_test_start = iperf_on_test_start;
 2968:     testp->on_connect = iperf_on_connect;
 2969:     testp->on_test_finish = iperf_on_test_finish;
 2970: 
 2971:     TAILQ_INIT(&testp->server_output_list);
 2972: 
 2973:     return 0;
 2974: }
 2975: 
 2976: 
 2977: /**************************************************************************/
 2978: void
 2979: iperf_free_test(struct iperf_test *test)
 2980: {
 2981:     struct protocol *prot;
 2982:     struct iperf_stream *sp;
 2983: 
 2984:     /* Free streams */
 2985:     while (!SLIST_EMPTY(&test->streams)) {
 2986:         sp = SLIST_FIRST(&test->streams);
 2987:         SLIST_REMOVE_HEAD(&test->streams, streams);
 2988:         iperf_free_stream(sp);
 2989:     }
 2990:     if (test->server_hostname)
 2991: 	free(test->server_hostname);
 2992:     if (test->tmp_template)
 2993: 	free(test->tmp_template);
 2994:     if (test->bind_address)
 2995: 	free(test->bind_address);
 2996:     if (test->bind_dev)
 2997: 	free(test->bind_dev);
 2998:     if (!TAILQ_EMPTY(&test->xbind_addrs)) {
 2999:         struct xbind_entry *xbe;
 3000: 
 3001:         while (!TAILQ_EMPTY(&test->xbind_addrs)) {
 3002:             xbe = TAILQ_FIRST(&test->xbind_addrs);
 3003:             TAILQ_REMOVE(&test->xbind_addrs, xbe, link);
 3004:             if (xbe->ai)
 3005:                 freeaddrinfo(xbe->ai);
 3006:             free(xbe->name);
 3007:             free(xbe);
 3008:         }
 3009:     }
 3010: #if defined(HAVE_SSL)
 3011: 
 3012:     if (test->server_rsa_private_key)
 3013:       EVP_PKEY_free(test->server_rsa_private_key);
 3014:     test->server_rsa_private_key = NULL;
 3015: 
 3016:     free(test->settings->authtoken);
 3017:     test->settings->authtoken = NULL;
 3018: 
 3019:     free(test->settings->client_username);
 3020:     test->settings->client_username = NULL;
 3021: 
 3022:     free(test->settings->client_password);
 3023:     test->settings->client_password = NULL;
 3024: 
 3025:     if (test->settings->client_rsa_pubkey)
 3026:       EVP_PKEY_free(test->settings->client_rsa_pubkey);
 3027:     test->settings->client_rsa_pubkey = NULL;
 3028: #endif /* HAVE_SSL */
 3029: 
 3030:     if (test->settings)
 3031:     free(test->settings);
 3032:     if (test->title)
 3033: 	free(test->title);
 3034:     if (test->extra_data)
 3035: 	free(test->extra_data);
 3036:     if (test->congestion)
 3037: 	free(test->congestion);
 3038:     if (test->congestion_used)
 3039: 	free(test->congestion_used);
 3040:     if (test->remote_congestion_used)
 3041: 	free(test->remote_congestion_used);
 3042:     if (test->timestamp_format)
 3043: 	free(test->timestamp_format);
 3044:     if (test->omit_timer != NULL)
 3045: 	tmr_cancel(test->omit_timer);
 3046:     if (test->timer != NULL)
 3047: 	tmr_cancel(test->timer);
 3048:     if (test->stats_timer != NULL)
 3049: 	tmr_cancel(test->stats_timer);
 3050:     if (test->reporter_timer != NULL)
 3051: 	tmr_cancel(test->reporter_timer);
 3052: 
 3053:     /* Free protocol list */
 3054:     while (!SLIST_EMPTY(&test->protocols)) {
 3055:         prot = SLIST_FIRST(&test->protocols);
 3056:         SLIST_REMOVE_HEAD(&test->protocols, protocols);
 3057:         free(prot);
 3058:     }
 3059: 
 3060:     if (test->logfile) {
 3061: 	free(test->logfile);
 3062: 	test->logfile = NULL;
 3063:         iperf_close_logfile(test);
 3064:     }
 3065: 
 3066:     if (test->server_output_text) {
 3067: 	free(test->server_output_text);
 3068: 	test->server_output_text = NULL;
 3069:     }
 3070: 
 3071:     if (test->json_output_string) {
 3072: 	free(test->json_output_string);
 3073: 	test->json_output_string = NULL;
 3074:     }
 3075: 
 3076:     /* Free output line buffers, if any (on the server only) */
 3077:     struct iperf_textline *t;
 3078:     while (!TAILQ_EMPTY(&test->server_output_list)) {
 3079: 	t = TAILQ_FIRST(&test->server_output_list);
 3080: 	TAILQ_REMOVE(&test->server_output_list, t, textlineentries);
 3081: 	free(t->line);
 3082: 	free(t);
 3083:     }
 3084: 
 3085:     /* sctp_bindx: do not free the arguments, only the resolver results */
 3086:     if (!TAILQ_EMPTY(&test->xbind_addrs)) {
 3087:         struct xbind_entry *xbe;
 3088: 
 3089:         TAILQ_FOREACH(xbe, &test->xbind_addrs, link) {
 3090:             if (xbe->ai) {
 3091:                 freeaddrinfo(xbe->ai);
 3092:                 xbe->ai = NULL;
 3093:             }
 3094:         }
 3095:     }
 3096: 
 3097:     /* Free interval's traffic array for average rate calculations */
 3098:     if (test->bitrate_limit_intervals_traffic_bytes != NULL)
 3099:         free(test->bitrate_limit_intervals_traffic_bytes);
 3100: 
 3101:     /* XXX: Why are we setting these values to NULL? */
 3102:     // test->streams = NULL;
 3103:     test->stats_callback = NULL;
 3104:     test->reporter_callback = NULL;
 3105:     free(test);
 3106: }
 3107: 
 3108: 
 3109: void
 3110: iperf_reset_test(struct iperf_test *test)
 3111: {
 3112:     struct iperf_stream *sp;
 3113:     int i;
 3114: 
 3115:     iperf_close_logfile(test);
 3116: 
 3117:     /* Free streams */
 3118:     while (!SLIST_EMPTY(&test->streams)) {
 3119:         sp = SLIST_FIRST(&test->streams);
 3120:         SLIST_REMOVE_HEAD(&test->streams, streams);
 3121:         iperf_free_stream(sp);
 3122:     }
 3123:     if (test->omit_timer != NULL) {
 3124: 	tmr_cancel(test->omit_timer);
 3125: 	test->omit_timer = NULL;
 3126:     }
 3127:     if (test->timer != NULL) {
 3128: 	tmr_cancel(test->timer);
 3129: 	test->timer = NULL;
 3130:     }
 3131:     if (test->stats_timer != NULL) {
 3132: 	tmr_cancel(test->stats_timer);
 3133: 	test->stats_timer = NULL;
 3134:     }
 3135:     if (test->reporter_timer != NULL) {
 3136: 	tmr_cancel(test->reporter_timer);
 3137: 	test->reporter_timer = NULL;
 3138:     }
 3139:     test->done = 0;
 3140: 
 3141:     SLIST_INIT(&test->streams);
 3142: 
 3143:     if (test->remote_congestion_used)
 3144:         free(test->remote_congestion_used);
 3145:     test->remote_congestion_used = NULL;
 3146:     test->role = 's';
 3147:     test->mode = RECEIVER;
 3148:     test->sender_has_retransmits = 0;
 3149:     set_protocol(test, Ptcp);
 3150:     test->omit = OMIT;
 3151:     test->duration = DURATION;
 3152:     test->server_affinity = -1;
 3153: #if defined(HAVE_CPUSET_SETAFFINITY)
 3154:     CPU_ZERO(&test->cpumask);
 3155: #endif /* HAVE_CPUSET_SETAFFINITY */
 3156:     test->state = 0;
 3157: 
 3158:     test->ctrl_sck = -1;
 3159:     test->listener = -1;
 3160:     test->prot_listener = -1;
 3161: 
 3162:     test->bytes_sent = 0;
 3163:     test->blocks_sent = 0;
 3164: 
 3165:     test->bytes_received = 0;
 3166:     test->blocks_received = 0;
 3167: 
 3168:     test->other_side_has_retransmits = 0;
 3169: 
 3170:     test->bitrate_limit_stats_count = 0;
 3171:     test->bitrate_limit_last_interval_index = 0;
 3172:     test->bitrate_limit_exceeded = 0;
 3173: 
 3174:     for (i = 0; i < MAX_INTERVAL; i++)
 3175:         test->bitrate_limit_intervals_traffic_bytes[i] = 0;
 3176: 
 3177:     test->reverse = 0;
 3178:     test->bidirectional = 0;
 3179:     test->no_delay = 0;
 3180: 
 3181:     FD_ZERO(&test->read_set);
 3182:     FD_ZERO(&test->write_set);
 3183: 
 3184:     test->num_streams = 1;
 3185:     test->settings->socket_bufsize = 0;
 3186:     test->settings->blksize = DEFAULT_TCP_BLKSIZE;
 3187:     test->settings->rate = 0;
 3188:     test->settings->burst = 0;
 3189:     test->settings->mss = 0;
 3190:     test->settings->tos = 0;
 3191:     test->settings->dont_fragment = 0;
 3192:     test->zerocopy = 0;
 3193: 
 3194: #if defined(HAVE_SSL)
 3195:     if (test->settings->authtoken) {
 3196:         free(test->settings->authtoken);
 3197:         test->settings->authtoken = NULL;
 3198:     }
 3199:     if (test->settings->client_username) {
 3200:         free(test->settings->client_username);
 3201:         test->settings->client_username = NULL;
 3202:     }
 3203:     if (test->settings->client_password) {
 3204:         free(test->settings->client_password);
 3205:         test->settings->client_password = NULL;
 3206:     }
 3207:     if (test->settings->client_rsa_pubkey) {
 3208:         EVP_PKEY_free(test->settings->client_rsa_pubkey);
 3209:         test->settings->client_rsa_pubkey = NULL;
 3210:     }
 3211: #endif /* HAVE_SSL */
 3212: 
 3213:     memset(test->cookie, 0, COOKIE_SIZE);
 3214:     test->multisend = 10;	/* arbitrary */
 3215:     test->udp_counters_64bit = 0;
 3216:     if (test->title) {
 3217: 	free(test->title);
 3218: 	test->title = NULL;
 3219:     }
 3220:     if (test->extra_data) {
 3221: 	free(test->extra_data);
 3222: 	test->extra_data = NULL;
 3223:     }
 3224: 
 3225:     /* Free output line buffers, if any (on the server only) */
 3226:     struct iperf_textline *t;
 3227:     while (!TAILQ_EMPTY(&test->server_output_list)) {
 3228: 	t = TAILQ_FIRST(&test->server_output_list);
 3229: 	TAILQ_REMOVE(&test->server_output_list, t, textlineentries);
 3230: 	free(t->line);
 3231: 	free(t);
 3232:     }
 3233: }
 3234: 
 3235: 
 3236: /* Reset all of a test's stats back to zero.  Called when the omitting
 3237: ** period is over.
 3238: */
 3239: void
 3240: iperf_reset_stats(struct iperf_test *test)
 3241: {
 3242:     struct iperf_time now;
 3243:     struct iperf_stream *sp;
 3244:     struct iperf_stream_result *rp;
 3245: 
 3246:     test->bytes_sent = 0;
 3247:     test->blocks_sent = 0;
 3248:     iperf_time_now(&now);
 3249:     SLIST_FOREACH(sp, &test->streams, streams) {
 3250: 	sp->omitted_packet_count = sp->packet_count;
 3251:         sp->omitted_cnt_error = sp->cnt_error;
 3252:         sp->omitted_outoforder_packets = sp->outoforder_packets;
 3253: 	sp->jitter = 0;
 3254: 	rp = sp->result;
 3255:         rp->bytes_sent_omit = rp->bytes_sent;
 3256:         rp->bytes_received = 0;
 3257:         rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
 3258: 	if (test->sender_has_retransmits == 1) {
 3259: 	    struct iperf_interval_results ir; /* temporary results structure */
 3260: 	    save_tcpinfo(sp, &ir);
 3261: 	    rp->stream_prev_total_retrans = get_total_retransmits(&ir);
 3262: 	}
 3263: 	rp->stream_retrans = 0;
 3264: 	rp->start_time = now;
 3265:     }
 3266: }
 3267: 
 3268: 
 3269: /**************************************************************************/
 3270: 
 3271: /**
 3272:  * Gather statistics during a test.
 3273:  * This function works for both the client and server side.
 3274:  */
 3275: void
 3276: iperf_stats_callback(struct iperf_test *test)
 3277: {
 3278:     struct iperf_stream *sp;
 3279:     struct iperf_stream_result *rp = NULL;
 3280:     struct iperf_interval_results *irp, temp;
 3281:     struct iperf_time temp_time;
 3282:     iperf_size_t total_interval_bytes_transferred = 0;
 3283: 
 3284:     temp.omitted = test->omitting;
 3285:     SLIST_FOREACH(sp, &test->streams, streams) {
 3286:         rp = sp->result;
 3287: 	temp.bytes_transferred = sp->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval;
 3288: 
 3289:         // Total bytes transferred this interval
 3290: 	total_interval_bytes_transferred += rp->bytes_sent_this_interval + rp->bytes_received_this_interval;
 3291: 
 3292: 	irp = TAILQ_LAST(&rp->interval_results, irlisthead);
 3293:         /* result->end_time contains timestamp of previous interval */
 3294:         if ( irp != NULL ) /* not the 1st interval */
 3295:             memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct iperf_time));
 3296:         else /* or use timestamp from beginning */
 3297:             memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct iperf_time));
 3298:         /* now save time of end of this interval */
 3299:         iperf_time_now(&rp->end_time);
 3300:         memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct iperf_time));
 3301:         iperf_time_diff(&temp.interval_start_time, &temp.interval_end_time, &temp_time);
 3302:         temp.interval_duration = iperf_time_in_secs(&temp_time);
 3303: 	if (test->protocol->id == Ptcp) {
 3304: 	    if ( has_tcpinfo()) {
 3305: 		save_tcpinfo(sp, &temp);
 3306: 		if (test->sender_has_retransmits == 1) {
 3307: 		    long total_retrans = get_total_retransmits(&temp);
 3308: 		    temp.interval_retrans = total_retrans - rp->stream_prev_total_retrans;
 3309: 		    rp->stream_retrans += temp.interval_retrans;
 3310: 		    rp->stream_prev_total_retrans = total_retrans;
 3311: 
 3312: 		    temp.snd_cwnd = get_snd_cwnd(&temp);
 3313: 		    if (temp.snd_cwnd > rp->stream_max_snd_cwnd) {
 3314: 			rp->stream_max_snd_cwnd = temp.snd_cwnd;
 3315: 		    }
 3316: 
 3317: 		    temp.snd_wnd = get_snd_wnd(&temp);
 3318: 		    if (temp.snd_wnd > rp->stream_max_snd_wnd) {
 3319: 			rp->stream_max_snd_wnd = temp.snd_wnd;
 3320: 		    }
 3321: 
 3322: 		    temp.rtt = get_rtt(&temp);
 3323: 		    if (temp.rtt > rp->stream_max_rtt) {
 3324: 			rp->stream_max_rtt = temp.rtt;
 3325: 		    }
 3326: 		    if (rp->stream_min_rtt == 0 ||
 3327: 			temp.rtt < rp->stream_min_rtt) {
 3328: 			rp->stream_min_rtt = temp.rtt;
 3329: 		    }
 3330: 		    rp->stream_sum_rtt += temp.rtt;
 3331: 		    rp->stream_count_rtt++;
 3332: 
 3333: 		    temp.rttvar = get_rttvar(&temp);
 3334: 		    temp.pmtu = get_pmtu(&temp);
 3335: 		}
 3336: 	    }
 3337: 	} else {
 3338: 	    if (irp == NULL) {
 3339: 		temp.interval_packet_count = sp->packet_count;
 3340: 		temp.interval_outoforder_packets = sp->outoforder_packets;
 3341: 		temp.interval_cnt_error = sp->cnt_error;
 3342: 	    } else {
 3343: 		temp.interval_packet_count = sp->packet_count - irp->packet_count;
 3344: 		temp.interval_outoforder_packets = sp->outoforder_packets - irp->outoforder_packets;
 3345: 		temp.interval_cnt_error = sp->cnt_error - irp->cnt_error;
 3346: 	    }
 3347: 	    temp.packet_count = sp->packet_count;
 3348: 	    temp.jitter = sp->jitter;
 3349: 	    temp.outoforder_packets = sp->outoforder_packets;
 3350: 	    temp.cnt_error = sp->cnt_error;
 3351: 	}
 3352:         add_to_interval_list(rp, &temp);
 3353:         rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
 3354:     }
 3355: 
 3356:     /* Verify that total server's throughput is not above specified limit */
 3357:     if (test->role == 's') {
 3358: 	iperf_check_total_rate(test, total_interval_bytes_transferred);
 3359:     }
 3360: }
 3361: 
 3362: /**
 3363:  * Print intermediate results during a test (interval report).
 3364:  * Uses print_interval_results to print the results for each stream,
 3365:  * then prints an interval summary for all streams in this
 3366:  * interval.
 3367:  */
 3368: static void
 3369: iperf_print_intermediate(struct iperf_test *test)
 3370: {
 3371:     struct iperf_stream *sp = NULL;
 3372:     struct iperf_interval_results *irp;
 3373:     struct iperf_time temp_time;
 3374:     cJSON *json_interval;
 3375:     cJSON *json_interval_streams;
 3376: 
 3377:     int lower_mode, upper_mode;
 3378:     int current_mode;
 3379: 
 3380:     /*
 3381:      * Due to timing oddities, there can be cases, especially on the
 3382:      * server side, where at the end of a test there is a fairly short
 3383:      * interval with no data transferred.  This could caused by
 3384:      * the control and data flows sharing the same path in the network,
 3385:      * and having the control messages for stopping the test being
 3386:      * queued behind the data packets.
 3387:      *
 3388:      * We'd like to try to omit that last interval when it happens, to
 3389:      * avoid cluttering data and output with useless stuff.
 3390:      * So we're going to try to ignore very short intervals (less than
 3391:      * 10% of the interval time) that have no data.
 3392:      */
 3393:     int interval_ok = 0;
 3394:     SLIST_FOREACH(sp, &test->streams, streams) {
 3395: 	irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
 3396: 	if (irp) {
 3397: 	    iperf_time_diff(&irp->interval_start_time, &irp->interval_end_time, &temp_time);
 3398: 	    double interval_len = iperf_time_in_secs(&temp_time);
 3399: 	    if (test->debug) {
 3400: 		printf("interval_len %f bytes_transferred %" PRIu64 "\n", interval_len, irp->bytes_transferred);
 3401: 	    }
 3402: 
 3403: 	    /*
 3404: 	     * If the interval is at least 10% the normal interval
 3405: 	     * length, or if there were actual bytes transferred,
 3406: 	     * then we want to keep this interval.
 3407: 	     */
 3408: 	    if (interval_len >= test->stats_interval * 0.10 ||
 3409: 		irp->bytes_transferred > 0) {
 3410: 		interval_ok = 1;
 3411: 		if (test->debug) {
 3412: 		    printf("interval forces keep\n");
 3413: 		}
 3414: 	    }
 3415: 	}
 3416:     }
 3417:     if (!interval_ok) {
 3418: 	if (test->debug) {
 3419: 	    printf("ignoring short interval with no data\n");
 3420: 	}
 3421: 	return;
 3422:     }
 3423: 
 3424:     if (test->json_output) {
 3425:         json_interval = cJSON_CreateObject();
 3426: 	if (json_interval == NULL)
 3427: 	    return;
 3428: 	cJSON_AddItemToArray(test->json_intervals, json_interval);
 3429:         json_interval_streams = cJSON_CreateArray();
 3430: 	if (json_interval_streams == NULL)
 3431: 	    return;
 3432: 	cJSON_AddItemToObject(json_interval, "streams", json_interval_streams);
 3433:     } else {
 3434:         json_interval = NULL;
 3435:         json_interval_streams = NULL;
 3436:     }
 3437: 
 3438:     /*
 3439:      * We must to sum streams separately.
 3440:      * For bidirectional mode we must to display
 3441:      * information about sender and receiver streams.
 3442:      * For client side we must handle sender streams
 3443:      * firstly and receiver streams for server side.
 3444:      * The following design allows us to do this.
 3445:      */
 3446: 
 3447:     if (test->mode == BIDIRECTIONAL) {
 3448:         if (test->role == 'c') {
 3449:             lower_mode = -1;
 3450:             upper_mode = 0;
 3451:         } else {
 3452:             lower_mode = 0;
 3453:             upper_mode = 1;
 3454:         }
 3455:     } else {
 3456:         lower_mode = test->mode;
 3457:         upper_mode = lower_mode;
 3458:     }
 3459: 
 3460: 
 3461:     for (current_mode = lower_mode; current_mode <= upper_mode; ++current_mode) {
 3462:         char ubuf[UNIT_LEN];
 3463:         char nbuf[UNIT_LEN];
 3464:         char mbuf[UNIT_LEN];
 3465:         char zbuf[] = "          ";
 3466: 
 3467:         iperf_size_t bytes = 0;
 3468:         double bandwidth;
 3469:         int retransmits = 0;
 3470:         double start_time, end_time;
 3471: 
 3472:         int64_t total_packets = 0, lost_packets = 0;
 3473:         double avg_jitter = 0.0, lost_percent;
 3474:         int stream_must_be_sender = current_mode * current_mode;
 3475: 
 3476:         char *sum_name;
 3477: 
 3478:         /*  Print stream role just for bidirectional mode. */
 3479: 
 3480:         if (test->mode == BIDIRECTIONAL) {
 3481:             sprintf(mbuf, "[%s-%s]", stream_must_be_sender?"TX":"RX", test->role == 'c'?"C":"S");
 3482:         } else {
 3483:             mbuf[0] = '\0';
 3484:             zbuf[0] = '\0';
 3485:         }
 3486: 
 3487:         SLIST_FOREACH(sp, &test->streams, streams) {
 3488:             if (sp->sender == stream_must_be_sender) {
 3489:                 print_interval_results(test, sp, json_interval_streams);
 3490:                 /* sum up all streams */
 3491:                 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
 3492:                 if (irp == NULL) {
 3493:                     iperf_err(test,
 3494:                             "iperf_print_intermediate error: interval_results is NULL");
 3495:                     return;
 3496:                 }
 3497:                 bytes += irp->bytes_transferred;
 3498:                 if (test->protocol->id == Ptcp) {
 3499:                     if (test->sender_has_retransmits == 1) {
 3500:                         retransmits += irp->interval_retrans;
 3501:                     }
 3502:                 } else {
 3503:                     total_packets += irp->interval_packet_count;
 3504:                     lost_packets += irp->interval_cnt_error;
 3505:                     avg_jitter += irp->jitter;
 3506:                 }
 3507:             }
 3508:         }
 3509: 
 3510:         /* next build string with sum of all streams */
 3511:         if (test->num_streams > 1 || test->json_output) {
 3512:             /*
 3513:              * With BIDIR give a different JSON object name to the one sent/receive sums.
 3514:              * The different name is given to the data sent from the server, which is
 3515:              * the "reverse" channel.  This makes sure that the name reported on the server
 3516:              * and client are compatible, and the names are the same as with non-bidir,
 3517:              * except for when reverse is used.
 3518:              */
 3519:             sum_name = "sum";
 3520:             if (test->mode == BIDIRECTIONAL) {
 3521:                 if ((test->role == 'c' && !stream_must_be_sender) ||
 3522:                     (test->role != 'c' && stream_must_be_sender))
 3523:                 {
 3524:                     sum_name = "sum_bidir_reverse";
 3525:                 }
 3526:             }
 3527: 
 3528:             sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */
 3529:             /* Only do this of course if there was a first stream */
 3530:             if (sp) {
 3531: 	    irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);    /* use 1st stream for timing info */
 3532: 
 3533: 	    unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A');
 3534: 	    bandwidth = (double) bytes / (double) irp->interval_duration;
 3535: 	    unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
 3536: 
 3537: 	    iperf_time_diff(&sp->result->start_time,&irp->interval_start_time, &temp_time);
 3538: 	    start_time = iperf_time_in_secs(&temp_time);
 3539: 	    iperf_time_diff(&sp->result->start_time,&irp->interval_end_time, &temp_time);
 3540: 	    end_time = iperf_time_in_secs(&temp_time);
 3541:                 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
 3542:                     if (test->sender_has_retransmits == 1 && stream_must_be_sender) {
 3543:                         /* Interval sum, TCP with retransmits. */
 3544:                         if (test->json_output)
 3545:                             cJSON_AddItemToObject(json_interval, sum_name, 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? */
 3546:                         else
 3547:                             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? */
 3548:                     } else {
 3549:                         /* Interval sum, TCP without retransmits. */
 3550:                         if (test->json_output)
 3551:                             cJSON_AddItemToObject(json_interval, sum_name, 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));
 3552:                         else
 3553:                             iperf_printf(test, report_sum_bw_format, mbuf, start_time, end_time, ubuf, nbuf, test->omitting?report_omitted:"");
 3554:                     }
 3555:                 } else {
 3556:                     /* Interval sum, UDP. */
 3557:                     if (stream_must_be_sender) {
 3558:                         if (test->json_output)
 3559:                             cJSON_AddItemToObject(json_interval, sum_name, 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));
 3560:                         else
 3561:                             iperf_printf(test, report_sum_bw_udp_sender_format, mbuf, start_time, end_time, ubuf, nbuf, zbuf, total_packets, test->omitting?report_omitted:"");
 3562:                     } else {
 3563:                         avg_jitter /= test->num_streams;
 3564:                         if (total_packets > 0) {
 3565:                             lost_percent = 100.0 * lost_packets / total_packets;
 3566:                         }
 3567:                         else {
 3568:                             lost_percent = 0.0;
 3569:                         }
 3570:                         if (test->json_output)
 3571:                             cJSON_AddItemToObject(json_interval, sum_name, 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));
 3572:                         else
 3573:                             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:"");
 3574:                     }
 3575:                 }
 3576:             }
 3577:         }
 3578:     }
 3579: }
 3580: 
 3581: /**
 3582:  * Print overall summary statistics at the end of a test.
 3583:  */
 3584: static void
 3585: iperf_print_results(struct iperf_test *test)
 3586: {
 3587: 
 3588:     cJSON *json_summary_streams = NULL;
 3589: 
 3590:     int lower_mode, upper_mode;
 3591:     int current_mode;
 3592: 
 3593:     char *sum_sent_name, *sum_received_name, *sum_name;
 3594: 
 3595:     int tmp_sender_has_retransmits = test->sender_has_retransmits;
 3596: 
 3597:     /* print final summary for all intervals */
 3598: 
 3599:     if (test->json_output) {
 3600:         json_summary_streams = cJSON_CreateArray();
 3601: 	if (json_summary_streams == NULL)
 3602: 	    return;
 3603: 	cJSON_AddItemToObject(test->json_end, "streams", json_summary_streams);
 3604:     } else {
 3605: 	iperf_printf(test, "%s", report_bw_separator);
 3606: 	if (test->verbose)
 3607: 	    iperf_printf(test, "%s", report_summary);
 3608: 	if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
 3609: 	    if (test->sender_has_retransmits || test->other_side_has_retransmits) {
 3610: 	        if (test->bidirectional)
 3611: 	            iperf_printf(test, "%s", report_bw_retrans_header_bidir);
 3612: 	        else
 3613: 	            iperf_printf(test, "%s", report_bw_retrans_header);
 3614: 	    }
 3615: 	    else {
 3616: 	        if (test->bidirectional)
 3617: 	            iperf_printf(test, "%s", report_bw_header_bidir);
 3618: 	        else
 3619: 	            iperf_printf(test, "%s", report_bw_header);
 3620: 	    }
 3621: 	} else {
 3622: 	    if (test->bidirectional)
 3623: 	        iperf_printf(test, "%s", report_bw_udp_header_bidir);
 3624: 	    else
 3625: 	        iperf_printf(test, "%s", report_bw_udp_header);
 3626: 	}
 3627:     }
 3628: 
 3629:     /*
 3630:      * We must to sum streams separately.
 3631:      * For bidirectional mode we must to display
 3632:      * information about sender and receiver streams.
 3633:      * For client side we must handle sender streams
 3634:      * firstly and receiver streams for server side.
 3635:      * The following design allows us to do this.
 3636:      */
 3637: 
 3638:     if (test->mode == BIDIRECTIONAL) {
 3639:         if (test->role == 'c') {
 3640:             lower_mode = -1;
 3641:             upper_mode = 0;
 3642:         } else {
 3643:             lower_mode = 0;
 3644:             upper_mode = 1;
 3645:         }
 3646:     } else {
 3647:         lower_mode = test->mode;
 3648:         upper_mode = lower_mode;
 3649:     }
 3650: 
 3651: 
 3652:     for (current_mode = lower_mode; current_mode <= upper_mode; ++current_mode) {
 3653:         cJSON *json_summary_stream = NULL;
 3654:         int64_t total_retransmits = 0;
 3655:         int64_t total_packets = 0, lost_packets = 0;
 3656:         int64_t sender_packet_count = 0, receiver_packet_count = 0; /* for this stream, this interval */
 3657:         int64_t sender_omitted_packet_count = 0, receiver_omitted_packet_count = 0; /* for this stream, this interval */
 3658:         int64_t sender_total_packets = 0, receiver_total_packets = 0; /* running total */
 3659:         char ubuf[UNIT_LEN];
 3660:         char nbuf[UNIT_LEN];
 3661:         struct stat sb;
 3662:         char sbuf[UNIT_LEN];
 3663:         struct iperf_stream *sp = NULL;
 3664:         iperf_size_t bytes_sent, total_sent = 0;
 3665:         iperf_size_t bytes_received, total_received = 0;
 3666:         double start_time, end_time = 0.0, avg_jitter = 0.0, lost_percent = 0.0;
 3667:         double sender_time = 0.0, receiver_time = 0.0;
 3668:         struct iperf_time temp_time;
 3669:         double bandwidth;
 3670: 
 3671:         char mbuf[UNIT_LEN];
 3672:         int stream_must_be_sender = current_mode * current_mode;
 3673: 
 3674: 
 3675:         /*  Print stream role just for bidirectional mode. */
 3676: 
 3677:         if (test->mode == BIDIRECTIONAL) {
 3678:             sprintf(mbuf, "[%s-%s]", stream_must_be_sender?"TX":"RX", test->role == 'c'?"C":"S");
 3679:         } else {
 3680:             mbuf[0] = '\0';
 3681:         }
 3682: 
 3683:         /* Get sender_has_retransmits for each sender side (client and server) */
 3684:         if (test->mode == BIDIRECTIONAL && stream_must_be_sender)
 3685:             test->sender_has_retransmits = tmp_sender_has_retransmits;
 3686:         else if (test->mode == BIDIRECTIONAL && !stream_must_be_sender)
 3687:             test->sender_has_retransmits = test->other_side_has_retransmits;
 3688: 
 3689:         start_time = 0.;
 3690:         sp = SLIST_FIRST(&test->streams);
 3691: 
 3692:         /*
 3693:          * If there is at least one stream, then figure out the length of time
 3694:          * we were running the tests and print out some statistics about
 3695:          * the streams.  It's possible to not have any streams at all
 3696:          * if the client got interrupted before it got to do anything.
 3697:          *
 3698:          * Also note that we try to keep separate values for the sender
 3699:          * and receiver ending times.  Earlier iperf (3.1 and earlier)
 3700:          * servers didn't send that to the clients, so in this case we fall
 3701:          * back to using the client's ending timestamp.  The fallback is
 3702:          * basically emulating what iperf 3.1 did.
 3703:          */
 3704: 
 3705:         if (sp) {
 3706:         iperf_time_diff(&sp->result->start_time, &sp->result->end_time, &temp_time);
 3707:         end_time = iperf_time_in_secs(&temp_time);
 3708:         if (sp->sender) {
 3709:             sp->result->sender_time = end_time;
 3710:             if (sp->result->receiver_time == 0.0) {
 3711:                 sp->result->receiver_time = sp->result->sender_time;
 3712:             }
 3713:         }
 3714:         else {
 3715:             sp->result->receiver_time = end_time;
 3716:             if (sp->result->sender_time == 0.0) {
 3717:                 sp->result->sender_time = sp->result->receiver_time;
 3718:             }
 3719:         }
 3720:         sender_time = sp->result->sender_time;
 3721:         receiver_time = sp->result->receiver_time;
 3722:         SLIST_FOREACH(sp, &test->streams, streams) {
 3723:             if (sp->sender == stream_must_be_sender) {
 3724:                 if (test->json_output) {
 3725:                     json_summary_stream = cJSON_CreateObject();
 3726:                     if (json_summary_stream == NULL)
 3727:                         return;
 3728:                     cJSON_AddItemToArray(json_summary_streams, json_summary_stream);
 3729:                 }
 3730: 
 3731:                 bytes_sent = sp->result->bytes_sent - sp->result->bytes_sent_omit;
 3732:                 bytes_received = sp->result->bytes_received;
 3733:                 total_sent += bytes_sent;
 3734:                 total_received += bytes_received;
 3735: 
 3736:                 if (sp->sender) {
 3737:                     sender_packet_count = sp->packet_count;
 3738:                     sender_omitted_packet_count = sp->omitted_packet_count;
 3739:                     receiver_packet_count = sp->peer_packet_count;
 3740:                     receiver_omitted_packet_count = sp->peer_omitted_packet_count;
 3741:                 }
 3742:                 else {
 3743:                     sender_packet_count = sp->peer_packet_count;
 3744:                     sender_omitted_packet_count = sp->peer_omitted_packet_count;
 3745:                     receiver_packet_count = sp->packet_count;
 3746:                     receiver_omitted_packet_count = sp->omitted_packet_count;
 3747:                 }
 3748: 
 3749:                 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
 3750:                     if (test->sender_has_retransmits) {
 3751:                         total_retransmits += sp->result->stream_retrans;
 3752:                     }
 3753:                 } else {
 3754:                     /*
 3755:                      * Running total of the total number of packets.  Use the sender packet count if we
 3756:                      * have it, otherwise use the receiver packet count.
 3757:                      */
 3758:                     int64_t packet_count = sender_packet_count ? sender_packet_count : receiver_packet_count;
 3759:                     total_packets += (packet_count - sp->omitted_packet_count);
 3760:                     sender_total_packets += (sender_packet_count - sender_omitted_packet_count);
 3761:                     receiver_total_packets += (receiver_packet_count - receiver_omitted_packet_count);
 3762:                     lost_packets += sp->cnt_error;
 3763:                     if (sp->omitted_cnt_error > -1)
 3764:                          lost_packets -= sp->omitted_cnt_error;
 3765:                     avg_jitter += sp->jitter;
 3766:                 }
 3767: 
 3768:                 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_sent, 'A');
 3769:                 if (sender_time > 0.0) {
 3770:                     bandwidth = (double) bytes_sent / (double) sender_time;
 3771:                 }
 3772:                 else {
 3773:                     bandwidth = 0.0;
 3774:                 }
 3775:                 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
 3776:                 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
 3777:                     if (test->sender_has_retransmits) {
 3778:                         /* Sender summary, TCP and SCTP with retransmits. */
 3779:                         if (test->json_output)
 3780:                             cJSON_AddItemToObject(json_summary_stream, report_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_snd_wnd:  %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_snd_wnd, (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));
 3781:                         else
 3782:                             if (test->role == 's' && !sp->sender) {
 3783:                                 if (test->verbose)
 3784:                                     iperf_printf(test, report_sender_not_available_format, sp->socket);
 3785:                             }
 3786:                             else {
 3787:                                 iperf_printf(test, report_bw_retrans_format, sp->socket, mbuf, start_time, sender_time, ubuf, nbuf, sp->result->stream_retrans, report_sender);
 3788:                             }
 3789:                     } else {
 3790:                         /* Sender summary, TCP and SCTP without retransmits. */
 3791:                         if (test->json_output)
 3792:                             cJSON_AddItemToObject(json_summary_stream, report_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));
 3793:                         else
 3794:                             if (test->role == 's' && !sp->sender) {
 3795:                                 if (test->verbose)
 3796:                                     iperf_printf(test, report_sender_not_available_format, sp->socket);
 3797:                             }
 3798:                             else {
 3799:                                 iperf_printf(test, report_bw_format, sp->socket, mbuf, start_time, sender_time, ubuf, nbuf, report_sender);
 3800:                             }
 3801:                     }
 3802:                 } else {
 3803:                     /* Sender summary, UDP. */
 3804:                     if (sender_packet_count - sender_omitted_packet_count > 0) {
 3805:                         lost_percent = 100.0 * (sp->cnt_error - sp->omitted_cnt_error) / (sender_packet_count - sender_omitted_packet_count);
 3806:                     }
 3807:                     else {
 3808:                         lost_percent = 0.0;
 3809:                     }
 3810:                     if (test->json_output) {
 3811:                         /*
 3812:                          * For historical reasons, we only emit one JSON
 3813:                          * object for the UDP summary, and it contains
 3814:                          * information for both the sender and receiver
 3815:                          * side.
 3816:                          *
 3817:                          * The JSON format as currently defined only includes one
 3818:                          * value for the number of packets.  We usually want that
 3819:                          * to be the sender's value (how many packets were sent
 3820:                          * by the sender).  However this value might not be
 3821:                          * available on the receiver in certain circumstances
 3822:                          * specifically on the server side for a normal test or
 3823:                          * the client side for a reverse-mode test.  If this
 3824:                          * is the case, then use the receiver's count of packets
 3825:                          * instead.
 3826:                          */
 3827:                         int64_t packet_count = sender_packet_count ? sender_packet_count : receiver_packet_count;
 3828:                         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));
 3829:                     }
 3830:                     else {
 3831:                         /*
 3832:                          * Due to ordering of messages on the control channel,
 3833:                          * the server cannot report on client-side summary
 3834:                          * statistics.  If we're the server, omit one set of
 3835:                          * summary statistics to avoid giving meaningless
 3836:                          * results.
 3837:                          */
 3838:                         if (test->role == 's' && !sp->sender) {
 3839:                             if (test->verbose)
 3840:                                 iperf_printf(test, report_sender_not_available_format, sp->socket);
 3841:                         }
 3842:                         else {
 3843:                             iperf_printf(test, report_bw_udp_format, sp->socket, mbuf, start_time, sender_time, ubuf, nbuf, 0.0, (int64_t) 0, (sender_packet_count - sender_omitted_packet_count), (double) 0, report_sender);
 3844:                         }
 3845:                         if ((sp->outoforder_packets - sp->omitted_outoforder_packets) > 0)
 3846:                           iperf_printf(test, report_sum_outoforder, mbuf, start_time, sender_time, (sp->outoforder_packets - sp->omitted_outoforder_packets));
 3847:                     }
 3848:                 }
 3849: 
 3850:                 if (sp->diskfile_fd >= 0) {
 3851:                     if (fstat(sp->diskfile_fd, &sb) == 0) {
 3852:                         /* In the odd case that it's a zero-sized file, say it was all transferred. */
 3853:                         int percent_sent = 100, percent_received = 100;
 3854:                         if (sb.st_size > 0) {
 3855:                             percent_sent = (int) ( ( (double) bytes_sent / (double) sb.st_size ) * 100.0 );
 3856:                             percent_received = (int) ( ( (double) bytes_received / (double) sb.st_size ) * 100.0 );
 3857:                         }
 3858:                         unit_snprintf(sbuf, UNIT_LEN, (double) sb.st_size, 'A');
 3859:                         if (test->json_output)
 3860:                             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));
 3861:                         else
 3862:                             if (stream_must_be_sender) {
 3863:                                 iperf_printf(test, report_diskfile, ubuf, sbuf, percent_sent, test->diskfile_name);
 3864:                             }
 3865:                             else {
 3866:                                 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
 3867:                                 iperf_printf(test, report_diskfile, ubuf, sbuf, percent_received, test->diskfile_name);
 3868:                             }
 3869:                     }
 3870:                 }
 3871: 
 3872:                 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
 3873:                 if (receiver_time > 0) {
 3874:                     bandwidth = (double) bytes_received / (double) receiver_time;
 3875:                 }
 3876:                 else {
 3877:                     bandwidth = 0.0;
 3878:                 }
 3879:                 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
 3880:                 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
 3881:                     /* Receiver summary, TCP and SCTP */
 3882:                     if (test->json_output)
 3883:                         cJSON_AddItemToObject(json_summary_stream, report_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));
 3884:                     else
 3885:                         if (test->role == 's' && sp->sender) {
 3886:                             if (test->verbose)
 3887:                                 iperf_printf(test, report_receiver_not_available_format, sp->socket);
 3888:                         }
 3889:                         else {
 3890:                             iperf_printf(test, report_bw_format, sp->socket, mbuf, start_time, receiver_time, ubuf, nbuf, report_receiver);
 3891:                         }
 3892:                 }
 3893:                 else {
 3894:                     /*
 3895:                      * Receiver summary, UDP.  Note that JSON was emitted with
 3896:                      * the sender summary, so we only deal with human-readable
 3897:                      * data here.
 3898:                      */
 3899:                     if (! test->json_output) {
 3900:                         if (receiver_packet_count - receiver_omitted_packet_count > 0 && sp->omitted_cnt_error > -1) {
 3901:                             lost_percent = 100.0 * (sp->cnt_error - sp->omitted_cnt_error) / (receiver_packet_count - receiver_omitted_packet_count);
 3902:                         }
 3903:                         else {
 3904:                             lost_percent = 0.0;
 3905:                         }
 3906: 
 3907:                         if (test->role == 's' && sp->sender) {
 3908:                             if (test->verbose)
 3909:                                 iperf_printf(test, report_receiver_not_available_format, sp->socket);
 3910:                         }
 3911:                         else {
 3912:                             if (sp->omitted_cnt_error > -1) {
 3913:                                 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 - receiver_omitted_packet_count), lost_percent, report_receiver);
 3914:                             } else {
 3915:                                 iperf_printf(test, report_bw_udp_format_no_omitted_error, sp->socket, mbuf, start_time, receiver_time, ubuf, nbuf, sp->jitter * 1000.0, (receiver_packet_count - receiver_omitted_packet_count), report_receiver);
 3916:                             }
 3917:                         }
 3918:                     }
 3919:                 }
 3920:             }
 3921:         }
 3922:         }
 3923: 
 3924:         if (test->num_streams > 1 || test->json_output) {
 3925:             /*
 3926:              * With BIDIR give a different JSON object name to the one sent/receive sums.
 3927:              * The different name is given to the data sent from the server, which is
 3928:              * the "reverse" channel.  This makes sure that the name reported on the server
 3929:              * and client are compatible, and the names are the same as with non-bidir,
 3930:              * except for when reverse is used.
 3931:              */
 3932:             sum_name = "sum";
 3933:             sum_sent_name = "sum_sent";
 3934:             sum_received_name = "sum_received";
 3935:             if (test->mode == BIDIRECTIONAL) {
 3936:                 if ((test->role == 'c' && !stream_must_be_sender) ||
 3937:                     (test->role != 'c' && stream_must_be_sender))
 3938:                 {
 3939:                     sum_name = "sum_bidir_reverse";
 3940:                     sum_sent_name = "sum_sent_bidir_reverse";
 3941:                     sum_received_name = "sum_received_bidir_reverse";
 3942:                 }
 3943: 
 3944:             }
 3945: 
 3946:             unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');
 3947:             /* If no tests were run, arbitrarily set bandwidth to 0. */
 3948:             if (sender_time > 0.0) {
 3949:                 bandwidth = (double) total_sent / (double) sender_time;
 3950:             }
 3951:             else {
 3952:                 bandwidth = 0.0;
 3953:             }
 3954:             unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
 3955:             if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
 3956:                 if (test->sender_has_retransmits) {
 3957:                     /* Summary sum, TCP with retransmits. */
 3958:                     if (test->json_output)
 3959:                         cJSON_AddItemToObject(test->json_end, sum_sent_name, 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));
 3960:                     else
 3961:                         if (test->role == 's' && !stream_must_be_sender) {
 3962:                             if (test->verbose)
 3963:                                 iperf_printf(test, report_sender_not_available_summary_format, "SUM");
 3964:                         }
 3965:                         else {
 3966:                           iperf_printf(test, report_sum_bw_retrans_format, mbuf, start_time, sender_time, ubuf, nbuf, total_retransmits, report_sender);
 3967:                         }
 3968:                 } else {
 3969:                     /* Summary sum, TCP without retransmits. */
 3970:                     if (test->json_output)
 3971:                         cJSON_AddItemToObject(test->json_end, sum_sent_name, 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));
 3972:                     else
 3973:                         if (test->role == 's' && !stream_must_be_sender) {
 3974:                             if (test->verbose)
 3975:                                 iperf_printf(test, report_sender_not_available_summary_format, "SUM");
 3976:                         }
 3977:                         else {
 3978:                             iperf_printf(test, report_sum_bw_format, mbuf, start_time, sender_time, ubuf, nbuf, report_sender);
 3979:                         }
 3980:                 }
 3981:                 unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A');
 3982:                 /* If no tests were run, set received bandwidth to 0 */
 3983:                 if (receiver_time > 0.0) {
 3984:                     bandwidth = (double) total_received / (double) receiver_time;
 3985:                 }
 3986:                 else {
 3987:                     bandwidth = 0.0;
 3988:                 }
 3989:                 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
 3990:                 if (test->json_output)
 3991:                     cJSON_AddItemToObject(test->json_end, sum_received_name, 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));
 3992:                 else
 3993:                     if (test->role == 's' && stream_must_be_sender) {
 3994:                         if (test->verbose)
 3995:                             iperf_printf(test, report_receiver_not_available_summary_format, "SUM");
 3996:                     }
 3997:                     else {
 3998:                         iperf_printf(test, report_sum_bw_format, mbuf, start_time, receiver_time, ubuf, nbuf, report_receiver);
 3999:                     }
 4000:             } else {
 4001:                 /* Summary sum, UDP. */
 4002:                 avg_jitter /= test->num_streams;
 4003:                 /* If no packets were sent, arbitrarily set loss percentage to 0. */
 4004:                 if (total_packets > 0) {
 4005:                     lost_percent = 100.0 * lost_packets / total_packets;
 4006:                 }
 4007:                 else {
 4008:                     lost_percent = 0.0;
 4009:                 }
 4010:                 if (test->json_output) {
 4011:                     /*
 4012:                      * Original, summary structure. Using this
 4013:                      * structure is not recommended due to
 4014:                      * ambiguities between the sender and receiver.
 4015:                      */
 4016:                     cJSON_AddItemToObject(test->json_end, sum_name, 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));
 4017:                     /*
 4018:                      * Separate sum_sent and sum_received structures.
 4019:                      * Using these structures to get the most complete
 4020:                      * information about UDP transfer.
 4021:                      */
 4022:                     cJSON_AddItemToObject(test->json_end, sum_sent_name, 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) sender_time, (double) sender_time, (int64_t) total_sent, (double) total_sent * 8 / sender_time, (double) 0.0, (int64_t) 0, (int64_t) sender_total_packets, (double) 0.0, 1));
 4023:                     cJSON_AddItemToObject(test->json_end, sum_received_name, 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_received, (double) total_received * 8 / receiver_time, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) receiver_total_packets, (double) lost_percent, 0));
 4024:                 } else {
 4025:                     /*
 4026:                      * On the client we have both sender and receiver overall summary
 4027:                      * stats.  On the server we have only the side that was on the
 4028:                      * server.  Output whatever we have.
 4029:                      */
 4030:                     if (! (test->role == 's' && !stream_must_be_sender) ) {
 4031:                         unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');
 4032:                         iperf_printf(test, report_sum_bw_udp_format, mbuf, start_time, sender_time, ubuf, nbuf, 0.0, (int64_t) 0, sender_total_packets, 0.0, report_sender);
 4033:                     }
 4034:                     if (! (test->role == 's' && stream_must_be_sender) ) {
 4035: 
 4036:                         unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A');
 4037:                         /* Compute received bandwidth. */
 4038:                         if (end_time > 0.0) {
 4039:                             bandwidth = (double) total_received / (double) receiver_time;
 4040:                         }
 4041:                         else {
 4042:                             bandwidth = 0.0;
 4043:                         }
 4044:                         unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
 4045:                         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, report_receiver);
 4046:                     }
 4047:                 }
 4048:             }
 4049:         }
 4050: 
 4051:         if (test->json_output && current_mode == upper_mode) {
 4052:             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]));
 4053:             if (test->protocol->id == Ptcp) {
 4054:                 char *snd_congestion = NULL, *rcv_congestion = NULL;
 4055:                 if (stream_must_be_sender) {
 4056:                     snd_congestion = test->congestion_used;
 4057:                     rcv_congestion = test->remote_congestion_used;
 4058:                 }
 4059:                 else {
 4060:                     snd_congestion = test->remote_congestion_used;
 4061:                     rcv_congestion = test->congestion_used;
 4062:                 }
 4063:                 if (snd_congestion) {
 4064:                     cJSON_AddStringToObject(test->json_end, "sender_tcp_congestion", snd_congestion);
 4065:                 }
 4066:                 if (rcv_congestion) {
 4067:                     cJSON_AddStringToObject(test->json_end, "receiver_tcp_congestion", rcv_congestion);
 4068:                 }
 4069:             }
 4070:         }
 4071:         else {
 4072:             if (test->verbose) {
 4073:                 if (stream_must_be_sender) {
 4074:                     if (test->bidirectional) {
 4075:                         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]);
 4076:                         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]);
 4077:                     } else
 4078:                         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]);
 4079:                 }
 4080:                 if (test->protocol->id == Ptcp) {
 4081:                     char *snd_congestion = NULL, *rcv_congestion = NULL;
 4082:                     if (stream_must_be_sender) {
 4083:                         snd_congestion = test->congestion_used;
 4084:                         rcv_congestion = test->remote_congestion_used;
 4085:                     }
 4086:                     else {
 4087:                         snd_congestion = test->remote_congestion_used;
 4088:                         rcv_congestion = test->congestion_used;
 4089:                     }
 4090:                     if (snd_congestion) {
 4091:                         iperf_printf(test, "snd_tcp_congestion %s\n", snd_congestion);
 4092:                     }
 4093:                     if (rcv_congestion) {
 4094:                         iperf_printf(test, "rcv_tcp_congestion %s\n", rcv_congestion);
 4095:                     }
 4096:                 }
 4097:             }
 4098: 
 4099:             /* Print server output if we're on the client and it was requested/provided */
 4100:             if (test->role == 'c' && iperf_get_test_get_server_output(test) && !test->json_output) {
 4101:                 if (test->json_server_output) {
 4102: 		    char *str = cJSON_Print(test->json_server_output);
 4103:                     iperf_printf(test, "\nServer JSON output:\n%s\n", str);
 4104: 		    cJSON_free(str);
 4105:                     cJSON_Delete(test->json_server_output);
 4106:                     test->json_server_output = NULL;
 4107:                 }
 4108:                 if (test->server_output_text) {
 4109:                     iperf_printf(test, "\nServer output:\n%s\n", test->server_output_text);
 4110:                     test->server_output_text = NULL;
 4111:                 }
 4112:             }
 4113:         }
 4114:     }
 4115: 
 4116:     /* Set real sender_has_retransmits for current side */
 4117:     if (test->mode == BIDIRECTIONAL)
 4118:         test->sender_has_retransmits = tmp_sender_has_retransmits;
 4119: }
 4120: 
 4121: /**************************************************************************/
 4122: 
 4123: /**
 4124:  * Main report-printing callback.
 4125:  * Prints results either during a test (interval report only) or
 4126:  * after the entire test has been run (last interval report plus
 4127:  * overall summary).
 4128:  */
 4129: void
 4130: iperf_reporter_callback(struct iperf_test *test)
 4131: {
 4132:     switch (test->state) {
 4133:         case TEST_RUNNING:
 4134:         case STREAM_RUNNING:
 4135:             /* print interval results for each stream */
 4136:             iperf_print_intermediate(test);
 4137:             break;
 4138:         case TEST_END:
 4139:         case DISPLAY_RESULTS:
 4140:             iperf_print_intermediate(test);
 4141:             iperf_print_results(test);
 4142:             break;
 4143:     }
 4144: 
 4145: }
 4146: 
 4147: /**
 4148:  * Print the interval results for one stream.
 4149:  * This function needs to know about the overall test so it can determine the
 4150:  * context for printing headers, separators, etc.
 4151:  */
 4152: static void
 4153: print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams)
 4154: {
 4155:     char ubuf[UNIT_LEN];
 4156:     char nbuf[UNIT_LEN];
 4157:     char cbuf[UNIT_LEN];
 4158:     char mbuf[UNIT_LEN];
 4159:     char zbuf[] = "          ";
 4160:     double st = 0., et = 0.;
 4161:     struct iperf_time temp_time;
 4162:     struct iperf_interval_results *irp = NULL;
 4163:     double bandwidth, lost_percent;
 4164: 
 4165:     if (test->mode == BIDIRECTIONAL) {
 4166:         sprintf(mbuf, "[%s-%s]", sp->sender?"TX":"RX", test->role == 'c'?"C":"S");
 4167:     } else {
 4168:         mbuf[0] = '\0';
 4169:         zbuf[0] = '\0';
 4170:     }
 4171: 
 4172:     irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* get last entry in linked list */
 4173:     if (irp == NULL) {
 4174: 	iperf_err(test, "print_interval_results error: interval_results is NULL");
 4175:         return;
 4176:     }
 4177:     if (!test->json_output) {
 4178: 	/* First stream? */
 4179: 	if (sp == SLIST_FIRST(&test->streams)) {
 4180: 	    /* It it's the first interval, print the header;
 4181: 	    ** else if there's more than one stream, print the separator;
 4182: 	    ** else nothing.
 4183: 	    */
 4184: 	    if (iperf_time_compare(&sp->result->start_time, &irp->interval_start_time) == 0) {
 4185: 		if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
 4186: 		    if (test->sender_has_retransmits == 1) {
 4187: 		        if (test->bidirectional)
 4188: 		            iperf_printf(test, "%s", report_bw_retrans_cwnd_header_bidir);
 4189: 		        else
 4190: 		            iperf_printf(test, "%s", report_bw_retrans_cwnd_header);
 4191: 		    }
 4192: 		    else {
 4193: 	                if (test->bidirectional)
 4194: 	                    iperf_printf(test, "%s", report_bw_header_bidir);
 4195: 	                else
 4196: 	                    iperf_printf(test, "%s", report_bw_header);
 4197: 	            }
 4198: 		} else {
 4199: 		    if (test->mode == SENDER) {
 4200: 		        iperf_printf(test, "%s", report_bw_udp_sender_header);
 4201: 		    } else if (test->mode == RECEIVER){
 4202: 		        iperf_printf(test, "%s", report_bw_udp_header);
 4203: 		    } else {
 4204: 		        /* BIDIRECTIONAL */
 4205: 		        iperf_printf(test, "%s", report_bw_udp_header_bidir);
 4206: 		    }
 4207: 		}
 4208: 	    } else if (test->num_streams > 1)
 4209: 		iperf_printf(test, "%s", report_bw_separator);
 4210: 	}
 4211:     }
 4212: 
 4213:     unit_snprintf(ubuf, UNIT_LEN, (double) (irp->bytes_transferred), 'A');
 4214:     if (irp->interval_duration > 0.0) {
 4215: 	bandwidth = (double) irp->bytes_transferred / (double) irp->interval_duration;
 4216:     }
 4217:     else {
 4218: 	bandwidth = 0.0;
 4219:     }
 4220:     unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
 4221: 
 4222:     iperf_time_diff(&sp->result->start_time, &irp->interval_start_time, &temp_time);
 4223:     st = iperf_time_in_secs(&temp_time);
 4224:     iperf_time_diff(&sp->result->start_time, &irp->interval_end_time, &temp_time);
 4225:     et = iperf_time_in_secs(&temp_time);
 4226: 
 4227:     if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
 4228: 	if (test->sender_has_retransmits == 1 && sp->sender) {
 4229: 	    /* Interval, TCP with retransmits. */
 4230: 	    if (test->json_output)
 4231: 		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  snd_wnd:  %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->snd_wnd, (int64_t) irp->rtt, (int64_t) irp->rttvar, (int64_t) irp->pmtu, irp->omitted, sp->sender));
 4232: 	    else {
 4233: 		unit_snprintf(cbuf, UNIT_LEN, irp->snd_cwnd, 'A');
 4234: 		iperf_printf(test, report_bw_retrans_cwnd_format, sp->socket, mbuf, st, et, ubuf, nbuf, irp->interval_retrans, cbuf, irp->omitted?report_omitted:"");
 4235: 	    }
 4236: 	} else {
 4237: 	    /* Interval, TCP without retransmits. */
 4238: 	    if (test->json_output)
 4239: 		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));
 4240: 	    else
 4241: 		iperf_printf(test, report_bw_format, sp->socket, mbuf, st, et, ubuf, nbuf, irp->omitted?report_omitted:"");
 4242: 	}
 4243:     } else {
 4244: 	/* Interval, UDP. */
 4245: 	if (sp->sender) {
 4246: 	    if (test->json_output)
 4247: 		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));
 4248: 	    else
 4249: 		iperf_printf(test, report_bw_udp_sender_format, sp->socket, mbuf, st, et, ubuf, nbuf, zbuf, irp->interval_packet_count, irp->omitted?report_omitted:"");
 4250: 	} else {
 4251: 	    if (irp->interval_packet_count > 0) {
 4252: 		lost_percent = 100.0 * irp->interval_cnt_error / irp->interval_packet_count;
 4253: 	    }
 4254: 	    else {
 4255: 		lost_percent = 0.0;
 4256: 	    }
 4257: 	    if (test->json_output)
 4258: 		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));
 4259: 	    else
 4260: 		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:"");
 4261: 	}
 4262:     }
 4263: 
 4264:     if (test->logfile || test->forceflush)
 4265:         iflush(test);
 4266: }
 4267: 
 4268: /**************************************************************************/
 4269: void
 4270: iperf_free_stream(struct iperf_stream *sp)
 4271: {
 4272:     struct iperf_interval_results *irp, *nirp;
 4273: 
 4274:     /* XXX: need to free interval list too! */
 4275:     munmap(sp->buffer, sp->test->settings->blksize);
 4276:     close(sp->buffer_fd);
 4277:     if (sp->diskfile_fd >= 0)
 4278: 	close(sp->diskfile_fd);
 4279:     for (irp = TAILQ_FIRST(&sp->result->interval_results); irp != NULL; irp = nirp) {
 4280:         nirp = TAILQ_NEXT(irp, irlistentries);
 4281:         free(irp);
 4282:     }
 4283:     free(sp->result);
 4284:     if (sp->send_timer != NULL)
 4285: 	tmr_cancel(sp->send_timer);
 4286:     free(sp);
 4287: }
 4288: 
 4289: /**************************************************************************/
 4290: struct iperf_stream *
 4291: iperf_new_stream(struct iperf_test *test, int s, int sender)
 4292: {
 4293:     struct iperf_stream *sp;
 4294:     int ret = 0;
 4295: 
 4296:     char template[1024];
 4297:     if (test->tmp_template) {
 4298:         snprintf(template, sizeof(template) / sizeof(char), "%s", test->tmp_template);
 4299:     } else {
 4300:         //find the system temporary dir *unix, windows, cygwin support
 4301:         char* tempdir = getenv("TMPDIR");
 4302:         if (tempdir == 0){
 4303:             tempdir = getenv("TEMP");
 4304:         }
 4305:         if (tempdir == 0){
 4306:             tempdir = getenv("TMP");
 4307:         }
 4308:         if (tempdir == 0){
 4309: #if defined(__ANDROID__)
 4310:             tempdir = "/data/local/tmp";
 4311: #else
 4312:             tempdir = "/tmp";
 4313: #endif
 4314:         }
 4315:         snprintf(template, sizeof(template) / sizeof(char), "%s/iperf3.XXXXXX", tempdir);
 4316:     }
 4317: 
 4318:     sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream));
 4319:     if (!sp) {
 4320:         i_errno = IECREATESTREAM;
 4321:         return NULL;
 4322:     }
 4323: 
 4324:     memset(sp, 0, sizeof(struct iperf_stream));
 4325: 
 4326:     sp->sender = sender;
 4327:     sp->test = test;
 4328:     sp->settings = test->settings;
 4329:     sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));
 4330:     if (!sp->result) {
 4331:         free(sp);
 4332:         i_errno = IECREATESTREAM;
 4333:         return NULL;
 4334:     }
 4335: 
 4336:     memset(sp->result, 0, sizeof(struct iperf_stream_result));
 4337:     TAILQ_INIT(&sp->result->interval_results);
 4338: 
 4339:     /* Create and randomize the buffer */
 4340:     sp->buffer_fd = mkstemp(template);
 4341:     if (sp->buffer_fd == -1) {
 4342:         i_errno = IECREATESTREAM;
 4343:         free(sp->result);
 4344:         free(sp);
 4345:         return NULL;
 4346:     }
 4347:     if (unlink(template) < 0) {
 4348:         i_errno = IECREATESTREAM;
 4349:         free(sp->result);
 4350:         free(sp);
 4351:         return NULL;
 4352:     }
 4353:     if (ftruncate(sp->buffer_fd, test->settings->blksize) < 0) {
 4354:         i_errno = IECREATESTREAM;
 4355:         free(sp->result);
 4356:         free(sp);
 4357:         return NULL;
 4358:     }
 4359:     sp->buffer = (char *) mmap(NULL, test->settings->blksize, PROT_READ|PROT_WRITE, MAP_PRIVATE, sp->buffer_fd, 0);
 4360:     if (sp->buffer == MAP_FAILED) {
 4361:         i_errno = IECREATESTREAM;
 4362:         free(sp->result);
 4363:         free(sp);
 4364:         return NULL;
 4365:     }
 4366:     sp->pending_size = 0;
 4367: 
 4368:     /* Set socket */
 4369:     sp->socket = s;
 4370: 
 4371:     sp->snd = test->protocol->send;
 4372:     sp->rcv = test->protocol->recv;
 4373: 
 4374:     if (test->diskfile_name != (char*) 0) {
 4375: 	sp->diskfile_fd = open(test->diskfile_name, sender ? O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC), S_IRUSR|S_IWUSR);
 4376: 	if (sp->diskfile_fd == -1) {
 4377: 	    i_errno = IEFILE;
 4378:             munmap(sp->buffer, sp->test->settings->blksize);
 4379:             free(sp->result);
 4380:             free(sp);
 4381: 	    return NULL;
 4382: 	}
 4383:         sp->snd2 = sp->snd;
 4384: 	sp->snd = diskfile_send;
 4385: 	sp->rcv2 = sp->rcv;
 4386: 	sp->rcv = diskfile_recv;
 4387:     } else
 4388:         sp->diskfile_fd = -1;
 4389: 
 4390:     /* Initialize stream */
 4391:     if (test->repeating_payload)
 4392:         fill_with_repeating_pattern(sp->buffer, test->settings->blksize);
 4393:     else
 4394:         ret = readentropy(sp->buffer, test->settings->blksize);
 4395: 
 4396:     if ((ret < 0) || (iperf_init_stream(sp, test) < 0)) {
 4397:         close(sp->buffer_fd);
 4398:         munmap(sp->buffer, sp->test->settings->blksize);
 4399:         free(sp->result);
 4400:         free(sp);
 4401:         return NULL;
 4402:     }
 4403:     iperf_add_stream(test, sp);
 4404: 
 4405:     return sp;
 4406: }
 4407: 
 4408: /**************************************************************************/
 4409: int
 4410: iperf_common_sockopts(struct iperf_test *test, int s)
 4411: {
 4412:     int opt;
 4413: 
 4414:     /* Set IP TOS */
 4415:     if ((opt = test->settings->tos)) {
 4416: 	if (getsockdomain(s) == AF_INET6) {
 4417: #ifdef IPV6_TCLASS
 4418: 	    if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) < 0) {
 4419:                 i_errno = IESETCOS;
 4420:                 return -1;
 4421:             }
 4422: 
 4423: 	    /* if the control connection was established with a mapped v4 address
 4424: 	       then set IP_TOS on v6 stream socket as well */
 4425: 	    if (iperf_get_mapped_v4(test)) {
 4426: 		if (setsockopt(s, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) < 0) {
 4427:                     /* ignore any failure of v4 TOS in IPv6 case */
 4428:                 }
 4429:             }
 4430: #else
 4431:             i_errno = IESETCOS;
 4432:             return -1;
 4433: #endif
 4434:         } else {
 4435:             if (setsockopt(s, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) < 0) {
 4436:                 i_errno = IESETTOS;
 4437:                 return -1;
 4438:             }
 4439:         }
 4440:     }
 4441:     return 0;
 4442: }
 4443: 
 4444: /**************************************************************************/
 4445: int
 4446: iperf_init_stream(struct iperf_stream *sp, struct iperf_test *test)
 4447: {
 4448:     int opt;
 4449:     socklen_t len;
 4450: 
 4451:     len = sizeof(struct sockaddr_storage);
 4452:     if (getsockname(sp->socket, (struct sockaddr *) &sp->local_addr, &len) < 0) {
 4453:         i_errno = IEINITSTREAM;
 4454:         return -1;
 4455:     }
 4456:     len = sizeof(struct sockaddr_storage);
 4457:     if (getpeername(sp->socket, (struct sockaddr *) &sp->remote_addr, &len) < 0) {
 4458:         i_errno = IEINITSTREAM;
 4459:         return -1;
 4460:     }
 4461: 
 4462: #if defined(HAVE_DONT_FRAGMENT)
 4463:     /* Set Don't Fragment (DF). Only applicable to IPv4/UDP tests. */
 4464:     if (iperf_get_test_protocol_id(test) == Pudp &&
 4465:         getsockdomain(sp->socket) == AF_INET &&
 4466:         iperf_get_dont_fragment(test)) {
 4467: 
 4468:         /*
 4469:          * There are multiple implementations of this feature depending on the OS.
 4470:          * We need to handle separately Linux, UNIX, and Windows, as well as
 4471:          * the case that DF isn't supported at all (such as on macOS).
 4472:          */
 4473: #if defined(IP_MTU_DISCOVER) /* Linux version of IP_DONTFRAG */
 4474:         opt = IP_PMTUDISC_DO;
 4475:         if (setsockopt(sp->socket, IPPROTO_IP, IP_MTU_DISCOVER, &opt, sizeof(opt)) < 0) {
 4476:             i_errno = IESETDONTFRAGMENT;
 4477:             return -1;
 4478:         }
 4479: #else
 4480: #if defined(IP_DONTFRAG) /* UNIX does IP_DONTFRAG */
 4481:         opt = 1;
 4482:         if (setsockopt(sp->socket, IPPROTO_IP, IP_DONTFRAG, &opt, sizeof(opt)) < 0) {
 4483:             i_errno = IESETDONTFRAGMENT;
 4484:             return -1;
 4485:         }
 4486: #else
 4487: #if defined(IP_DONTFRAGMENT) /* Windows does IP_DONTFRAGMENT */
 4488:         opt = 1;
 4489:         if (setsockopt(sp->socket, IPPROTO_IP, IP_DONTFRAGMENT, &opt, sizeof(opt)) < 0) {
 4490:             i_errno = IESETDONTFRAGMENT;
 4491:             return -1;
 4492:         }
 4493: #else
 4494: 	i_errno = IESETDONTFRAGMENT;
 4495: 	return -1;
 4496: #endif /* IP_DONTFRAGMENT */
 4497: #endif /* IP_DONTFRAG */
 4498: #endif /* IP_MTU_DISCOVER */
 4499:     }
 4500: #endif /* HAVE_DONT_FRAGMENT */
 4501: 
 4502:     return 0;
 4503: }
 4504: 
 4505: /**************************************************************************/
 4506: void
 4507: iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp)
 4508: {
 4509:     int i;
 4510:     struct iperf_stream *n, *prev;
 4511: 
 4512:     if (SLIST_EMPTY(&test->streams)) {
 4513:         SLIST_INSERT_HEAD(&test->streams, sp, streams);
 4514:         sp->id = 1;
 4515:     } else {
 4516:         // for (n = test->streams, i = 2; n->next; n = n->next, ++i);
 4517:         // NOTE: this would ideally be set to 1, however this will not
 4518:         //       be changed since it is not causing a significant problem
 4519:         //       and changing it would break multi-stream tests between old
 4520:         //       and new iperf3 versions.
 4521:         i = 2;
 4522:         prev = NULL;
 4523:         SLIST_FOREACH(n, &test->streams, streams) {
 4524:             prev = n;
 4525:             ++i;
 4526:         }
 4527:         if (prev) {
 4528:             SLIST_INSERT_AFTER(prev, sp, streams);
 4529:             sp->id = i;
 4530:          }
 4531:     }
 4532: }
 4533: 
 4534: /* This pair of routines gets inserted into the snd/rcv function pointers
 4535: ** when there's a -F flag. They handle the file stuff and call the real
 4536: ** snd/rcv functions, which have been saved in snd2/rcv2.
 4537: **
 4538: ** The advantage of doing it this way is that in the much more common
 4539: ** case of no -F flag, there is zero extra overhead.
 4540: */
 4541: 
 4542: static int
 4543: diskfile_send(struct iperf_stream *sp)
 4544: {
 4545:     int r;
 4546:     int buffer_left = sp->diskfile_left; // represents total data in buffer to be sent out
 4547:     static int rtot;
 4548: 
 4549:     /* if needed, read enough data from the disk to fill up the buffer */
 4550:     if (sp->diskfile_left < sp->test->settings->blksize && !sp->test->done) {
 4551:     	r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize -
 4552:     		 sp->diskfile_left);
 4553:         buffer_left += r;
 4554:     	rtot += r;
 4555:     	if (sp->test->debug) {
 4556:     	    printf("read %d bytes from file, %d total\n", r, rtot);
 4557:     	}
 4558: 
 4559:         // If the buffer doesn't contain a full buffer at this point,
 4560:         // adjust the size of the data to send.
 4561:         if (buffer_left != sp->test->settings->blksize) {
 4562:             if (sp->test->debug)
 4563:                 printf("possible eof\n");
 4564:             // setting data size to be sent,
 4565:             // which is less than full block/buffer size
 4566:             // (to be used by iperf_tcp_send, etc.)
 4567:             sp->pending_size = buffer_left;
 4568:         }
 4569: 
 4570:         // If there's no work left, we're done.
 4571:         if (buffer_left == 0) {
 4572:     	    sp->test->done = 1;
 4573:     	    if (sp->test->debug)
 4574:     		  printf("done\n");
 4575:     	}
 4576:     }
 4577: 
 4578:     // If there's no data left in the file or in the buffer, we're done.
 4579:     // No more data available to be sent.
 4580:     // Return without sending data to the network
 4581:     if( sp->test->done || buffer_left == 0 ){
 4582:         if (sp->test->debug)
 4583:               printf("already done\n");
 4584:         sp->test->done = 1;
 4585:         return 0;
 4586:     }
 4587: 
 4588:     r = sp->snd2(sp);
 4589:     if (r < 0) {
 4590: 	return r;
 4591:     }
 4592:     /*
 4593:      * Compute how much data is in the buffer but didn't get sent.
 4594:      * If there are bytes that got left behind, slide them to the
 4595:      * front of the buffer so they can hopefully go out on the next
 4596:      * pass.
 4597:      */
 4598:     sp->diskfile_left = buffer_left - r;
 4599:     if (sp->diskfile_left && sp->diskfile_left < sp->test->settings->blksize) {
 4600: 	memcpy(sp->buffer,
 4601: 	       sp->buffer + (sp->test->settings->blksize - sp->diskfile_left),
 4602: 	       sp->diskfile_left);
 4603: 	if (sp->test->debug)
 4604: 	    printf("Shifting %d bytes by %d\n", sp->diskfile_left, (sp->test->settings->blksize - sp->diskfile_left));
 4605:     }
 4606:     return r;
 4607: }
 4608: 
 4609: static int
 4610: diskfile_recv(struct iperf_stream *sp)
 4611: {
 4612:     int r;
 4613: 
 4614:     r = sp->rcv2(sp);
 4615:     if (r > 0) {
 4616: 	// NOTE: Currently ignoring the return value of writing to disk
 4617: 	(void) (write(sp->diskfile_fd, sp->buffer, r) + 1);
 4618:     }
 4619:     return r;
 4620: }
 4621: 
 4622: 
 4623: void
 4624: iperf_catch_sigend(void (*handler)(int))
 4625: {
 4626: #ifdef SIGINT
 4627:     signal(SIGINT, handler);
 4628: #endif
 4629: #ifdef SIGTERM
 4630:     signal(SIGTERM, handler);
 4631: #endif
 4632: #ifdef SIGHUP
 4633:     signal(SIGHUP, handler);
 4634: #endif
 4635: }
 4636: 
 4637: /**
 4638:  * Called as a result of getting a signal.
 4639:  * Depending on the current state of the test (and the role of this
 4640:  * process) compute and report one more set of ending statistics
 4641:  * before cleaning up and exiting.
 4642:  */
 4643: void
 4644: iperf_got_sigend(struct iperf_test *test)
 4645: {
 4646:     /*
 4647:      * If we're the client, or if we're a server and running a test,
 4648:      * then dump out the accumulated stats so far.
 4649:      */
 4650:     if (test->role == 'c' ||
 4651:       (test->role == 's' && test->state == TEST_RUNNING)) {
 4652: 
 4653: 	test->done = 1;
 4654: 	cpu_util(test->cpu_util);
 4655: 	test->stats_callback(test);
 4656: 	test->state = DISPLAY_RESULTS; /* change local state only */
 4657: 	if (test->on_test_finish)
 4658: 	    test->on_test_finish(test);
 4659: 	test->reporter_callback(test);
 4660:     }
 4661: 
 4662:     if (test->ctrl_sck >= 0) {
 4663: 	test->state = (test->role == 'c') ? CLIENT_TERMINATE : SERVER_TERMINATE;
 4664: 	(void) Nwrite(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp);
 4665:     }
 4666:     i_errno = (test->role == 'c') ? IECLIENTTERM : IESERVERTERM;
 4667:     iperf_errexit(test, "interrupt - %s", iperf_strerror(i_errno));
 4668: }
 4669: 
 4670: /* Try to write a PID file if requested, return -1 on an error. */
 4671: int
 4672: iperf_create_pidfile(struct iperf_test *test)
 4673: {
 4674:     if (test->pidfile) {
 4675: 	int fd;
 4676: 	char buf[8];
 4677: 
 4678: 	/* See if the file already exists and we can read it. */
 4679: 	fd = open(test->pidfile, O_RDONLY, 0);
 4680: 	if (fd >= 0) {
 4681: 	    if (read(fd, buf, sizeof(buf) - 1) >= 0) {
 4682: 
 4683: 		/* We read some bytes, see if they correspond to a valid PID */
 4684: 		pid_t pid;
 4685: 		pid = atoi(buf);
 4686: 		if (pid > 0) {
 4687: 
 4688: 		    /* See if the process exists. */
 4689: 		    if (kill(pid, 0) == 0) {
 4690: 			/*
 4691: 			 * Make sure not to try to delete existing PID file by
 4692: 			 * scribbling over the pathname we'd use to refer to it.
 4693: 			 * Then exit with an error.
 4694: 			 */
 4695: 			free(test->pidfile);
 4696: 			test->pidfile = NULL;
 4697: 			iperf_errexit(test, "Another instance of iperf3 appears to be running");
 4698: 		    }
 4699: 		}
 4700: 	    }
 4701: 	}
 4702: 
 4703: 	/*
 4704: 	 * File didn't exist, we couldn't read it, or it didn't correspond to
 4705: 	 * a running process.  Try to create it.
 4706: 	 */
 4707: 	fd = open(test->pidfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR|S_IWUSR);
 4708: 	if (fd < 0) {
 4709: 	    return -1;
 4710: 	}
 4711: 	snprintf(buf, sizeof(buf), "%d", getpid()); /* no trailing newline */
 4712: 	if (write(fd, buf, strlen(buf)) < 0) {
 4713: 	    (void)close(fd);
 4714: 	    return -1;
 4715: 	}
 4716: 	if (close(fd) < 0) {
 4717: 	    return -1;
 4718: 	};
 4719:     }
 4720:     return 0;
 4721: }
 4722: 
 4723: /* Get rid of a PID file, return -1 on error. */
 4724: int
 4725: iperf_delete_pidfile(struct iperf_test *test)
 4726: {
 4727:     if (test->pidfile) {
 4728: 	if (unlink(test->pidfile) < 0) {
 4729: 	    return -1;
 4730: 	}
 4731:     }
 4732:     return 0;
 4733: }
 4734: 
 4735: int
 4736: iperf_json_start(struct iperf_test *test)
 4737: {
 4738:     test->json_top = cJSON_CreateObject();
 4739:     if (test->json_top == NULL)
 4740:         return -1;
 4741:     test->json_start = cJSON_CreateObject();
 4742:     if (test->json_start == NULL)
 4743:         return -1;
 4744:     cJSON_AddItemToObject(test->json_top, "start", test->json_start);
 4745:     test->json_connected = cJSON_CreateArray();
 4746:     if (test->json_connected == NULL)
 4747:         return -1;
 4748:     cJSON_AddItemToObject(test->json_start, "connected", test->json_connected);
 4749:     test->json_intervals = cJSON_CreateArray();
 4750:     if (test->json_intervals == NULL)
 4751:         return -1;
 4752:     cJSON_AddItemToObject(test->json_top, "intervals", test->json_intervals);
 4753:     test->json_end = cJSON_CreateObject();
 4754:     if (test->json_end == NULL)
 4755:         return -1;
 4756:     cJSON_AddItemToObject(test->json_top, "end", test->json_end);
 4757:     return 0;
 4758: }
 4759: 
 4760: int
 4761: iperf_json_finish(struct iperf_test *test)
 4762: {
 4763:     if (test->json_top) {
 4764:         if (test->title) {
 4765:             cJSON_AddStringToObject(test->json_top, "title", test->title);
 4766:         }
 4767:         if (test->extra_data) {
 4768:             cJSON_AddStringToObject(test->json_top, "extra_data", test->extra_data);
 4769:         }
 4770:         /* Include server output */
 4771:         if (test->json_server_output) {
 4772:             cJSON_AddItemToObject(test->json_top, "server_output_json", test->json_server_output);
 4773:         }
 4774:         if (test->server_output_text) {
 4775:             cJSON_AddStringToObject(test->json_top, "server_output_text", test->server_output_text);
 4776:         }
 4777:         // Get ASCII rendering of JSON structure.  Then make our
 4778:         // own copy of it and return the storage that cJSON allocated
 4779:         // on our behalf.  We keep our own copy around.
 4780:         char *str = cJSON_Print(test->json_top);
 4781:         if (str == NULL) {
 4782:             return -1;
 4783:         }
 4784:         test->json_output_string = strdup(str);
 4785:         cJSON_free(str);
 4786:         if (test->json_output_string == NULL) {
 4787:             return -1;
 4788:         }
 4789:         fprintf(test->outfile, "%s\n", test->json_output_string);
 4790:         iflush(test);
 4791:         cJSON_Delete(test->json_top);
 4792:         test->json_top = NULL;
 4793:     }
 4794:     test->json_start = test->json_connected = test->json_intervals = test->json_server_output = test->json_end = NULL;
 4795:     return 0;
 4796: }
 4797: 
 4798: 
 4799: /* CPU affinity stuff - Linux, FreeBSD, and Windows only. */
 4800: 
 4801: int
 4802: iperf_setaffinity(struct iperf_test *test, int affinity)
 4803: {
 4804: #if defined(HAVE_SCHED_SETAFFINITY)
 4805:     cpu_set_t cpu_set;
 4806: 
 4807:     CPU_ZERO(&cpu_set);
 4808:     CPU_SET(affinity, &cpu_set);
 4809:     if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) {
 4810: 	i_errno = IEAFFINITY;
 4811:         return -1;
 4812:     }
 4813:     return 0;
 4814: #elif defined(HAVE_CPUSET_SETAFFINITY)
 4815:     cpuset_t cpumask;
 4816: 
 4817:     if(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
 4818:                           sizeof(cpuset_t), &test->cpumask) != 0) {
 4819:         i_errno = IEAFFINITY;
 4820:         return -1;
 4821:     }
 4822: 
 4823:     CPU_ZERO(&cpumask);
 4824:     CPU_SET(affinity, &cpumask);
 4825: 
 4826:     if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1,
 4827:                           sizeof(cpuset_t), &cpumask) != 0) {
 4828:         i_errno = IEAFFINITY;
 4829:         return -1;
 4830:     }
 4831:     return 0;
 4832: #elif defined(HAVE_SETPROCESSAFFINITYMASK)
 4833: 	HANDLE process = GetCurrentProcess();
 4834: 	DWORD_PTR processAffinityMask = 1 << affinity;
 4835: 
 4836: 	if (SetProcessAffinityMask(process, processAffinityMask) == 0) {
 4837: 		i_errno = IEAFFINITY;
 4838: 		return -1;
 4839: 	}
 4840: 	return 0;
 4841: #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
 4842:     i_errno = IEAFFINITY;
 4843:     return -1;
 4844: #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
 4845: }
 4846: 
 4847: int
 4848: iperf_clearaffinity(struct iperf_test *test)
 4849: {
 4850: #if defined(HAVE_SCHED_SETAFFINITY)
 4851:     cpu_set_t cpu_set;
 4852:     int i;
 4853: 
 4854:     CPU_ZERO(&cpu_set);
 4855:     for (i = 0; i < CPU_SETSIZE; ++i)
 4856: 	CPU_SET(i, &cpu_set);
 4857:     if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) {
 4858: 	i_errno = IEAFFINITY;
 4859:         return -1;
 4860:     }
 4861:     return 0;
 4862: #elif defined(HAVE_CPUSET_SETAFFINITY)
 4863:     if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1,
 4864:                           sizeof(cpuset_t), &test->cpumask) != 0) {
 4865:         i_errno = IEAFFINITY;
 4866:         return -1;
 4867:     }
 4868:     return 0;
 4869: #elif defined(HAVE_SETPROCESSAFFINITYMASK)
 4870: 	HANDLE process = GetCurrentProcess();
 4871: 	DWORD_PTR processAffinityMask;
 4872: 	DWORD_PTR lpSystemAffinityMask;
 4873: 
 4874: 	if (GetProcessAffinityMask(process, &processAffinityMask, &lpSystemAffinityMask) == 0
 4875: 			|| SetProcessAffinityMask(process, lpSystemAffinityMask) == 0) {
 4876: 		i_errno = IEAFFINITY;
 4877: 		return -1;
 4878: 	}
 4879: 	return 0;
 4880: #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
 4881:     i_errno = IEAFFINITY;
 4882:     return -1;
 4883: #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
 4884: }
 4885: 
 4886: static char iperf_timestr[100];
 4887: static char linebuffer[1024];
 4888: 
 4889: int
 4890: iperf_printf(struct iperf_test *test, const char* format, ...)
 4891: {
 4892:     va_list argp;
 4893:     int r = 0, r0;
 4894:     time_t now;
 4895:     struct tm *ltm = NULL;
 4896:     char *ct = NULL;
 4897: 
 4898:     /* Timestamp if requested */
 4899:     if (iperf_get_test_timestamps(test)) {
 4900: 	time(&now);
 4901: 	ltm = localtime(&now);
 4902: 	strftime(iperf_timestr, sizeof(iperf_timestr), iperf_get_test_timestamp_format(test), ltm);
 4903: 	ct = iperf_timestr;
 4904:     }
 4905: 
 4906:     /*
 4907:      * There are roughly two use cases here.  If we're the client,
 4908:      * want to print stuff directly to the output stream.
 4909:      * If we're the sender we might need to buffer up output to send
 4910:      * to the client.
 4911:      *
 4912:      * This doesn't make a whole lot of difference except there are
 4913:      * some chunks of output on the client (on particular the whole
 4914:      * of the server output with --get-server-output) that could
 4915:      * easily exceed the size of the line buffer, but which don't need
 4916:      * to be buffered up anyway.
 4917:      */
 4918:     if (test->role == 'c') {
 4919: 	if (ct) {
 4920:             r0 = fprintf(test->outfile, "%s", ct);
 4921:             if (r0 < 0)
 4922:                 return r0;
 4923:             r += r0;
 4924: 	}
 4925: 	if (test->title) {
 4926: 	    r0 = fprintf(test->outfile, "%s:  ", test->title);
 4927:             if (r0 < 0)
 4928:                 return r0;
 4929:             r += r0;
 4930:         }
 4931: 	va_start(argp, format);
 4932: 	r0 = vfprintf(test->outfile, format, argp);
 4933: 	va_end(argp);
 4934:         if (r0 < 0)
 4935:             return r0;
 4936:         r += r0;
 4937:     }
 4938:     else if (test->role == 's') {
 4939: 	if (ct) {
 4940: 	    r0 = snprintf(linebuffer, sizeof(linebuffer), "%s", ct);
 4941:             if (r0 < 0)
 4942:                 return r0;
 4943:             r += r0;
 4944: 	}
 4945:         /* Should always be true as long as sizeof(ct) < sizeof(linebuffer) */
 4946:         if (r < sizeof(linebuffer)) {
 4947:             va_start(argp, format);
 4948:             r0 = vsnprintf(linebuffer + r, sizeof(linebuffer) - r, format, argp);
 4949:             va_end(argp);
 4950:             if (r0 < 0)
 4951:                 return r0;
 4952:             r += r0;
 4953:         }
 4954: 	fprintf(test->outfile, "%s", linebuffer);
 4955: 
 4956: 	if (test->role == 's' && iperf_get_test_get_server_output(test)) {
 4957: 	    struct iperf_textline *l = (struct iperf_textline *) malloc(sizeof(struct iperf_textline));
 4958: 	    l->line = strdup(linebuffer);
 4959: 	    TAILQ_INSERT_TAIL(&(test->server_output_list), l, textlineentries);
 4960: 	}
 4961:     }
 4962:     return r;
 4963: }
 4964: 
 4965: int
 4966: iflush(struct iperf_test *test)
 4967: {
 4968:     return fflush(test->outfile);
 4969: }

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