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