File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / iperf / src / iperf_api.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:36:46 2021 UTC (3 years, 4 months ago) by misho
Branches: iperf, MAIN
CVS tags: v3_3_9, HEAD
iperf 3.3.9

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

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