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