Annotation of embedaddon/iperf/src/iperf_api.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * iperf, Copyright (c) 2014, 2015, 2016, 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: #define _GNU_SOURCE
        !            28: #define __USE_GNU
        !            29: 
        !            30: #include "iperf_config.h"
        !            31: 
        !            32: #include <stdio.h>
        !            33: #include <stdlib.h>
        !            34: #include <string.h>
        !            35: #include <getopt.h>
        !            36: #include <errno.h>
        !            37: #include <signal.h>
        !            38: #include <unistd.h>
        !            39: #include <assert.h>
        !            40: #include <fcntl.h>
        !            41: #include <sys/socket.h>
        !            42: #include <sys/types.h>
        !            43: #include <netinet/in.h>
        !            44: #include <arpa/inet.h>
        !            45: #include <netdb.h>
        !            46: #include <pthread.h>
        !            47: #ifdef HAVE_STDINT_H
        !            48: #include <stdint.h>
        !            49: #endif
        !            50: #include <netinet/tcp.h>
        !            51: #include <sys/time.h>
        !            52: #include <sys/resource.h>
        !            53: #include <sys/mman.h>
        !            54: #include <sys/stat.h>
        !            55: #include <sched.h>
        !            56: #include <setjmp.h>
        !            57: #include <stdarg.h>
        !            58: 
        !            59: #if defined(HAVE_CPUSET_SETAFFINITY)
        !            60: #include <sys/param.h>
        !            61: #include <sys/cpuset.h>
        !            62: #endif /* HAVE_CPUSET_SETAFFINITY */
        !            63: 
        !            64: #include "net.h"
        !            65: #include "iperf.h"
        !            66: #include "iperf_api.h"
        !            67: #include "iperf_udp.h"
        !            68: #include "iperf_tcp.h"
        !            69: #if defined(HAVE_SCTP)
        !            70: #include "iperf_sctp.h"
        !            71: #endif /* HAVE_SCTP */
        !            72: #include "timer.h"
        !            73: 
        !            74: #include "cjson.h"
        !            75: #include "units.h"
        !            76: #include "tcp_window_size.h"
        !            77: #include "iperf_util.h"
        !            78: #include "iperf_locale.h"
        !            79: #include "version.h"
        !            80: 
        !            81: /* Forwards. */
        !            82: static int send_parameters(struct iperf_test *test);
        !            83: static int get_parameters(struct iperf_test *test);
        !            84: static int send_results(struct iperf_test *test);
        !            85: static int get_results(struct iperf_test *test);
        !            86: static int diskfile_send(struct iperf_stream *sp);
        !            87: static int diskfile_recv(struct iperf_stream *sp);
        !            88: static int JSON_write(int fd, cJSON *json);
        !            89: static void print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams);
        !            90: static cJSON *JSON_read(int fd);
        !            91: 
        !            92: 
        !            93: /*************************** Print usage functions ****************************/
        !            94: 
        !            95: void
        !            96: usage()
        !            97: {
        !            98:     fputs(usage_shortstr, stderr);
        !            99: }
        !           100: 
        !           101: 
        !           102: void
        !           103: usage_long()
        !           104: {
        !           105:     fprintf(stderr, usage_longstr, UDP_RATE / (1024*1024), DURATION, DEFAULT_TCP_BLKSIZE / 1024, DEFAULT_UDP_BLKSIZE / 1024);
        !           106: }
        !           107: 
        !           108: 
        !           109: void warning(char *str)
        !           110: {
        !           111:     fprintf(stderr, "warning: %s\n", str);
        !           112: }
        !           113: 
        !           114: 
        !           115: /************** Getter routines for some fields inside iperf_test *************/
        !           116: 
        !           117: int
        !           118: iperf_get_verbose(struct iperf_test *ipt)
        !           119: {
        !           120:     return ipt->verbose;
        !           121: }
        !           122: 
        !           123: int
        !           124: iperf_get_control_socket(struct iperf_test *ipt)
        !           125: {
        !           126:     return ipt->ctrl_sck;
        !           127: }
        !           128: 
        !           129: int
        !           130: iperf_get_test_omit(struct iperf_test *ipt)
        !           131: {
        !           132:     return ipt->omit;
        !           133: }
        !           134: 
        !           135: int
        !           136: iperf_get_test_duration(struct iperf_test *ipt)
        !           137: {
        !           138:     return ipt->duration;
        !           139: }
        !           140: 
        !           141: uint64_t
        !           142: iperf_get_test_rate(struct iperf_test *ipt)
        !           143: {
        !           144:     return ipt->settings->rate;
        !           145: }
        !           146: 
        !           147: int
        !           148: iperf_get_test_burst(struct iperf_test *ipt)
        !           149: {
        !           150:     return ipt->settings->burst;
        !           151: }
        !           152: 
        !           153: char
        !           154: iperf_get_test_role(struct iperf_test *ipt)
        !           155: {
        !           156:     return ipt->role;
        !           157: }
        !           158: 
        !           159: int
        !           160: iperf_get_test_reverse(struct iperf_test *ipt)
        !           161: {
        !           162:     return ipt->reverse;
        !           163: }
        !           164: 
        !           165: int
        !           166: iperf_get_test_blksize(struct iperf_test *ipt)
        !           167: {
        !           168:     return ipt->settings->blksize;
        !           169: }
        !           170: 
        !           171: FILE *
        !           172: iperf_get_test_outfile (struct iperf_test *ipt)
        !           173: {
        !           174:     return ipt->outfile;
        !           175: }
        !           176: 
        !           177: int
        !           178: iperf_get_test_socket_bufsize(struct iperf_test *ipt)
        !           179: {
        !           180:     return ipt->settings->socket_bufsize;
        !           181: }
        !           182: 
        !           183: double
        !           184: iperf_get_test_reporter_interval(struct iperf_test *ipt)
        !           185: {
        !           186:     return ipt->reporter_interval;
        !           187: }
        !           188: 
        !           189: double
        !           190: iperf_get_test_stats_interval(struct iperf_test *ipt)
        !           191: {
        !           192:     return ipt->stats_interval;
        !           193: }
        !           194: 
        !           195: int
        !           196: iperf_get_test_num_streams(struct iperf_test *ipt)
        !           197: {
        !           198:     return ipt->num_streams;
        !           199: }
        !           200: 
        !           201: int
        !           202: iperf_get_test_server_port(struct iperf_test *ipt)
        !           203: {
        !           204:     return ipt->server_port;
        !           205: }
        !           206: 
        !           207: char*
        !           208: iperf_get_test_server_hostname(struct iperf_test *ipt)
        !           209: {
        !           210:     return ipt->server_hostname;
        !           211: }
        !           212: 
        !           213: char*
        !           214: iperf_get_test_template(struct iperf_test *ipt)
        !           215: {
        !           216:     return ipt->tmp_template;
        !           217: }
        !           218: 
        !           219: int
        !           220: iperf_get_test_protocol_id(struct iperf_test *ipt)
        !           221: {
        !           222:     return ipt->protocol->id;
        !           223: }
        !           224: 
        !           225: int
        !           226: iperf_get_test_json_output(struct iperf_test *ipt)
        !           227: {
        !           228:     return ipt->json_output;
        !           229: }
        !           230: 
        !           231: char *
        !           232: iperf_get_test_json_output_string(struct iperf_test *ipt)
        !           233: {
        !           234:     return ipt->json_output_string;
        !           235: }
        !           236: 
        !           237: int
        !           238: iperf_get_test_zerocopy(struct iperf_test *ipt)
        !           239: {
        !           240:     return ipt->zerocopy;
        !           241: }
        !           242: 
        !           243: int
        !           244: iperf_get_test_get_server_output(struct iperf_test *ipt)
        !           245: {
        !           246:     return ipt->get_server_output;
        !           247: }
        !           248: 
        !           249: char
        !           250: iperf_get_test_unit_format(struct iperf_test *ipt)
        !           251: {
        !           252:     return ipt->settings->unit_format;
        !           253: }
        !           254: 
        !           255: char *
        !           256: iperf_get_test_bind_address(struct iperf_test *ipt)
        !           257: {
        !           258:     return ipt->bind_address;
        !           259: }
        !           260: 
        !           261: int
        !           262: iperf_get_test_udp_counters_64bit(struct iperf_test *ipt)
        !           263: {
        !           264:     return ipt->udp_counters_64bit;
        !           265: }
        !           266: 
        !           267: int
        !           268: iperf_get_test_one_off(struct iperf_test *ipt)
        !           269: {
        !           270:     return ipt->one_off;
        !           271: }
        !           272: 
        !           273: int
        !           274: iperf_get_no_fq_socket_pacing(struct iperf_test *ipt)
        !           275: {
        !           276:     return ipt->no_fq_socket_pacing;
        !           277: }
        !           278: 
        !           279: /************** Setter routines for some fields inside iperf_test *************/
        !           280: 
        !           281: void
        !           282: iperf_set_verbose(struct iperf_test *ipt, int verbose)
        !           283: {
        !           284:     ipt->verbose = verbose;
        !           285: }
        !           286: 
        !           287: void
        !           288: iperf_set_control_socket(struct iperf_test *ipt, int ctrl_sck)
        !           289: {
        !           290:     ipt->ctrl_sck = ctrl_sck;
        !           291: }
        !           292: 
        !           293: void
        !           294: iperf_set_test_omit(struct iperf_test *ipt, int omit)
        !           295: {
        !           296:     ipt->omit = omit;
        !           297: }
        !           298: 
        !           299: void
        !           300: iperf_set_test_duration(struct iperf_test *ipt, int duration)
        !           301: {
        !           302:     ipt->duration = duration;
        !           303: }
        !           304: 
        !           305: void
        !           306: iperf_set_test_reporter_interval(struct iperf_test *ipt, double reporter_interval)
        !           307: {
        !           308:     ipt->reporter_interval = reporter_interval;
        !           309: }
        !           310: 
        !           311: void
        !           312: iperf_set_test_stats_interval(struct iperf_test *ipt, double stats_interval)
        !           313: {
        !           314:     ipt->stats_interval = stats_interval;
        !           315: }
        !           316: 
        !           317: void
        !           318: iperf_set_test_state(struct iperf_test *ipt, signed char state)
        !           319: {
        !           320:     ipt->state = state;
        !           321: }
        !           322: 
        !           323: void
        !           324: iperf_set_test_blksize(struct iperf_test *ipt, int blksize)
        !           325: {
        !           326:     ipt->settings->blksize = blksize;
        !           327: }
        !           328: 
        !           329: void
        !           330: iperf_set_test_rate(struct iperf_test *ipt, uint64_t rate)
        !           331: {
        !           332:     ipt->settings->rate = rate;
        !           333: }
        !           334: 
        !           335: void
        !           336: iperf_set_test_burst(struct iperf_test *ipt, int burst)
        !           337: {
        !           338:     ipt->settings->burst = burst;
        !           339: }
        !           340: 
        !           341: void
        !           342: iperf_set_test_server_port(struct iperf_test *ipt, int server_port)
        !           343: {
        !           344:     ipt->server_port = server_port;
        !           345: }
        !           346: 
        !           347: void
        !           348: iperf_set_test_socket_bufsize(struct iperf_test *ipt, int socket_bufsize)
        !           349: {
        !           350:     ipt->settings->socket_bufsize = socket_bufsize;
        !           351: }
        !           352: 
        !           353: void
        !           354: iperf_set_test_num_streams(struct iperf_test *ipt, int num_streams)
        !           355: {
        !           356:     ipt->num_streams = num_streams;
        !           357: }
        !           358: 
        !           359: static void
        !           360: check_sender_has_retransmits(struct iperf_test *ipt)
        !           361: {
        !           362:     if (ipt->sender && ipt->protocol->id == Ptcp && has_tcpinfo_retransmits())
        !           363:        ipt->sender_has_retransmits = 1;
        !           364:     else
        !           365:        ipt->sender_has_retransmits = 0;
        !           366: }
        !           367: 
        !           368: void
        !           369: iperf_set_test_role(struct iperf_test *ipt, char role)
        !           370: {
        !           371:     ipt->role = role;
        !           372:     if (role == 'c')
        !           373:        ipt->sender = 1;
        !           374:     else if (role == 's')
        !           375:        ipt->sender = 0;
        !           376:     if (ipt->reverse)
        !           377:         ipt->sender = ! ipt->sender;
        !           378:     check_sender_has_retransmits(ipt);
        !           379: }
        !           380: 
        !           381: void
        !           382: iperf_set_test_server_hostname(struct iperf_test *ipt, char *server_hostname)
        !           383: {
        !           384:     ipt->server_hostname = strdup(server_hostname);
        !           385: }
        !           386: 
        !           387: void
        !           388: iperf_set_test_template(struct iperf_test *ipt, char *tmp_template)
        !           389: {
        !           390:     ipt->tmp_template = strdup(tmp_template);
        !           391: }
        !           392: 
        !           393: void
        !           394: iperf_set_test_reverse(struct iperf_test *ipt, int reverse)
        !           395: {
        !           396:     ipt->reverse = reverse;
        !           397:     if (ipt->reverse)
        !           398:         ipt->sender = ! ipt->sender;
        !           399:     check_sender_has_retransmits(ipt);
        !           400: }
        !           401: 
        !           402: void
        !           403: iperf_set_test_json_output(struct iperf_test *ipt, int json_output)
        !           404: {
        !           405:     ipt->json_output = json_output;
        !           406: }
        !           407: 
        !           408: int
        !           409: iperf_has_zerocopy( void )
        !           410: {
        !           411:     return has_sendfile();
        !           412: }
        !           413: 
        !           414: void
        !           415: iperf_set_test_zerocopy(struct iperf_test *ipt, int zerocopy)
        !           416: {
        !           417:     ipt->zerocopy = (zerocopy && has_sendfile());
        !           418: }
        !           419: 
        !           420: void
        !           421: iperf_set_test_get_server_output(struct iperf_test *ipt, int get_server_output)
        !           422: {
        !           423:     ipt->get_server_output = get_server_output;
        !           424: }
        !           425: 
        !           426: void
        !           427: iperf_set_test_unit_format(struct iperf_test *ipt, char unit_format)
        !           428: {
        !           429:     ipt->settings->unit_format = unit_format;
        !           430: }
        !           431: 
        !           432: void
        !           433: iperf_set_test_bind_address(struct iperf_test *ipt, char *bind_address)
        !           434: {
        !           435:     ipt->bind_address = strdup(bind_address);
        !           436: }
        !           437: 
        !           438: void
        !           439: iperf_set_test_udp_counters_64bit(struct iperf_test *ipt, int udp_counters_64bit)
        !           440: {
        !           441:     ipt->udp_counters_64bit = udp_counters_64bit;
        !           442: }
        !           443: 
        !           444: void
        !           445: iperf_set_test_one_off(struct iperf_test *ipt, int one_off)
        !           446: {
        !           447:     ipt->one_off = one_off;
        !           448: }
        !           449: 
        !           450: void
        !           451: iperf_set_no_fq_socket_pacing(struct iperf_test *ipt, int no_pacing)
        !           452: {
        !           453:     ipt->no_fq_socket_pacing = no_pacing;
        !           454: }
        !           455: 
        !           456: /********************** Get/set test protocol structure ***********************/
        !           457: 
        !           458: struct protocol *
        !           459: get_protocol(struct iperf_test *test, int prot_id)
        !           460: {
        !           461:     struct protocol *prot;
        !           462: 
        !           463:     SLIST_FOREACH(prot, &test->protocols, protocols) {
        !           464:         if (prot->id == prot_id)
        !           465:             break;
        !           466:     }
        !           467: 
        !           468:     if (prot == NULL)
        !           469:         i_errno = IEPROTOCOL;
        !           470: 
        !           471:     return prot;
        !           472: }
        !           473: 
        !           474: int
        !           475: set_protocol(struct iperf_test *test, int prot_id)
        !           476: {
        !           477:     struct protocol *prot = NULL;
        !           478: 
        !           479:     SLIST_FOREACH(prot, &test->protocols, protocols) {
        !           480:         if (prot->id == prot_id) {
        !           481:             test->protocol = prot;
        !           482:            check_sender_has_retransmits(test);
        !           483:             return 0;
        !           484:         }
        !           485:     }
        !           486: 
        !           487:     i_errno = IEPROTOCOL;
        !           488:     return -1;
        !           489: }
        !           490: 
        !           491: 
        !           492: /************************** Iperf callback functions **************************/
        !           493: 
        !           494: void
        !           495: iperf_on_new_stream(struct iperf_stream *sp)
        !           496: {
        !           497:     connect_msg(sp);
        !           498: }
        !           499: 
        !           500: void
        !           501: iperf_on_test_start(struct iperf_test *test)
        !           502: {
        !           503:     if (test->json_output) {
        !           504:        cJSON_AddItemToObject(test->json_start, "test_start", iperf_json_printf("protocol: %s  num_streams: %d  blksize: %d  omit: %d  duration: %d  bytes: %d  blocks: %d  reverse: %d", test->protocol->name, (int64_t) test->num_streams, (int64_t) test->settings->blksize, (int64_t) test->omit, (int64_t) test->duration, (int64_t) test->settings->bytes, (int64_t) test->settings->blocks, test->reverse?(int64_t)1:(int64_t)0));
        !           505:     } else {
        !           506:        if (test->verbose) {
        !           507:            if (test->settings->bytes)
        !           508:                iprintf(test, test_start_bytes, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->bytes);
        !           509:            else if (test->settings->blocks)
        !           510:                iprintf(test, test_start_blocks, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->blocks);
        !           511:            else
        !           512:                iprintf(test, test_start_time, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->duration);
        !           513:        }
        !           514:     }
        !           515: }
        !           516: 
        !           517: /* This converts an IPv6 string address from IPv4-mapped format into regular
        !           518: ** old IPv4 format, which is easier on the eyes of network veterans.
        !           519: **
        !           520: ** If the v6 address is not v4-mapped it is left alone.
        !           521: */
        !           522: static void
        !           523: mapped_v4_to_regular_v4(char *str)
        !           524: {
        !           525:     char *prefix = "::ffff:";
        !           526:     int prefix_len;
        !           527: 
        !           528:     prefix_len = strlen(prefix);
        !           529:     if (strncmp(str, prefix, prefix_len) == 0) {
        !           530:        int str_len = strlen(str);
        !           531:        memmove(str, str + prefix_len, str_len - prefix_len + 1);
        !           532:     }
        !           533: }
        !           534: 
        !           535: void
        !           536: iperf_on_connect(struct iperf_test *test)
        !           537: {
        !           538:     time_t now_secs;
        !           539:     const char* rfc1123_fmt = "%a, %d %b %Y %H:%M:%S GMT";
        !           540:     char now_str[100];
        !           541:     char ipr[INET6_ADDRSTRLEN];
        !           542:     int port;
        !           543:     struct sockaddr_storage sa;
        !           544:     struct sockaddr_in *sa_inP;
        !           545:     struct sockaddr_in6 *sa_in6P;
        !           546:     socklen_t len;
        !           547:     int opt;
        !           548: 
        !           549:     now_secs = time((time_t*) 0);
        !           550:     (void) strftime(now_str, sizeof(now_str), rfc1123_fmt, gmtime(&now_secs));
        !           551:     if (test->json_output)
        !           552:        cJSON_AddItemToObject(test->json_start, "timestamp", iperf_json_printf("time: %s  timesecs: %d", now_str, (int64_t) now_secs));
        !           553:     else if (test->verbose)
        !           554:        iprintf(test, report_time, now_str);
        !           555: 
        !           556:     if (test->role == 'c') {
        !           557:        if (test->json_output)
        !           558:            cJSON_AddItemToObject(test->json_start, "connecting_to", iperf_json_printf("host: %s  port: %d", test->server_hostname, (int64_t) test->server_port));
        !           559:        else {
        !           560:            iprintf(test, report_connecting, test->server_hostname, test->server_port);
        !           561:            if (test->reverse)
        !           562:                iprintf(test, report_reverse, test->server_hostname);
        !           563:        }
        !           564:     } else {
        !           565:         len = sizeof(sa);
        !           566:         getpeername(test->ctrl_sck, (struct sockaddr *) &sa, &len);
        !           567:         if (getsockdomain(test->ctrl_sck) == AF_INET) {
        !           568:            sa_inP = (struct sockaddr_in *) &sa;
        !           569:             inet_ntop(AF_INET, &sa_inP->sin_addr, ipr, sizeof(ipr));
        !           570:            port = ntohs(sa_inP->sin_port);
        !           571:         } else {
        !           572:            sa_in6P = (struct sockaddr_in6 *) &sa;
        !           573:             inet_ntop(AF_INET6, &sa_in6P->sin6_addr, ipr, sizeof(ipr));
        !           574:            port = ntohs(sa_in6P->sin6_port);
        !           575:         }
        !           576:        mapped_v4_to_regular_v4(ipr);
        !           577:        if (test->json_output)
        !           578:            cJSON_AddItemToObject(test->json_start, "accepted_connection", iperf_json_printf("host: %s  port: %d", ipr, (int64_t) port));
        !           579:        else
        !           580:            iprintf(test, report_accepted, ipr, port);
        !           581:     }
        !           582:     if (test->json_output) {
        !           583:        cJSON_AddStringToObject(test->json_start, "cookie", test->cookie);
        !           584:         if (test->protocol->id == SOCK_STREAM) {
        !           585:            if (test->settings->mss)
        !           586:                cJSON_AddNumberToObject(test->json_start, "tcp_mss", test->settings->mss);
        !           587:            else {
        !           588:                len = sizeof(opt);
        !           589:                getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len);
        !           590:                cJSON_AddNumberToObject(test->json_start, "tcp_mss_default", opt);
        !           591:            }
        !           592:        }
        !           593:     } else if (test->verbose) {
        !           594:         iprintf(test, report_cookie, test->cookie);
        !           595:         if (test->protocol->id == SOCK_STREAM) {
        !           596:             if (test->settings->mss)
        !           597:                 iprintf(test, "      TCP MSS: %d\n", test->settings->mss);
        !           598:             else {
        !           599:                 len = sizeof(opt);
        !           600:                 getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len);
        !           601:                 iprintf(test, "      TCP MSS: %d (default)\n", opt);
        !           602:             }
        !           603:         }
        !           604: 
        !           605:     }
        !           606: }
        !           607: 
        !           608: void
        !           609: iperf_on_test_finish(struct iperf_test *test)
        !           610: {
        !           611: }
        !           612: 
        !           613: 
        !           614: /******************************************************************************/
        !           615: 
        !           616: int
        !           617: iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
        !           618: {
        !           619:     static struct option longopts[] =
        !           620:     {
        !           621:         {"port", required_argument, NULL, 'p'},
        !           622:         {"format", required_argument, NULL, 'f'},
        !           623:         {"interval", required_argument, NULL, 'i'},
        !           624:         {"daemon", no_argument, NULL, 'D'},
        !           625:         {"one-off", no_argument, NULL, '1'},
        !           626:         {"verbose", no_argument, NULL, 'V'},
        !           627:         {"json", no_argument, NULL, 'J'},
        !           628:         {"version", no_argument, NULL, 'v'},
        !           629:         {"server", no_argument, NULL, 's'},
        !           630:         {"client", required_argument, NULL, 'c'},
        !           631:         {"udp", no_argument, NULL, 'u'},
        !           632:         {"bandwidth", required_argument, NULL, 'b'},
        !           633:         {"time", required_argument, NULL, 't'},
        !           634:         {"bytes", required_argument, NULL, 'n'},
        !           635:         {"blockcount", required_argument, NULL, 'k'},
        !           636:         {"length", required_argument, NULL, 'l'},
        !           637:         {"parallel", required_argument, NULL, 'P'},
        !           638:         {"reverse", no_argument, NULL, 'R'},
        !           639:         {"window", required_argument, NULL, 'w'},
        !           640:         {"bind", required_argument, NULL, 'B'},
        !           641:         {"cport", required_argument, NULL, OPT_CLIENT_PORT},
        !           642:         {"set-mss", required_argument, NULL, 'M'},
        !           643:         {"no-delay", no_argument, NULL, 'N'},
        !           644:         {"version4", no_argument, NULL, '4'},
        !           645:         {"version6", no_argument, NULL, '6'},
        !           646:         {"tos", required_argument, NULL, 'S'},
        !           647: #if defined(HAVE_FLOWLABEL)
        !           648:         {"flowlabel", required_argument, NULL, 'L'},
        !           649: #endif /* HAVE_FLOWLABEL */
        !           650:         {"zerocopy", no_argument, NULL, 'Z'},
        !           651:         {"omit", required_argument, NULL, 'O'},
        !           652:         {"file", required_argument, NULL, 'F'},
        !           653: #if defined(HAVE_CPU_AFFINITY)
        !           654:         {"affinity", required_argument, NULL, 'A'},
        !           655: #endif /* HAVE_CPU_AFFINITY */
        !           656:         {"title", required_argument, NULL, 'T'},
        !           657: #if defined(HAVE_TCP_CONGESTION)
        !           658:         {"congestion", required_argument, NULL, 'C'},
        !           659:         {"linux-congestion", required_argument, NULL, 'C'},
        !           660: #endif /* HAVE_TCP_CONGESTION */
        !           661: #if defined(HAVE_SCTP)
        !           662:         {"sctp", no_argument, NULL, OPT_SCTP},
        !           663:         {"nstreams", required_argument, NULL, OPT_NUMSTREAMS},
        !           664:         {"xbind", required_argument, NULL, 'X'},
        !           665: #endif
        !           666:        {"pidfile", required_argument, NULL, 'I'},
        !           667:        {"logfile", required_argument, NULL, OPT_LOGFILE},
        !           668:        {"get-server-output", no_argument, NULL, OPT_GET_SERVER_OUTPUT},
        !           669:        {"udp-counters-64bit", no_argument, NULL, OPT_UDP_COUNTERS_64BIT},
        !           670:        {"no-fq-socket-pacing", no_argument, NULL, OPT_NO_FQ_SOCKET_PACING},
        !           671:         {"debug", no_argument, NULL, 'd'},
        !           672:         {"help", no_argument, NULL, 'h'},
        !           673:         {NULL, 0, NULL, 0}
        !           674:     };
        !           675:     int flag;
        !           676:     int blksize;
        !           677:     int server_flag, client_flag, rate_flag, duration_flag;
        !           678:     char *endptr;
        !           679: #if defined(HAVE_CPU_AFFINITY)
        !           680:     char* comma;
        !           681: #endif /* HAVE_CPU_AFFINITY */
        !           682:     char* slash;
        !           683:     struct xbind_entry *xbe;
        !           684: 
        !           685:     blksize = 0;
        !           686:     server_flag = client_flag = rate_flag = duration_flag = 0;
        !           687:     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) {
        !           688:         switch (flag) {
        !           689:             case 'p':
        !           690:                 test->server_port = atoi(optarg);
        !           691:                 break;
        !           692:             case 'f':
        !           693:                 test->settings->unit_format = *optarg;
        !           694:                 break;
        !           695:             case 'i':
        !           696:                 /* XXX: could potentially want separate stat collection and reporting intervals,
        !           697:                    but just set them to be the same for now */
        !           698:                 test->stats_interval = test->reporter_interval = atof(optarg);
        !           699:                 if ((test->stats_interval < MIN_INTERVAL || test->stats_interval > MAX_INTERVAL) && test->stats_interval != 0) {
        !           700:                     i_errno = IEINTERVAL;
        !           701:                     return -1;
        !           702:                 }
        !           703:                 break;
        !           704:             case 'D':
        !           705:                test->daemon = 1;
        !           706:                server_flag = 1;
        !           707:                break;
        !           708:             case '1':
        !           709:                test->one_off = 1;
        !           710:                server_flag = 1;
        !           711:                break;
        !           712:             case 'V':
        !           713:                 test->verbose = 1;
        !           714:                 break;
        !           715:             case 'J':
        !           716:                 test->json_output = 1;
        !           717:                 break;
        !           718:             case 'v':
        !           719:                 printf("%s\n%s\n%s\n", version, get_system_info(), 
        !           720:                       get_optional_features());
        !           721:                 exit(0);
        !           722:             case 's':
        !           723:                 if (test->role == 'c') {
        !           724:                     i_errno = IESERVCLIENT;
        !           725:                     return -1;
        !           726:                 }
        !           727:                iperf_set_test_role(test, 's');
        !           728:                 break;
        !           729:             case 'c':
        !           730:                 if (test->role == 's') {
        !           731:                     i_errno = IESERVCLIENT;
        !           732:                     return -1;
        !           733:                 }
        !           734:                iperf_set_test_role(test, 'c');
        !           735:                iperf_set_test_server_hostname(test, optarg);
        !           736:                 break;
        !           737:             case 'u':
        !           738:                 set_protocol(test, Pudp);
        !           739:                client_flag = 1;
        !           740:                 break;
        !           741:             case OPT_SCTP:
        !           742: #if defined(HAVE_SCTP)
        !           743:                 set_protocol(test, Psctp);
        !           744:                 client_flag = 1;
        !           745: #else /* HAVE_SCTP */
        !           746:                 i_errno = IEUNIMP;
        !           747:                 return -1;
        !           748: #endif /* HAVE_SCTP */
        !           749:             break;
        !           750: 
        !           751:             case OPT_NUMSTREAMS:
        !           752: #if defined(linux) || defined(__FreeBSD__)
        !           753:                 test->settings->num_ostreams = unit_atoi(optarg);
        !           754:                 client_flag = 1;
        !           755: #else /* linux */
        !           756:                 i_errno = IEUNIMP;
        !           757:                 return -1;
        !           758: #endif /* linux */
        !           759:             case 'b':
        !           760:                slash = strchr(optarg, '/');
        !           761:                if (slash) {
        !           762:                    *slash = '\0';
        !           763:                    ++slash;
        !           764:                    test->settings->burst = atoi(slash);
        !           765:                    if (test->settings->burst <= 0 ||
        !           766:                        test->settings->burst > MAX_BURST) {
        !           767:                        i_errno = IEBURST;
        !           768:                        return -1;
        !           769:                    }
        !           770:                }
        !           771:                 test->settings->rate = unit_atof_rate(optarg);
        !           772:                rate_flag = 1;
        !           773:                client_flag = 1;
        !           774:                 break;
        !           775:             case 't':
        !           776:                 test->duration = atoi(optarg);
        !           777:                 if (test->duration > MAX_TIME) {
        !           778:                     i_errno = IEDURATION;
        !           779:                     return -1;
        !           780:                 }
        !           781:                duration_flag = 1;
        !           782:                client_flag = 1;
        !           783:                 break;
        !           784:             case 'n':
        !           785:                 test->settings->bytes = unit_atoi(optarg);
        !           786:                client_flag = 1;
        !           787:                 break;
        !           788:             case 'k':
        !           789:                 test->settings->blocks = unit_atoi(optarg);
        !           790:                client_flag = 1;
        !           791:                 break;
        !           792:             case 'l':
        !           793:                 blksize = unit_atoi(optarg);
        !           794:                client_flag = 1;
        !           795:                 break;
        !           796:             case 'P':
        !           797:                 test->num_streams = atoi(optarg);
        !           798:                 if (test->num_streams > MAX_STREAMS) {
        !           799:                     i_errno = IENUMSTREAMS;
        !           800:                     return -1;
        !           801:                 }
        !           802:                client_flag = 1;
        !           803:                 break;
        !           804:             case 'R':
        !           805:                iperf_set_test_reverse(test, 1);
        !           806:                client_flag = 1;
        !           807:                 break;
        !           808:             case 'w':
        !           809:                 // XXX: This is a socket buffer, not specific to TCP
        !           810:                 test->settings->socket_bufsize = unit_atof(optarg);
        !           811:                 if (test->settings->socket_bufsize > MAX_TCP_BUFFER) {
        !           812:                     i_errno = IEBUFSIZE;
        !           813:                     return -1;
        !           814:                 }
        !           815:                client_flag = 1;
        !           816:                 break;
        !           817:             case 'B':
        !           818:                 test->bind_address = strdup(optarg);
        !           819:                 break;
        !           820:             case OPT_CLIENT_PORT:
        !           821:                 test->bind_port = atoi(optarg);
        !           822:                 break;
        !           823:             case 'M':
        !           824:                 test->settings->mss = atoi(optarg);
        !           825:                 if (test->settings->mss > MAX_MSS) {
        !           826:                     i_errno = IEMSS;
        !           827:                     return -1;
        !           828:                 }
        !           829:                client_flag = 1;
        !           830:                 break;
        !           831:             case 'N':
        !           832:                 test->no_delay = 1;
        !           833:                client_flag = 1;
        !           834:                 break;
        !           835:             case '4':
        !           836:                 test->settings->domain = AF_INET;
        !           837:                 break;
        !           838:             case '6':
        !           839:                 test->settings->domain = AF_INET6;
        !           840:                 break;
        !           841:             case 'S':
        !           842:                 test->settings->tos = strtol(optarg, &endptr, 0);
        !           843:                if (endptr == optarg ||
        !           844:                    test->settings->tos < 0 ||
        !           845:                    test->settings->tos > 255) {
        !           846:                    i_errno = IEBADTOS;
        !           847:                    return -1;
        !           848:                }
        !           849:                client_flag = 1;
        !           850:                 break;
        !           851:             case 'L':
        !           852: #if defined(HAVE_FLOWLABEL)
        !           853:                 test->settings->flowlabel = strtol(optarg, &endptr, 0);
        !           854:                if (endptr == optarg ||
        !           855:                    test->settings->flowlabel < 1 || test->settings->flowlabel > 0xfffff) {
        !           856:                     i_errno = IESETFLOW;
        !           857:                     return -1;
        !           858:                }
        !           859:                client_flag = 1;
        !           860: #else /* HAVE_FLOWLABEL */
        !           861:                 i_errno = IEUNIMP;
        !           862:                 return -1;
        !           863: #endif /* HAVE_FLOWLABEL */
        !           864:                 break;
        !           865:             case 'X':
        !           866:                xbe = (struct xbind_entry *)malloc(sizeof(struct xbind_entry));
        !           867:                 if (!xbe) {
        !           868:                    i_errno = IESETSCTPBINDX;
        !           869:                     return -1;
        !           870:                 }
        !           871:                memset(xbe, 0, sizeof(*xbe));
        !           872:                 xbe->name = strdup(optarg);
        !           873:                 if (!xbe->name) {
        !           874:                    i_errno = IESETSCTPBINDX;
        !           875:                     return -1;
        !           876:                 }
        !           877:                TAILQ_INSERT_TAIL(&test->xbind_addrs, xbe, link);
        !           878:                 break;
        !           879:             case 'Z':
        !           880:                 if (!has_sendfile()) {
        !           881:                     i_errno = IENOSENDFILE;
        !           882:                     return -1;
        !           883:                 }
        !           884:                 test->zerocopy = 1;
        !           885:                client_flag = 1;
        !           886:                 break;
        !           887:             case 'O':
        !           888:                 test->omit = atoi(optarg);
        !           889:                 if (test->omit < 0 || test->omit > 60) {
        !           890:                     i_errno = IEOMIT;
        !           891:                     return -1;
        !           892:                 }
        !           893:                client_flag = 1;
        !           894:                 break;
        !           895:             case 'F':
        !           896:                 test->diskfile_name = optarg;
        !           897:                 break;
        !           898:             case 'A':
        !           899: #if defined(HAVE_CPU_AFFINITY)
        !           900:                 test->affinity = strtol(optarg, &endptr, 0);
        !           901:                 if (endptr == optarg || 
        !           902:                    test->affinity < 0 || test->affinity > 1024) {
        !           903:                     i_errno = IEAFFINITY;
        !           904:                     return -1;
        !           905:                 }
        !           906:                comma = strchr(optarg, ',');
        !           907:                if (comma != NULL) {
        !           908:                    test->server_affinity = atoi(comma+1);
        !           909:                    if (test->server_affinity < 0 || test->server_affinity > 1024) {
        !           910:                        i_errno = IEAFFINITY;
        !           911:                        return -1;
        !           912:                    }
        !           913:                    client_flag = 1;
        !           914:                }
        !           915: #else /* HAVE_CPU_AFFINITY */
        !           916:                 i_errno = IEUNIMP;
        !           917:                 return -1;
        !           918: #endif /* HAVE_CPU_AFFINITY */
        !           919:                 break;
        !           920:             case 'T':
        !           921:                 test->title = strdup(optarg);
        !           922:                client_flag = 1;
        !           923:                 break;
        !           924:            case 'C':
        !           925: #if defined(HAVE_TCP_CONGESTION)
        !           926:                test->congestion = strdup(optarg);
        !           927:                client_flag = 1;
        !           928: #else /* HAVE_TCP_CONGESTION */
        !           929:                i_errno = IEUNIMP;
        !           930:                return -1;
        !           931: #endif /* HAVE_TCP_CONGESTION */
        !           932:                break;
        !           933:            case 'd':
        !           934:                test->debug = 1;
        !           935:                break;
        !           936:            case 'I':
        !           937:                test->pidfile = strdup(optarg);
        !           938:                server_flag = 1;
        !           939:                break;
        !           940:            case OPT_LOGFILE:
        !           941:                test->logfile = strdup(optarg);
        !           942:                break;
        !           943:            case OPT_GET_SERVER_OUTPUT:
        !           944:                test->get_server_output = 1;
        !           945:                client_flag = 1;
        !           946:                break;
        !           947:            case OPT_UDP_COUNTERS_64BIT:
        !           948:                test->udp_counters_64bit = 1;
        !           949:                break;
        !           950:            case OPT_NO_FQ_SOCKET_PACING:
        !           951: #if defined(HAVE_SO_MAX_PACING_RATE)
        !           952:                test->no_fq_socket_pacing = 1;
        !           953: #else /* HAVE_SO_MAX_PACING_RATE */
        !           954:                i_errno = IEUNIMP;
        !           955:                return -1;
        !           956: #endif
        !           957:                break;
        !           958:             case 'h':
        !           959:             default:
        !           960:                 usage_long();
        !           961:                 exit(1);
        !           962:         }
        !           963:     }
        !           964: 
        !           965:     /* Set logging to a file if specified, otherwise use the default (stdout) */
        !           966:     if (test->logfile) {
        !           967:        test->outfile = fopen(test->logfile, "a+");
        !           968:        if (test->outfile == NULL) {
        !           969:            i_errno = IELOGFILE;
        !           970:            return -1;
        !           971:        }
        !           972:     }
        !           973: 
        !           974:     /* Check flag / role compatibility. */
        !           975:     if (test->role == 'c' && server_flag) {
        !           976:        i_errno = IESERVERONLY;
        !           977:        return -1;
        !           978:     }
        !           979:     if (test->role == 's' && client_flag) {
        !           980:        i_errno = IECLIENTONLY;
        !           981:        return -1;
        !           982:     }
        !           983: 
        !           984:     if (!test->bind_address && test->bind_port) {
        !           985:         i_errno = IEBIND;
        !           986:         return -1;
        !           987:     }
        !           988:     if (blksize == 0) {
        !           989:        if (test->protocol->id == Pudp)
        !           990:            blksize = DEFAULT_UDP_BLKSIZE;
        !           991:        else if (test->protocol->id == Psctp)
        !           992:            blksize = DEFAULT_SCTP_BLKSIZE;
        !           993:        else
        !           994:            blksize = DEFAULT_TCP_BLKSIZE;
        !           995:     }
        !           996:     if (blksize <= 0 || blksize > MAX_BLOCKSIZE) {
        !           997:        i_errno = IEBLOCKSIZE;
        !           998:        return -1;
        !           999:     }
        !          1000:     if (test->protocol->id == Pudp &&
        !          1001:        blksize > MAX_UDP_BLOCKSIZE) {
        !          1002:        i_errno = IEUDPBLOCKSIZE;
        !          1003:        return -1;
        !          1004:     }
        !          1005:     test->settings->blksize = blksize;
        !          1006: 
        !          1007:     if (!rate_flag)
        !          1008:        test->settings->rate = test->protocol->id == Pudp ? UDP_RATE : 0;
        !          1009: 
        !          1010:     if ((test->settings->bytes != 0 || test->settings->blocks != 0) && ! duration_flag)
        !          1011:         test->duration = 0;
        !          1012: 
        !          1013:     /* Disallow specifying multiple test end conditions. The code actually
        !          1014:     ** works just fine without this prohibition. As soon as any one of the
        !          1015:     ** three possible end conditions is met, the test ends. So this check
        !          1016:     ** could be removed if desired.
        !          1017:     */
        !          1018:     if ((duration_flag && test->settings->bytes != 0) ||
        !          1019:         (duration_flag && test->settings->blocks != 0) ||
        !          1020:        (test->settings->bytes != 0 && test->settings->blocks != 0)) {
        !          1021:         i_errno = IEENDCONDITIONS;
        !          1022:         return -1;
        !          1023:     }
        !          1024: 
        !          1025:     /* For subsequent calls to getopt */
        !          1026: #ifdef __APPLE__
        !          1027:     optreset = 1;
        !          1028: #endif
        !          1029:     optind = 0;
        !          1030: 
        !          1031:     if ((test->role != 'c') && (test->role != 's')) {
        !          1032:         i_errno = IENOROLE;
        !          1033:         return -1;
        !          1034:     }
        !          1035: 
        !          1036:     return 0;
        !          1037: }
        !          1038: 
        !          1039: int
        !          1040: iperf_set_send_state(struct iperf_test *test, signed char state)
        !          1041: {
        !          1042:     test->state = state;
        !          1043:     if (Nwrite(test->ctrl_sck, (char*) &state, sizeof(state), Ptcp) < 0) {
        !          1044:        i_errno = IESENDMESSAGE;
        !          1045:        return -1;
        !          1046:     }
        !          1047:     return 0;
        !          1048: }
        !          1049: 
        !          1050: void
        !          1051: iperf_check_throttle(struct iperf_stream *sp, struct timeval *nowP)
        !          1052: {
        !          1053:     double seconds;
        !          1054:     uint64_t bits_per_second;
        !          1055: 
        !          1056:     if (sp->test->done)
        !          1057:         return;
        !          1058:     seconds = timeval_diff(&sp->result->start_time_fixed, nowP);
        !          1059:     bits_per_second = sp->result->bytes_sent * 8 / seconds;
        !          1060:     if (bits_per_second < sp->test->settings->rate) {
        !          1061:         sp->green_light = 1;
        !          1062:         FD_SET(sp->socket, &sp->test->write_set);
        !          1063:     } else {
        !          1064:         sp->green_light = 0;
        !          1065:         FD_CLR(sp->socket, &sp->test->write_set);
        !          1066:     }
        !          1067: }
        !          1068: 
        !          1069: int
        !          1070: iperf_send(struct iperf_test *test, fd_set *write_setP)
        !          1071: {
        !          1072:     register int multisend, r, streams_active;
        !          1073:     register struct iperf_stream *sp;
        !          1074:     struct timeval now;
        !          1075: 
        !          1076:     /* Can we do multisend mode? */
        !          1077:     if (test->settings->burst != 0)
        !          1078:         multisend = test->settings->burst;
        !          1079:     else if (test->settings->rate == 0)
        !          1080:         multisend = test->multisend;
        !          1081:     else
        !          1082:         multisend = 1; /* nope */
        !          1083: 
        !          1084:     for (; multisend > 0; --multisend) {
        !          1085:        if (test->settings->rate != 0 && test->settings->burst == 0)
        !          1086:            gettimeofday(&now, NULL);
        !          1087:        streams_active = 0;
        !          1088:        SLIST_FOREACH(sp, &test->streams, streams) {
        !          1089:            if (! test->no_fq_socket_pacing ||
        !          1090:                (sp->green_light &&
        !          1091:                 (write_setP == NULL || FD_ISSET(sp->socket, write_setP)))) {
        !          1092:                if ((r = sp->snd(sp)) < 0) {
        !          1093:                    if (r == NET_SOFTERROR)
        !          1094:                        break;
        !          1095:                    i_errno = IESTREAMWRITE;
        !          1096:                    return r;
        !          1097:                }
        !          1098:                streams_active = 1;
        !          1099:                test->bytes_sent += r;
        !          1100:                ++test->blocks_sent;
        !          1101:                if (test->settings->rate != 0 && test->settings->burst == 0)
        !          1102:                    iperf_check_throttle(sp, &now);
        !          1103:                if (multisend > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes)
        !          1104:                    break;
        !          1105:                if (multisend > 1 && test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks)
        !          1106:                    break;
        !          1107:            }
        !          1108:        }
        !          1109:        if (!streams_active)
        !          1110:            break;
        !          1111:     }
        !          1112:     if (test->settings->burst != 0) {
        !          1113:        gettimeofday(&now, NULL);
        !          1114:        SLIST_FOREACH(sp, &test->streams, streams)
        !          1115:            iperf_check_throttle(sp, &now);
        !          1116:     }
        !          1117:     if (write_setP != NULL)
        !          1118:        SLIST_FOREACH(sp, &test->streams, streams)
        !          1119:            if (FD_ISSET(sp->socket, write_setP))
        !          1120:                FD_CLR(sp->socket, write_setP);
        !          1121: 
        !          1122:     return 0;
        !          1123: }
        !          1124: 
        !          1125: int
        !          1126: iperf_recv(struct iperf_test *test, fd_set *read_setP)
        !          1127: {
        !          1128:     int r;
        !          1129:     struct iperf_stream *sp;
        !          1130: 
        !          1131:     SLIST_FOREACH(sp, &test->streams, streams) {
        !          1132:        if (FD_ISSET(sp->socket, read_setP)) {
        !          1133:            if ((r = sp->rcv(sp)) < 0) {
        !          1134:                i_errno = IESTREAMREAD;
        !          1135:                return r;
        !          1136:            }
        !          1137:            test->bytes_sent += r;
        !          1138:            ++test->blocks_sent;
        !          1139:            FD_CLR(sp->socket, read_setP);
        !          1140:        }
        !          1141:     }
        !          1142: 
        !          1143:     return 0;
        !          1144: }
        !          1145: 
        !          1146: int
        !          1147: iperf_init_test(struct iperf_test *test)
        !          1148: {
        !          1149:     struct timeval now;
        !          1150:     struct iperf_stream *sp;
        !          1151: 
        !          1152:     if (test->protocol->init) {
        !          1153:         if (test->protocol->init(test) < 0)
        !          1154:             return -1;
        !          1155:     }
        !          1156: 
        !          1157:     /* Init each stream. */
        !          1158:     if (gettimeofday(&now, NULL) < 0) {
        !          1159:        i_errno = IEINITTEST;
        !          1160:        return -1;
        !          1161:     }
        !          1162:     SLIST_FOREACH(sp, &test->streams, streams) {
        !          1163:        sp->result->start_time = sp->result->start_time_fixed = now;
        !          1164:     }
        !          1165: 
        !          1166:     if (test->on_test_start)
        !          1167:         test->on_test_start(test);
        !          1168: 
        !          1169:     return 0;
        !          1170: }
        !          1171: 
        !          1172: static void
        !          1173: send_timer_proc(TimerClientData client_data, struct timeval *nowP)
        !          1174: {
        !          1175:     struct iperf_stream *sp = client_data.p;
        !          1176: 
        !          1177:     /* All we do here is set or clear the flag saying that this stream may
        !          1178:     ** be sent to.  The actual sending gets done in the send proc, after
        !          1179:     ** checking the flag.
        !          1180:     */
        !          1181:     iperf_check_throttle(sp, nowP);
        !          1182: }
        !          1183: 
        !          1184: int
        !          1185: iperf_create_send_timers(struct iperf_test * test)
        !          1186: {
        !          1187:     struct timeval now;
        !          1188:     struct iperf_stream *sp;
        !          1189:     TimerClientData cd;
        !          1190: 
        !          1191:     if (gettimeofday(&now, NULL) < 0) {
        !          1192:        i_errno = IEINITTEST;
        !          1193:        return -1;
        !          1194:     }
        !          1195:     SLIST_FOREACH(sp, &test->streams, streams) {
        !          1196:         sp->green_light = 1;
        !          1197:        if (test->settings->rate != 0) {
        !          1198:            cd.p = sp;
        !          1199:            sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, 100000L, 1);
        !          1200:            /* (Repeat every tenth second - arbitrary often value.) */
        !          1201:            if (sp->send_timer == NULL) {
        !          1202:                i_errno = IEINITTEST;
        !          1203:                return -1;
        !          1204:            }
        !          1205:        }
        !          1206:     }
        !          1207:     return 0;
        !          1208: }
        !          1209: 
        !          1210: /**
        !          1211:  * iperf_exchange_parameters - handles the param_Exchange part for client
        !          1212:  *
        !          1213:  */
        !          1214: 
        !          1215: int
        !          1216: iperf_exchange_parameters(struct iperf_test *test)
        !          1217: {
        !          1218:     int s;
        !          1219:     int32_t err;
        !          1220: 
        !          1221:     if (test->role == 'c') {
        !          1222: 
        !          1223:         if (send_parameters(test) < 0)
        !          1224:             return -1;
        !          1225: 
        !          1226:     } else {
        !          1227: 
        !          1228:         if (get_parameters(test) < 0)
        !          1229:             return -1;
        !          1230: 
        !          1231:         if ((s = test->protocol->listen(test)) < 0) {
        !          1232:            if (iperf_set_send_state(test, SERVER_ERROR) != 0)
        !          1233:                 return -1;
        !          1234:             err = htonl(i_errno);
        !          1235:             if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
        !          1236:                 i_errno = IECTRLWRITE;
        !          1237:                 return -1;
        !          1238:             }
        !          1239:             err = htonl(errno);
        !          1240:             if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
        !          1241:                 i_errno = IECTRLWRITE;
        !          1242:                 return -1;
        !          1243:             }
        !          1244:             return -1;
        !          1245:         }
        !          1246:         FD_SET(s, &test->read_set);
        !          1247:         test->max_fd = (s > test->max_fd) ? s : test->max_fd;
        !          1248:         test->prot_listener = s;
        !          1249: 
        !          1250:         // Send the control message to create streams and start the test
        !          1251:        if (iperf_set_send_state(test, CREATE_STREAMS) != 0)
        !          1252:             return -1;
        !          1253: 
        !          1254:     }
        !          1255: 
        !          1256:     return 0;
        !          1257: }
        !          1258: 
        !          1259: /*************************************************************/
        !          1260: 
        !          1261: int
        !          1262: iperf_exchange_results(struct iperf_test *test)
        !          1263: {
        !          1264:     if (test->role == 'c') {
        !          1265:         /* Send results to server. */
        !          1266:        if (send_results(test) < 0)
        !          1267:             return -1;
        !          1268:         /* Get server results. */
        !          1269:         if (get_results(test) < 0)
        !          1270:             return -1;
        !          1271:     } else {
        !          1272:         /* Get client results. */
        !          1273:         if (get_results(test) < 0)
        !          1274:             return -1;
        !          1275:         /* Send results to client. */
        !          1276:        if (send_results(test) < 0)
        !          1277:             return -1;
        !          1278:     }
        !          1279:     return 0;
        !          1280: }
        !          1281: 
        !          1282: /*************************************************************/
        !          1283: 
        !          1284: static int
        !          1285: send_parameters(struct iperf_test *test)
        !          1286: {
        !          1287:     int r = 0;
        !          1288:     cJSON *j;
        !          1289: 
        !          1290:     j = cJSON_CreateObject();
        !          1291:     if (j == NULL) {
        !          1292:        i_errno = IESENDPARAMS;
        !          1293:        r = -1;
        !          1294:     } else {
        !          1295:        if (test->protocol->id == Ptcp)
        !          1296:            cJSON_AddTrueToObject(j, "tcp");
        !          1297:        else if (test->protocol->id == Pudp)
        !          1298:            cJSON_AddTrueToObject(j, "udp");
        !          1299:         else if (test->protocol->id == Psctp)
        !          1300:             cJSON_AddTrueToObject(j, "sctp");
        !          1301:        cJSON_AddNumberToObject(j, "omit", test->omit);
        !          1302:        if (test->server_affinity != -1)
        !          1303:            cJSON_AddNumberToObject(j, "server_affinity", test->server_affinity);
        !          1304:        if (test->duration)
        !          1305:            cJSON_AddNumberToObject(j, "time", test->duration);
        !          1306:        if (test->settings->bytes)
        !          1307:            cJSON_AddNumberToObject(j, "num", test->settings->bytes);
        !          1308:        if (test->settings->blocks)
        !          1309:            cJSON_AddNumberToObject(j, "blockcount", test->settings->blocks);
        !          1310:        if (test->settings->mss)
        !          1311:            cJSON_AddNumberToObject(j, "MSS", test->settings->mss);
        !          1312:        if (test->no_delay)
        !          1313:            cJSON_AddTrueToObject(j, "nodelay");
        !          1314:        cJSON_AddNumberToObject(j, "parallel", test->num_streams);
        !          1315:        if (test->reverse)
        !          1316:            cJSON_AddTrueToObject(j, "reverse");
        !          1317:        if (test->settings->socket_bufsize)
        !          1318:            cJSON_AddNumberToObject(j, "window", test->settings->socket_bufsize);
        !          1319:        if (test->settings->blksize)
        !          1320:            cJSON_AddNumberToObject(j, "len", test->settings->blksize);
        !          1321:        if (test->settings->rate)
        !          1322:            cJSON_AddNumberToObject(j, "bandwidth", test->settings->rate);
        !          1323:        if (test->settings->burst)
        !          1324:            cJSON_AddNumberToObject(j, "burst", test->settings->burst);
        !          1325:        if (test->settings->tos)
        !          1326:            cJSON_AddNumberToObject(j, "TOS", test->settings->tos);
        !          1327:        if (test->settings->flowlabel)
        !          1328:            cJSON_AddNumberToObject(j, "flowlabel", test->settings->flowlabel);
        !          1329:        if (test->title)
        !          1330:            cJSON_AddStringToObject(j, "title", test->title);
        !          1331:        if (test->congestion)
        !          1332:            cJSON_AddStringToObject(j, "congestion", test->congestion);
        !          1333:        if (test->get_server_output)
        !          1334:            cJSON_AddNumberToObject(j, "get_server_output", iperf_get_test_get_server_output(test));
        !          1335:        if (test->udp_counters_64bit)
        !          1336:            cJSON_AddNumberToObject(j, "udp_counters_64bit", iperf_get_test_udp_counters_64bit(test));
        !          1337:        if (test->no_fq_socket_pacing)
        !          1338:            cJSON_AddNumberToObject(j, "no_fq_socket_pacing", iperf_get_no_fq_socket_pacing(test));
        !          1339: 
        !          1340:        cJSON_AddStringToObject(j, "client_version", IPERF_VERSION);
        !          1341: 
        !          1342:        if (test->debug) {
        !          1343:            printf("send_parameters:\n%s\n", cJSON_Print(j));
        !          1344:        }
        !          1345: 
        !          1346:        if (JSON_write(test->ctrl_sck, j) < 0) {
        !          1347:            i_errno = IESENDPARAMS;
        !          1348:            r = -1;
        !          1349:        }
        !          1350:        cJSON_Delete(j);
        !          1351:     }
        !          1352:     return r;
        !          1353: }
        !          1354: 
        !          1355: /*************************************************************/
        !          1356: 
        !          1357: static int
        !          1358: get_parameters(struct iperf_test *test)
        !          1359: {
        !          1360:     int r = 0;
        !          1361:     cJSON *j;
        !          1362:     cJSON *j_p;
        !          1363: 
        !          1364:     j = JSON_read(test->ctrl_sck);
        !          1365:     if (j == NULL) {
        !          1366:        i_errno = IERECVPARAMS;
        !          1367:         r = -1;
        !          1368:     } else {
        !          1369:        if (test->debug) {
        !          1370:            printf("get_parameters:\n%s\n", cJSON_Print(j));
        !          1371:        }
        !          1372: 
        !          1373:        if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL)
        !          1374:            set_protocol(test, Ptcp);
        !          1375:        if ((j_p = cJSON_GetObjectItem(j, "udp")) != NULL)
        !          1376:            set_protocol(test, Pudp);
        !          1377:         if ((j_p = cJSON_GetObjectItem(j, "sctp")) != NULL)
        !          1378:             set_protocol(test, Psctp);
        !          1379:        if ((j_p = cJSON_GetObjectItem(j, "omit")) != NULL)
        !          1380:            test->omit = j_p->valueint;
        !          1381:        if ((j_p = cJSON_GetObjectItem(j, "server_affinity")) != NULL)
        !          1382:            test->server_affinity = j_p->valueint;
        !          1383:        if ((j_p = cJSON_GetObjectItem(j, "time")) != NULL)
        !          1384:            test->duration = j_p->valueint;
        !          1385:        if ((j_p = cJSON_GetObjectItem(j, "num")) != NULL)
        !          1386:            test->settings->bytes = j_p->valueint;
        !          1387:        if ((j_p = cJSON_GetObjectItem(j, "blockcount")) != NULL)
        !          1388:            test->settings->blocks = j_p->valueint;
        !          1389:        if ((j_p = cJSON_GetObjectItem(j, "MSS")) != NULL)
        !          1390:            test->settings->mss = j_p->valueint;
        !          1391:        if ((j_p = cJSON_GetObjectItem(j, "nodelay")) != NULL)
        !          1392:            test->no_delay = 1;
        !          1393:        if ((j_p = cJSON_GetObjectItem(j, "parallel")) != NULL)
        !          1394:            test->num_streams = j_p->valueint;
        !          1395:        if ((j_p = cJSON_GetObjectItem(j, "reverse")) != NULL)
        !          1396:            iperf_set_test_reverse(test, 1);
        !          1397:        if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL)
        !          1398:            test->settings->socket_bufsize = j_p->valueint;
        !          1399:        if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL)
        !          1400:            test->settings->blksize = j_p->valueint;
        !          1401:        if ((j_p = cJSON_GetObjectItem(j, "bandwidth")) != NULL)
        !          1402:            test->settings->rate = j_p->valueint;
        !          1403:        if ((j_p = cJSON_GetObjectItem(j, "burst")) != NULL)
        !          1404:            test->settings->burst = j_p->valueint;
        !          1405:        if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL)
        !          1406:            test->settings->tos = j_p->valueint;
        !          1407:        if ((j_p = cJSON_GetObjectItem(j, "flowlabel")) != NULL)
        !          1408:            test->settings->flowlabel = j_p->valueint;
        !          1409:        if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL)
        !          1410:            test->title = strdup(j_p->valuestring);
        !          1411:        if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL)
        !          1412:            test->congestion = strdup(j_p->valuestring);
        !          1413:        if ((j_p = cJSON_GetObjectItem(j, "get_server_output")) != NULL)
        !          1414:            iperf_set_test_get_server_output(test, 1);
        !          1415:        if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL)
        !          1416:            iperf_set_test_udp_counters_64bit(test, 1);
        !          1417:        if ((j_p = cJSON_GetObjectItem(j, "no_fq_socket_pacing")) != NULL)
        !          1418:            iperf_set_no_fq_socket_pacing(test, 1);
        !          1419:        
        !          1420:        if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits())
        !          1421:            test->sender_has_retransmits = 1;
        !          1422:        cJSON_Delete(j);
        !          1423:     }
        !          1424:     return r;
        !          1425: }
        !          1426: 
        !          1427: /*************************************************************/
        !          1428: 
        !          1429: static int
        !          1430: send_results(struct iperf_test *test)
        !          1431: {
        !          1432:     int r = 0;
        !          1433:     cJSON *j;
        !          1434:     cJSON *j_streams;
        !          1435:     struct iperf_stream *sp;
        !          1436:     cJSON *j_stream;
        !          1437:     int sender_has_retransmits;
        !          1438:     iperf_size_t bytes_transferred;
        !          1439:     int retransmits;
        !          1440: 
        !          1441:     j = cJSON_CreateObject();
        !          1442:     if (j == NULL) {
        !          1443:        i_errno = IEPACKAGERESULTS;
        !          1444:        r = -1;
        !          1445:     } else {
        !          1446:        cJSON_AddNumberToObject(j, "cpu_util_total", test->cpu_util[0]);
        !          1447:        cJSON_AddNumberToObject(j, "cpu_util_user", test->cpu_util[1]);
        !          1448:        cJSON_AddNumberToObject(j, "cpu_util_system", test->cpu_util[2]);
        !          1449:        if ( ! test->sender )
        !          1450:            sender_has_retransmits = -1;
        !          1451:        else
        !          1452:            sender_has_retransmits = test->sender_has_retransmits;
        !          1453:        cJSON_AddNumberToObject(j, "sender_has_retransmits", sender_has_retransmits);
        !          1454: 
        !          1455:        /* If on the server and sending server output, then do this */
        !          1456:        if (test->role == 's' && test->get_server_output) {
        !          1457:            if (test->json_output) {
        !          1458:                /* Add JSON output */
        !          1459:                cJSON_AddItemReferenceToObject(j, "server_output_json", test->json_top);
        !          1460:            }
        !          1461:            else {
        !          1462:                /* Add textual output */
        !          1463:                size_t buflen = 0;
        !          1464: 
        !          1465:                /* Figure out how much room we need to hold the complete output string */
        !          1466:                struct iperf_textline *t;
        !          1467:                TAILQ_FOREACH(t, &(test->server_output_list), textlineentries) {
        !          1468:                    buflen += strlen(t->line);
        !          1469:                }
        !          1470: 
        !          1471:                /* Allocate and build it up from the component lines */
        !          1472:                char *output = calloc(buflen + 1, 1);
        !          1473:                TAILQ_FOREACH(t, &(test->server_output_list), textlineentries) {
        !          1474:                    strncat(output, t->line, buflen);
        !          1475:                    buflen -= strlen(t->line);
        !          1476:                }
        !          1477: 
        !          1478:                cJSON_AddStringToObject(j, "server_output_text", output);
        !          1479:            }
        !          1480:        }
        !          1481: 
        !          1482:        j_streams = cJSON_CreateArray();
        !          1483:        if (j_streams == NULL) {
        !          1484:            i_errno = IEPACKAGERESULTS;
        !          1485:            r = -1;
        !          1486:        } else {
        !          1487:            cJSON_AddItemToObject(j, "streams", j_streams);
        !          1488:            SLIST_FOREACH(sp, &test->streams, streams) {
        !          1489:                j_stream = cJSON_CreateObject();
        !          1490:                if (j_stream == NULL) {
        !          1491:                    i_errno = IEPACKAGERESULTS;
        !          1492:                    r = -1;
        !          1493:                } else {
        !          1494:                    cJSON_AddItemToArray(j_streams, j_stream);
        !          1495:                    bytes_transferred = test->sender ? (sp->result->bytes_sent - sp->result->bytes_sent_omit) : sp->result->bytes_received;
        !          1496:                    retransmits = (test->sender && test->sender_has_retransmits) ? sp->result->stream_retrans : -1;
        !          1497:                    cJSON_AddNumberToObject(j_stream, "id", sp->id);
        !          1498:                    cJSON_AddNumberToObject(j_stream, "bytes", bytes_transferred);
        !          1499:                    cJSON_AddNumberToObject(j_stream, "retransmits", retransmits);
        !          1500:                    cJSON_AddNumberToObject(j_stream, "jitter", sp->jitter);
        !          1501:                    cJSON_AddNumberToObject(j_stream, "errors", sp->cnt_error);
        !          1502:                    cJSON_AddNumberToObject(j_stream, "packets", sp->packet_count);
        !          1503:                }
        !          1504:            }
        !          1505:            if (r == 0 && test->debug) {
        !          1506:                printf("send_results\n%s\n", cJSON_Print(j));
        !          1507:            }
        !          1508:            if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) {
        !          1509:                i_errno = IESENDRESULTS;
        !          1510:                r = -1;
        !          1511:            }
        !          1512:        }
        !          1513:        cJSON_Delete(j);
        !          1514:     }
        !          1515:     return r;
        !          1516: }
        !          1517: 
        !          1518: /*************************************************************/
        !          1519: 
        !          1520: static int
        !          1521: get_results(struct iperf_test *test)
        !          1522: {
        !          1523:     int r = 0;
        !          1524:     cJSON *j;
        !          1525:     cJSON *j_cpu_util_total;
        !          1526:     cJSON *j_cpu_util_user;
        !          1527:     cJSON *j_cpu_util_system;
        !          1528:     cJSON *j_sender_has_retransmits;
        !          1529:     int result_has_retransmits;
        !          1530:     cJSON *j_streams;
        !          1531:     int n, i;
        !          1532:     cJSON *j_stream;
        !          1533:     cJSON *j_id;
        !          1534:     cJSON *j_bytes;
        !          1535:     cJSON *j_retransmits;
        !          1536:     cJSON *j_jitter;
        !          1537:     cJSON *j_errors;
        !          1538:     cJSON *j_packets;
        !          1539:     cJSON *j_server_output;
        !          1540:     int sid, cerror, pcount;
        !          1541:     double jitter;
        !          1542:     iperf_size_t bytes_transferred;
        !          1543:     int retransmits;
        !          1544:     struct iperf_stream *sp;
        !          1545: 
        !          1546:     j = JSON_read(test->ctrl_sck);
        !          1547:     if (j == NULL) {
        !          1548:        i_errno = IERECVRESULTS;
        !          1549:         r = -1;
        !          1550:     } else {
        !          1551:        j_cpu_util_total = cJSON_GetObjectItem(j, "cpu_util_total");
        !          1552:        j_cpu_util_user = cJSON_GetObjectItem(j, "cpu_util_user");
        !          1553:        j_cpu_util_system = cJSON_GetObjectItem(j, "cpu_util_system");
        !          1554:        j_sender_has_retransmits = cJSON_GetObjectItem(j, "sender_has_retransmits");
        !          1555:        if (j_cpu_util_total == NULL || j_cpu_util_user == NULL || j_cpu_util_system == NULL || j_sender_has_retransmits == NULL) {
        !          1556:            i_errno = IERECVRESULTS;
        !          1557:            r = -1;
        !          1558:        } else {
        !          1559:            if (test->debug) {
        !          1560:                printf("get_results\n%s\n", cJSON_Print(j));
        !          1561:            }
        !          1562: 
        !          1563:            test->remote_cpu_util[0] = j_cpu_util_total->valuedouble;
        !          1564:            test->remote_cpu_util[1] = j_cpu_util_user->valuedouble;
        !          1565:            test->remote_cpu_util[2] = j_cpu_util_system->valuedouble;
        !          1566:            result_has_retransmits = j_sender_has_retransmits->valueint;
        !          1567:            if (! test->sender)
        !          1568:                test->sender_has_retransmits = result_has_retransmits;
        !          1569:            j_streams = cJSON_GetObjectItem(j, "streams");
        !          1570:            if (j_streams == NULL) {
        !          1571:                i_errno = IERECVRESULTS;
        !          1572:                r = -1;
        !          1573:            } else {
        !          1574:                n = cJSON_GetArraySize(j_streams);
        !          1575:                for (i=0; i<n; ++i) {
        !          1576:                    j_stream = cJSON_GetArrayItem(j_streams, i);
        !          1577:                    if (j_stream == NULL) {
        !          1578:                        i_errno = IERECVRESULTS;
        !          1579:                        r = -1;
        !          1580:                    } else {
        !          1581:                        j_id = cJSON_GetObjectItem(j_stream, "id");
        !          1582:                        j_bytes = cJSON_GetObjectItem(j_stream, "bytes");
        !          1583:                        j_retransmits = cJSON_GetObjectItem(j_stream, "retransmits");
        !          1584:                        j_jitter = cJSON_GetObjectItem(j_stream, "jitter");
        !          1585:                        j_errors = cJSON_GetObjectItem(j_stream, "errors");
        !          1586:                        j_packets = cJSON_GetObjectItem(j_stream, "packets");
        !          1587:                        if (j_id == NULL || j_bytes == NULL || j_retransmits == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) {
        !          1588:                            i_errno = IERECVRESULTS;
        !          1589:                            r = -1;
        !          1590:                        } else {
        !          1591:                            sid = j_id->valueint;
        !          1592:                            bytes_transferred = j_bytes->valueint;
        !          1593:                            retransmits = j_retransmits->valueint;
        !          1594:                            jitter = j_jitter->valuedouble;
        !          1595:                            cerror = j_errors->valueint;
        !          1596:                            pcount = j_packets->valueint;
        !          1597:                            SLIST_FOREACH(sp, &test->streams, streams)
        !          1598:                                if (sp->id == sid) break;
        !          1599:                            if (sp == NULL) {
        !          1600:                                i_errno = IESTREAMID;
        !          1601:                                r = -1;
        !          1602:                            } else {
        !          1603:                                if (test->sender) {
        !          1604:                                    sp->jitter = jitter;
        !          1605:                                    sp->cnt_error = cerror;
        !          1606:                                    sp->packet_count = pcount;
        !          1607:                                    sp->result->bytes_received = bytes_transferred;
        !          1608:                                } else {
        !          1609:                                    sp->result->bytes_sent = bytes_transferred;
        !          1610:                                    sp->result->stream_retrans = retransmits;
        !          1611:                                }
        !          1612:                            }
        !          1613:                        }
        !          1614:                    }
        !          1615:                }
        !          1616:                /*
        !          1617:                 * If we're the client and we're supposed to get remote results,
        !          1618:                 * look them up and process accordingly.
        !          1619:                 */
        !          1620:                if (test->role == 'c' && iperf_get_test_get_server_output(test)) {
        !          1621:                    /* Look for JSON.  If we find it, grab the object so it doesn't get deleted. */
        !          1622:                    j_server_output = cJSON_DetachItemFromObject(j, "server_output_json");
        !          1623:                    if (j_server_output != NULL) {
        !          1624:                        test->json_server_output = j_server_output;
        !          1625:                    }
        !          1626:                    else {
        !          1627:                        /* No JSON, look for textual output.  Make a copy of the text for later. */
        !          1628:                        j_server_output = cJSON_GetObjectItem(j, "server_output_text");
        !          1629:                        if (j_server_output != NULL) {
        !          1630:                            test->server_output_text = strdup(j_server_output->valuestring);
        !          1631:                        }
        !          1632:                    }
        !          1633:                }
        !          1634:            }
        !          1635:        }
        !          1636:        cJSON_Delete(j);
        !          1637:     }
        !          1638:     return r;
        !          1639: }
        !          1640: 
        !          1641: /*************************************************************/
        !          1642: 
        !          1643: static int
        !          1644: JSON_write(int fd, cJSON *json)
        !          1645: {
        !          1646:     uint32_t hsize, nsize;
        !          1647:     char *str;
        !          1648:     int r = 0;
        !          1649: 
        !          1650:     str = cJSON_PrintUnformatted(json);
        !          1651:     if (str == NULL)
        !          1652:        r = -1;
        !          1653:     else {
        !          1654:        hsize = strlen(str);
        !          1655:        nsize = htonl(hsize);
        !          1656:        if (Nwrite(fd, (char*) &nsize, sizeof(nsize), Ptcp) < 0)
        !          1657:            r = -1;
        !          1658:        else {
        !          1659:            if (Nwrite(fd, str, hsize, Ptcp) < 0)
        !          1660:                r = -1;
        !          1661:        }
        !          1662:        free(str);
        !          1663:     }
        !          1664:     return r;
        !          1665: }
        !          1666: 
        !          1667: /*************************************************************/
        !          1668: 
        !          1669: static cJSON *
        !          1670: JSON_read(int fd)
        !          1671: {
        !          1672:     uint32_t hsize, nsize;
        !          1673:     char *str;
        !          1674:     cJSON *json = NULL;
        !          1675:     int rc;
        !          1676: 
        !          1677:     /*
        !          1678:      * Read a four-byte integer, which is the length of the JSON to follow.
        !          1679:      * Then read the JSON into a buffer and parse it.  Return a parsed JSON
        !          1680:      * structure, NULL if there was an error.
        !          1681:      */
        !          1682:     if (Nread(fd, (char*) &nsize, sizeof(nsize), Ptcp) >= 0) {
        !          1683:        hsize = ntohl(nsize);
        !          1684:        /* Allocate a buffer to hold the JSON */
        !          1685:        str = (char *) calloc(sizeof(char), hsize+1);   /* +1 for trailing null */
        !          1686:        if (str != NULL) {
        !          1687:            rc = Nread(fd, str, hsize, Ptcp);
        !          1688:            if (rc >= 0) {
        !          1689:                /*
        !          1690:                 * We should be reading in the number of bytes corresponding to the
        !          1691:                 * length in that 4-byte integer.  If we don't the socket might have
        !          1692:                 * prematurely closed.  Only do the JSON parsing if we got the
        !          1693:                 * correct number of bytes.
        !          1694:                 */
        !          1695:                if (rc == hsize) {
        !          1696:                    json = cJSON_Parse(str);
        !          1697:                }
        !          1698:                else {
        !          1699:                    printf("WARNING:  Size of data read does not correspond to offered length\n");
        !          1700:                }
        !          1701:            }
        !          1702:        }
        !          1703:        free(str);
        !          1704:     }
        !          1705:     return json;
        !          1706: }
        !          1707: 
        !          1708: /*************************************************************/
        !          1709: /**
        !          1710:  * add_to_interval_list -- adds new interval to the interval_list
        !          1711:  */
        !          1712: 
        !          1713: void
        !          1714: add_to_interval_list(struct iperf_stream_result * rp, struct iperf_interval_results * new)
        !          1715: {
        !          1716:     struct iperf_interval_results *irp;
        !          1717: 
        !          1718:     irp = (struct iperf_interval_results *) malloc(sizeof(struct iperf_interval_results));
        !          1719:     memcpy(irp, new, sizeof(struct iperf_interval_results));
        !          1720:     TAILQ_INSERT_TAIL(&rp->interval_results, irp, irlistentries);
        !          1721: }
        !          1722: 
        !          1723: 
        !          1724: /************************************************************/
        !          1725: 
        !          1726: /**
        !          1727:  * connect_msg -- displays connection message
        !          1728:  * denoting sender/receiver details
        !          1729:  *
        !          1730:  */
        !          1731: 
        !          1732: void
        !          1733: connect_msg(struct iperf_stream *sp)
        !          1734: {
        !          1735:     char ipl[INET6_ADDRSTRLEN], ipr[INET6_ADDRSTRLEN];
        !          1736:     int lport, rport;
        !          1737: 
        !          1738:     if (getsockdomain(sp->socket) == AF_INET) {
        !          1739:         inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->local_addr)->sin_addr, ipl, sizeof(ipl));
        !          1740:        mapped_v4_to_regular_v4(ipl);
        !          1741:         inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->remote_addr)->sin_addr, ipr, sizeof(ipr));
        !          1742:        mapped_v4_to_regular_v4(ipr);
        !          1743:         lport = ntohs(((struct sockaddr_in *) &sp->local_addr)->sin_port);
        !          1744:         rport = ntohs(((struct sockaddr_in *) &sp->remote_addr)->sin_port);
        !          1745:     } else {
        !          1746:         inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->local_addr)->sin6_addr, ipl, sizeof(ipl));
        !          1747:        mapped_v4_to_regular_v4(ipl);
        !          1748:         inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->remote_addr)->sin6_addr, ipr, sizeof(ipr));
        !          1749:        mapped_v4_to_regular_v4(ipr);
        !          1750:         lport = ntohs(((struct sockaddr_in6 *) &sp->local_addr)->sin6_port);
        !          1751:         rport = ntohs(((struct sockaddr_in6 *) &sp->remote_addr)->sin6_port);
        !          1752:     }
        !          1753: 
        !          1754:     if (sp->test->json_output)
        !          1755:         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));
        !          1756:     else
        !          1757:        iprintf(sp->test, report_connected, sp->socket, ipl, lport, ipr, rport);
        !          1758: }
        !          1759: 
        !          1760: 
        !          1761: /**************************************************************************/
        !          1762: 
        !          1763: struct iperf_test *
        !          1764: iperf_new_test()
        !          1765: {
        !          1766:     struct iperf_test *test;
        !          1767: 
        !          1768:     test = (struct iperf_test *) malloc(sizeof(struct iperf_test));
        !          1769:     if (!test) {
        !          1770:         i_errno = IENEWTEST;
        !          1771:         return NULL;
        !          1772:     }
        !          1773:     /* initialize everything to zero */
        !          1774:     memset(test, 0, sizeof(struct iperf_test));
        !          1775: 
        !          1776:     test->settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings));
        !          1777:     if (!test->settings) {
        !          1778:         free(test);
        !          1779:        i_errno = IENEWTEST;
        !          1780:        return NULL;
        !          1781:     }
        !          1782:     memset(test->settings, 0, sizeof(struct iperf_settings));
        !          1783: 
        !          1784:     /* By default all output goes to stdout */
        !          1785:     test->outfile = stdout;
        !          1786: 
        !          1787:     return test;
        !          1788: }
        !          1789: 
        !          1790: /**************************************************************************/
        !          1791: 
        !          1792: struct protocol *
        !          1793: protocol_new(void)
        !          1794: {
        !          1795:     struct protocol *proto;
        !          1796: 
        !          1797:     proto = malloc(sizeof(struct protocol));
        !          1798:     if(!proto) {
        !          1799:         return NULL;
        !          1800:     }
        !          1801:     memset(proto, 0, sizeof(struct protocol));
        !          1802: 
        !          1803:     return proto;
        !          1804: }
        !          1805: 
        !          1806: void
        !          1807: protocol_free(struct protocol *proto)
        !          1808: {
        !          1809:     free(proto); 
        !          1810: }
        !          1811: 
        !          1812: /**************************************************************************/
        !          1813: int
        !          1814: iperf_defaults(struct iperf_test *testp)
        !          1815: {
        !          1816:     struct protocol *tcp, *udp;
        !          1817: #if defined(HAVE_SCTP)
        !          1818:     struct protocol *sctp;
        !          1819: #endif /* HAVE_SCTP */
        !          1820: 
        !          1821:     testp->omit = OMIT;
        !          1822:     testp->duration = DURATION;
        !          1823:     testp->diskfile_name = (char*) 0;
        !          1824:     testp->affinity = -1;
        !          1825:     testp->server_affinity = -1;
        !          1826:     TAILQ_INIT(&testp->xbind_addrs);
        !          1827: #if defined(HAVE_CPUSET_SETAFFINITY)
        !          1828:     CPU_ZERO(&testp->cpumask);
        !          1829: #endif /* HAVE_CPUSET_SETAFFINITY */
        !          1830:     testp->title = NULL;
        !          1831:     testp->congestion = NULL;
        !          1832:     testp->server_port = PORT;
        !          1833:     testp->ctrl_sck = -1;
        !          1834:     testp->prot_listener = -1;
        !          1835: 
        !          1836:     testp->stats_callback = iperf_stats_callback;
        !          1837:     testp->reporter_callback = iperf_reporter_callback;
        !          1838: 
        !          1839:     testp->stats_interval = testp->reporter_interval = 1;
        !          1840:     testp->num_streams = 1;
        !          1841: 
        !          1842:     testp->settings->domain = AF_UNSPEC;
        !          1843:     testp->settings->unit_format = 'a';
        !          1844:     testp->settings->socket_bufsize = 0;    /* use autotuning */
        !          1845:     testp->settings->blksize = DEFAULT_TCP_BLKSIZE;
        !          1846:     testp->settings->rate = 0;
        !          1847:     testp->settings->burst = 0;
        !          1848:     testp->settings->mss = 0;
        !          1849:     testp->settings->bytes = 0;
        !          1850:     testp->settings->blocks = 0;
        !          1851:     memset(testp->cookie, 0, COOKIE_SIZE);
        !          1852: 
        !          1853:     testp->multisend = 10;     /* arbitrary */
        !          1854: 
        !          1855:     /* Set up protocol list */
        !          1856:     SLIST_INIT(&testp->streams);
        !          1857:     SLIST_INIT(&testp->protocols);
        !          1858: 
        !          1859:     tcp = protocol_new();
        !          1860:     if (!tcp)
        !          1861:         return -1;
        !          1862: 
        !          1863:     tcp->id = Ptcp;
        !          1864:     tcp->name = "TCP";
        !          1865:     tcp->accept = iperf_tcp_accept;
        !          1866:     tcp->listen = iperf_tcp_listen;
        !          1867:     tcp->connect = iperf_tcp_connect;
        !          1868:     tcp->send = iperf_tcp_send;
        !          1869:     tcp->recv = iperf_tcp_recv;
        !          1870:     tcp->init = NULL;
        !          1871:     SLIST_INSERT_HEAD(&testp->protocols, tcp, protocols);
        !          1872: 
        !          1873:     udp = protocol_new();
        !          1874:     if (!udp) {
        !          1875:         protocol_free(tcp);
        !          1876:         return -1;
        !          1877:     }
        !          1878: 
        !          1879:     udp->id = Pudp;
        !          1880:     udp->name = "UDP";
        !          1881:     udp->accept = iperf_udp_accept;
        !          1882:     udp->listen = iperf_udp_listen;
        !          1883:     udp->connect = iperf_udp_connect;
        !          1884:     udp->send = iperf_udp_send;
        !          1885:     udp->recv = iperf_udp_recv;
        !          1886:     udp->init = iperf_udp_init;
        !          1887:     SLIST_INSERT_AFTER(tcp, udp, protocols);
        !          1888: 
        !          1889:     set_protocol(testp, Ptcp);
        !          1890: 
        !          1891: #if defined(HAVE_SCTP)
        !          1892:     sctp = protocol_new();
        !          1893:     if (!sctp) {
        !          1894:         protocol_free(tcp);
        !          1895:         protocol_free(udp);
        !          1896:         return -1;
        !          1897:     }
        !          1898: 
        !          1899:     sctp->id = Psctp;
        !          1900:     sctp->name = "SCTP";
        !          1901:     sctp->accept = iperf_sctp_accept;
        !          1902:     sctp->listen = iperf_sctp_listen;
        !          1903:     sctp->connect = iperf_sctp_connect;
        !          1904:     sctp->send = iperf_sctp_send;
        !          1905:     sctp->recv = iperf_sctp_recv;
        !          1906:     sctp->init = iperf_sctp_init;
        !          1907: 
        !          1908:     SLIST_INSERT_AFTER(udp, sctp, protocols);
        !          1909: #endif /* HAVE_SCTP */
        !          1910: 
        !          1911:     testp->on_new_stream = iperf_on_new_stream;
        !          1912:     testp->on_test_start = iperf_on_test_start;
        !          1913:     testp->on_connect = iperf_on_connect;
        !          1914:     testp->on_test_finish = iperf_on_test_finish;
        !          1915: 
        !          1916:     TAILQ_INIT(&testp->server_output_list);
        !          1917: 
        !          1918:     return 0;
        !          1919: }
        !          1920: 
        !          1921: 
        !          1922: /**************************************************************************/
        !          1923: void
        !          1924: iperf_free_test(struct iperf_test *test)
        !          1925: {
        !          1926:     struct protocol *prot;
        !          1927:     struct iperf_stream *sp;
        !          1928: 
        !          1929:     /* Free streams */
        !          1930:     while (!SLIST_EMPTY(&test->streams)) {
        !          1931:         sp = SLIST_FIRST(&test->streams);
        !          1932:         SLIST_REMOVE_HEAD(&test->streams, streams);
        !          1933:         iperf_free_stream(sp);
        !          1934:     }
        !          1935: 
        !          1936:     if (test->server_hostname)
        !          1937:        free(test->server_hostname);
        !          1938:     if (test->tmp_template)
        !          1939:        free(test->tmp_template);
        !          1940:     if (test->bind_address)
        !          1941:        free(test->bind_address);
        !          1942:     if (!TAILQ_EMPTY(&test->xbind_addrs)) {
        !          1943:         struct xbind_entry *xbe;
        !          1944: 
        !          1945:         while (!TAILQ_EMPTY(&test->xbind_addrs)) {
        !          1946:             xbe = TAILQ_FIRST(&test->xbind_addrs);
        !          1947:             TAILQ_REMOVE(&test->xbind_addrs, xbe, link);
        !          1948:             if (xbe->ai)
        !          1949:                 freeaddrinfo(xbe->ai);
        !          1950:             free(xbe->name);
        !          1951:             free(xbe);
        !          1952:         }
        !          1953:     }
        !          1954:     if (test->settings)
        !          1955:     free(test->settings);
        !          1956:     if (test->title)
        !          1957:        free(test->title);
        !          1958:     if (test->congestion)
        !          1959:        free(test->congestion);
        !          1960:     if (test->omit_timer != NULL)
        !          1961:        tmr_cancel(test->omit_timer);
        !          1962:     if (test->timer != NULL)
        !          1963:        tmr_cancel(test->timer);
        !          1964:     if (test->stats_timer != NULL)
        !          1965:        tmr_cancel(test->stats_timer);
        !          1966:     if (test->reporter_timer != NULL)
        !          1967:        tmr_cancel(test->reporter_timer);
        !          1968: 
        !          1969:     /* Free protocol list */
        !          1970:     while (!SLIST_EMPTY(&test->protocols)) {
        !          1971:         prot = SLIST_FIRST(&test->protocols);
        !          1972:         SLIST_REMOVE_HEAD(&test->protocols, protocols);        
        !          1973:         free(prot);
        !          1974:     }
        !          1975: 
        !          1976:     if (test->server_output_text) {
        !          1977:        free(test->server_output_text);
        !          1978:        test->server_output_text = NULL;
        !          1979:     }
        !          1980: 
        !          1981:     if (test->json_output_string) {
        !          1982:        free(test->json_output_string);
        !          1983:        test->json_output_string = NULL;
        !          1984:     }
        !          1985: 
        !          1986:     /* Free output line buffers, if any (on the server only) */
        !          1987:     struct iperf_textline *t;
        !          1988:     while (!TAILQ_EMPTY(&test->server_output_list)) {
        !          1989:        t = TAILQ_FIRST(&test->server_output_list);
        !          1990:        TAILQ_REMOVE(&test->server_output_list, t, textlineentries);
        !          1991:        free(t->line);
        !          1992:        free(t);
        !          1993:     }
        !          1994: 
        !          1995:     /* sctp_bindx: do not free the arguments, only the resolver results */
        !          1996:     if (!TAILQ_EMPTY(&test->xbind_addrs)) {
        !          1997:         struct xbind_entry *xbe;
        !          1998: 
        !          1999:         TAILQ_FOREACH(xbe, &test->xbind_addrs, link) {
        !          2000:             if (xbe->ai) {
        !          2001:                 freeaddrinfo(xbe->ai);
        !          2002:                 xbe->ai = NULL;
        !          2003:             }
        !          2004:         }
        !          2005:     }
        !          2006: 
        !          2007:     /* XXX: Why are we setting these values to NULL? */
        !          2008:     // test->streams = NULL;
        !          2009:     test->stats_callback = NULL;
        !          2010:     test->reporter_callback = NULL;
        !          2011:     free(test);
        !          2012: }
        !          2013: 
        !          2014: 
        !          2015: void
        !          2016: iperf_reset_test(struct iperf_test *test)
        !          2017: {
        !          2018:     struct iperf_stream *sp;
        !          2019: 
        !          2020:     /* Free streams */
        !          2021:     while (!SLIST_EMPTY(&test->streams)) {
        !          2022:         sp = SLIST_FIRST(&test->streams);
        !          2023:         SLIST_REMOVE_HEAD(&test->streams, streams);
        !          2024:         iperf_free_stream(sp);
        !          2025:     }
        !          2026:     if (test->omit_timer != NULL) {
        !          2027:        tmr_cancel(test->omit_timer);
        !          2028:        test->omit_timer = NULL;
        !          2029:     }
        !          2030:     if (test->timer != NULL) {
        !          2031:        tmr_cancel(test->timer);
        !          2032:        test->timer = NULL;
        !          2033:     }
        !          2034:     if (test->stats_timer != NULL) {
        !          2035:        tmr_cancel(test->stats_timer);
        !          2036:        test->stats_timer = NULL;
        !          2037:     }
        !          2038:     if (test->reporter_timer != NULL) {
        !          2039:        tmr_cancel(test->reporter_timer);
        !          2040:        test->reporter_timer = NULL;
        !          2041:     }
        !          2042:     test->done = 0;
        !          2043: 
        !          2044:     SLIST_INIT(&test->streams);
        !          2045: 
        !          2046:     test->role = 's';
        !          2047:     test->sender = 0;
        !          2048:     test->sender_has_retransmits = 0;
        !          2049:     set_protocol(test, Ptcp);
        !          2050:     test->omit = OMIT;
        !          2051:     test->duration = DURATION;
        !          2052:     test->server_affinity = -1;
        !          2053: #if defined(HAVE_CPUSET_SETAFFINITY)
        !          2054:     CPU_ZERO(&test->cpumask);
        !          2055: #endif /* HAVE_CPUSET_SETAFFINITY */
        !          2056:     test->state = 0;
        !          2057:     
        !          2058:     test->ctrl_sck = -1;
        !          2059:     test->prot_listener = -1;
        !          2060: 
        !          2061:     test->bytes_sent = 0;
        !          2062:     test->blocks_sent = 0;
        !          2063: 
        !          2064:     test->reverse = 0;
        !          2065:     test->no_delay = 0;
        !          2066: 
        !          2067:     FD_ZERO(&test->read_set);
        !          2068:     FD_ZERO(&test->write_set);
        !          2069:     
        !          2070:     test->num_streams = 1;
        !          2071:     test->settings->socket_bufsize = 0;
        !          2072:     test->settings->blksize = DEFAULT_TCP_BLKSIZE;
        !          2073:     test->settings->rate = 0;
        !          2074:     test->settings->burst = 0;
        !          2075:     test->settings->mss = 0;
        !          2076:     memset(test->cookie, 0, COOKIE_SIZE);
        !          2077:     test->multisend = 10;      /* arbitrary */
        !          2078:     test->udp_counters_64bit = 0;
        !          2079: 
        !          2080:     /* Free output line buffers, if any (on the server only) */
        !          2081:     struct iperf_textline *t;
        !          2082:     while (!TAILQ_EMPTY(&test->server_output_list)) {
        !          2083:        t = TAILQ_FIRST(&test->server_output_list);
        !          2084:        TAILQ_REMOVE(&test->server_output_list, t, textlineentries);
        !          2085:        free(t->line);
        !          2086:        free(t);
        !          2087:     }
        !          2088: }
        !          2089: 
        !          2090: 
        !          2091: /* Reset all of a test's stats back to zero.  Called when the omitting
        !          2092: ** period is over.
        !          2093: */
        !          2094: void
        !          2095: iperf_reset_stats(struct iperf_test *test)
        !          2096: {
        !          2097:     struct timeval now;
        !          2098:     struct iperf_stream *sp;
        !          2099:     struct iperf_stream_result *rp;
        !          2100: 
        !          2101:     test->bytes_sent = 0;
        !          2102:     test->blocks_sent = 0;
        !          2103:     gettimeofday(&now, NULL);
        !          2104:     SLIST_FOREACH(sp, &test->streams, streams) {
        !          2105:        sp->omitted_packet_count = sp->packet_count;
        !          2106:         sp->omitted_cnt_error = sp->cnt_error;
        !          2107:         sp->omitted_outoforder_packets = sp->outoforder_packets;
        !          2108:        sp->jitter = 0;
        !          2109:        rp = sp->result;
        !          2110:         rp->bytes_sent_omit = rp->bytes_sent;
        !          2111:         rp->bytes_received = 0;
        !          2112:         rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
        !          2113:        if (test->sender && test->sender_has_retransmits) {
        !          2114:            struct iperf_interval_results ir; /* temporary results structure */
        !          2115:            save_tcpinfo(sp, &ir);
        !          2116:            rp->stream_prev_total_retrans = get_total_retransmits(&ir);
        !          2117:        }
        !          2118:        rp->stream_retrans = 0;
        !          2119:        rp->start_time = now;
        !          2120:     }
        !          2121: }
        !          2122: 
        !          2123: 
        !          2124: /**************************************************************************/
        !          2125: 
        !          2126: /**
        !          2127:  * Gather statistics during a test.
        !          2128:  * This function works for both the client and server side.
        !          2129:  */
        !          2130: void
        !          2131: iperf_stats_callback(struct iperf_test *test)
        !          2132: {
        !          2133:     struct iperf_stream *sp;
        !          2134:     struct iperf_stream_result *rp = NULL;
        !          2135:     struct iperf_interval_results *irp, temp;
        !          2136: 
        !          2137:     temp.omitted = test->omitting;
        !          2138:     SLIST_FOREACH(sp, &test->streams, streams) {
        !          2139:         rp = sp->result;
        !          2140: 
        !          2141:        temp.bytes_transferred = test->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval;
        !          2142:      
        !          2143:        irp = TAILQ_LAST(&rp->interval_results, irlisthead);
        !          2144:         /* result->end_time contains timestamp of previous interval */
        !          2145:         if ( irp != NULL ) /* not the 1st interval */
        !          2146:             memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct timeval));
        !          2147:         else /* or use timestamp from beginning */
        !          2148:             memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct timeval));
        !          2149:         /* now save time of end of this interval */
        !          2150:         gettimeofday(&rp->end_time, NULL);
        !          2151:         memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct timeval));
        !          2152:         temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
        !          2153:         //temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
        !          2154:        if (test->protocol->id == Ptcp) {
        !          2155:            if ( has_tcpinfo()) {
        !          2156:                save_tcpinfo(sp, &temp);
        !          2157:                if (test->sender && test->sender_has_retransmits) {
        !          2158:                    long total_retrans = get_total_retransmits(&temp);
        !          2159:                    temp.interval_retrans = total_retrans - rp->stream_prev_total_retrans;
        !          2160:                    rp->stream_retrans += temp.interval_retrans;
        !          2161:                    rp->stream_prev_total_retrans = total_retrans;
        !          2162: 
        !          2163:                    temp.snd_cwnd = get_snd_cwnd(&temp);
        !          2164:                    if (temp.snd_cwnd > rp->stream_max_snd_cwnd) {
        !          2165:                        rp->stream_max_snd_cwnd = temp.snd_cwnd;
        !          2166:                    }
        !          2167:                    
        !          2168:                    temp.rtt = get_rtt(&temp);
        !          2169:                    if (temp.rtt > rp->stream_max_rtt) {
        !          2170:                        rp->stream_max_rtt = temp.rtt;
        !          2171:                    }
        !          2172:                    if (rp->stream_min_rtt == 0 ||
        !          2173:                        temp.rtt < rp->stream_min_rtt) {
        !          2174:                        rp->stream_min_rtt = temp.rtt;
        !          2175:                    }
        !          2176:                    rp->stream_sum_rtt += temp.rtt;
        !          2177:                    rp->stream_count_rtt++;
        !          2178:                }
        !          2179:            }
        !          2180:        } else {
        !          2181:            if (irp == NULL) {
        !          2182:                temp.interval_packet_count = sp->packet_count;
        !          2183:                temp.interval_outoforder_packets = sp->outoforder_packets;
        !          2184:                temp.interval_cnt_error = sp->cnt_error;
        !          2185:            } else {
        !          2186:                temp.interval_packet_count = sp->packet_count - irp->packet_count;
        !          2187:                temp.interval_outoforder_packets = sp->outoforder_packets - irp->outoforder_packets;
        !          2188:                temp.interval_cnt_error = sp->cnt_error - irp->cnt_error;
        !          2189:            }
        !          2190:            temp.packet_count = sp->packet_count;
        !          2191:            temp.jitter = sp->jitter;
        !          2192:            temp.outoforder_packets = sp->outoforder_packets;
        !          2193:            temp.cnt_error = sp->cnt_error;
        !          2194:        }
        !          2195:         add_to_interval_list(rp, &temp);
        !          2196:         rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
        !          2197:     }
        !          2198: }
        !          2199: 
        !          2200: /**
        !          2201:  * Print intermediate results during a test (interval report).
        !          2202:  * Uses print_interval_results to print the results for each stream,
        !          2203:  * then prints an interval summary for all streams in this
        !          2204:  * interval.
        !          2205:  */
        !          2206: static void
        !          2207: iperf_print_intermediate(struct iperf_test *test)
        !          2208: {
        !          2209:     char ubuf[UNIT_LEN];
        !          2210:     char nbuf[UNIT_LEN];
        !          2211:     struct iperf_stream *sp = NULL;
        !          2212:     struct iperf_interval_results *irp;
        !          2213:     iperf_size_t bytes = 0;
        !          2214:     double bandwidth;
        !          2215:     int retransmits = 0;
        !          2216:     double start_time, end_time;
        !          2217:     cJSON *json_interval;
        !          2218:     cJSON *json_interval_streams;
        !          2219:     int total_packets = 0, lost_packets = 0;
        !          2220:     double avg_jitter = 0.0, lost_percent;
        !          2221: 
        !          2222:     if (test->json_output) {
        !          2223:         json_interval = cJSON_CreateObject();
        !          2224:        if (json_interval == NULL)
        !          2225:            return;
        !          2226:        cJSON_AddItemToArray(test->json_intervals, json_interval);
        !          2227:         json_interval_streams = cJSON_CreateArray();
        !          2228:        if (json_interval_streams == NULL)
        !          2229:            return;
        !          2230:        cJSON_AddItemToObject(json_interval, "streams", json_interval_streams);
        !          2231:     } else {
        !          2232:         json_interval = NULL;
        !          2233:         json_interval_streams = NULL;
        !          2234:     }
        !          2235: 
        !          2236:     SLIST_FOREACH(sp, &test->streams, streams) {
        !          2237:         print_interval_results(test, sp, json_interval_streams);
        !          2238:        /* sum up all streams */
        !          2239:        irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
        !          2240:        if (irp == NULL) {
        !          2241:            iperf_err(test, "iperf_print_intermediate error: interval_results is NULL");
        !          2242:            return;
        !          2243:        }
        !          2244:         bytes += irp->bytes_transferred;
        !          2245:        if (test->protocol->id == Ptcp) {
        !          2246:            if (test->sender && test->sender_has_retransmits) {
        !          2247:                retransmits += irp->interval_retrans;
        !          2248:            }
        !          2249:        } else {
        !          2250:             total_packets += irp->interval_packet_count;
        !          2251:             lost_packets += irp->interval_cnt_error;
        !          2252:             avg_jitter += irp->jitter;
        !          2253:        }
        !          2254:     }
        !          2255: 
        !          2256:     /* next build string with sum of all streams */
        !          2257:     if (test->num_streams > 1 || test->json_output) {
        !          2258:         sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */
        !          2259:        /* Only do this of course if there was a first stream */
        !          2260:        if (sp) {
        !          2261:         irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);    /* use 1st stream for timing info */
        !          2262: 
        !          2263:         unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A');
        !          2264:        bandwidth = (double) bytes / (double) irp->interval_duration;
        !          2265:         unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
        !          2266: 
        !          2267:         start_time = timeval_diff(&sp->result->start_time,&irp->interval_start_time);
        !          2268:         end_time = timeval_diff(&sp->result->start_time,&irp->interval_end_time);
        !          2269:        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
        !          2270:            if (test->sender && test->sender_has_retransmits) {
        !          2271:                /* Interval sum, TCP with retransmits. */
        !          2272:                if (test->json_output)
        !          2273:                    cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d  omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) retransmits, irp->omitted)); /* XXX irp->omitted or test->omitting? */
        !          2274:                else
        !          2275:                    iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits, irp->omitted?report_omitted:""); /* XXX irp->omitted or test->omitting? */
        !          2276:            } else {
        !          2277:                /* Interval sum, TCP without retransmits. */
        !          2278:                if (test->json_output)
        !          2279:                    cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, test->omitting));
        !          2280:                else
        !          2281:                    iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, test->omitting?report_omitted:"");
        !          2282:            }
        !          2283:        } else {
        !          2284:            /* Interval sum, UDP. */
        !          2285:            if (test->sender) {
        !          2286:                if (test->json_output)
        !          2287:                    cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  packets: %d  omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) total_packets, test->omitting));
        !          2288:                else
        !          2289:                    iprintf(test, report_sum_bw_udp_sender_format, start_time, end_time, ubuf, nbuf, total_packets, test->omitting?report_omitted:"");
        !          2290:            } else {
        !          2291:                avg_jitter /= test->num_streams;
        !          2292:                if (total_packets > 0) {
        !          2293:                    lost_percent = 100.0 * lost_packets / total_packets;
        !          2294:                }
        !          2295:                else {
        !          2296:                    lost_percent = 0.0;
        !          2297:                }
        !          2298:                if (test->json_output)
        !          2299:                    cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  jitter_ms: %f  lost_packets: %d  packets: %d  lost_percent: %f  omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) total_packets, (double) lost_percent, test->omitting));
        !          2300:                else
        !          2301:                    iprintf(test, report_sum_bw_udp_format, start_time, end_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, total_packets, lost_percent, test->omitting?report_omitted:"");
        !          2302:            }
        !          2303:        }
        !          2304:        }
        !          2305:     }
        !          2306: }
        !          2307: 
        !          2308: /**
        !          2309:  * Print overall summary statistics at the end of a test.
        !          2310:  */
        !          2311: static void
        !          2312: iperf_print_results(struct iperf_test *test)
        !          2313: {
        !          2314: 
        !          2315:     cJSON *json_summary_streams = NULL;
        !          2316:     cJSON *json_summary_stream = NULL;
        !          2317:     int total_retransmits = 0;
        !          2318:     int total_packets = 0, lost_packets = 0;
        !          2319:     char ubuf[UNIT_LEN];
        !          2320:     char nbuf[UNIT_LEN];
        !          2321:     struct stat sb;
        !          2322:     char sbuf[UNIT_LEN];
        !          2323:     struct iperf_stream *sp = NULL;
        !          2324:     iperf_size_t bytes_sent, total_sent = 0;
        !          2325:     iperf_size_t bytes_received, total_received = 0;
        !          2326:     double start_time, end_time, avg_jitter = 0.0, lost_percent;
        !          2327:     double bandwidth;
        !          2328: 
        !          2329:     /* print final summary for all intervals */
        !          2330: 
        !          2331:     if (test->json_output) {
        !          2332:         json_summary_streams = cJSON_CreateArray();
        !          2333:        if (json_summary_streams == NULL)
        !          2334:            return;
        !          2335:        cJSON_AddItemToObject(test->json_end, "streams", json_summary_streams);
        !          2336:     } else {
        !          2337:        iprintf(test, "%s", report_bw_separator);
        !          2338:        if (test->verbose)
        !          2339:            iprintf(test, "%s", report_summary);
        !          2340:        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
        !          2341:            if (test->sender_has_retransmits)
        !          2342:                iprintf(test, "%s", report_bw_retrans_header);
        !          2343:            else
        !          2344:                iprintf(test, "%s", report_bw_header);
        !          2345:        } else
        !          2346:            iprintf(test, "%s", report_bw_udp_header);
        !          2347:     }
        !          2348: 
        !          2349:     start_time = 0.;
        !          2350:     sp = SLIST_FIRST(&test->streams);
        !          2351:     /* 
        !          2352:      * If there is at least one stream, then figure out the length of time
        !          2353:      * we were running the tests and print out some statistics about
        !          2354:      * the streams.  It's possible to not have any streams at all
        !          2355:      * if the client got interrupted before it got to do anything.
        !          2356:      */
        !          2357:     if (sp) {
        !          2358:     end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time);
        !          2359:     SLIST_FOREACH(sp, &test->streams, streams) {
        !          2360:        if (test->json_output) {
        !          2361:            json_summary_stream = cJSON_CreateObject();
        !          2362:            if (json_summary_stream == NULL)
        !          2363:                return;
        !          2364:            cJSON_AddItemToArray(json_summary_streams, json_summary_stream);
        !          2365:        }
        !          2366: 
        !          2367:         bytes_sent = sp->result->bytes_sent - sp->result->bytes_sent_omit;
        !          2368:         bytes_received = sp->result->bytes_received;
        !          2369:         total_sent += bytes_sent;
        !          2370:         total_received += bytes_received;
        !          2371: 
        !          2372:         if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
        !          2373:            if (test->sender_has_retransmits) {
        !          2374:                total_retransmits += sp->result->stream_retrans;
        !          2375:            }
        !          2376:        } else {
        !          2377:             total_packets += (sp->packet_count - sp->omitted_packet_count);
        !          2378:             lost_packets += (sp->cnt_error - sp->omitted_cnt_error);
        !          2379:             avg_jitter += sp->jitter;
        !          2380:         }
        !          2381: 
        !          2382:        unit_snprintf(ubuf, UNIT_LEN, (double) bytes_sent, 'A');
        !          2383:        bandwidth = (double) bytes_sent / (double) end_time;
        !          2384:        unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
        !          2385:        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
        !          2386:            if (test->sender_has_retransmits) {
        !          2387:                /* Summary, TCP with retransmits. */
        !          2388:                if (test->json_output)
        !          2389:                    cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d  max_snd_cwnd:  %d  max_rtt:  %d  min_rtt:  %d  mean_rtt:  %d", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) sp->result->stream_retrans, (int64_t) sp->result->stream_max_snd_cwnd, (int64_t) sp->result->stream_max_rtt, (int64_t) sp->result->stream_min_rtt, (int64_t) ((sp->result->stream_count_rtt == 0) ? 0 : sp->result->stream_sum_rtt / sp->result->stream_count_rtt)));
        !          2390:                else
        !          2391:                    iprintf(test, report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->result->stream_retrans, report_sender);
        !          2392:            } else {
        !          2393:                /* Summary, TCP without retransmits. */
        !          2394:                if (test->json_output)
        !          2395:                    cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8));
        !          2396:                else
        !          2397:                    iprintf(test, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf, report_sender);
        !          2398:            }
        !          2399:        } else {
        !          2400:            /* Summary, UDP. */
        !          2401:            if (sp->packet_count - sp->omitted_packet_count > 0) {
        !          2402:               lost_percent = 100.0 * (sp->cnt_error - sp->omitted_cnt_error) / (sp->packet_count - sp->omitted_packet_count);
        !          2403:            }
        !          2404:            else {
        !          2405:                lost_percent = 0.0;
        !          2406:            }
        !          2407:            if (test->json_output)
        !          2408:               cJSON_AddItemToObject(json_summary_stream, "udp", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  jitter_ms: %f  lost_packets: %d  packets: %d  lost_percent: %f  out_of_order: %d", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8, (double) sp->jitter * 1000.0, (int64_t) (sp->cnt_error - sp->omitted_cnt_error), (int64_t) (sp->packet_count - sp->omitted_packet_count), (double) lost_percent, (int64_t) (sp->outoforder_packets - sp->omitted_outoforder_packets)));
        !          2409:            else {
        !          2410:               iprintf(test, report_bw_udp_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->jitter * 1000.0, (sp->cnt_error - sp->omitted_cnt_error), (sp->packet_count - sp->omitted_packet_count), lost_percent, "");
        !          2411:                if (test->role == 'c')
        !          2412:                    iprintf(test, report_datagrams, sp->socket, (sp->packet_count - sp->omitted_packet_count));
        !          2413:                if ((sp->outoforder_packets - sp->omitted_outoforder_packets) > 0)
        !          2414:                   iprintf(test, report_sum_outoforder, start_time, end_time, (sp->outoforder_packets - sp->omitted_outoforder_packets));
        !          2415:            }
        !          2416:        }
        !          2417: 
        !          2418:        if (sp->diskfile_fd >= 0) {
        !          2419:            if (fstat(sp->diskfile_fd, &sb) == 0) {
        !          2420:                int percent = (int) ( ( (double) bytes_sent / (double) sb.st_size ) * 100.0 );
        !          2421:                unit_snprintf(sbuf, UNIT_LEN, (double) sb.st_size, 'A');
        !          2422:                if (test->json_output)
        !          2423:                    cJSON_AddItemToObject(json_summary_stream, "diskfile", iperf_json_printf("sent: %d  size: %d  percent: %d  filename: %s", (int64_t) bytes_sent, (int64_t) sb.st_size, (int64_t) percent, test->diskfile_name));
        !          2424:                else
        !          2425:                    iprintf(test, report_diskfile, ubuf, sbuf, percent, test->diskfile_name);
        !          2426:            }
        !          2427:        }
        !          2428: 
        !          2429:        unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
        !          2430:        bandwidth = (double) bytes_received / (double) end_time;
        !          2431:        unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
        !          2432:        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
        !          2433:            if (test->json_output)
        !          2434:                cJSON_AddItemToObject(json_summary_stream, "receiver", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_received, bandwidth * 8));
        !          2435:            else
        !          2436:                iprintf(test, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf, report_receiver);
        !          2437:        }
        !          2438:     }
        !          2439:     }
        !          2440: 
        !          2441:     if (test->num_streams > 1 || test->json_output) {
        !          2442:         unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');
        !          2443:        /* If no tests were run, arbitrariliy set bandwidth to 0. */
        !          2444:        if (end_time > 0.0) {
        !          2445:            bandwidth = (double) total_sent / (double) end_time;
        !          2446:        }
        !          2447:        else {
        !          2448:            bandwidth = 0.0;
        !          2449:        }
        !          2450:         unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
        !          2451:         if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
        !          2452:            if (test->sender_has_retransmits) {
        !          2453:                /* Summary sum, TCP with retransmits. */
        !          2454:                if (test->json_output)
        !          2455:                    cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8, (int64_t) total_retransmits));
        !          2456:                else
        !          2457:                    iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, total_retransmits, report_sender);
        !          2458:            } else {
        !          2459:                /* Summary sum, TCP without retransmits. */
        !          2460:                if (test->json_output)
        !          2461:                    cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8));
        !          2462:                else
        !          2463:                    iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, report_sender);
        !          2464:            }
        !          2465:             unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A');
        !          2466:            /* If no tests were run, set received bandwidth to 0 */
        !          2467:            if (end_time > 0.0) {
        !          2468:                bandwidth = (double) total_received / (double) end_time;
        !          2469:            }
        !          2470:            else {
        !          2471:                bandwidth = 0.0;
        !          2472:            }
        !          2473:             unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
        !          2474:            if (test->json_output)
        !          2475:                cJSON_AddItemToObject(test->json_end, "sum_received", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_received, bandwidth * 8));
        !          2476:            else
        !          2477:                iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, report_receiver);
        !          2478:         } else {
        !          2479:            /* Summary sum, UDP. */
        !          2480:             avg_jitter /= test->num_streams;
        !          2481:            /* If no packets were sent, arbitrarily set loss percentage to 0. */
        !          2482:            if (total_packets > 0) {
        !          2483:                lost_percent = 100.0 * lost_packets / total_packets;
        !          2484:            }
        !          2485:            else {
        !          2486:                lost_percent = 0.0;
        !          2487:            }
        !          2488:            if (test->json_output)
        !          2489:                cJSON_AddItemToObject(test->json_end, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  jitter_ms: %f  lost_packets: %d  packets: %d  lost_percent: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) total_packets, (double) lost_percent));
        !          2490:            else
        !          2491:                iprintf(test, report_sum_bw_udp_format, start_time, end_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, total_packets, lost_percent, "");
        !          2492:         }
        !          2493:     }
        !          2494: 
        !          2495:     if (test->json_output)
        !          2496:        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]));
        !          2497:     else {
        !          2498:        if (test->verbose) {
        !          2499:            iprintf(test, report_cpu, report_local, test->sender?report_sender:report_receiver, test->cpu_util[0], test->cpu_util[1], test->cpu_util[2], report_remote, test->sender?report_receiver:report_sender, test->remote_cpu_util[0], test->remote_cpu_util[1], test->remote_cpu_util[2]);
        !          2500:        }
        !          2501: 
        !          2502:        /* Print server output if we're on the client and it was requested/provided */
        !          2503:        if (test->role == 'c' && iperf_get_test_get_server_output(test)) {
        !          2504:            if (test->json_server_output) {
        !          2505:                iprintf(test, "\nServer JSON output:\n%s\n", cJSON_Print(test->json_server_output));
        !          2506:                cJSON_Delete(test->json_server_output);
        !          2507:                test->json_server_output = NULL;
        !          2508:            }
        !          2509:            if (test->server_output_text) {
        !          2510:                iprintf(test, "\nServer output:\n%s\n", test->server_output_text);
        !          2511:                test->server_output_text = NULL;
        !          2512:            }
        !          2513:        }
        !          2514:     }
        !          2515: }
        !          2516: 
        !          2517: /**************************************************************************/
        !          2518: 
        !          2519: /**
        !          2520:  * Main report-printing callback.
        !          2521:  * Prints results either during a test (interval report only) or 
        !          2522:  * after the entire test has been run (last interval report plus 
        !          2523:  * overall summary).
        !          2524:  */
        !          2525: void
        !          2526: iperf_reporter_callback(struct iperf_test *test)
        !          2527: {
        !          2528:     switch (test->state) {
        !          2529:         case TEST_RUNNING:
        !          2530:         case STREAM_RUNNING:
        !          2531:             /* print interval results for each stream */
        !          2532:             iperf_print_intermediate(test);
        !          2533:             break;
        !          2534:         case TEST_END:
        !          2535:         case DISPLAY_RESULTS:
        !          2536:             iperf_print_intermediate(test);
        !          2537:             iperf_print_results(test);
        !          2538:             break;
        !          2539:     } 
        !          2540: 
        !          2541: }
        !          2542: 
        !          2543: /**
        !          2544:  * Print the interval results for one stream.
        !          2545:  * This function needs to know about the overall test so it can determine the
        !          2546:  * context for printing headers, separators, etc.
        !          2547:  */
        !          2548: static void
        !          2549: print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams)
        !          2550: {
        !          2551:     char ubuf[UNIT_LEN];
        !          2552:     char nbuf[UNIT_LEN];
        !          2553:     char cbuf[UNIT_LEN];
        !          2554:     double st = 0., et = 0.;
        !          2555:     struct iperf_interval_results *irp = NULL;
        !          2556:     double bandwidth, lost_percent;
        !          2557: 
        !          2558:     irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* get last entry in linked list */
        !          2559:     if (irp == NULL) {
        !          2560:        iperf_err(test, "print_interval_results error: interval_results is NULL");
        !          2561:         return;
        !          2562:     }
        !          2563:     if (!test->json_output) {
        !          2564:        /* First stream? */
        !          2565:        if (sp == SLIST_FIRST(&test->streams)) {
        !          2566:            /* It it's the first interval, print the header;
        !          2567:            ** else if there's more than one stream, print the separator;
        !          2568:            ** else nothing.
        !          2569:            */
        !          2570:            if (timeval_equals(&sp->result->start_time, &irp->interval_start_time)) {
        !          2571:                if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
        !          2572:                    if (test->sender && test->sender_has_retransmits)
        !          2573:                        iprintf(test, "%s", report_bw_retrans_cwnd_header);
        !          2574:                    else
        !          2575:                        iprintf(test, "%s", report_bw_header);
        !          2576:                } else {
        !          2577:                    if (test->sender)
        !          2578:                        iprintf(test, "%s", report_bw_udp_sender_header);
        !          2579:                    else
        !          2580:                        iprintf(test, "%s", report_bw_udp_header);
        !          2581:                }
        !          2582:            } else if (test->num_streams > 1)
        !          2583:                iprintf(test, "%s", report_bw_separator);
        !          2584:        }
        !          2585:     }
        !          2586: 
        !          2587:     unit_snprintf(ubuf, UNIT_LEN, (double) (irp->bytes_transferred), 'A');
        !          2588:     bandwidth = (double) irp->bytes_transferred / (double) irp->interval_duration;
        !          2589:     unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
        !          2590:     
        !          2591:     st = timeval_diff(&sp->result->start_time, &irp->interval_start_time);
        !          2592:     et = timeval_diff(&sp->result->start_time, &irp->interval_end_time);
        !          2593:     
        !          2594:     if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
        !          2595:        if (test->sender && test->sender_has_retransmits) {
        !          2596:            /* Interval, TCP with retransmits. */
        !          2597:            if (test->json_output)
        !          2598:                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d  snd_cwnd:  %d  rtt:  %d  omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_retrans, (int64_t) irp->snd_cwnd, (int64_t) irp->rtt, irp->omitted));
        !          2599:            else {
        !          2600:                unit_snprintf(cbuf, UNIT_LEN, irp->snd_cwnd, 'A');
        !          2601:                iprintf(test, report_bw_retrans_cwnd_format, sp->socket, st, et, ubuf, nbuf, irp->interval_retrans, cbuf, irp->omitted?report_omitted:"");
        !          2602:            }
        !          2603:        } else {
        !          2604:            /* Interval, TCP without retransmits. */
        !          2605:            if (test->json_output)
        !          2606:                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, irp->omitted));
        !          2607:            else
        !          2608:                iprintf(test, report_bw_format, sp->socket, st, et, ubuf, nbuf, irp->omitted?report_omitted:"");
        !          2609:        }
        !          2610:     } else {
        !          2611:        /* Interval, UDP. */
        !          2612:        if (test->sender) {
        !          2613:            if (test->json_output)
        !          2614:                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  packets: %d  omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_packet_count, irp->omitted));
        !          2615:            else
        !          2616:                iprintf(test, report_bw_udp_sender_format, sp->socket, st, et, ubuf, nbuf, irp->interval_packet_count, irp->omitted?report_omitted:"");
        !          2617:        } else {
        !          2618:            if (irp->interval_packet_count > 0) {
        !          2619:                lost_percent = 100.0 * irp->interval_cnt_error / irp->interval_packet_count;
        !          2620:            }
        !          2621:            else {
        !          2622:                lost_percent = 0.0;
        !          2623:            }
        !          2624:            if (test->json_output)
        !          2625:                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  jitter_ms: %f  lost_packets: %d  packets: %d  lost_percent: %f  omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (double) irp->jitter * 1000.0, (int64_t) irp->interval_cnt_error, (int64_t) irp->interval_packet_count, (double) lost_percent, irp->omitted));
        !          2626:            else
        !          2627:                iprintf(test, report_bw_udp_format, sp->socket, st, et, ubuf, nbuf, irp->jitter * 1000.0, irp->interval_cnt_error, irp->interval_packet_count, lost_percent, irp->omitted?report_omitted:"");
        !          2628:        }
        !          2629:     }
        !          2630: 
        !          2631:     if (test->logfile)
        !          2632:         iflush(test);
        !          2633: }
        !          2634: 
        !          2635: /**************************************************************************/
        !          2636: void
        !          2637: iperf_free_stream(struct iperf_stream *sp)
        !          2638: {
        !          2639:     struct iperf_interval_results *irp, *nirp;
        !          2640: 
        !          2641:     /* XXX: need to free interval list too! */
        !          2642:     munmap(sp->buffer, sp->test->settings->blksize);
        !          2643:     close(sp->buffer_fd);
        !          2644:     if (sp->diskfile_fd >= 0)
        !          2645:        close(sp->diskfile_fd);
        !          2646:     for (irp = TAILQ_FIRST(&sp->result->interval_results); irp != NULL; irp = nirp) {
        !          2647:         nirp = TAILQ_NEXT(irp, irlistentries);
        !          2648:         free(irp);
        !          2649:     }
        !          2650:     free(sp->result);
        !          2651:     if (sp->send_timer != NULL)
        !          2652:        tmr_cancel(sp->send_timer);
        !          2653:     free(sp);
        !          2654: }
        !          2655: 
        !          2656: /**************************************************************************/
        !          2657: struct iperf_stream *
        !          2658: iperf_new_stream(struct iperf_test *test, int s)
        !          2659: {
        !          2660:     int i;
        !          2661:     struct iperf_stream *sp;
        !          2662:     
        !          2663:     char template[1024];
        !          2664:     if (test->tmp_template) {
        !          2665:         snprintf(template, sizeof(template) / sizeof(char), "%s", test->tmp_template);
        !          2666:     } else {
        !          2667:         char buf[] = "/tmp/iperf3.XXXXXX";
        !          2668:         snprintf(template, sizeof(template) / sizeof(char), "%s", buf);
        !          2669:     }
        !          2670: 
        !          2671:     h_errno = 0;
        !          2672: 
        !          2673:     sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream));
        !          2674:     if (!sp) {
        !          2675:         i_errno = IECREATESTREAM;
        !          2676:         return NULL;
        !          2677:     }
        !          2678: 
        !          2679:     memset(sp, 0, sizeof(struct iperf_stream));
        !          2680: 
        !          2681:     sp->test = test;
        !          2682:     sp->settings = test->settings;
        !          2683:     sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));
        !          2684:     if (!sp->result) {
        !          2685:         free(sp);
        !          2686:         i_errno = IECREATESTREAM;
        !          2687:         return NULL;
        !          2688:     }
        !          2689: 
        !          2690:     memset(sp->result, 0, sizeof(struct iperf_stream_result));
        !          2691:     TAILQ_INIT(&sp->result->interval_results);
        !          2692:     
        !          2693:     /* Create and randomize the buffer */
        !          2694:     sp->buffer_fd = mkstemp(template);
        !          2695:     if (sp->buffer_fd == -1) {
        !          2696:         i_errno = IECREATESTREAM;
        !          2697:         free(sp->result);
        !          2698:         free(sp);
        !          2699:         return NULL;
        !          2700:     }
        !          2701:     if (unlink(template) < 0) {
        !          2702:         i_errno = IECREATESTREAM;
        !          2703:         free(sp->result);
        !          2704:         free(sp);
        !          2705:         return NULL;
        !          2706:     }
        !          2707:     if (ftruncate(sp->buffer_fd, test->settings->blksize) < 0) {
        !          2708:         i_errno = IECREATESTREAM;
        !          2709:         free(sp->result);
        !          2710:         free(sp);
        !          2711:         return NULL;
        !          2712:     }
        !          2713:     sp->buffer = (char *) mmap(NULL, test->settings->blksize, PROT_READ|PROT_WRITE, MAP_PRIVATE, sp->buffer_fd, 0);
        !          2714:     if (sp->buffer == MAP_FAILED) {
        !          2715:         i_errno = IECREATESTREAM;
        !          2716:         free(sp->result);
        !          2717:         free(sp);
        !          2718:         return NULL;
        !          2719:     }
        !          2720:     srandom(time(NULL));
        !          2721:     for (i = 0; i < test->settings->blksize; ++i)
        !          2722:         sp->buffer[i] = random();
        !          2723: 
        !          2724:     /* Set socket */
        !          2725:     sp->socket = s;
        !          2726: 
        !          2727:     sp->snd = test->protocol->send;
        !          2728:     sp->rcv = test->protocol->recv;
        !          2729: 
        !          2730:     if (test->diskfile_name != (char*) 0) {
        !          2731:        sp->diskfile_fd = open(test->diskfile_name, test->sender ? O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC), S_IRUSR|S_IWUSR);
        !          2732:        if (sp->diskfile_fd == -1) {
        !          2733:            i_errno = IEFILE;
        !          2734:             munmap(sp->buffer, sp->test->settings->blksize);
        !          2735:             free(sp->result);
        !          2736:             free(sp);
        !          2737:            return NULL;
        !          2738:        }
        !          2739:         sp->snd2 = sp->snd;
        !          2740:        sp->snd = diskfile_send;
        !          2741:        sp->rcv2 = sp->rcv;
        !          2742:        sp->rcv = diskfile_recv;
        !          2743:     } else
        !          2744:         sp->diskfile_fd = -1;
        !          2745: 
        !          2746:     /* Initialize stream */
        !          2747:     if (iperf_init_stream(sp, test) < 0) {
        !          2748:         close(sp->buffer_fd);
        !          2749:         munmap(sp->buffer, sp->test->settings->blksize);
        !          2750:         free(sp->result);
        !          2751:         free(sp);
        !          2752:         return NULL;
        !          2753:     }
        !          2754:     iperf_add_stream(test, sp);
        !          2755: 
        !          2756:     return sp;
        !          2757: }
        !          2758: 
        !          2759: /**************************************************************************/
        !          2760: int
        !          2761: iperf_init_stream(struct iperf_stream *sp, struct iperf_test *test)
        !          2762: {
        !          2763:     socklen_t len;
        !          2764:     int opt;
        !          2765: 
        !          2766:     len = sizeof(struct sockaddr_storage);
        !          2767:     if (getsockname(sp->socket, (struct sockaddr *) &sp->local_addr, &len) < 0) {
        !          2768:         i_errno = IEINITSTREAM;
        !          2769:         return -1;
        !          2770:     }
        !          2771:     len = sizeof(struct sockaddr_storage);
        !          2772:     if (getpeername(sp->socket, (struct sockaddr *) &sp->remote_addr, &len) < 0) {
        !          2773:         i_errno = IEINITSTREAM;
        !          2774:         return -1;
        !          2775:     }
        !          2776: 
        !          2777:     /* Set IP TOS */
        !          2778:     if ((opt = test->settings->tos)) {
        !          2779:         if (getsockdomain(sp->socket) == AF_INET6) {
        !          2780: #ifdef IPV6_TCLASS
        !          2781:             if (setsockopt(sp->socket, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) < 0) {
        !          2782:                 i_errno = IESETCOS;
        !          2783:                 return -1;
        !          2784:             }
        !          2785: #else
        !          2786:             i_errno = IESETCOS;
        !          2787:             return -1;
        !          2788: #endif
        !          2789:         } else {
        !          2790:             if (setsockopt(sp->socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) < 0) {
        !          2791:                 i_errno = IESETTOS;
        !          2792:                 return -1;
        !          2793:             }
        !          2794:         }
        !          2795:     }
        !          2796: 
        !          2797:     return 0;
        !          2798: }
        !          2799: 
        !          2800: /**************************************************************************/
        !          2801: void
        !          2802: iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp)
        !          2803: {
        !          2804:     int i;
        !          2805:     struct iperf_stream *n, *prev;
        !          2806: 
        !          2807:     if (SLIST_EMPTY(&test->streams)) {
        !          2808:         SLIST_INSERT_HEAD(&test->streams, sp, streams);
        !          2809:         sp->id = 1;
        !          2810:     } else {
        !          2811:         // for (n = test->streams, i = 2; n->next; n = n->next, ++i);
        !          2812:         i = 2;
        !          2813:         SLIST_FOREACH(n, &test->streams, streams) {
        !          2814:             prev = n;
        !          2815:             ++i;
        !          2816:         }
        !          2817:         SLIST_INSERT_AFTER(prev, sp, streams);
        !          2818:         sp->id = i;
        !          2819:     }
        !          2820: }
        !          2821: 
        !          2822: /* This pair of routines gets inserted into the snd/rcv function pointers
        !          2823: ** when there's a -F flag. They handle the file stuff and call the real
        !          2824: ** snd/rcv functions, which have been saved in snd2/rcv2.
        !          2825: **
        !          2826: ** The advantage of doing it this way is that in the much more common
        !          2827: ** case of no -F flag, there is zero extra overhead.
        !          2828: */
        !          2829: 
        !          2830: static int
        !          2831: diskfile_send(struct iperf_stream *sp)
        !          2832: {
        !          2833:     int r;
        !          2834: 
        !          2835:     r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize);
        !          2836:     if (r == 0)
        !          2837:         sp->test->done = 1;
        !          2838:     else
        !          2839:        r = sp->snd2(sp);
        !          2840:     return r;
        !          2841: }
        !          2842: 
        !          2843: static int
        !          2844: diskfile_recv(struct iperf_stream *sp)
        !          2845: {
        !          2846:     int r;
        !          2847: 
        !          2848:     r = sp->rcv2(sp);
        !          2849:     if (r > 0) {
        !          2850:        (void) write(sp->diskfile_fd, sp->buffer, r);
        !          2851:        (void) fsync(sp->diskfile_fd);
        !          2852:     }
        !          2853:     return r;
        !          2854: }
        !          2855: 
        !          2856: 
        !          2857: void
        !          2858: iperf_catch_sigend(void (*handler)(int))
        !          2859: {
        !          2860:     signal(SIGINT, handler);
        !          2861:     signal(SIGTERM, handler);
        !          2862:     signal(SIGHUP, handler);
        !          2863: }
        !          2864: 
        !          2865: /**
        !          2866:  * Called as a result of getting a signal.
        !          2867:  * Depending on the current state of the test (and the role of this
        !          2868:  * process) compute and report one more set of ending statistics
        !          2869:  * before cleaning up and exiting.
        !          2870:  */
        !          2871: void
        !          2872: iperf_got_sigend(struct iperf_test *test)
        !          2873: {
        !          2874:     /*
        !          2875:      * If we're the client, or if we're a server and running a test,
        !          2876:      * then dump out the accumulated stats so far.
        !          2877:      */
        !          2878:     if (test->role == 'c' ||
        !          2879:       (test->role == 's' && test->state == TEST_RUNNING)) {
        !          2880: 
        !          2881:        test->done = 1;
        !          2882:        cpu_util(test->cpu_util);
        !          2883:        test->stats_callback(test);
        !          2884:        test->state = DISPLAY_RESULTS; /* change local state only */
        !          2885:        if (test->on_test_finish)
        !          2886:            test->on_test_finish(test);
        !          2887:        test->reporter_callback(test);
        !          2888:     }
        !          2889: 
        !          2890:     if (test->ctrl_sck >= 0) {
        !          2891:        test->state = (test->role == 'c') ? CLIENT_TERMINATE : SERVER_TERMINATE;
        !          2892:        (void) Nwrite(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp);
        !          2893:     }
        !          2894:     i_errno = (test->role == 'c') ? IECLIENTTERM : IESERVERTERM;
        !          2895:     iperf_errexit(test, "interrupt - %s", iperf_strerror(i_errno));
        !          2896: }
        !          2897: 
        !          2898: /* Try to write a PID file if requested, return -1 on an error. */
        !          2899: int
        !          2900: iperf_create_pidfile(struct iperf_test *test)
        !          2901: {
        !          2902:     if (test->pidfile) {
        !          2903:        int fd;
        !          2904:        char buf[8];
        !          2905:        fd = open(test->pidfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR|S_IWUSR);
        !          2906:        if (fd < 0) {
        !          2907:            return -1;
        !          2908:        }
        !          2909:        snprintf(buf, sizeof(buf), "%d", getpid()); /* no trailing newline */
        !          2910:        if (write(fd, buf, strlen(buf) + 1) < 0) {
        !          2911:            return -1;
        !          2912:        }
        !          2913:        if (close(fd) < 0) {
        !          2914:            return -1;
        !          2915:        };
        !          2916:     }
        !          2917:     return 0;
        !          2918: }
        !          2919: 
        !          2920: /* Get rid of a PID file, return -1 on error. */
        !          2921: int
        !          2922: iperf_delete_pidfile(struct iperf_test *test)
        !          2923: {
        !          2924:     if (test->pidfile) {
        !          2925:        if (unlink(test->pidfile) < 0) {
        !          2926:            return -1;
        !          2927:        }
        !          2928:     }
        !          2929:     return 0;
        !          2930: }
        !          2931: 
        !          2932: int
        !          2933: iperf_json_start(struct iperf_test *test)
        !          2934: {
        !          2935:     test->json_top = cJSON_CreateObject();
        !          2936:     if (test->json_top == NULL)
        !          2937:         return -1;
        !          2938:     test->json_start = cJSON_CreateObject();
        !          2939:     if (test->json_start == NULL)
        !          2940:         return -1;
        !          2941:     cJSON_AddItemToObject(test->json_top, "start", test->json_start);
        !          2942:     test->json_connected = cJSON_CreateArray();
        !          2943:     if (test->json_connected == NULL)
        !          2944:         return -1;
        !          2945:     cJSON_AddItemToObject(test->json_start, "connected", test->json_connected);
        !          2946:     test->json_intervals = cJSON_CreateArray();
        !          2947:     if (test->json_intervals == NULL)
        !          2948:         return -1;
        !          2949:     cJSON_AddItemToObject(test->json_top, "intervals", test->json_intervals);
        !          2950:     test->json_end = cJSON_CreateObject();
        !          2951:     if (test->json_end == NULL)
        !          2952:         return -1;
        !          2953:     cJSON_AddItemToObject(test->json_top, "end", test->json_end);
        !          2954:     return 0;
        !          2955: }
        !          2956: 
        !          2957: int
        !          2958: iperf_json_finish(struct iperf_test *test)
        !          2959: {
        !          2960:     if (test->title)
        !          2961:        cJSON_AddStringToObject(test->json_top, "title", test->title);
        !          2962:     /* Include server output */
        !          2963:     if (test->json_server_output) {
        !          2964:        cJSON_AddItemToObject(test->json_top, "server_output_json", test->json_server_output);
        !          2965:     }
        !          2966:     if (test->server_output_text) {
        !          2967:        cJSON_AddStringToObject(test->json_top, "server_output_text", test->server_output_text);
        !          2968:     }
        !          2969:     test->json_output_string = cJSON_Print(test->json_top);
        !          2970:     if (test->json_output_string == NULL)
        !          2971:         return -1;
        !          2972:     fprintf(test->outfile, "%s\n", test->json_output_string);
        !          2973:     iflush(test);
        !          2974:     cJSON_Delete(test->json_top);
        !          2975:     test->json_top = test->json_start = test->json_connected = test->json_intervals = test->json_server_output = test->json_end = NULL;
        !          2976:     return 0;
        !          2977: }
        !          2978: 
        !          2979: 
        !          2980: /* CPU affinity stuff - Linux and FreeBSD only. */
        !          2981: 
        !          2982: int
        !          2983: iperf_setaffinity(struct iperf_test *test, int affinity)
        !          2984: {
        !          2985: #if defined(HAVE_SCHED_SETAFFINITY)
        !          2986:     cpu_set_t cpu_set;
        !          2987: 
        !          2988:     CPU_ZERO(&cpu_set);
        !          2989:     CPU_SET(affinity, &cpu_set);
        !          2990:     if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) {
        !          2991:        i_errno = IEAFFINITY;
        !          2992:         return -1;
        !          2993:     }
        !          2994:     return 0;
        !          2995: #elif defined(HAVE_CPUSET_SETAFFINITY)
        !          2996:     cpuset_t cpumask;
        !          2997: 
        !          2998:     if(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
        !          2999:                           sizeof(cpuset_t), &test->cpumask) != 0) {
        !          3000:         i_errno = IEAFFINITY;
        !          3001:         return -1;
        !          3002:     }
        !          3003: 
        !          3004:     CPU_ZERO(&cpumask);
        !          3005:     CPU_SET(affinity, &cpumask);
        !          3006: 
        !          3007:     if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1,
        !          3008:                           sizeof(cpuset_t), &cpumask) != 0) {
        !          3009:         i_errno = IEAFFINITY;
        !          3010:         return -1;
        !          3011:     }
        !          3012:     return 0;
        !          3013: #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */
        !          3014:     i_errno = IEAFFINITY;
        !          3015:     return -1;
        !          3016: #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */
        !          3017: }
        !          3018: 
        !          3019: int
        !          3020: iperf_clearaffinity(struct iperf_test *test)
        !          3021: {
        !          3022: #if defined(HAVE_SCHED_SETAFFINITY)
        !          3023:     cpu_set_t cpu_set;
        !          3024:     int i;
        !          3025: 
        !          3026:     CPU_ZERO(&cpu_set);
        !          3027:     for (i = 0; i < CPU_SETSIZE; ++i)
        !          3028:        CPU_SET(i, &cpu_set);
        !          3029:     if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) {
        !          3030:        i_errno = IEAFFINITY;
        !          3031:         return -1;
        !          3032:     }
        !          3033:     return 0;
        !          3034: #elif defined(HAVE_CPUSET_SETAFFINITY)
        !          3035:     if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1,
        !          3036:                           sizeof(cpuset_t), &test->cpumask) != 0) {
        !          3037:         i_errno = IEAFFINITY;
        !          3038:         return -1;
        !          3039:     }
        !          3040:     return 0;
        !          3041: #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */
        !          3042:     i_errno = IEAFFINITY;
        !          3043:     return -1;
        !          3044: #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */
        !          3045: }
        !          3046: 
        !          3047: int
        !          3048: iprintf(struct iperf_test *test, const char* format, ...)
        !          3049: {
        !          3050:     va_list argp;
        !          3051:     int r = -1;
        !          3052: 
        !          3053:     /*
        !          3054:      * There are roughly two use cases here.  If we're the client,
        !          3055:      * want to print stuff directly to the output stream.
        !          3056:      * If we're the sender we might need to buffer up output to send
        !          3057:      * to the client.
        !          3058:      *
        !          3059:      * This doesn't make a whole lot of difference except there are
        !          3060:      * some chunks of output on the client (on particular the whole
        !          3061:      * of the server output with --get-server-output) that could
        !          3062:      * easily exceed the size of the line buffer, but which don't need
        !          3063:      * to be buffered up anyway.
        !          3064:      */
        !          3065:     if (test->role == 'c') {
        !          3066:        if (test->title)
        !          3067:            fprintf(test->outfile, "%s:  ", test->title);
        !          3068:        va_start(argp, format);
        !          3069:        r = vfprintf(test->outfile, format, argp);
        !          3070:        va_end(argp);
        !          3071:     }
        !          3072:     else if (test->role == 's') {
        !          3073:        char linebuffer[1024];
        !          3074:        va_start(argp, format);
        !          3075:        r = vsnprintf(linebuffer, sizeof(linebuffer), format, argp);
        !          3076:        va_end(argp);
        !          3077:        fprintf(test->outfile, "%s", linebuffer);
        !          3078: 
        !          3079:        if (test->role == 's' && iperf_get_test_get_server_output(test)) {
        !          3080:            struct iperf_textline *l = (struct iperf_textline *) malloc(sizeof(struct iperf_textline));
        !          3081:            l->line = strdup(linebuffer);
        !          3082:            TAILQ_INSERT_TAIL(&(test->server_output_list), l, textlineentries);
        !          3083:        }
        !          3084:     }
        !          3085:     return r;
        !          3086: }
        !          3087: 
        !          3088: int
        !          3089: iflush(struct iperf_test *test)
        !          3090: {
        !          3091:     return fflush(test->outfile);
        !          3092: }

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