xref: /iperf/src/iperf_api.c (revision 081ba8e4)
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     if (test->debug) {
814 	printf("fubar\n");
815     }
816 
817     /* Set logging to a file if specified, otherwise use the default (stdout) */
818     if (test->logfile) {
819 	test->outfile = fopen(test->logfile, "a+");
820 	if (test->outfile == NULL) {
821 	    i_errno = IELOGFILE;
822 	    return -1;
823 	}
824     }
825 
826     /* Check flag / role compatibility. */
827     if (test->role == 'c' && server_flag) {
828 	i_errno = IESERVERONLY;
829 	return -1;
830     }
831     if (test->role == 's' && client_flag) {
832 	i_errno = IECLIENTONLY;
833 	return -1;
834     }
835 
836     if (blksize == 0) {
837 	if (test->protocol->id == Pudp)
838 	    blksize = DEFAULT_UDP_BLKSIZE;
839 	else if (test->protocol->id == Psctp)
840 	    blksize = DEFAULT_SCTP_BLKSIZE;
841 	else
842 	    blksize = DEFAULT_TCP_BLKSIZE;
843     }
844     if (blksize <= 0 || blksize > MAX_BLOCKSIZE) {
845 	i_errno = IEBLOCKSIZE;
846 	return -1;
847     }
848     test->settings->blksize = blksize;
849 
850     if (!rate_flag)
851 	test->settings->rate = test->protocol->id == Pudp ? UDP_RATE : 0;
852 
853     if ((test->settings->bytes != 0 || test->settings->blocks != 0) && ! duration_flag)
854         test->duration = 0;
855 
856     /* Disallow specifying multiple test end conditions. The code actually
857     ** works just fine without this prohibition. As soon as any one of the
858     ** three possible end conditions is met, the test ends. So this check
859     ** could be removed if desired.
860     */
861     if ((duration_flag && test->settings->bytes != 0) ||
862         (duration_flag && test->settings->blocks != 0) ||
863 	(test->settings->bytes != 0 && test->settings->blocks != 0)) {
864         i_errno = IEENDCONDITIONS;
865         return -1;
866     }
867 
868     /* For subsequent calls to getopt */
869 #ifdef __APPLE__
870     optreset = 1;
871 #endif
872     optind = 0;
873 
874     if ((test->role != 'c') && (test->role != 's')) {
875         i_errno = IENOROLE;
876         return -1;
877     }
878 
879     return 0;
880 }
881 
882 int
883 iperf_set_send_state(struct iperf_test *test, signed char state)
884 {
885     test->state = state;
886     if (Nwrite(test->ctrl_sck, (char*) &state, sizeof(state), Ptcp) < 0) {
887 	i_errno = IESENDMESSAGE;
888 	return -1;
889     }
890     return 0;
891 }
892 
893 void
894 iperf_check_throttle(struct iperf_stream *sp, struct timeval *nowP)
895 {
896     double seconds;
897     uint64_t bits_per_second;
898 
899     if (sp->test->done)
900         return;
901     seconds = timeval_diff(&sp->result->start_time, nowP);
902     bits_per_second = sp->result->bytes_sent * 8 / seconds;
903     if (bits_per_second < sp->test->settings->rate) {
904         sp->green_light = 1;
905         FD_SET(sp->socket, &sp->test->write_set);
906     } else {
907         sp->green_light = 0;
908         FD_CLR(sp->socket, &sp->test->write_set);
909     }
910 }
911 
912 int
913 iperf_send(struct iperf_test *test, fd_set *write_setP)
914 {
915     register int multisend, r;
916     register struct iperf_stream *sp;
917     struct timeval now;
918 
919     /* Can we do multisend mode? */
920     if (test->settings->burst != 0)
921         multisend = test->settings->burst;
922     else if (test->settings->rate == 0)
923         multisend = test->multisend;
924     else
925         multisend = 1;	/* nope */
926 
927     for (; multisend > 0; --multisend) {
928 	if (test->settings->rate != 0 && test->settings->burst == 0)
929 	    gettimeofday(&now, NULL);
930 	SLIST_FOREACH(sp, &test->streams, streams) {
931 	    if (sp->green_light &&
932 	        (write_setP == NULL || FD_ISSET(sp->socket, write_setP))) {
933 		if ((r = sp->snd(sp)) < 0) {
934 		    if (r == NET_SOFTERROR)
935 			break;
936 		    i_errno = IESTREAMWRITE;
937 		    return r;
938 		}
939 		test->bytes_sent += r;
940 		++test->blocks_sent;
941 		if (test->settings->rate != 0 && test->settings->burst == 0)
942 		    iperf_check_throttle(sp, &now);
943 		if (multisend > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes)
944 		    break;
945 		if (multisend > 1 && test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks)
946 		    break;
947 	    }
948 	}
949     }
950     if (test->settings->burst != 0) {
951 	gettimeofday(&now, NULL);
952 	SLIST_FOREACH(sp, &test->streams, streams)
953 	    iperf_check_throttle(sp, &now);
954     }
955     if (write_setP != NULL)
956 	SLIST_FOREACH(sp, &test->streams, streams)
957 	    if (FD_ISSET(sp->socket, write_setP))
958 		FD_CLR(sp->socket, write_setP);
959 
960     return 0;
961 }
962 
963 int
964 iperf_recv(struct iperf_test *test, fd_set *read_setP)
965 {
966     int r;
967     struct iperf_stream *sp;
968 
969     SLIST_FOREACH(sp, &test->streams, streams) {
970 	if (FD_ISSET(sp->socket, read_setP)) {
971 	    if ((r = sp->rcv(sp)) < 0) {
972 		i_errno = IESTREAMREAD;
973 		return r;
974 	    }
975 	    test->bytes_sent += r;
976 	    ++test->blocks_sent;
977 	    FD_CLR(sp->socket, read_setP);
978 	}
979     }
980 
981     return 0;
982 }
983 
984 int
985 iperf_init_test(struct iperf_test *test)
986 {
987     struct timeval now;
988     struct iperf_stream *sp;
989 
990     if (test->protocol->init) {
991         if (test->protocol->init(test) < 0)
992             return -1;
993     }
994 
995     /* Init each stream. */
996     if (gettimeofday(&now, NULL) < 0) {
997 	i_errno = IEINITTEST;
998 	return -1;
999     }
1000     SLIST_FOREACH(sp, &test->streams, streams) {
1001 	sp->result->start_time = now;
1002     }
1003 
1004     if (test->on_test_start)
1005         test->on_test_start(test);
1006 
1007     return 0;
1008 }
1009 
1010 static void
1011 send_timer_proc(TimerClientData client_data, struct timeval *nowP)
1012 {
1013     struct iperf_stream *sp = client_data.p;
1014 
1015     /* All we do here is set or clear the flag saying that this stream may
1016     ** be sent to.  The actual sending gets done in the send proc, after
1017     ** checking the flag.
1018     */
1019     iperf_check_throttle(sp, nowP);
1020 }
1021 
1022 int
1023 iperf_create_send_timers(struct iperf_test * test)
1024 {
1025     struct timeval now;
1026     struct iperf_stream *sp;
1027     TimerClientData cd;
1028 
1029     if (gettimeofday(&now, NULL) < 0) {
1030 	i_errno = IEINITTEST;
1031 	return -1;
1032     }
1033     SLIST_FOREACH(sp, &test->streams, streams) {
1034         sp->green_light = 1;
1035 	if (test->settings->rate != 0) {
1036 	    cd.p = sp;
1037 	    sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, 100000L, 1);
1038 	    /* (Repeat every tenth second - arbitrary often value.) */
1039 	    if (sp->send_timer == NULL) {
1040 		i_errno = IEINITTEST;
1041 		return -1;
1042 	    }
1043 	}
1044     }
1045     return 0;
1046 }
1047 
1048 /**
1049  * iperf_exchange_parameters - handles the param_Exchange part for client
1050  *
1051  */
1052 
1053 int
1054 iperf_exchange_parameters(struct iperf_test *test)
1055 {
1056     int s;
1057     int32_t err;
1058 
1059     if (test->role == 'c') {
1060 
1061         if (send_parameters(test) < 0)
1062             return -1;
1063 
1064     } else {
1065 
1066         if (get_parameters(test) < 0)
1067             return -1;
1068 
1069         if ((s = test->protocol->listen(test)) < 0) {
1070 	    if (iperf_set_send_state(test, SERVER_ERROR) != 0)
1071                 return -1;
1072             err = htonl(i_errno);
1073             if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
1074                 i_errno = IECTRLWRITE;
1075                 return -1;
1076             }
1077             err = htonl(errno);
1078             if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
1079                 i_errno = IECTRLWRITE;
1080                 return -1;
1081             }
1082             return -1;
1083         }
1084         FD_SET(s, &test->read_set);
1085         test->max_fd = (s > test->max_fd) ? s : test->max_fd;
1086         test->prot_listener = s;
1087 
1088         // Send the control message to create streams and start the test
1089 	if (iperf_set_send_state(test, CREATE_STREAMS) != 0)
1090             return -1;
1091 
1092     }
1093 
1094     return 0;
1095 }
1096 
1097 /*************************************************************/
1098 
1099 int
1100 iperf_exchange_results(struct iperf_test *test)
1101 {
1102     if (test->role == 'c') {
1103         /* Send results to server. */
1104 	if (send_results(test) < 0)
1105             return -1;
1106         /* Get server results. */
1107         if (get_results(test) < 0)
1108             return -1;
1109     } else {
1110         /* Get client results. */
1111         if (get_results(test) < 0)
1112             return -1;
1113         /* Send results to client. */
1114 	if (send_results(test) < 0)
1115             return -1;
1116     }
1117     return 0;
1118 }
1119 
1120 /*************************************************************/
1121 
1122 static int
1123 send_parameters(struct iperf_test *test)
1124 {
1125     int r = 0;
1126     cJSON *j;
1127 
1128     j = cJSON_CreateObject();
1129     if (j == NULL) {
1130 	i_errno = IESENDPARAMS;
1131 	r = -1;
1132     } else {
1133 	if (test->protocol->id == Ptcp)
1134 	    cJSON_AddTrueToObject(j, "tcp");
1135 	else if (test->protocol->id == Pudp)
1136 	    cJSON_AddTrueToObject(j, "udp");
1137         else if (test->protocol->id == Psctp)
1138             cJSON_AddTrueToObject(j, "sctp");
1139 	cJSON_AddIntToObject(j, "omit", test->omit);
1140 	if (test->server_affinity != -1)
1141 	    cJSON_AddIntToObject(j, "server_affinity", test->server_affinity);
1142 	if (test->duration)
1143 	    cJSON_AddIntToObject(j, "time", test->duration);
1144 	if (test->settings->bytes)
1145 	    cJSON_AddIntToObject(j, "num", test->settings->bytes);
1146 	if (test->settings->blocks)
1147 	    cJSON_AddIntToObject(j, "blockcount", test->settings->blocks);
1148 	if (test->settings->mss)
1149 	    cJSON_AddIntToObject(j, "MSS", test->settings->mss);
1150 	if (test->no_delay)
1151 	    cJSON_AddTrueToObject(j, "nodelay");
1152 	cJSON_AddIntToObject(j, "parallel", test->num_streams);
1153 	if (test->reverse)
1154 	    cJSON_AddTrueToObject(j, "reverse");
1155 	if (test->settings->socket_bufsize)
1156 	    cJSON_AddIntToObject(j, "window", test->settings->socket_bufsize);
1157 	if (test->settings->blksize)
1158 	    cJSON_AddIntToObject(j, "len", test->settings->blksize);
1159 	if (test->settings->rate)
1160 	    cJSON_AddIntToObject(j, "bandwidth", test->settings->rate);
1161 	if (test->settings->burst)
1162 	    cJSON_AddIntToObject(j, "burst", test->settings->burst);
1163 	if (test->settings->tos)
1164 	    cJSON_AddIntToObject(j, "TOS", test->settings->tos);
1165 	if (test->settings->flowlabel)
1166 	    cJSON_AddIntToObject(j, "flowlabel", test->settings->flowlabel);
1167 	if (test->title)
1168 	    cJSON_AddStringToObject(j, "title", test->title);
1169 	if (test->congestion)
1170 	    cJSON_AddStringToObject(j, "congestion", test->congestion);
1171 	if (JSON_write(test->ctrl_sck, j) < 0) {
1172 	    i_errno = IESENDPARAMS;
1173 	    r = -1;
1174 	}
1175 	cJSON_Delete(j);
1176     }
1177     return r;
1178 }
1179 
1180 /*************************************************************/
1181 
1182 static int
1183 get_parameters(struct iperf_test *test)
1184 {
1185     int r = 0;
1186     cJSON *j;
1187     cJSON *j_p;
1188 
1189     j = JSON_read(test->ctrl_sck);
1190     if (j == NULL) {
1191 	i_errno = IERECVPARAMS;
1192         r = -1;
1193     } else {
1194 	if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL)
1195 	    set_protocol(test, Ptcp);
1196 	if ((j_p = cJSON_GetObjectItem(j, "udp")) != NULL)
1197 	    set_protocol(test, Pudp);
1198         if ((j_p = cJSON_GetObjectItem(j, "sctp")) != NULL)
1199             set_protocol(test, Psctp);
1200 	if ((j_p = cJSON_GetObjectItem(j, "omit")) != NULL)
1201 	    test->omit = j_p->valueint;
1202 	if ((j_p = cJSON_GetObjectItem(j, "server_affinity")) != NULL)
1203 	    test->server_affinity = j_p->valueint;
1204 	if ((j_p = cJSON_GetObjectItem(j, "time")) != NULL)
1205 	    test->duration = j_p->valueint;
1206 	if ((j_p = cJSON_GetObjectItem(j, "num")) != NULL)
1207 	    test->settings->bytes = j_p->valueint;
1208 	if ((j_p = cJSON_GetObjectItem(j, "blockcount")) != NULL)
1209 	    test->settings->blocks = j_p->valueint;
1210 	if ((j_p = cJSON_GetObjectItem(j, "MSS")) != NULL)
1211 	    test->settings->mss = j_p->valueint;
1212 	if ((j_p = cJSON_GetObjectItem(j, "nodelay")) != NULL)
1213 	    test->no_delay = 1;
1214 	if ((j_p = cJSON_GetObjectItem(j, "parallel")) != NULL)
1215 	    test->num_streams = j_p->valueint;
1216 	if ((j_p = cJSON_GetObjectItem(j, "reverse")) != NULL)
1217 	    iperf_set_test_reverse(test, 1);
1218 	if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL)
1219 	    test->settings->socket_bufsize = j_p->valueint;
1220 	if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL)
1221 	    test->settings->blksize = j_p->valueint;
1222 	if ((j_p = cJSON_GetObjectItem(j, "bandwidth")) != NULL)
1223 	    test->settings->rate = j_p->valueint;
1224 	if ((j_p = cJSON_GetObjectItem(j, "burst")) != NULL)
1225 	    test->settings->burst = j_p->valueint;
1226 	if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL)
1227 	    test->settings->tos = j_p->valueint;
1228 	if ((j_p = cJSON_GetObjectItem(j, "flowlabel")) != NULL)
1229 	    test->settings->flowlabel = j_p->valueint;
1230 	if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL)
1231 	    test->title = strdup(j_p->valuestring);
1232 	if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL)
1233 	    test->congestion = strdup(j_p->valuestring);
1234 	if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits())
1235 	    test->sender_has_retransmits = 1;
1236 	cJSON_Delete(j);
1237     }
1238     return r;
1239 }
1240 
1241 /*************************************************************/
1242 
1243 static int
1244 send_results(struct iperf_test *test)
1245 {
1246     int r = 0;
1247     cJSON *j;
1248     cJSON *j_streams;
1249     struct iperf_stream *sp;
1250     cJSON *j_stream;
1251     int sender_has_retransmits;
1252     iperf_size_t bytes_transferred;
1253     int retransmits;
1254 
1255     j = cJSON_CreateObject();
1256     if (j == NULL) {
1257 	i_errno = IEPACKAGERESULTS;
1258 	r = -1;
1259     } else {
1260 	cJSON_AddFloatToObject(j, "cpu_util_total", test->cpu_util[0]);
1261 	cJSON_AddFloatToObject(j, "cpu_util_user", test->cpu_util[1]);
1262 	cJSON_AddFloatToObject(j, "cpu_util_system", test->cpu_util[2]);
1263 	if ( ! test->sender )
1264 	    sender_has_retransmits = -1;
1265 	else
1266 	    sender_has_retransmits = test->sender_has_retransmits;
1267 	cJSON_AddIntToObject(j, "sender_has_retransmits", sender_has_retransmits);
1268 	j_streams = cJSON_CreateArray();
1269 	if (j_streams == NULL) {
1270 	    i_errno = IEPACKAGERESULTS;
1271 	    r = -1;
1272 	} else {
1273 	    cJSON_AddItemToObject(j, "streams", j_streams);
1274 	    SLIST_FOREACH(sp, &test->streams, streams) {
1275 		j_stream = cJSON_CreateObject();
1276 		if (j_stream == NULL) {
1277 		    i_errno = IEPACKAGERESULTS;
1278 		    r = -1;
1279 		} else {
1280 		    cJSON_AddItemToArray(j_streams, j_stream);
1281 		    bytes_transferred = test->sender ? sp->result->bytes_sent : sp->result->bytes_received;
1282 		    retransmits = (test->sender && test->sender_has_retransmits) ? sp->result->stream_retrans : -1;
1283 		    cJSON_AddIntToObject(j_stream, "id", sp->id);
1284 		    cJSON_AddIntToObject(j_stream, "bytes", bytes_transferred);
1285 		    cJSON_AddIntToObject(j_stream, "retransmits", retransmits);
1286 		    cJSON_AddFloatToObject(j_stream, "jitter", sp->jitter);
1287 		    cJSON_AddIntToObject(j_stream, "errors", sp->cnt_error);
1288 		    cJSON_AddIntToObject(j_stream, "packets", sp->packet_count);
1289 		}
1290 	    }
1291 	    if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) {
1292 		i_errno = IESENDRESULTS;
1293 		r = -1;
1294 	    }
1295 	}
1296 	cJSON_Delete(j);
1297     }
1298     return r;
1299 }
1300 
1301 /*************************************************************/
1302 
1303 static int
1304 get_results(struct iperf_test *test)
1305 {
1306     int r = 0;
1307     cJSON *j;
1308     cJSON *j_cpu_util_total;
1309     cJSON *j_cpu_util_user;
1310     cJSON *j_cpu_util_system;
1311     cJSON *j_sender_has_retransmits;
1312     int result_has_retransmits;
1313     cJSON *j_streams;
1314     int n, i;
1315     cJSON *j_stream;
1316     cJSON *j_id;
1317     cJSON *j_bytes;
1318     cJSON *j_retransmits;
1319     cJSON *j_jitter;
1320     cJSON *j_errors;
1321     cJSON *j_packets;
1322     int sid, cerror, pcount;
1323     double jitter;
1324     iperf_size_t bytes_transferred;
1325     int retransmits;
1326     struct iperf_stream *sp;
1327 
1328     j = JSON_read(test->ctrl_sck);
1329     if (j == NULL) {
1330 	i_errno = IERECVRESULTS;
1331         r = -1;
1332     } else {
1333 	j_cpu_util_total = cJSON_GetObjectItem(j, "cpu_util_total");
1334 	j_cpu_util_user = cJSON_GetObjectItem(j, "cpu_util_user");
1335 	j_cpu_util_system = cJSON_GetObjectItem(j, "cpu_util_system");
1336 	j_sender_has_retransmits = cJSON_GetObjectItem(j, "sender_has_retransmits");
1337 	if (j_cpu_util_total == NULL || j_cpu_util_user == NULL || j_cpu_util_system == NULL || j_sender_has_retransmits == NULL) {
1338 	    i_errno = IERECVRESULTS;
1339 	    r = -1;
1340 	} else {
1341 	    test->remote_cpu_util[0] = j_cpu_util_total->valuefloat;
1342 	    test->remote_cpu_util[1] = j_cpu_util_user->valuefloat;
1343 	    test->remote_cpu_util[2] = j_cpu_util_system->valuefloat;
1344 	    result_has_retransmits = j_sender_has_retransmits->valueint;
1345 	    if (! test->sender)
1346 		test->sender_has_retransmits = result_has_retransmits;
1347 	    j_streams = cJSON_GetObjectItem(j, "streams");
1348 	    if (j_streams == NULL) {
1349 		i_errno = IERECVRESULTS;
1350 		r = -1;
1351 	    } else {
1352 	        n = cJSON_GetArraySize(j_streams);
1353 		for (i=0; i<n; ++i) {
1354 		    j_stream = cJSON_GetArrayItem(j_streams, i);
1355 		    if (j_stream == NULL) {
1356 			i_errno = IERECVRESULTS;
1357 			r = -1;
1358 		    } else {
1359 			j_id = cJSON_GetObjectItem(j_stream, "id");
1360 			j_bytes = cJSON_GetObjectItem(j_stream, "bytes");
1361 			j_retransmits = cJSON_GetObjectItem(j_stream, "retransmits");
1362 			j_jitter = cJSON_GetObjectItem(j_stream, "jitter");
1363 			j_errors = cJSON_GetObjectItem(j_stream, "errors");
1364 			j_packets = cJSON_GetObjectItem(j_stream, "packets");
1365 			if (j_id == NULL || j_bytes == NULL || j_retransmits == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) {
1366 			    i_errno = IERECVRESULTS;
1367 			    r = -1;
1368 			} else {
1369 			    sid = j_id->valueint;
1370 			    bytes_transferred = j_bytes->valueint;
1371 			    retransmits = j_retransmits->valueint;
1372 			    jitter = j_jitter->valuefloat;
1373 			    cerror = j_errors->valueint;
1374 			    pcount = j_packets->valueint;
1375 			    SLIST_FOREACH(sp, &test->streams, streams)
1376 				if (sp->id == sid) break;
1377 			    if (sp == NULL) {
1378 				i_errno = IESTREAMID;
1379 				r = -1;
1380 			    } else {
1381 				if (test->sender) {
1382 				    sp->jitter = jitter;
1383 				    sp->cnt_error = cerror;
1384 				    sp->packet_count = pcount;
1385 				    sp->result->bytes_received = bytes_transferred;
1386 				} else {
1387 				    sp->result->bytes_sent = bytes_transferred;
1388 				    sp->result->stream_retrans = retransmits;
1389 				}
1390 			    }
1391 			}
1392 		    }
1393 		}
1394 	    }
1395 	}
1396 	cJSON_Delete(j);
1397     }
1398     return r;
1399 }
1400 
1401 /*************************************************************/
1402 
1403 static int
1404 JSON_write(int fd, cJSON *json)
1405 {
1406     uint32_t hsize, nsize;
1407     char *str;
1408     int r = 0;
1409 
1410     str = cJSON_PrintUnformatted(json);
1411     if (str == NULL)
1412 	r = -1;
1413     else {
1414 	hsize = strlen(str);
1415 	nsize = htonl(hsize);
1416 	if (Nwrite(fd, (char*) &nsize, sizeof(nsize), Ptcp) < 0)
1417 	    r = -1;
1418 	else {
1419 	    if (Nwrite(fd, str, hsize, Ptcp) < 0)
1420 		r = -1;
1421 	}
1422 	free(str);
1423     }
1424     return r;
1425 }
1426 
1427 /*************************************************************/
1428 
1429 static cJSON *
1430 JSON_read(int fd)
1431 {
1432     uint32_t hsize, nsize;
1433     char *str;
1434     cJSON *json = NULL;
1435 
1436     if (Nread(fd, (char*) &nsize, sizeof(nsize), Ptcp) >= 0) {
1437 	hsize = ntohl(nsize);
1438 	str = (char *) malloc(hsize+1);	/* +1 for EOS */
1439 	if (str != NULL) {
1440 	    if (Nread(fd, str, hsize, Ptcp) >= 0) {
1441 		str[hsize] = '\0';	/* add the EOS */
1442 		json = cJSON_Parse(str);
1443 	    }
1444 	}
1445 	free(str);
1446     }
1447     return json;
1448 }
1449 
1450 /*************************************************************/
1451 /**
1452  * add_to_interval_list -- adds new interval to the interval_list
1453  */
1454 
1455 void
1456 add_to_interval_list(struct iperf_stream_result * rp, struct iperf_interval_results * new)
1457 {
1458     struct iperf_interval_results *irp;
1459 
1460     irp = (struct iperf_interval_results *) malloc(sizeof(struct iperf_interval_results));
1461     memcpy(irp, new, sizeof(struct iperf_interval_results));
1462     TAILQ_INSERT_TAIL(&rp->interval_results, irp, irlistentries);
1463 }
1464 
1465 
1466 /************************************************************/
1467 
1468 /**
1469  * connect_msg -- displays connection message
1470  * denoting sender/receiver details
1471  *
1472  */
1473 
1474 void
1475 connect_msg(struct iperf_stream *sp)
1476 {
1477     char ipl[INET6_ADDRSTRLEN], ipr[INET6_ADDRSTRLEN];
1478     int lport, rport;
1479 
1480     if (getsockdomain(sp->socket) == AF_INET) {
1481         inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->local_addr)->sin_addr, ipl, sizeof(ipl));
1482 	mapped_v4_to_regular_v4(ipl);
1483         inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->remote_addr)->sin_addr, ipr, sizeof(ipr));
1484 	mapped_v4_to_regular_v4(ipr);
1485         lport = ntohs(((struct sockaddr_in *) &sp->local_addr)->sin_port);
1486         rport = ntohs(((struct sockaddr_in *) &sp->remote_addr)->sin_port);
1487     } else {
1488         inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->local_addr)->sin6_addr, ipl, sizeof(ipl));
1489 	mapped_v4_to_regular_v4(ipl);
1490         inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->remote_addr)->sin6_addr, ipr, sizeof(ipr));
1491 	mapped_v4_to_regular_v4(ipr);
1492         lport = ntohs(((struct sockaddr_in6 *) &sp->local_addr)->sin6_port);
1493         rport = ntohs(((struct sockaddr_in6 *) &sp->remote_addr)->sin6_port);
1494     }
1495 
1496     if (sp->test->json_output)
1497         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));
1498     else
1499 	iprintf(sp->test, report_connected, sp->socket, ipl, lport, ipr, rport);
1500 }
1501 
1502 
1503 /**************************************************************************/
1504 
1505 struct iperf_test *
1506 iperf_new_test()
1507 {
1508     struct iperf_test *test;
1509 
1510     test = (struct iperf_test *) malloc(sizeof(struct iperf_test));
1511     if (!test) {
1512         i_errno = IENEWTEST;
1513         return NULL;
1514     }
1515     /* initialize everything to zero */
1516     memset(test, 0, sizeof(struct iperf_test));
1517 
1518     test->settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings));
1519     if (!test->settings) {
1520         free(test);
1521 	i_errno = IENEWTEST;
1522 	return NULL;
1523     }
1524     memset(test->settings, 0, sizeof(struct iperf_settings));
1525 
1526     /* By default all output goes to stdout */
1527     test->outfile = stdout;
1528 
1529     return test;
1530 }
1531 
1532 /**************************************************************************/
1533 
1534 struct protocol *
1535 protocol_new(void)
1536 {
1537     struct protocol *proto;
1538 
1539     proto = malloc(sizeof(struct protocol));
1540     if(!proto) {
1541         return NULL;
1542     }
1543     memset(proto, 0, sizeof(struct protocol));
1544 
1545     return proto;
1546 }
1547 
1548 void
1549 protocol_free(struct protocol *proto)
1550 {
1551     free(proto);
1552 }
1553 
1554 /**************************************************************************/
1555 int
1556 iperf_defaults(struct iperf_test *testp)
1557 {
1558     struct protocol *tcp, *udp;
1559 #if defined(HAVE_SCTP)
1560     struct protocol *sctp;
1561 #endif /* HAVE_SCTP */
1562 
1563     testp->omit = OMIT;
1564     testp->duration = DURATION;
1565     testp->diskfile_name = (char*) 0;
1566     testp->affinity = -1;
1567     testp->server_affinity = -1;
1568 #if defined(HAVE_CPUSET_SETAFFINITY)
1569     CPU_ZERO(&testp->cpumask);
1570 #endif /* HAVE_CPUSET_SETAFFINITY */
1571     testp->title = NULL;
1572     testp->congestion = NULL;
1573     testp->server_port = PORT;
1574     testp->ctrl_sck = -1;
1575     testp->prot_listener = -1;
1576 
1577     testp->stats_callback = iperf_stats_callback;
1578     testp->reporter_callback = iperf_reporter_callback;
1579 
1580     testp->stats_interval = testp->reporter_interval = 1;
1581     testp->num_streams = 1;
1582 
1583     testp->settings->domain = AF_UNSPEC;
1584     testp->settings->unit_format = 'a';
1585     testp->settings->socket_bufsize = 0;    /* use autotuning */
1586     testp->settings->blksize = DEFAULT_TCP_BLKSIZE;
1587     testp->settings->rate = 0;
1588     testp->settings->burst = 0;
1589     testp->settings->mss = 0;
1590     testp->settings->bytes = 0;
1591     testp->settings->blocks = 0;
1592     memset(testp->cookie, 0, COOKIE_SIZE);
1593 
1594     testp->multisend = 10;	/* arbitrary */
1595 
1596     /* Set up protocol list */
1597     SLIST_INIT(&testp->streams);
1598     SLIST_INIT(&testp->protocols);
1599 
1600     tcp = protocol_new();
1601     if (!tcp)
1602         return -1;
1603 
1604     tcp->id = Ptcp;
1605     tcp->name = "TCP";
1606     tcp->accept = iperf_tcp_accept;
1607     tcp->listen = iperf_tcp_listen;
1608     tcp->connect = iperf_tcp_connect;
1609     tcp->send = iperf_tcp_send;
1610     tcp->recv = iperf_tcp_recv;
1611     tcp->init = NULL;
1612     SLIST_INSERT_HEAD(&testp->protocols, tcp, protocols);
1613 
1614     udp = protocol_new();
1615     if (!udp) {
1616         protocol_free(tcp);
1617         return -1;
1618     }
1619 
1620     udp->id = Pudp;
1621     udp->name = "UDP";
1622     udp->accept = iperf_udp_accept;
1623     udp->listen = iperf_udp_listen;
1624     udp->connect = iperf_udp_connect;
1625     udp->send = iperf_udp_send;
1626     udp->recv = iperf_udp_recv;
1627     udp->init = iperf_udp_init;
1628     SLIST_INSERT_AFTER(tcp, udp, protocols);
1629 
1630     set_protocol(testp, Ptcp);
1631 
1632 #if defined(HAVE_SCTP)
1633     sctp = protocol_new();
1634     if (!sctp) {
1635         protocol_free(tcp);
1636         protocol_free(udp);
1637         return -1;
1638     }
1639 
1640     sctp->id = Psctp;
1641     sctp->name = "SCTP";
1642     sctp->accept = iperf_sctp_accept;
1643     sctp->listen = iperf_sctp_listen;
1644     sctp->connect = iperf_sctp_connect;
1645     sctp->send = iperf_sctp_send;
1646     sctp->recv = iperf_sctp_recv;
1647     sctp->init = iperf_sctp_init;
1648 
1649     SLIST_INSERT_AFTER(udp, sctp, protocols);
1650 #endif /* HAVE_SCTP */
1651 
1652     testp->on_new_stream = iperf_on_new_stream;
1653     testp->on_test_start = iperf_on_test_start;
1654     testp->on_connect = iperf_on_connect;
1655     testp->on_test_finish = iperf_on_test_finish;
1656 
1657     return 0;
1658 }
1659 
1660 
1661 /**************************************************************************/
1662 void
1663 iperf_free_test(struct iperf_test *test)
1664 {
1665     struct protocol *prot;
1666     struct iperf_stream *sp;
1667 
1668     /* Free streams */
1669     while (!SLIST_EMPTY(&test->streams)) {
1670         sp = SLIST_FIRST(&test->streams);
1671         SLIST_REMOVE_HEAD(&test->streams, streams);
1672         iperf_free_stream(sp);
1673     }
1674 
1675     if (test->server_hostname)
1676 	free(test->server_hostname);
1677     if (test->bind_address)
1678 	free(test->bind_address);
1679     free(test->settings);
1680     if (test->title)
1681 	free(test->title);
1682     if (test->congestion)
1683 	free(test->congestion);
1684     if (test->omit_timer != NULL)
1685 	tmr_cancel(test->omit_timer);
1686     if (test->timer != NULL)
1687 	tmr_cancel(test->timer);
1688     if (test->stats_timer != NULL)
1689 	tmr_cancel(test->stats_timer);
1690     if (test->reporter_timer != NULL)
1691 	tmr_cancel(test->reporter_timer);
1692 
1693     /* Free protocol list */
1694     while (!SLIST_EMPTY(&test->protocols)) {
1695         prot = SLIST_FIRST(&test->protocols);
1696         SLIST_REMOVE_HEAD(&test->protocols, protocols);
1697         free(prot);
1698     }
1699 
1700     if (test->json_output_string) {
1701 	free(test->json_output_string);
1702 	test->json_output_string = NULL;
1703     }
1704 
1705     /* XXX: Why are we setting these values to NULL? */
1706     // test->streams = NULL;
1707     test->stats_callback = NULL;
1708     test->reporter_callback = NULL;
1709     free(test);
1710 }
1711 
1712 
1713 void
1714 iperf_reset_test(struct iperf_test *test)
1715 {
1716     struct iperf_stream *sp;
1717 
1718     /* Free streams */
1719     while (!SLIST_EMPTY(&test->streams)) {
1720         sp = SLIST_FIRST(&test->streams);
1721         SLIST_REMOVE_HEAD(&test->streams, streams);
1722         iperf_free_stream(sp);
1723     }
1724     if (test->omit_timer != NULL) {
1725 	tmr_cancel(test->omit_timer);
1726 	test->omit_timer = NULL;
1727     }
1728     if (test->timer != NULL) {
1729 	tmr_cancel(test->timer);
1730 	test->timer = NULL;
1731     }
1732     if (test->stats_timer != NULL) {
1733 	tmr_cancel(test->stats_timer);
1734 	test->stats_timer = NULL;
1735     }
1736     if (test->reporter_timer != NULL) {
1737 	tmr_cancel(test->reporter_timer);
1738 	test->reporter_timer = NULL;
1739     }
1740     test->done = 0;
1741 
1742     SLIST_INIT(&test->streams);
1743 
1744     test->role = 's';
1745     test->sender = 0;
1746     test->sender_has_retransmits = 0;
1747     set_protocol(test, Ptcp);
1748     test->omit = OMIT;
1749     test->duration = DURATION;
1750     test->server_affinity = -1;
1751 #if defined(HAVE_CPUSET_SETAFFINITY)
1752     CPU_ZERO(&test->cpumask);
1753 #endif /* HAVE_CPUSET_SETAFFINITY */
1754     test->state = 0;
1755 
1756     if(test->title) {
1757         free(test->title);
1758         test->title = NULL;
1759     }
1760     if(test->server_hostname) {
1761         free(test->server_hostname);
1762         test->server_hostname = NULL;
1763     }
1764     if(test->bind_address) {
1765         free(test->bind_address);
1766         test->bind_address = NULL;
1767     }
1768     if(test->congestion) {
1769         free(test->congestion);
1770         test->congestion = NULL;
1771     }
1772 
1773     test->ctrl_sck = -1;
1774     test->prot_listener = -1;
1775 
1776     test->bytes_sent = 0;
1777     test->blocks_sent = 0;
1778 
1779     test->reverse = 0;
1780     test->no_delay = 0;
1781 
1782     FD_ZERO(&test->read_set);
1783     FD_ZERO(&test->write_set);
1784 
1785     test->num_streams = 1;
1786     test->settings->socket_bufsize = 0;
1787     test->settings->blksize = DEFAULT_TCP_BLKSIZE;
1788     test->settings->rate = 0;
1789     test->settings->burst = 0;
1790     test->settings->mss = 0;
1791     memset(test->cookie, 0, COOKIE_SIZE);
1792     test->multisend = 10;	/* arbitrary */
1793 }
1794 
1795 
1796 /* Reset all of a test's stats back to zero.  Called when the omitting
1797 ** period is over.
1798 */
1799 void
1800 iperf_reset_stats(struct iperf_test *test)
1801 {
1802     struct timeval now;
1803     struct iperf_stream *sp;
1804     struct iperf_stream_result *rp;
1805 
1806     test->bytes_sent = 0;
1807     test->blocks_sent = 0;
1808     gettimeofday(&now, NULL);
1809     SLIST_FOREACH(sp, &test->streams, streams) {
1810 	sp->omitted_packet_count = sp->packet_count;
1811 	sp->jitter = 0;
1812 	sp->outoforder_packets = 0;
1813 	sp->cnt_error = 0;
1814 	rp = sp->result;
1815         rp->bytes_sent = rp->bytes_received = 0;
1816         rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
1817 	if (test->sender && test->sender_has_retransmits) {
1818 	    struct iperf_interval_results ir; /* temporary results structure */
1819 	    save_tcpinfo(sp, &ir);
1820 	    rp->stream_prev_total_retrans = get_total_retransmits(&ir);
1821 	}
1822 	rp->stream_retrans = 0;
1823 	rp->start_time = now;
1824     }
1825 }
1826 
1827 
1828 /**************************************************************************/
1829 
1830 /**
1831  * iperf_stats_callback -- handles the statistic gathering for both the client and server
1832  *
1833  * XXX: This function needs to be updated to reflect the new code
1834  */
1835 
1836 
1837 void
1838 iperf_stats_callback(struct iperf_test *test)
1839 {
1840     struct iperf_stream *sp;
1841     struct iperf_stream_result *rp = NULL;
1842     struct iperf_interval_results *irp, temp;
1843 
1844     temp.omitted = test->omitting;
1845     SLIST_FOREACH(sp, &test->streams, streams) {
1846         rp = sp->result;
1847 
1848 	temp.bytes_transferred = test->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval;
1849 
1850 	irp = TAILQ_LAST(&rp->interval_results, irlisthead);
1851         /* result->end_time contains timestamp of previous interval */
1852         if ( irp != NULL ) /* not the 1st interval */
1853             memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct timeval));
1854         else /* or use timestamp from beginning */
1855             memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct timeval));
1856         /* now save time of end of this interval */
1857         gettimeofday(&rp->end_time, NULL);
1858         memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct timeval));
1859         temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
1860         //temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
1861 	if (test->protocol->id == Ptcp) {
1862 	    if ( has_tcpinfo()) {
1863 		save_tcpinfo(sp, &temp);
1864 		if (test->sender && test->sender_has_retransmits) {
1865 		    long total_retrans = get_total_retransmits(&temp);
1866 		    temp.interval_retrans = total_retrans - rp->stream_prev_total_retrans;
1867 		    rp->stream_retrans += temp.interval_retrans;
1868 		    rp->stream_prev_total_retrans = total_retrans;
1869 
1870 		    temp.snd_cwnd = get_snd_cwnd(&temp);
1871 		}
1872 	    }
1873 	} else {
1874 	    if (irp == NULL) {
1875 		temp.interval_packet_count = sp->packet_count;
1876 		temp.interval_outoforder_packets = sp->outoforder_packets;
1877 		temp.interval_cnt_error = sp->cnt_error;
1878 	    } else {
1879 		temp.interval_packet_count = sp->packet_count - irp->packet_count;
1880 		temp.interval_outoforder_packets = sp->outoforder_packets - irp->outoforder_packets;
1881 		temp.interval_cnt_error = sp->cnt_error - irp->cnt_error;
1882 	    }
1883 	    temp.packet_count = sp->packet_count;
1884 	    temp.jitter = sp->jitter;
1885 	    temp.outoforder_packets = sp->outoforder_packets;
1886 	    temp.cnt_error = sp->cnt_error;
1887 	}
1888         add_to_interval_list(rp, &temp);
1889         rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
1890     }
1891 }
1892 
1893 static void
1894 iperf_print_intermediate(struct iperf_test *test)
1895 {
1896     char ubuf[UNIT_LEN];
1897     char nbuf[UNIT_LEN];
1898     struct iperf_stream *sp = NULL;
1899     struct iperf_interval_results *irp;
1900     iperf_size_t bytes = 0;
1901     double bandwidth;
1902     int retransmits = 0;
1903     double start_time, end_time;
1904     cJSON *json_interval;
1905     cJSON *json_interval_streams;
1906     int total_packets = 0, lost_packets = 0;
1907     double avg_jitter = 0.0, lost_percent;
1908 
1909     if (test->json_output) {
1910         json_interval = cJSON_CreateObject();
1911 	if (json_interval == NULL)
1912 	    return;
1913 	cJSON_AddItemToArray(test->json_intervals, json_interval);
1914         json_interval_streams = cJSON_CreateArray();
1915 	if (json_interval_streams == NULL)
1916 	    return;
1917 	cJSON_AddItemToObject(json_interval, "streams", json_interval_streams);
1918     } else {
1919         json_interval = NULL;
1920         json_interval_streams = NULL;
1921     }
1922 
1923     SLIST_FOREACH(sp, &test->streams, streams) {
1924         print_interval_results(test, sp, json_interval_streams);
1925 	/* sum up all streams */
1926 	irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
1927 	if (irp == NULL) {
1928 	    iperf_err(test, "iperf_print_intermediate error: interval_results is NULL");
1929 	    return;
1930 	}
1931         bytes += irp->bytes_transferred;
1932 	if (test->protocol->id == Ptcp) {
1933 	    if (test->sender && test->sender_has_retransmits) {
1934 		retransmits += irp->interval_retrans;
1935 	    }
1936 	} else {
1937             total_packets += irp->interval_packet_count;
1938             lost_packets += irp->interval_cnt_error;
1939             avg_jitter += irp->jitter;
1940 	}
1941     }
1942 
1943     /* next build string with sum of all streams */
1944     if (test->num_streams > 1 || test->json_output) {
1945         sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */
1946         irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);    /* use 1st stream for timing info */
1947 
1948         unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A');
1949 	bandwidth = (double) bytes / (double) irp->interval_duration;
1950         unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
1951 
1952         start_time = timeval_diff(&sp->result->start_time,&irp->interval_start_time);
1953         end_time = timeval_diff(&sp->result->start_time,&irp->interval_end_time);
1954 	if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
1955 	    if (test->sender && test->sender_has_retransmits) {
1956 		/* Interval sum, TCP with retransmits. */
1957 		if (test->json_output)
1958 		    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? */
1959 		else
1960 		    iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits, irp->omitted?report_omitted:""); /* XXX irp->omitted or test->omitting? */
1961 	    } else {
1962 		/* Interval sum, TCP without retransmits. */
1963 		if (test->json_output)
1964 		    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));
1965 		else
1966 		    iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, test->omitting?report_omitted:"");
1967 	    }
1968 	} else {
1969 	    /* Interval sum, UDP. */
1970 	    if (test->sender) {
1971 		if (test->json_output)
1972 		    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));
1973 		else
1974 		    iprintf(test, report_sum_bw_udp_sender_format, start_time, end_time, ubuf, nbuf, total_packets, test->omitting?report_omitted:"");
1975 	    } else {
1976 		avg_jitter /= test->num_streams;
1977 		lost_percent = 100.0 * lost_packets / total_packets;
1978 		if (test->json_output)
1979 		    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));
1980 		else
1981 		    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:"");
1982 	    }
1983 	}
1984     }
1985 }
1986 
1987 static void
1988 iperf_print_results(struct iperf_test *test)
1989 {
1990 
1991     cJSON *json_summary_streams = NULL;
1992     cJSON *json_summary_stream = NULL;
1993     int total_retransmits = 0;
1994     int total_packets = 0, lost_packets = 0;
1995     char ubuf[UNIT_LEN];
1996     char nbuf[UNIT_LEN];
1997     struct stat sb;
1998     char sbuf[UNIT_LEN];
1999     struct iperf_stream *sp = NULL;
2000     iperf_size_t bytes_sent, total_sent = 0;
2001     iperf_size_t bytes_received, total_received = 0;
2002     double start_time, end_time, avg_jitter = 0.0, lost_percent;
2003     double bandwidth;
2004 
2005     /* print final summary for all intervals */
2006 
2007     if (test->json_output) {
2008         json_summary_streams = cJSON_CreateArray();
2009 	if (json_summary_streams == NULL)
2010 	    return;
2011 	cJSON_AddItemToObject(test->json_end, "streams", json_summary_streams);
2012     } else {
2013 	iprintf(test, "%s", report_bw_separator);
2014 	if (test->verbose)
2015 	    iprintf(test, "%s", report_summary);
2016 	if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
2017 	    if (test->sender_has_retransmits)
2018 		iprintf(test, "%s", report_bw_retrans_header);
2019 	    else
2020 		iprintf(test, "%s", report_bw_header);
2021 	} else
2022 	    iprintf(test, "%s", report_bw_udp_header);
2023     }
2024 
2025     start_time = 0.;
2026     sp = SLIST_FIRST(&test->streams);
2027     end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time);
2028     SLIST_FOREACH(sp, &test->streams, streams) {
2029 	if (test->json_output) {
2030 	    json_summary_stream = cJSON_CreateObject();
2031 	    if (json_summary_stream == NULL)
2032 		return;
2033 	    cJSON_AddItemToArray(json_summary_streams, json_summary_stream);
2034 	}
2035 
2036         bytes_sent = sp->result->bytes_sent;
2037         bytes_received = sp->result->bytes_received;
2038         total_sent += bytes_sent;
2039         total_received += bytes_received;
2040 
2041         if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
2042 	    if (test->sender_has_retransmits) {
2043 		total_retransmits += sp->result->stream_retrans;
2044 	    }
2045 	} else {
2046             total_packets += (sp->packet_count - sp->omitted_packet_count);
2047             lost_packets += sp->cnt_error;
2048             avg_jitter += sp->jitter;
2049         }
2050 
2051 	unit_snprintf(ubuf, UNIT_LEN, (double) bytes_sent, 'A');
2052 	bandwidth = (double) bytes_sent / (double) end_time;
2053 	unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
2054 	if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
2055 	    if (test->sender_has_retransmits) {
2056 		/* Summary, TCP with retransmits. */
2057 		if (test->json_output)
2058 		    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));
2059 		else
2060 		    iprintf(test, report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->result->stream_retrans, report_sender);
2061 	    } else {
2062 		/* Summary, TCP without retransmits. */
2063 		if (test->json_output)
2064 		    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));
2065 		else
2066 		    iprintf(test, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf, report_sender);
2067 	    }
2068 	} else {
2069 	    /* Summary, UDP. */
2070 	    lost_percent = 100.0 * sp->cnt_error / (sp->packet_count - sp->omitted_packet_count);
2071 	    if (test->json_output)
2072 		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));
2073 	    else {
2074 		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, "");
2075 		if (test->role == 'c')
2076 		    iprintf(test, report_datagrams, sp->socket, (sp->packet_count - sp->omitted_packet_count));
2077 		if (sp->outoforder_packets > 0)
2078 		    iprintf(test, report_sum_outoforder, start_time, end_time, sp->cnt_error);
2079 	    }
2080 	}
2081 
2082 	if (sp->diskfile_fd >= 0) {
2083 	    if (fstat(sp->diskfile_fd, &sb) == 0) {
2084 		int percent = (int) ( ( (double) bytes_sent / (double) sb.st_size ) * 100.0 );
2085 		unit_snprintf(sbuf, UNIT_LEN, (double) sb.st_size, 'A');
2086 		if (test->json_output)
2087 		    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));
2088 		else
2089 		    iprintf(test, report_diskfile, ubuf, sbuf, percent, test->diskfile_name);
2090 	    }
2091 	}
2092 
2093 	unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
2094 	bandwidth = (double) bytes_received / (double) end_time;
2095 	unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
2096 	if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
2097 	    if (test->json_output)
2098 		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));
2099 	    else
2100 		iprintf(test, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf, report_receiver);
2101 	}
2102     }
2103 
2104     if (test->num_streams > 1 || test->json_output) {
2105         unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');
2106 	bandwidth = (double) total_sent / (double) end_time;
2107         unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
2108         if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
2109 	    if (test->sender_has_retransmits) {
2110 		/* Summary sum, TCP with retransmits. */
2111 		if (test->json_output)
2112 		    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));
2113 		else
2114 		    iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, total_retransmits, report_sender);
2115 	    } else {
2116 		/* Summary sum, TCP without retransmits. */
2117 		if (test->json_output)
2118 		    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));
2119 		else
2120 		    iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, report_sender);
2121 	    }
2122             unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A');
2123 	    bandwidth = (double) total_received / (double) end_time;
2124             unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
2125 	    if (test->json_output)
2126 		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));
2127 	    else
2128 		iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, report_receiver);
2129         } else {
2130 	    /* Summary sum, UDP. */
2131             avg_jitter /= test->num_streams;
2132 	    lost_percent = 100.0 * lost_packets / total_packets;
2133 	    if (test->json_output)
2134 		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));
2135 	    else
2136 		iprintf(test, report_sum_bw_udp_format, start_time, end_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, total_packets, lost_percent, "");
2137         }
2138     }
2139 
2140     if (test->json_output)
2141 	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]));
2142     else if (test->verbose)
2143         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]);
2144 }
2145 
2146 /**************************************************************************/
2147 
2148 /**
2149  * iperf_reporter_callback -- handles the report printing
2150  *
2151  */
2152 
2153 void
2154 iperf_reporter_callback(struct iperf_test *test)
2155 {
2156     switch (test->state) {
2157         case TEST_RUNNING:
2158         case STREAM_RUNNING:
2159             /* print interval results for each stream */
2160             iperf_print_intermediate(test);
2161             break;
2162         case DISPLAY_RESULTS:
2163             iperf_print_intermediate(test);
2164             iperf_print_results(test);
2165             break;
2166     }
2167 
2168 }
2169 
2170 /**************************************************************************/
2171 static void
2172 print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams)
2173 {
2174     char ubuf[UNIT_LEN];
2175     char nbuf[UNIT_LEN];
2176     char cbuf[UNIT_LEN];
2177     double st = 0., et = 0.;
2178     struct iperf_interval_results *irp = NULL;
2179     double bandwidth, lost_percent;
2180 
2181     irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* get last entry in linked list */
2182     if (irp == NULL) {
2183 	iperf_err(test, "print_interval_results error: interval_results is NULL");
2184         return;
2185     }
2186     if (!test->json_output) {
2187 	/* First stream? */
2188 	if (sp == SLIST_FIRST(&test->streams)) {
2189 	    /* It it's the first interval, print the header;
2190 	    ** else if there's more than one stream, print the separator;
2191 	    ** else nothing.
2192 	    */
2193 	    if (timeval_equals(&sp->result->start_time, &irp->interval_start_time)) {
2194 		if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
2195 		    if (test->sender && test->sender_has_retransmits)
2196 			iprintf(test, "%s", report_bw_retrans_cwnd_header);
2197 		    else
2198 			iprintf(test, "%s", report_bw_header);
2199 		} else {
2200 		    if (test->sender)
2201 			iprintf(test, "%s", report_bw_udp_sender_header);
2202 		    else
2203 			iprintf(test, "%s", report_bw_udp_header);
2204 		}
2205 	    } else if (test->num_streams > 1)
2206 		iprintf(test, "%s", report_bw_separator);
2207 	}
2208     }
2209 
2210     unit_snprintf(ubuf, UNIT_LEN, (double) (irp->bytes_transferred), 'A');
2211     bandwidth = (double) irp->bytes_transferred / (double) irp->interval_duration;
2212     unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
2213 
2214     st = timeval_diff(&sp->result->start_time, &irp->interval_start_time);
2215     et = timeval_diff(&sp->result->start_time, &irp->interval_end_time);
2216 
2217     if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
2218 	if (test->sender && test->sender_has_retransmits) {
2219 	    /* Interval, TCP with retransmits. */
2220 	    if (test->json_output)
2221 		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));
2222 	    else
2223 		unit_snprintf(cbuf, UNIT_LEN, irp->snd_cwnd, 'A');
2224 		iprintf(test, report_bw_retrans_cwnd_format, sp->socket, st, et, ubuf, nbuf, irp->interval_retrans, cbuf, irp->omitted?report_omitted:"");
2225 	} else {
2226 	    /* Interval, TCP without retransmits. */
2227 	    if (test->json_output)
2228 		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));
2229 	    else
2230 		iprintf(test, report_bw_format, sp->socket, st, et, ubuf, nbuf, irp->omitted?report_omitted:"");
2231 	}
2232     } else {
2233 	/* Interval, UDP. */
2234 	if (test->sender) {
2235 	    if (test->json_output)
2236 		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));
2237 	    else
2238 		iprintf(test, report_bw_udp_sender_format, sp->socket, st, et, ubuf, nbuf, irp->interval_packet_count, irp->omitted?report_omitted:"");
2239 	} else {
2240 	    lost_percent = 100.0 * irp->interval_cnt_error / irp->interval_packet_count;
2241 	    if (test->json_output)
2242 		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));
2243 	    else
2244 		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:"");
2245 	}
2246     }
2247 }
2248 
2249 /**************************************************************************/
2250 void
2251 iperf_free_stream(struct iperf_stream *sp)
2252 {
2253     struct iperf_interval_results *irp, *nirp;
2254 
2255     /* XXX: need to free interval list too! */
2256     munmap(sp->buffer, sp->test->settings->blksize);
2257     close(sp->buffer_fd);
2258     if (sp->diskfile_fd >= 0)
2259 	close(sp->diskfile_fd);
2260     for (irp = TAILQ_FIRST(&sp->result->interval_results); irp != TAILQ_END(sp->result->interval_results); irp = nirp) {
2261         nirp = TAILQ_NEXT(irp, irlistentries);
2262         free(irp);
2263     }
2264     free(sp->result);
2265     if (sp->send_timer != NULL)
2266 	tmr_cancel(sp->send_timer);
2267     free(sp);
2268 }
2269 
2270 /**************************************************************************/
2271 struct iperf_stream *
2272 iperf_new_stream(struct iperf_test *test, int s)
2273 {
2274     int i;
2275     struct iperf_stream *sp;
2276     char template[] = "/tmp/iperf3.XXXXXX";
2277 
2278     h_errno = 0;
2279 
2280     sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream));
2281     if (!sp) {
2282         i_errno = IECREATESTREAM;
2283         return NULL;
2284     }
2285 
2286     memset(sp, 0, sizeof(struct iperf_stream));
2287 
2288     sp->test = test;
2289     sp->settings = test->settings;
2290     sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));
2291     if (!sp->result) {
2292         free(sp);
2293         i_errno = IECREATESTREAM;
2294         return NULL;
2295     }
2296 
2297     memset(sp->result, 0, sizeof(struct iperf_stream_result));
2298     TAILQ_INIT(&sp->result->interval_results);
2299 
2300     /* Create and randomize the buffer */
2301     sp->buffer_fd = mkstemp(template);
2302     if (sp->buffer_fd == -1) {
2303         i_errno = IECREATESTREAM;
2304         free(sp->result);
2305         free(sp);
2306         return NULL;
2307     }
2308     if (unlink(template) < 0) {
2309         i_errno = IECREATESTREAM;
2310         free(sp->result);
2311         free(sp);
2312         return NULL;
2313     }
2314     if (ftruncate(sp->buffer_fd, test->settings->blksize) < 0) {
2315         i_errno = IECREATESTREAM;
2316         free(sp->result);
2317         free(sp);
2318         return NULL;
2319     }
2320     sp->buffer = (char *) mmap(NULL, test->settings->blksize, PROT_READ|PROT_WRITE, MAP_PRIVATE, sp->buffer_fd, 0);
2321     if (sp->buffer == MAP_FAILED) {
2322         i_errno = IECREATESTREAM;
2323         free(sp->result);
2324         free(sp);
2325         return NULL;
2326     }
2327     srandom(time(NULL));
2328     for (i = 0; i < test->settings->blksize; ++i)
2329         sp->buffer[i] = random();
2330 
2331     /* Set socket */
2332     sp->socket = s;
2333 
2334     sp->snd = test->protocol->send;
2335     sp->rcv = test->protocol->recv;
2336 
2337     if (test->diskfile_name != (char*) 0) {
2338 	sp->diskfile_fd = open(test->diskfile_name, test->sender ? O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC));
2339 	if (sp->diskfile_fd == -1) {
2340 	    i_errno = IEFILE;
2341             munmap(sp->buffer, sp->test->settings->blksize);
2342             free(sp->result);
2343             free(sp);
2344 	    return NULL;
2345 	}
2346         sp->snd2 = sp->snd;
2347 	sp->snd = diskfile_send;
2348 	sp->rcv2 = sp->rcv;
2349 	sp->rcv = diskfile_recv;
2350     } else
2351         sp->diskfile_fd = -1;
2352 
2353     /* Initialize stream */
2354     if (iperf_init_stream(sp, test) < 0) {
2355         close(sp->buffer_fd);
2356         munmap(sp->buffer, sp->test->settings->blksize);
2357         free(sp->result);
2358         free(sp);
2359         return NULL;
2360     }
2361     iperf_add_stream(test, sp);
2362 
2363     return sp;
2364 }
2365 
2366 /**************************************************************************/
2367 int
2368 iperf_init_stream(struct iperf_stream *sp, struct iperf_test *test)
2369 {
2370     socklen_t len;
2371     int opt;
2372 
2373     len = sizeof(struct sockaddr_storage);
2374     if (getsockname(sp->socket, (struct sockaddr *) &sp->local_addr, &len) < 0) {
2375         i_errno = IEINITSTREAM;
2376         return -1;
2377     }
2378     len = sizeof(struct sockaddr_storage);
2379     if (getpeername(sp->socket, (struct sockaddr *) &sp->remote_addr, &len) < 0) {
2380         i_errno = IEINITSTREAM;
2381         return -1;
2382     }
2383 
2384     /* Set IP TOS */
2385     if ((opt = test->settings->tos)) {
2386         if (getsockdomain(sp->socket) == AF_INET6) {
2387 #ifdef IPV6_TCLASS
2388             if (setsockopt(sp->socket, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) < 0) {
2389                 i_errno = IESETCOS;
2390                 return -1;
2391             }
2392 #else
2393             i_errno = IESETCOS;
2394             return -1;
2395 #endif
2396         } else {
2397             if (setsockopt(sp->socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) < 0) {
2398                 i_errno = IESETTOS;
2399                 return -1;
2400             }
2401         }
2402     }
2403 
2404     return 0;
2405 }
2406 
2407 /**************************************************************************/
2408 void
2409 iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp)
2410 {
2411     int i;
2412     struct iperf_stream *n, *prev;
2413 
2414     if (SLIST_EMPTY(&test->streams)) {
2415         SLIST_INSERT_HEAD(&test->streams, sp, streams);
2416         sp->id = 1;
2417     } else {
2418         // for (n = test->streams, i = 2; n->next; n = n->next, ++i);
2419         i = 2;
2420         SLIST_FOREACH(n, &test->streams, streams) {
2421             prev = n;
2422             ++i;
2423         }
2424         SLIST_INSERT_AFTER(prev, sp, streams);
2425         sp->id = i;
2426     }
2427 }
2428 
2429 /* This pair of routines gets inserted into the snd/rcv function pointers
2430 ** when there's a -F flag. They handle the file stuff and call the real
2431 ** snd/rcv functions, which have been saved in snd2/rcv2.
2432 **
2433 ** The advantage of doing it this way is that in the much more common
2434 ** case of no -F flag, there is zero extra overhead.
2435 */
2436 
2437 static int
2438 diskfile_send(struct iperf_stream *sp)
2439 {
2440     int r;
2441 
2442     r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize);
2443     if (r == 0)
2444         sp->test->done = 1;
2445     else
2446 	r = sp->snd2(sp);
2447     return r;
2448 }
2449 
2450 static int
2451 diskfile_recv(struct iperf_stream *sp)
2452 {
2453     int r;
2454 
2455     r = sp->rcv2(sp);
2456     if (r > 0) {
2457 	(void) write(sp->diskfile_fd, sp->buffer, r);
2458 	(void) fsync(sp->diskfile_fd);
2459     }
2460     return r;
2461 }
2462 
2463 
2464 void
2465 iperf_catch_sigend(void (*handler)(int))
2466 {
2467     signal(SIGINT, handler);
2468     signal(SIGTERM, handler);
2469     signal(SIGHUP, handler);
2470 }
2471 
2472 void
2473 iperf_got_sigend(struct iperf_test *test)
2474 {
2475     /*
2476      * If we're the client, or if we're a server and running a test,
2477      * then dump out the accumulated stats so far.
2478      */
2479     if (test->role == 'c' ||
2480       (test->role == 's' && test->state == TEST_RUNNING)) {
2481 
2482 	test->done = 1;
2483 	cpu_util(test->cpu_util);
2484 	test->stats_callback(test);
2485 	test->state = DISPLAY_RESULTS; /* change local state only */
2486 	if (test->on_test_finish)
2487 	    test->on_test_finish(test);
2488 	test->reporter_callback(test);
2489     }
2490 
2491     if (test->ctrl_sck >= 0) {
2492 	test->state = (test->role == 'c') ? CLIENT_TERMINATE : SERVER_TERMINATE;
2493 	(void) Nwrite(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp);
2494     }
2495     i_errno = (test->role == 'c') ? IECLIENTTERM : IESERVERTERM;
2496     iperf_errexit(test, "interrupt - %s", iperf_strerror(i_errno));
2497 }
2498 
2499 /* Try to write a PID file if requested, return -1 on an error. */
2500 int
2501 iperf_create_pidfile(struct iperf_test *test)
2502 {
2503     if (test->pidfile) {
2504 	int fd;
2505 	char buf[8];
2506 	fd = open(test->pidfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
2507 	if (fd < 0) {
2508 	    return -1;
2509 	}
2510 	snprintf(buf, sizeof(buf), "%d", getpid()); /* no trailing newline */
2511 	if (write(fd, buf, strlen(buf) + 1) < 0) {
2512 	    return -1;
2513 	}
2514 	if (close(fd) < 0) {
2515 	    return -1;
2516 	};
2517     }
2518     return 0;
2519 }
2520 
2521 /* Get rid of a PID file, return -1 on error. */
2522 int
2523 iperf_delete_pidfile(struct iperf_test *test)
2524 {
2525     if (test->pidfile) {
2526 	if (unlink(test->pidfile) < 0) {
2527 	    return -1;
2528 	}
2529     }
2530     return 0;
2531 }
2532 
2533 int
2534 iperf_json_start(struct iperf_test *test)
2535 {
2536     test->json_top = cJSON_CreateObject();
2537     if (test->json_top == NULL)
2538         return -1;
2539     if (test->title)
2540 	cJSON_AddStringToObject(test->json_top, "title", test->title);
2541     test->json_start = cJSON_CreateObject();
2542     if (test->json_start == NULL)
2543         return -1;
2544     cJSON_AddItemToObject(test->json_top, "start", test->json_start);
2545     test->json_intervals = cJSON_CreateArray();
2546     if (test->json_intervals == NULL)
2547         return -1;
2548     cJSON_AddItemToObject(test->json_top, "intervals", test->json_intervals);
2549     test->json_end = cJSON_CreateObject();
2550     if (test->json_end == NULL)
2551         return -1;
2552     cJSON_AddItemToObject(test->json_top, "end", test->json_end);
2553     return 0;
2554 }
2555 
2556 int
2557 iperf_json_finish(struct iperf_test *test)
2558 {
2559     test->json_output_string = cJSON_Print(test->json_top);
2560     if (test->json_output_string == NULL)
2561         return -1;
2562     fprintf(test->outfile, "%s\n", test->json_output_string);
2563     iflush(test);
2564     cJSON_Delete(test->json_top);
2565     test->json_top = test->json_start = test->json_intervals = test->json_end = NULL;
2566     return 0;
2567 }
2568 
2569 
2570 /* CPU affinity stuff - Linux and FreeBSD only. */
2571 
2572 int
2573 iperf_setaffinity(struct iperf_test *test, int affinity)
2574 {
2575 #if defined(HAVE_SCHED_SETAFFINITY)
2576     cpu_set_t cpu_set;
2577 
2578     CPU_ZERO(&cpu_set);
2579     CPU_SET(affinity, &cpu_set);
2580     if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) {
2581 	i_errno = IEAFFINITY;
2582         return -1;
2583     }
2584     return 0;
2585 #elif defined(HAVE_CPUSET_SETAFFINITY)
2586     cpuset_t cpumask;
2587 
2588     if(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
2589                           sizeof(cpuset_t), &test->cpumask) != 0) {
2590         i_errno = IEAFFINITY;
2591         return -1;
2592     }
2593 
2594     CPU_ZERO(&cpumask);
2595     CPU_SET(affinity, &cpumask);
2596 
2597     if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1,
2598                           sizeof(cpuset_t), &cpumask) != 0) {
2599         i_errno = IEAFFINITY;
2600         return -1;
2601     }
2602     return 0;
2603 #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */
2604     i_errno = IEAFFINITY;
2605     return -1;
2606 #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */
2607 }
2608 
2609 int
2610 iperf_clearaffinity(struct iperf_test *test)
2611 {
2612 #if defined(HAVE_SCHED_SETAFFINITY)
2613     cpu_set_t cpu_set;
2614     int i;
2615 
2616     CPU_ZERO(&cpu_set);
2617     for (i = 0; i < CPU_SETSIZE; ++i)
2618 	CPU_SET(i, &cpu_set);
2619     if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) {
2620 	i_errno = IEAFFINITY;
2621         return -1;
2622     }
2623     return 0;
2624 #elif defined(HAVE_CPUSET_SETAFFINITY)
2625     if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1,
2626                           sizeof(cpuset_t), &test->cpumask) != 0) {
2627         i_errno = IEAFFINITY;
2628         return -1;
2629     }
2630     return 0;
2631 #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */
2632     i_errno = IEAFFINITY;
2633     return -1;
2634 #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */
2635 }
2636 
2637 int
2638 iprintf(struct iperf_test *test, const char* format, ...)
2639 {
2640     va_list argp;
2641     int r;
2642 
2643     if (test->title)
2644         fprintf(test->outfile, "%s:  ", test->title);
2645     va_start(argp, format);
2646     r = vfprintf(test->outfile, format, argp);
2647     va_end(argp);
2648     return r;
2649 }
2650 
2651 int
2652 iflush(struct iperf_test *test)
2653 {
2654     return fflush(test->outfile);
2655 }
2656