xref: /iperf/src/iperf_server_api.c (revision 081ba8e4)
1 /*
2  * Copyright (c) 2009-2014, The Regents of the University of California,
3  * through Lawrence Berkeley National Laboratory (subject to receipt of any
4  * required approvals from the U.S. Dept. of Energy).  All rights reserved.
5  *
6  * This code is distributed under a BSD style license, see the LICENSE file
7  * for complete information.
8  */
9 
10 /* iperf_server_api.c: Functions to be used by an iperf server
11 */
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <getopt.h>
17 #include <errno.h>
18 #include <unistd.h>
19 #include <assert.h>
20 #include <fcntl.h>
21 #include <sys/socket.h>
22 #include <sys/types.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 #include <netdb.h>
26 #include <pthread.h>
27 #include <stdint.h>
28 #include <netinet/tcp.h>
29 #include <sys/time.h>
30 #include <sys/resource.h>
31 #include <sched.h>
32 #include <setjmp.h>
33 
34 #include "iperf.h"
35 #include "iperf_api.h"
36 #include "iperf_udp.h"
37 #include "iperf_tcp.h"
38 #include "iperf_util.h"
39 #include "timer.h"
40 #include "net.h"
41 #include "units.h"
42 #include "tcp_window_size.h"
43 #include "iperf_util.h"
44 #include "locale.h"
45 
46 
47 int
48 iperf_server_listen(struct iperf_test *test)
49 {
50     retry:
51     if((test->listener = netannounce(test->settings->domain, Ptcp, test->bind_address, test->server_port)) < 0) {
52 	if (errno == EAFNOSUPPORT && (test->settings->domain == AF_INET6 || test->settings->domain == AF_UNSPEC)) {
53 	    /* If we get "Address family not supported by protocol", that
54 	    ** probably means we were compiled with IPv6 but the running
55 	    ** kernel does not actually do IPv6.  This is not too unusual,
56 	    ** v6 support is and perhaps always will be spotty.
57 	    */
58 	    warning("this system does not seem to support IPv6 - trying IPv4");
59 	    test->settings->domain = AF_INET;
60 	    goto retry;
61 	} else {
62 	    i_errno = IELISTEN;
63 	    return -1;
64 	}
65     }
66 
67     if (!test->json_output) {
68 	iprintf(test, "-----------------------------------------------------------\n");
69 	iprintf(test, "Server listening on %d\n", test->server_port);
70     }
71 
72     // This needs to be changed to reflect if client has different window size
73     // make sure we got what we asked for
74     /* XXX: This needs to be moved to the stream listener
75     if ((x = get_tcp_windowsize(test->listener, SO_RCVBUF)) < 0) {
76         // Needs to set some sort of error number/message
77         perror("SO_RCVBUF");
78         return -1;
79     }
80     */
81 
82     // XXX: This code needs to be moved to after parameter exhange
83     /*
84     char ubuf[UNIT_LEN];
85     int x;
86 
87     if (test->protocol->id == Ptcp) {
88         if (test->settings->socket_bufsize > 0) {
89             unit_snprintf(ubuf, UNIT_LEN, (double) x, 'A');
90 	    if (!test->json_output)
91 		iprintf(test, report_window, ubuf);
92         } else {
93 	    if (!test->json_output)
94 		iprintf(test, "%s", report_autotune);
95         }
96     }
97     */
98     if (!test->json_output)
99 	iprintf(test, "-----------------------------------------------------------\n");
100 
101     FD_ZERO(&test->read_set);
102     FD_ZERO(&test->write_set);
103     FD_SET(test->listener, &test->read_set);
104     if (test->listener > test->max_fd) test->max_fd = test->listener;
105 
106     return 0;
107 }
108 
109 int
110 iperf_accept(struct iperf_test *test)
111 {
112     int s;
113     signed char rbuf = ACCESS_DENIED;
114     char cookie[COOKIE_SIZE];
115     socklen_t len;
116     struct sockaddr_storage addr;
117 
118     len = sizeof(addr);
119     if ((s = accept(test->listener, (struct sockaddr *) &addr, &len)) < 0) {
120         i_errno = IEACCEPT;
121         return -1;
122     }
123 
124     if (test->ctrl_sck == -1) {
125         /* Server free, accept new client */
126         test->ctrl_sck = s;
127         if (Nread(test->ctrl_sck, test->cookie, COOKIE_SIZE, Ptcp) < 0) {
128             i_errno = IERECVCOOKIE;
129             return -1;
130         }
131 	FD_SET(test->ctrl_sck, &test->read_set);
132 	if (test->ctrl_sck > test->max_fd) test->max_fd = test->ctrl_sck;
133 
134 	if (iperf_set_send_state(test, PARAM_EXCHANGE) != 0)
135             return -1;
136         if (iperf_exchange_parameters(test) < 0)
137             return -1;
138 	if (test->server_affinity != -1)
139 	    if (iperf_setaffinity(test, test->server_affinity) != 0)
140 		return -1;
141         if (test->on_connect)
142             test->on_connect(test);
143     } else {
144         /* XXX: Do we even need to receive cookie if we're just going to deny anyways? */
145         if (Nread(s, cookie, COOKIE_SIZE, Ptcp) < 0) {
146             i_errno = IERECVCOOKIE;
147             return -1;
148         }
149         if (Nwrite(s, (char*) &rbuf, sizeof(rbuf), Ptcp) < 0) {
150             i_errno = IESENDMESSAGE;
151             return -1;
152         }
153         close(s);
154     }
155 
156     return 0;
157 }
158 
159 
160 /**************************************************************************/
161 int
162 iperf_handle_message_server(struct iperf_test *test)
163 {
164     int rval;
165     struct iperf_stream *sp;
166 
167     // XXX: Need to rethink how this behaves to fit API
168     if ((rval = Nread(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp)) <= 0) {
169         if (rval == 0) {
170 	    iperf_err(test, "the client has unexpectedly closed the connection");
171             i_errno = IECTRLCLOSE;
172             test->state = IPERF_DONE;
173             return 0;
174         } else {
175             i_errno = IERECVMESSAGE;
176             return -1;
177         }
178     }
179 
180     switch(test->state) {
181         case TEST_START:
182             break;
183         case TEST_END:
184 	    test->done = 1;
185             cpu_util(test->cpu_util);
186             test->stats_callback(test);
187             SLIST_FOREACH(sp, &test->streams, streams) {
188                 FD_CLR(sp->socket, &test->read_set);
189                 FD_CLR(sp->socket, &test->write_set);
190                 close(sp->socket);
191             }
192 	    if (iperf_set_send_state(test, EXCHANGE_RESULTS) != 0)
193                 return -1;
194             if (iperf_exchange_results(test) < 0)
195                 return -1;
196 	    if (iperf_set_send_state(test, DISPLAY_RESULTS) != 0)
197                 return -1;
198             if (test->on_test_finish)
199                 test->on_test_finish(test);
200             test->reporter_callback(test);
201             break;
202         case IPERF_DONE:
203             break;
204         case CLIENT_TERMINATE:
205             i_errno = IECLIENTTERM;
206 
207 	    // Temporarily be in DISPLAY_RESULTS phase so we can get
208 	    // ending summary statistics.
209 	    signed char oldstate = test->state;
210 	    cpu_util(test->cpu_util);
211 	    test->state = DISPLAY_RESULTS;
212 	    test->reporter_callback(test);
213 	    test->state = oldstate;
214 
215             // XXX: Remove this line below!
216 	    iperf_err(test, "the client has terminated");
217             SLIST_FOREACH(sp, &test->streams, streams) {
218                 FD_CLR(sp->socket, &test->read_set);
219                 FD_CLR(sp->socket, &test->write_set);
220                 close(sp->socket);
221             }
222             test->state = IPERF_DONE;
223             break;
224         default:
225             i_errno = IEMESSAGE;
226             return -1;
227     }
228 
229     return 0;
230 }
231 
232 /* XXX: This function is not used anymore */
233 void
234 iperf_test_reset(struct iperf_test *test)
235 {
236     struct iperf_stream *sp;
237 
238     close(test->ctrl_sck);
239 
240     /* Free streams */
241     while (!SLIST_EMPTY(&test->streams)) {
242         sp = SLIST_FIRST(&test->streams);
243         SLIST_REMOVE_HEAD(&test->streams, streams);
244         iperf_free_stream(sp);
245     }
246     if (test->timer != NULL) {
247 	tmr_cancel(test->timer);
248 	test->timer = NULL;
249     }
250     if (test->stats_timer != NULL) {
251 	tmr_cancel(test->stats_timer);
252 	test->stats_timer = NULL;
253     }
254     if (test->reporter_timer != NULL) {
255 	tmr_cancel(test->reporter_timer);
256 	test->reporter_timer = NULL;
257     }
258     test->done = 0;
259 
260     SLIST_INIT(&test->streams);
261 
262     test->role = 's';
263     set_protocol(test, Ptcp);
264     test->omit = OMIT;
265     test->duration = DURATION;
266     test->diskfile_name = (char*) 0;
267     test->affinity = -1;
268     test->server_affinity = -1;
269     test->title = NULL;
270     test->congestion = NULL;
271     test->state = 0;
272     test->server_hostname = NULL;
273 
274     test->ctrl_sck = -1;
275     test->prot_listener = -1;
276 
277     test->bytes_sent = 0;
278 
279     test->reverse = 0;
280     test->sender = 0;
281     test->sender_has_retransmits = 0;
282     test->no_delay = 0;
283 
284     FD_ZERO(&test->read_set);
285     FD_ZERO(&test->write_set);
286     FD_SET(test->listener, &test->read_set);
287     test->max_fd = test->listener;
288 
289     test->num_streams = 1;
290     test->settings->socket_bufsize = 0;
291     test->settings->blksize = DEFAULT_TCP_BLKSIZE;
292     test->settings->rate = 0;
293     test->settings->mss = 0;
294     memset(test->cookie, 0, COOKIE_SIZE);
295 }
296 
297 static void
298 server_stats_timer_proc(TimerClientData client_data, struct timeval *nowP)
299 {
300     struct iperf_test *test = client_data.p;
301 
302     if (test->done)
303         return;
304     if (test->stats_callback)
305 	test->stats_callback(test);
306 }
307 
308 static void
309 server_reporter_timer_proc(TimerClientData client_data, struct timeval *nowP)
310 {
311     struct iperf_test *test = client_data.p;
312 
313     if (test->done)
314         return;
315     if (test->reporter_callback)
316 	test->reporter_callback(test);
317 }
318 
319 static int
320 create_server_timers(struct iperf_test * test)
321 {
322     struct timeval now;
323     TimerClientData cd;
324 
325     if (gettimeofday(&now, NULL) < 0) {
326 	i_errno = IEINITTEST;
327 	return -1;
328     }
329     cd.p = test;
330     test->stats_timer = test->reporter_timer = NULL;
331     if (test->stats_interval != 0) {
332         test->stats_timer = tmr_create(&now, server_stats_timer_proc, cd, test->stats_interval * SEC_TO_US, 1);
333         if (test->stats_timer == NULL) {
334             i_errno = IEINITTEST;
335             return -1;
336 	}
337     }
338     if (test->reporter_interval != 0) {
339         test->reporter_timer = tmr_create(&now, server_reporter_timer_proc, cd, test->reporter_interval * SEC_TO_US, 1);
340         if (test->reporter_timer == NULL) {
341             i_errno = IEINITTEST;
342             return -1;
343 	}
344     }
345     return 0;
346 }
347 
348 static void
349 server_omit_timer_proc(TimerClientData client_data, struct timeval *nowP)
350 {
351     struct iperf_test *test = client_data.p;
352 
353     test->omit_timer = NULL;
354     test->omitting = 0;
355     iperf_reset_stats(test);
356     if (test->verbose && !test->json_output && test->reporter_interval == 0)
357 	iprintf(test, "%s", report_omit_done);
358 
359     /* Reset the timers. */
360     if (test->stats_timer != NULL)
361 	tmr_reset(nowP, test->stats_timer);
362     if (test->reporter_timer != NULL)
363 	tmr_reset(nowP, test->reporter_timer);
364 }
365 
366 static int
367 create_server_omit_timer(struct iperf_test * test)
368 {
369     struct timeval now;
370     TimerClientData cd;
371 
372     if (test->omit == 0) {
373 	test->omit_timer = NULL;
374 	test->omitting = 0;
375     } else {
376 	if (gettimeofday(&now, NULL) < 0) {
377 	    i_errno = IEINITTEST;
378 	    return -1;
379 	}
380 	test->omitting = 1;
381 	cd.p = test;
382 	test->omit_timer = tmr_create(&now, server_omit_timer_proc, cd, test->omit * SEC_TO_US, 0);
383 	if (test->omit_timer == NULL) {
384 	    i_errno = IEINITTEST;
385 	    return -1;
386 	}
387     }
388 
389     return 0;
390 }
391 
392 static void
393 cleanup_server(struct iperf_test *test)
394 {
395     /* Close open test sockets */
396     close(test->ctrl_sck);
397     close(test->listener);
398 
399     /* Cancel any remaining timers. */
400     if (test->stats_timer != NULL) {
401 	tmr_cancel(test->stats_timer);
402 	test->stats_timer = NULL;
403     }
404     if (test->reporter_timer != NULL) {
405 	tmr_cancel(test->reporter_timer);
406 	test->reporter_timer = NULL;
407     }
408     if (test->omit_timer != NULL) {
409 	tmr_cancel(test->omit_timer);
410 	test->omit_timer = NULL;
411     }
412 }
413 
414 
415 static jmp_buf sigend_jmp_buf;
416 
417 static void
418 sigend_handler(int sig)
419 {
420     longjmp(sigend_jmp_buf, 1);
421 }
422 
423 
424 int
425 iperf_run_server(struct iperf_test *test)
426 {
427     int result, s, streams_accepted;
428     fd_set read_set, write_set;
429     struct iperf_stream *sp;
430     struct timeval now;
431     struct timeval* timeout;
432 
433     /* Termination signals. */
434     iperf_catch_sigend(sigend_handler);
435     if (setjmp(sigend_jmp_buf))
436 	iperf_got_sigend(test);
437 
438     if (test->affinity != -1)
439 	if (iperf_setaffinity(test, test->affinity) != 0)
440 	    return -1;
441 
442     if (test->json_output)
443 	if (iperf_json_start(test) < 0)
444 	    return -1;
445 
446     if (test->json_output) {
447 	cJSON_AddItemToObject(test->json_start, "version", cJSON_CreateString(version));
448 	cJSON_AddItemToObject(test->json_start, "system_info", cJSON_CreateString(get_system_info()));
449     } else if (test->verbose) {
450 	iprintf(test, "%s\n", version);
451 	iprintf(test, "%s", "");
452 	iprintf(test, "%s\n", get_system_info());
453 	iflush(test);
454     }
455 
456     // Open socket and listen
457     if (iperf_server_listen(test) < 0) {
458         return -1;
459     }
460 
461     // Begin calculating CPU utilization
462     cpu_util(NULL);
463 
464     test->state = IPERF_START;
465     streams_accepted = 0;
466 
467     while (test->state != IPERF_DONE) {
468 
469         memcpy(&read_set, &test->read_set, sizeof(fd_set));
470         memcpy(&write_set, &test->write_set, sizeof(fd_set));
471 
472 	(void) gettimeofday(&now, NULL);
473 	timeout = tmr_timeout(&now);
474         result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
475         if (result < 0 && errno != EINTR) {
476 	    cleanup_server(test);
477             i_errno = IESELECT;
478             return -1;
479         }
480 	if (result > 0) {
481             if (FD_ISSET(test->listener, &read_set)) {
482                 if (test->state != CREATE_STREAMS) {
483                     if (iperf_accept(test) < 0) {
484 			cleanup_server(test);
485                         return -1;
486                     }
487                     FD_CLR(test->listener, &read_set);
488                 }
489             }
490             if (FD_ISSET(test->ctrl_sck, &read_set)) {
491                 if (iperf_handle_message_server(test) < 0) {
492 		    cleanup_server(test);
493                     return -1;
494 		}
495                 FD_CLR(test->ctrl_sck, &read_set);
496             }
497 
498             if (test->state == CREATE_STREAMS) {
499                 if (FD_ISSET(test->prot_listener, &read_set)) {
500 
501                     if ((s = test->protocol->accept(test)) < 0) {
502 			cleanup_server(test);
503                         return -1;
504 		    }
505 
506                     if (!is_closed(s)) {
507                         sp = iperf_new_stream(test, s);
508                         if (!sp) {
509 			    cleanup_server(test);
510                             return -1;
511 			}
512 
513 			if (test->sender)
514 			    FD_SET(s, &test->write_set);
515 			else
516 			    FD_SET(s, &test->read_set);
517 			if (s > test->max_fd) test->max_fd = s;
518 
519                         setnonblocking(s, 1);
520 
521                         streams_accepted++;
522                         if (test->on_new_stream)
523                             test->on_new_stream(sp);
524                     }
525                     FD_CLR(test->prot_listener, &read_set);
526                 }
527 
528                 if (streams_accepted == test->num_streams) {
529                     if (test->protocol->id != Ptcp) {
530                         FD_CLR(test->prot_listener, &test->read_set);
531                         close(test->prot_listener);
532                     } else {
533                         if (test->no_delay || test->settings->mss || test->settings->socket_bufsize) {
534                             FD_CLR(test->listener, &test->read_set);
535                             close(test->listener);
536                             if ((s = netannounce(test->settings->domain, Ptcp, test->bind_address, test->server_port)) < 0) {
537 				cleanup_server(test);
538                                 i_errno = IELISTEN;
539                                 return -1;
540                             }
541                             test->listener = s;
542                             FD_SET(test->listener, &test->read_set);
543 			    if (test->listener > test->max_fd) test->max_fd = test->listener;
544                         }
545                     }
546                     test->prot_listener = -1;
547 		    if (iperf_set_send_state(test, TEST_START) != 0) {
548 			cleanup_server(test);
549                         return -1;
550 		    }
551                     if (iperf_init_test(test) < 0) {
552 			cleanup_server(test);
553                         return -1;
554 		    }
555 		    if (create_server_timers(test) < 0) {
556 			cleanup_server(test);
557                         return -1;
558 		    }
559 		    if (create_server_omit_timer(test) < 0) {
560 			cleanup_server(test);
561                         return -1;
562 		    }
563 		    if (test->reverse)
564 			if (iperf_create_send_timers(test) < 0) {
565 			    cleanup_server(test);
566 			    return -1;
567 			}
568 		    if (iperf_set_send_state(test, TEST_RUNNING) != 0) {
569 			cleanup_server(test);
570                         return -1;
571 		    }
572                 }
573             }
574 
575             if (test->state == TEST_RUNNING) {
576                 if (test->reverse) {
577                     // Reverse mode. Server sends.
578                     if (iperf_send(test, &write_set) < 0) {
579 			cleanup_server(test);
580                         return -1;
581 		    }
582                 } else {
583                     // Regular mode. Server receives.
584                     if (iperf_recv(test, &read_set) < 0) {
585 			cleanup_server(test);
586                         return -1;
587 		    }
588                 }
589             }
590         }
591 
592 	if (result == 0 ||
593 	    (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0)) {
594 	    /* Run the timers. */
595 	    (void) gettimeofday(&now, NULL);
596 	    tmr_run(&now);
597 	}
598     }
599 
600     cleanup_server(test);
601 
602     if (test->json_output) {
603 	if (iperf_json_finish(test) < 0)
604 	    return -1;
605     }
606 
607     iflush(test);
608 
609     if (test->server_affinity != -1)
610 	if (iperf_clearaffinity(test) != 0)
611 	    return -1;
612 
613     return 0;
614 }
615