Annotation of embedaddon/iperf/src/iperf_server_api.c, revision 1.1.1.2

1.1       misho       1: /*
1.1.1.2 ! misho       2:  * iperf, Copyright (c) 2014-2020 The Regents of the University of
1.1       misho       3:  * California, through Lawrence Berkeley National Laboratory (subject
                      4:  * to receipt of any required approvals from the U.S. Dept. of
                      5:  * Energy).  All rights reserved.
                      6:  *
                      7:  * If you have questions about your rights to use or distribute this
                      8:  * software, please contact Berkeley Lab's Technology Transfer
                      9:  * Department at TTD@lbl.gov.
                     10:  *
                     11:  * NOTICE.  This software is owned by the U.S. Department of Energy.
                     12:  * As such, the U.S. Government has been granted for itself and others
                     13:  * acting on its behalf a paid-up, nonexclusive, irrevocable,
                     14:  * worldwide license in the Software to reproduce, prepare derivative
                     15:  * works, and perform publicly and display publicly.  Beginning five
                     16:  * (5) years after the date permission to assert copyright is obtained
                     17:  * from the U.S. Department of Energy, and subject to any subsequent
                     18:  * five (5) year renewals, the U.S. Government is granted for itself
                     19:  * and others acting on its behalf a paid-up, nonexclusive,
                     20:  * irrevocable, worldwide license in the Software to reproduce,
                     21:  * prepare derivative works, distribute copies to the public, perform
                     22:  * publicly and display publicly, and to permit others to do so.
                     23:  *
                     24:  * This code is distributed under a BSD style license, see the LICENSE
                     25:  * file for complete information.
                     26:  */
                     27: /* iperf_server_api.c: Functions to be used by an iperf server
                     28: */
                     29: 
                     30: #include <stdio.h>
                     31: #include <stdlib.h>
                     32: #include <string.h>
                     33: #include <getopt.h>
                     34: #include <errno.h>
                     35: #include <unistd.h>
                     36: #include <assert.h>
                     37: #include <fcntl.h>
                     38: #include <sys/socket.h>
                     39: #include <sys/types.h>
                     40: #include <netinet/in.h>
                     41: #include <arpa/inet.h>
                     42: #include <netdb.h>
                     43: #ifdef HAVE_STDINT_H
                     44: #include <stdint.h>
                     45: #endif
                     46: #include <sys/time.h>
                     47: #include <sys/resource.h>
                     48: #include <sched.h>
                     49: #include <setjmp.h>
                     50: 
                     51: #include "iperf.h"
                     52: #include "iperf_api.h"
                     53: #include "iperf_udp.h"
                     54: #include "iperf_tcp.h"
                     55: #include "iperf_util.h"
                     56: #include "timer.h"
1.1.1.2 ! misho      57: #include "iperf_time.h"
1.1       misho      58: #include "net.h"
                     59: #include "units.h"
                     60: #include "iperf_util.h"
                     61: #include "iperf_locale.h"
                     62: 
1.1.1.2 ! misho      63: #if defined(HAVE_TCP_CONGESTION)
        !            64: #if !defined(TCP_CA_NAME_MAX)
        !            65: #define TCP_CA_NAME_MAX 16
        !            66: #endif /* TCP_CA_NAME_MAX */
        !            67: #endif /* HAVE_TCP_CONGESTION */
1.1       misho      68: 
                     69: int
                     70: iperf_server_listen(struct iperf_test *test)
                     71: {
                     72:     retry:
                     73:     if((test->listener = netannounce(test->settings->domain, Ptcp, test->bind_address, test->server_port)) < 0) {
                     74:        if (errno == EAFNOSUPPORT && (test->settings->domain == AF_INET6 || test->settings->domain == AF_UNSPEC)) {
                     75:            /* If we get "Address family not supported by protocol", that
                     76:            ** probably means we were compiled with IPv6 but the running
                     77:            ** kernel does not actually do IPv6.  This is not too unusual,
                     78:            ** v6 support is and perhaps always will be spotty.
                     79:            */
                     80:            warning("this system does not seem to support IPv6 - trying IPv4");
                     81:            test->settings->domain = AF_INET;
                     82:            goto retry;
                     83:        } else {
                     84:            i_errno = IELISTEN;
                     85:            return -1;
                     86:        }
                     87:     }
                     88: 
                     89:     if (!test->json_output) {
1.1.1.2 ! misho      90:        iperf_printf(test, "-----------------------------------------------------------\n");
        !            91:        iperf_printf(test, "Server listening on %d\n", test->server_port);
        !            92:        iperf_printf(test, "-----------------------------------------------------------\n");
        !            93:        if (test->forceflush)
        !            94:            iflush(test);
1.1       misho      95:     }
                     96: 
                     97:     FD_ZERO(&test->read_set);
                     98:     FD_ZERO(&test->write_set);
                     99:     FD_SET(test->listener, &test->read_set);
                    100:     if (test->listener > test->max_fd) test->max_fd = test->listener;
                    101: 
                    102:     return 0;
                    103: }
                    104: 
                    105: int
                    106: iperf_accept(struct iperf_test *test)
                    107: {
                    108:     int s;
                    109:     signed char rbuf = ACCESS_DENIED;
                    110:     socklen_t len;
                    111:     struct sockaddr_storage addr;
                    112: 
                    113:     len = sizeof(addr);
                    114:     if ((s = accept(test->listener, (struct sockaddr *) &addr, &len)) < 0) {
                    115:         i_errno = IEACCEPT;
                    116:         return -1;
                    117:     }
                    118: 
                    119:     if (test->ctrl_sck == -1) {
                    120:         /* Server free, accept new client */
                    121:         test->ctrl_sck = s;
                    122:         if (Nread(test->ctrl_sck, test->cookie, COOKIE_SIZE, Ptcp) < 0) {
                    123:             i_errno = IERECVCOOKIE;
                    124:             return -1;
                    125:         }
                    126:        FD_SET(test->ctrl_sck, &test->read_set);
                    127:        if (test->ctrl_sck > test->max_fd) test->max_fd = test->ctrl_sck;
                    128: 
                    129:        if (iperf_set_send_state(test, PARAM_EXCHANGE) != 0)
                    130:             return -1;
                    131:         if (iperf_exchange_parameters(test) < 0)
                    132:             return -1;
                    133:        if (test->server_affinity != -1) 
                    134:            if (iperf_setaffinity(test, test->server_affinity) != 0)
                    135:                return -1;
                    136:         if (test->on_connect)
                    137:             test->on_connect(test);
                    138:     } else {
                    139:        /*
                    140:         * Don't try to read from the socket.  It could block an ongoing test. 
                    141:         * Just send ACCESS_DENIED.
                    142:         */
                    143:         if (Nwrite(s, (char*) &rbuf, sizeof(rbuf), Ptcp) < 0) {
                    144:             i_errno = IESENDMESSAGE;
                    145:             return -1;
                    146:         }
                    147:         close(s);
                    148:     }
                    149: 
                    150:     return 0;
                    151: }
                    152: 
                    153: 
                    154: /**************************************************************************/
                    155: int
                    156: iperf_handle_message_server(struct iperf_test *test)
                    157: {
                    158:     int rval;
                    159:     struct iperf_stream *sp;
                    160: 
                    161:     // XXX: Need to rethink how this behaves to fit API
                    162:     if ((rval = Nread(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp)) <= 0) {
                    163:         if (rval == 0) {
                    164:            iperf_err(test, "the client has unexpectedly closed the connection");
                    165:             i_errno = IECTRLCLOSE;
                    166:             test->state = IPERF_DONE;
                    167:             return 0;
                    168:         } else {
                    169:             i_errno = IERECVMESSAGE;
                    170:             return -1;
                    171:         }
                    172:     }
                    173: 
                    174:     switch(test->state) {
                    175:         case TEST_START:
                    176:             break;
                    177:         case TEST_END:
                    178:            test->done = 1;
                    179:             cpu_util(test->cpu_util);
                    180:             test->stats_callback(test);
                    181:             SLIST_FOREACH(sp, &test->streams, streams) {
                    182:                 FD_CLR(sp->socket, &test->read_set);
                    183:                 FD_CLR(sp->socket, &test->write_set);
                    184:                 close(sp->socket);
                    185:             }
                    186:             test->reporter_callback(test);
                    187:            if (iperf_set_send_state(test, EXCHANGE_RESULTS) != 0)
                    188:                 return -1;
                    189:             if (iperf_exchange_results(test) < 0)
                    190:                 return -1;
                    191:            if (iperf_set_send_state(test, DISPLAY_RESULTS) != 0)
                    192:                 return -1;
                    193:             if (test->on_test_finish)
                    194:                 test->on_test_finish(test);
                    195:             break;
                    196:         case IPERF_DONE:
                    197:             break;
                    198:         case CLIENT_TERMINATE:
                    199:             i_errno = IECLIENTTERM;
                    200: 
                    201:            // Temporarily be in DISPLAY_RESULTS phase so we can get
                    202:            // ending summary statistics.
                    203:            signed char oldstate = test->state;
                    204:            cpu_util(test->cpu_util);
                    205:            test->state = DISPLAY_RESULTS;
                    206:            test->reporter_callback(test);
                    207:            test->state = oldstate;
                    208: 
                    209:             // XXX: Remove this line below!
                    210:            iperf_err(test, "the client has terminated");
                    211:             SLIST_FOREACH(sp, &test->streams, streams) {
                    212:                 FD_CLR(sp->socket, &test->read_set);
                    213:                 FD_CLR(sp->socket, &test->write_set);
                    214:                 close(sp->socket);
                    215:             }
                    216:             test->state = IPERF_DONE;
                    217:             break;
                    218:         default:
                    219:             i_errno = IEMESSAGE;
                    220:             return -1;
                    221:     }
                    222: 
                    223:     return 0;
                    224: }
                    225: 
1.1.1.2 ! misho     226: static void
        !           227: server_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
1.1       misho     228: {
1.1.1.2 ! misho     229:     struct iperf_test *test = client_data.p;
1.1       misho     230:     struct iperf_stream *sp;
                    231: 
1.1.1.2 ! misho     232:     test->timer = NULL;
        !           233:     if (test->done)
        !           234:         return;
        !           235:     test->done = 1;
1.1       misho     236:     /* Free streams */
                    237:     while (!SLIST_EMPTY(&test->streams)) {
                    238:         sp = SLIST_FIRST(&test->streams);
                    239:         SLIST_REMOVE_HEAD(&test->streams, streams);
1.1.1.2 ! misho     240:         close(sp->socket);
1.1       misho     241:         iperf_free_stream(sp);
                    242:     }
1.1.1.2 ! misho     243:     close(test->ctrl_sck);
1.1       misho     244: }
                    245: 
                    246: static void
1.1.1.2 ! misho     247: server_stats_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
1.1       misho     248: {
                    249:     struct iperf_test *test = client_data.p;
                    250: 
                    251:     if (test->done)
                    252:         return;
                    253:     if (test->stats_callback)
                    254:        test->stats_callback(test);
                    255: }
                    256: 
                    257: static void
1.1.1.2 ! misho     258: server_reporter_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
1.1       misho     259: {
                    260:     struct iperf_test *test = client_data.p;
                    261: 
                    262:     if (test->done)
                    263:         return;
                    264:     if (test->reporter_callback)
                    265:        test->reporter_callback(test);
                    266: }
                    267: 
                    268: static int
                    269: create_server_timers(struct iperf_test * test)
                    270: {
1.1.1.2 ! misho     271:     struct iperf_time now;
1.1       misho     272:     TimerClientData cd;
1.1.1.2 ! misho     273:     int max_rtt = 4; /* seconds */
        !           274:     int state_transitions = 10; /* number of state transitions in iperf3 */
        !           275:     int grace_period = max_rtt * state_transitions;
1.1       misho     276: 
1.1.1.2 ! misho     277:     if (iperf_time_now(&now) < 0) {
1.1       misho     278:        i_errno = IEINITTEST;
                    279:        return -1;
                    280:     }
                    281:     cd.p = test;
1.1.1.2 ! misho     282:     test->timer = test->stats_timer = test->reporter_timer = NULL;
        !           283:     if (test->duration != 0 ) {
        !           284:         test->done = 0;
        !           285:         test->timer = tmr_create(&now, server_timer_proc, cd, (test->duration + test->omit + grace_period) * SEC_TO_US, 0);
        !           286:         if (test->timer == NULL) {
        !           287:             i_errno = IEINITTEST;
        !           288:             return -1;
        !           289:         }
        !           290:     }
        !           291: 
1.1       misho     292:     test->stats_timer = test->reporter_timer = NULL;
                    293:     if (test->stats_interval != 0) {
                    294:         test->stats_timer = tmr_create(&now, server_stats_timer_proc, cd, test->stats_interval * SEC_TO_US, 1);
                    295:         if (test->stats_timer == NULL) {
                    296:             i_errno = IEINITTEST;
                    297:             return -1;
                    298:        }
                    299:     }
                    300:     if (test->reporter_interval != 0) {
                    301:         test->reporter_timer = tmr_create(&now, server_reporter_timer_proc, cd, test->reporter_interval * SEC_TO_US, 1);
                    302:         if (test->reporter_timer == NULL) {
                    303:             i_errno = IEINITTEST;
                    304:             return -1;
                    305:        }
                    306:     }
                    307:     return 0;
                    308: }
                    309: 
                    310: static void
1.1.1.2 ! misho     311: server_omit_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
1.1       misho     312: {   
                    313:     struct iperf_test *test = client_data.p;
                    314: 
                    315:     test->omit_timer = NULL;
                    316:     test->omitting = 0;
                    317:     iperf_reset_stats(test);
                    318:     if (test->verbose && !test->json_output && test->reporter_interval == 0)
1.1.1.2 ! misho     319:        iperf_printf(test, "%s", report_omit_done);
1.1       misho     320: 
                    321:     /* Reset the timers. */
                    322:     if (test->stats_timer != NULL)
                    323:        tmr_reset(nowP, test->stats_timer);
                    324:     if (test->reporter_timer != NULL)
                    325:        tmr_reset(nowP, test->reporter_timer);
                    326: }
                    327: 
                    328: static int
                    329: create_server_omit_timer(struct iperf_test * test)
                    330: {
1.1.1.2 ! misho     331:     struct iperf_time now;
1.1       misho     332:     TimerClientData cd; 
                    333: 
                    334:     if (test->omit == 0) {
                    335:        test->omit_timer = NULL;
                    336:        test->omitting = 0;
                    337:     } else {
1.1.1.2 ! misho     338:        if (iperf_time_now(&now) < 0) {
1.1       misho     339:            i_errno = IEINITTEST;
                    340:            return -1; 
                    341:        }
                    342:        test->omitting = 1;
                    343:        cd.p = test;
                    344:        test->omit_timer = tmr_create(&now, server_omit_timer_proc, cd, test->omit * SEC_TO_US, 0); 
                    345:        if (test->omit_timer == NULL) {
                    346:            i_errno = IEINITTEST;
                    347:            return -1;
                    348:        }
                    349:     }
                    350: 
                    351:     return 0;
                    352: }
                    353: 
                    354: static void
                    355: cleanup_server(struct iperf_test *test)
                    356: {
1.1.1.2 ! misho     357:     struct iperf_stream *sp;
        !           358: 
        !           359:     /* Close open streams */
        !           360:     SLIST_FOREACH(sp, &test->streams, streams) {
        !           361:        FD_CLR(sp->socket, &test->read_set);
        !           362:        FD_CLR(sp->socket, &test->write_set);
        !           363:        close(sp->socket);
        !           364:     }
        !           365: 
1.1       misho     366:     /* Close open test sockets */
1.1.1.2 ! misho     367:     if (test->ctrl_sck) {
        !           368:        close(test->ctrl_sck);
        !           369:     }
        !           370:     if (test->listener) {
        !           371:        close(test->listener);
        !           372:     }
1.1       misho     373: 
                    374:     /* Cancel any remaining timers. */
                    375:     if (test->stats_timer != NULL) {
                    376:        tmr_cancel(test->stats_timer);
                    377:        test->stats_timer = NULL;
                    378:     }
                    379:     if (test->reporter_timer != NULL) {
                    380:        tmr_cancel(test->reporter_timer);
                    381:        test->reporter_timer = NULL;
                    382:     }
                    383:     if (test->omit_timer != NULL) {
                    384:        tmr_cancel(test->omit_timer);
                    385:        test->omit_timer = NULL;
                    386:     }
1.1.1.2 ! misho     387:     if (test->congestion_used != NULL) {
        !           388:         free(test->congestion_used);
        !           389:        test->congestion_used = NULL;
        !           390:     }
        !           391:     if (test->timer != NULL) {
        !           392:         tmr_cancel(test->timer);
        !           393:         test->timer = NULL;
        !           394:     }
1.1       misho     395: }
                    396: 
                    397: 
                    398: int
                    399: iperf_run_server(struct iperf_test *test)
                    400: {
1.1.1.2 ! misho     401:     int result, s;
        !           402:     int send_streams_accepted, rec_streams_accepted;
        !           403:     int streams_to_send = 0, streams_to_rec = 0;
        !           404: #if defined(HAVE_TCP_CONGESTION)
        !           405:     int saved_errno;
        !           406: #endif /* HAVE_TCP_CONGESTION */
1.1       misho     407:     fd_set read_set, write_set;
                    408:     struct iperf_stream *sp;
1.1.1.2 ! misho     409:     struct iperf_time now;
1.1       misho     410:     struct timeval* timeout;
1.1.1.2 ! misho     411:     int flag;
        !           412: 
        !           413:     if (test->logfile)
        !           414:         if (iperf_open_logfile(test) < 0)
        !           415:             return -1;
1.1       misho     416: 
                    417:     if (test->affinity != -1) 
                    418:        if (iperf_setaffinity(test, test->affinity) != 0)
                    419:            return -2;
                    420: 
                    421:     if (test->json_output)
                    422:        if (iperf_json_start(test) < 0)
                    423:            return -2;
                    424: 
                    425:     if (test->json_output) {
                    426:        cJSON_AddItemToObject(test->json_start, "version", cJSON_CreateString(version));
                    427:        cJSON_AddItemToObject(test->json_start, "system_info", cJSON_CreateString(get_system_info()));
                    428:     } else if (test->verbose) {
1.1.1.2 ! misho     429:        iperf_printf(test, "%s\n", version);
        !           430:        iperf_printf(test, "%s", "");
        !           431:        iperf_printf(test, "%s\n", get_system_info());
1.1       misho     432:        iflush(test);
                    433:     }
                    434: 
                    435:     // Open socket and listen
                    436:     if (iperf_server_listen(test) < 0) {
                    437:         return -2;
                    438:     }
                    439: 
                    440:     // Begin calculating CPU utilization
                    441:     cpu_util(NULL);
                    442: 
                    443:     test->state = IPERF_START;
1.1.1.2 ! misho     444:     send_streams_accepted = 0;
        !           445:     rec_streams_accepted = 0;
1.1       misho     446: 
                    447:     while (test->state != IPERF_DONE) {
                    448: 
1.1.1.2 ! misho     449:         // Check if average transfer rate was exceeded (condition set in the callback routines)
        !           450:        if (test->bitrate_limit_exceeded) {
        !           451:            cleanup_server(test);
        !           452:             i_errno = IETOTALRATE;
        !           453:             return -1; 
        !           454:        }
        !           455: 
1.1       misho     456:         memcpy(&read_set, &test->read_set, sizeof(fd_set));
                    457:         memcpy(&write_set, &test->write_set, sizeof(fd_set));
                    458: 
1.1.1.2 ! misho     459:        iperf_time_now(&now);
1.1       misho     460:        timeout = tmr_timeout(&now);
                    461:         result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
1.1.1.2 ! misho     462: 
1.1       misho     463:         if (result < 0 && errno != EINTR) {
                    464:            cleanup_server(test);
                    465:             i_errno = IESELECT;
                    466:             return -1;
                    467:         }
                    468:        if (result > 0) {
                    469:             if (FD_ISSET(test->listener, &read_set)) {
                    470:                 if (test->state != CREATE_STREAMS) {
                    471:                     if (iperf_accept(test) < 0) {
                    472:                        cleanup_server(test);
                    473:                         return -1;
                    474:                     }
                    475:                     FD_CLR(test->listener, &read_set);
1.1.1.2 ! misho     476: 
        !           477:                     // Set streams number
        !           478:                     if (test->mode == BIDIRECTIONAL) {
        !           479:                         streams_to_send = test->num_streams;
        !           480:                         streams_to_rec = test->num_streams;
        !           481:                     } else if (test->mode == RECEIVER) {
        !           482:                         streams_to_rec = test->num_streams;
        !           483:                         streams_to_send = 0;
        !           484:                     } else {
        !           485:                         streams_to_send = test->num_streams;
        !           486:                         streams_to_rec = 0;
        !           487:                     }
1.1       misho     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: 
1.1.1.2 ! misho     506: #if defined(HAVE_TCP_CONGESTION)
        !           507:                    if (test->protocol->id == Ptcp) {
        !           508:                        if (test->congestion) {
        !           509:                            if (setsockopt(s, IPPROTO_TCP, TCP_CONGESTION, test->congestion, strlen(test->congestion)) < 0) {
        !           510:                                /*
        !           511:                                 * ENOENT means we tried to set the
        !           512:                                 * congestion algorithm but the algorithm
        !           513:                                 * specified doesn't exist.  This can happen
        !           514:                                 * if the client and server have different
        !           515:                                 * congestion algorithms available.  In this
        !           516:                                 * case, print a warning, but otherwise
        !           517:                                 * continue.
        !           518:                                 */
        !           519:                                if (errno == ENOENT) {
        !           520:                                    warning("TCP congestion control algorithm not supported");
        !           521:                                }
        !           522:                                else {
        !           523:                                    saved_errno = errno;
        !           524:                                    close(s);
        !           525:                                    cleanup_server(test);
        !           526:                                    errno = saved_errno;
        !           527:                                    i_errno = IESETCONGESTION;
        !           528:                                    return -1;
        !           529:                                }
        !           530:                            } 
1.1       misho     531:                        }
1.1.1.2 ! misho     532:                        {
        !           533:                            socklen_t len = TCP_CA_NAME_MAX;
        !           534:                            char ca[TCP_CA_NAME_MAX + 1];
        !           535:                            if (getsockopt(s, IPPROTO_TCP, TCP_CONGESTION, ca, &len) < 0) {
        !           536:                                saved_errno = errno;
        !           537:                                close(s);
        !           538:                                cleanup_server(test);
        !           539:                                errno = saved_errno;
        !           540:                                i_errno = IESETCONGESTION;
        !           541:                                return -1;
        !           542:                            }
        !           543:                            test->congestion_used = strdup(ca);
        !           544:                            if (test->debug) {
        !           545:                                printf("Congestion algorithm is %s\n", test->congestion_used);
        !           546:                            }
1.1       misho     547:                        }
1.1.1.2 ! misho     548:                    }
        !           549: #endif /* HAVE_TCP_CONGESTION */
1.1       misho     550: 
1.1.1.2 ! misho     551:                     if (!is_closed(s)) {
        !           552: 
        !           553:                         if (rec_streams_accepted != streams_to_rec) {
        !           554:                             flag = 0;
        !           555:                             ++rec_streams_accepted;
        !           556:                         } else if (send_streams_accepted != streams_to_send) {
        !           557:                             flag = 1;
        !           558:                             ++send_streams_accepted;
        !           559:                         }
        !           560: 
        !           561:                         if (flag != -1) {
        !           562:                             sp = iperf_new_stream(test, s, flag);
        !           563:                             if (!sp) {
        !           564:                                 cleanup_server(test);
        !           565:                                 return -1;
        !           566:                             }
        !           567: 
        !           568:                             if (sp->sender)
        !           569:                                 FD_SET(s, &test->write_set);
        !           570:                             else
        !           571:                                 FD_SET(s, &test->read_set);
        !           572: 
        !           573:                             if (s > test->max_fd) test->max_fd = s;
        !           574: 
        !           575:                             /*
        !           576:                              * If the protocol isn't UDP, or even if it is but
        !           577:                              * we're the receiver, set nonblocking sockets.
        !           578:                              * We need this to allow a server receiver to
        !           579:                              * maintain interactivity with the control channel.
        !           580:                              */
        !           581:                             if (test->protocol->id != Pudp ||
        !           582:                                 !sp->sender) {
        !           583:                                 setnonblocking(s, 1);
        !           584:                             }
        !           585: 
        !           586:                             if (test->on_new_stream)
        !           587:                                 test->on_new_stream(sp);
        !           588: 
        !           589:                             flag = -1;
        !           590:                         }
1.1       misho     591:                     }
                    592:                     FD_CLR(test->prot_listener, &read_set);
                    593:                 }
                    594: 
1.1.1.2 ! misho     595: 
        !           596:                 if (rec_streams_accepted == streams_to_rec && send_streams_accepted == streams_to_send) {
1.1       misho     597:                     if (test->protocol->id != Ptcp) {
                    598:                         FD_CLR(test->prot_listener, &test->read_set);
                    599:                         close(test->prot_listener);
                    600:                     } else { 
                    601:                         if (test->no_delay || test->settings->mss || test->settings->socket_bufsize) {
                    602:                             FD_CLR(test->listener, &test->read_set);
                    603:                             close(test->listener);
1.1.1.2 ! misho     604:                            test->listener = 0;
1.1       misho     605:                             if ((s = netannounce(test->settings->domain, Ptcp, test->bind_address, test->server_port)) < 0) {
                    606:                                cleanup_server(test);
                    607:                                 i_errno = IELISTEN;
                    608:                                 return -1;
                    609:                             }
                    610:                             test->listener = s;
                    611:                             FD_SET(test->listener, &test->read_set);
                    612:                            if (test->listener > test->max_fd) test->max_fd = test->listener;
                    613:                         }
                    614:                     }
                    615:                     test->prot_listener = -1;
1.1.1.2 ! misho     616: 
        !           617:                    /* Ensure that total requested data rate is not above limit */
        !           618:                    iperf_size_t total_requested_rate = test->num_streams * test->settings->rate * (test->mode == BIDIRECTIONAL? 2 : 1);
        !           619:                    if (test->settings->bitrate_limit > 0 && total_requested_rate > test->settings->bitrate_limit) {
        !           620:                        iperf_err(test, "Client total requested throughput rate of %" PRIu64 " bps exceeded %" PRIu64 " bps limit",
        !           621:                                total_requested_rate, test->settings->bitrate_limit);
        !           622:                        cleanup_server(test);
        !           623:                        i_errno = IETOTALRATE;
        !           624:                        return -1;
        !           625:                    }
        !           626: 
1.1       misho     627:                    if (iperf_set_send_state(test, TEST_START) != 0) {
                    628:                        cleanup_server(test);
                    629:                         return -1;
                    630:                    }
                    631:                     if (iperf_init_test(test) < 0) {
                    632:                        cleanup_server(test);
                    633:                         return -1;
                    634:                    }
                    635:                    if (create_server_timers(test) < 0) {
                    636:                        cleanup_server(test);
                    637:                         return -1;
                    638:                    }
                    639:                    if (create_server_omit_timer(test) < 0) {
                    640:                        cleanup_server(test);
                    641:                         return -1;
                    642:                    }
1.1.1.2 ! misho     643:                    if (test->mode != RECEIVER)
1.1       misho     644:                        if (iperf_create_send_timers(test) < 0) {
                    645:                            cleanup_server(test);
                    646:                            return -1;
                    647:                        }
                    648:                    if (iperf_set_send_state(test, TEST_RUNNING) != 0) {
                    649:                        cleanup_server(test);
                    650:                         return -1;
                    651:                    }
                    652:                 }
                    653:             }
                    654: 
                    655:             if (test->state == TEST_RUNNING) {
1.1.1.2 ! misho     656:                 if (test->mode == BIDIRECTIONAL) {
        !           657:                     if (iperf_recv(test, &read_set) < 0) {
        !           658:                         cleanup_server(test);
        !           659:                         return -1;
        !           660:                     }
        !           661:                     if (iperf_send(test, &write_set) < 0) {
        !           662:                         cleanup_server(test);
        !           663:                         return -1;
        !           664:                     }
        !           665:                 } else if (test->mode == SENDER) {
1.1       misho     666:                     // Reverse mode. Server sends.
                    667:                     if (iperf_send(test, &write_set) < 0) {
                    668:                        cleanup_server(test);
                    669:                         return -1;
                    670:                    }
                    671:                 } else {
                    672:                     // Regular mode. Server receives.
                    673:                     if (iperf_recv(test, &read_set) < 0) {
                    674:                        cleanup_server(test);
                    675:                         return -1;
                    676:                    }
                    677:                 }
1.1.1.2 ! misho     678:            }
1.1       misho     679:         }
                    680: 
                    681:        if (result == 0 ||
                    682:            (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0)) {
                    683:            /* Run the timers. */
1.1.1.2 ! misho     684:            iperf_time_now(&now);
1.1       misho     685:            tmr_run(&now);
                    686:        }
                    687:     }
                    688: 
                    689:     cleanup_server(test);
                    690: 
                    691:     if (test->json_output) {
                    692:        if (iperf_json_finish(test) < 0)
                    693:            return -1;
                    694:     } 
                    695: 
                    696:     iflush(test);
                    697: 
                    698:     if (test->server_affinity != -1) 
                    699:        if (iperf_clearaffinity(test) != 0)
                    700:            return -1;
                    701: 
                    702:     return 0;
                    703: }

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