All client side error handling is now handled by iperf_error
Этот коммит содержится в:
родитель
01ca972b6c
Коммит
3118b42010
207
src/iperf_api.c
207
src/iperf_api.c
@ -287,16 +287,17 @@ iperf_send(struct iperf_test *test)
|
|||||||
|
|
||||||
result = select(test->max_fd + 1, NULL, &temp_write_set, NULL, &tv);
|
result = select(test->max_fd + 1, NULL, &temp_write_set, NULL, &tv);
|
||||||
if (result < 0 && errno != EINTR) {
|
if (result < 0 && errno != EINTR) {
|
||||||
perror("select iperf_send");
|
// perror("select iperf_send");
|
||||||
return -1;
|
i_errno = IESELECT;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
for (sp = test->streams; sp != NULL; sp = sp->next) {
|
for (sp = test->streams; sp != NULL; sp = sp->next) {
|
||||||
if (FD_ISSET(sp->socket, &temp_write_set)) {
|
if (FD_ISSET(sp->socket, &temp_write_set)) {
|
||||||
if ((bytes_sent = sp->snd(sp)) < 0) {
|
if ((bytes_sent = sp->snd(sp)) < 0) {
|
||||||
// XXX: Do better error handling
|
// perror("iperf stream->snd");
|
||||||
perror("iperf stream->snd");
|
i_errno = IESTREAMWRITE;
|
||||||
return -1;
|
return (-1);
|
||||||
}
|
}
|
||||||
test->bytes_sent += bytes_sent;
|
test->bytes_sent += bytes_sent;
|
||||||
FD_CLR(sp->socket, &temp_write_set);
|
FD_CLR(sp->socket, &temp_write_set);
|
||||||
@ -322,16 +323,17 @@ iperf_recv(struct iperf_test *test)
|
|||||||
|
|
||||||
result = select(test->max_fd + 1, &temp_read_set, NULL, NULL, &tv);
|
result = select(test->max_fd + 1, &temp_read_set, NULL, NULL, &tv);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
perror("select iperf_recv");
|
// perror("select iperf_recv");
|
||||||
return -1;
|
i_errno = IESELECT;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
for (sp = test->streams; sp != NULL; sp = sp->next) {
|
for (sp = test->streams; sp != NULL; sp = sp->next) {
|
||||||
if (FD_ISSET(sp->socket, &temp_read_set)) {
|
if (FD_ISSET(sp->socket, &temp_read_set)) {
|
||||||
if ((bytes_sent = sp->rcv(sp)) < 0) {
|
if ((bytes_sent = sp->rcv(sp)) < 0) {
|
||||||
// XXX: Do better error handling
|
// perror("sp->rcv(sp)");
|
||||||
perror("sp->rcv(sp)");
|
i_errno = IESTREAMREAD;
|
||||||
return -1;
|
return (-1);
|
||||||
}
|
}
|
||||||
test->bytes_sent += bytes_sent;
|
test->bytes_sent += bytes_sent;
|
||||||
FD_CLR(sp->socket, &temp_read_set);
|
FD_CLR(sp->socket, &temp_read_set);
|
||||||
@ -444,8 +446,8 @@ package_parameters(struct iperf_test *test)
|
|||||||
*pstring = (char) (strlen(pstring) - 1);
|
*pstring = (char) (strlen(pstring) - 1);
|
||||||
|
|
||||||
if (Nwrite(test->ctrl_sck, pstring, (size_t) strlen(pstring), Ptcp) < 0) {
|
if (Nwrite(test->ctrl_sck, pstring, (size_t) strlen(pstring), Ptcp) < 0) {
|
||||||
perror("Nwrite pstring");
|
i_errno = IESENDPARAMS;
|
||||||
return -1;
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -547,7 +549,8 @@ iperf_exchange_parameters(struct iperf_test * test)
|
|||||||
|
|
||||||
if (test->role == 'c') {
|
if (test->role == 'c') {
|
||||||
|
|
||||||
package_parameters(test);
|
if (package_parameters(test) < 0)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
parse_parameters(test);
|
parse_parameters(test);
|
||||||
@ -639,8 +642,9 @@ iperf_exchange_results(struct iperf_test *test)
|
|||||||
sp->cnt_error, sp->packet_count);
|
sp->cnt_error, sp->packet_count);
|
||||||
size += strlen(buf);
|
size += strlen(buf);
|
||||||
if ((results = realloc(results, size+1)) == NULL) {
|
if ((results = realloc(results, size+1)) == NULL) {
|
||||||
perror("realloc results");
|
// perror("realloc results");
|
||||||
return -1;
|
i_errno = IEPACKAGERESULTS;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
if (sp == test->streams)
|
if (sp == test->streams)
|
||||||
*results = '\0';
|
*results = '\0';
|
||||||
@ -649,32 +653,39 @@ iperf_exchange_results(struct iperf_test *test)
|
|||||||
size++;
|
size++;
|
||||||
size = htonl(size);
|
size = htonl(size);
|
||||||
if (Nwrite(test->ctrl_sck, &size, sizeof(size), Ptcp) < 0) {
|
if (Nwrite(test->ctrl_sck, &size, sizeof(size), Ptcp) < 0) {
|
||||||
perror("Nwrite size");
|
// perror("Nwrite size");
|
||||||
|
i_errno = IESENDRESULTS;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if (Nwrite(test->ctrl_sck, results, ntohl(size), Ptcp) < 0) {
|
if (Nwrite(test->ctrl_sck, results, ntohl(size), Ptcp) < 0) {
|
||||||
perror("Nwrite results");
|
// perror("Nwrite results");
|
||||||
|
i_errno = IESENDRESULTS;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
free(results);
|
free(results);
|
||||||
|
|
||||||
/* Get server results string */
|
/* Get server results string */
|
||||||
if (Nread(test->ctrl_sck, &size, sizeof(size), Ptcp) < 0) {
|
if (Nread(test->ctrl_sck, &size, sizeof(size), Ptcp) < 0) {
|
||||||
perror("Nread size");
|
// perror("Nread size");
|
||||||
|
i_errno = IERECVRESULTS;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
size = ntohl(size);
|
size = ntohl(size);
|
||||||
results = (char *) malloc(size * sizeof(char));
|
results = (char *) malloc(size * sizeof(char));
|
||||||
if (results == NULL) {
|
if (results == NULL) {
|
||||||
perror("malloc results");
|
// perror("malloc results");
|
||||||
|
i_errno = IERECVRESULTS;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if (Nread(test->ctrl_sck, results, size, Ptcp) < 0) {
|
if (Nread(test->ctrl_sck, results, size, Ptcp) < 0) {
|
||||||
perror("Nread results");
|
// perror("Nread results");
|
||||||
|
i_errno = IERECVRESULTS;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_results(test, results);
|
// XXX: The only error this sets is IESTREAMID, which may never be reached. Consider making void.
|
||||||
|
if (parse_results(test, results) < 0)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
free(results);
|
free(results);
|
||||||
|
|
||||||
@ -749,7 +760,8 @@ parse_results(struct iperf_test *test, char *results)
|
|||||||
for (sp = test->streams; sp; sp = sp->next)
|
for (sp = test->streams; sp; sp = sp->next)
|
||||||
if (sp->id == sid) break;
|
if (sp->id == sid) break;
|
||||||
if (sp == NULL) {
|
if (sp == NULL) {
|
||||||
fprintf(stderr, "error: No stream with id %d\n", sid);
|
// fprintf(stderr, "error: No stream with id %d\n", sid);
|
||||||
|
i_errno = IESTREAMID;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if ((test->role == 'c' && !test->reverse) || (test->role == 's' && test->reverse)) {
|
if ((test->role == 'c' && !test->reverse) || (test->role == 's' && test->reverse)) {
|
||||||
@ -871,7 +883,7 @@ iperf_new_test()
|
|||||||
|
|
||||||
testp = (struct iperf_test *) malloc(sizeof(struct iperf_test));
|
testp = (struct iperf_test *) malloc(sizeof(struct iperf_test));
|
||||||
if (!testp) {
|
if (!testp) {
|
||||||
perror("malloc");
|
i_errno = IENEWTEST;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
/* initialize everything to zero */
|
/* initialize everything to zero */
|
||||||
@ -923,11 +935,11 @@ iperf_create_streams(struct iperf_test *test)
|
|||||||
for (i = 0; i < test->num_streams; ++i) {
|
for (i = 0; i < test->num_streams; ++i) {
|
||||||
if (test->protocol == Ptcp && (test->no_delay || test->default_settings->mss)) {
|
if (test->protocol == Ptcp && (test->no_delay || test->default_settings->mss)) {
|
||||||
if ((hent = gethostbyname(test->server_hostname)) == 0) {
|
if ((hent = gethostbyname(test->server_hostname)) == 0) {
|
||||||
perror("gethostbyname");
|
i_errno = IECREATESTREAM;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||||
perror("socket");
|
i_errno = IECREATESTREAM;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
@ -938,42 +950,51 @@ iperf_create_streams(struct iperf_test *test)
|
|||||||
if (test->no_delay) {
|
if (test->no_delay) {
|
||||||
opt = 1;
|
opt = 1;
|
||||||
if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
|
if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
|
||||||
perror("setsockopt");
|
// perror("setsockopt");
|
||||||
|
i_errno = IECREATESTREAM;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (opt = test->default_settings->mss) {
|
if (opt = test->default_settings->mss) {
|
||||||
if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) {
|
if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) {
|
||||||
perror("setsockopt");
|
// perror("setsockopt");
|
||||||
|
i_errno = IECREATESTREAM;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0 && errno != EINPROGRESS) {
|
if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0 && errno != EINPROGRESS) {
|
||||||
perror("connect tcp stream");
|
// perror("connect tcp stream");
|
||||||
|
i_errno = IECREATESTREAM;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s = netdial(test->protocol, test->server_hostname, test->server_port);
|
s = netdial(test->protocol, test->server_hostname, test->server_port);
|
||||||
if (s < 0) {
|
if (s < 0) {
|
||||||
perror("netdial stream");
|
// perror("netdial stream");
|
||||||
return -1;
|
i_errno = IECREATESTREAM;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test->protocol == Ptcp) {
|
if (test->protocol == Ptcp) {
|
||||||
if (Nwrite(s, test->default_settings->cookie, COOKIE_SIZE, Ptcp) < 0) {
|
if (Nwrite(s, test->default_settings->cookie, COOKIE_SIZE, Ptcp) < 0) {
|
||||||
perror("Nwrite COOKIE\n");
|
// perror("Nwrite COOKIE\n");
|
||||||
return -1;
|
i_errno = IESTREAMWRITE;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
/* Write to the UDP stream to give the server this stream's credentials */
|
||||||
if (write(s, &buf, sizeof(i)) < 0) {
|
if (write(s, &buf, sizeof(i)) < 0) {
|
||||||
perror("write data");
|
// perror("write data");
|
||||||
return -1;
|
i_errno = IESTREAMWRITE;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
/* Wait until the server confirms the client UDP write */
|
||||||
// XXX: Should this read be TCP instead?
|
// XXX: Should this read be TCP instead?
|
||||||
if (read(s, &buf, sizeof(i)) < 0) {
|
if (read(s, &buf, sizeof(i)) < 0) {
|
||||||
perror("read data");
|
// perror("read data");
|
||||||
return -1;
|
i_errno = IESTREAMREAD;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -983,8 +1004,11 @@ iperf_create_streams(struct iperf_test *test)
|
|||||||
|
|
||||||
// XXX: This doesn't fit our API model!
|
// XXX: This doesn't fit our API model!
|
||||||
sp = test->new_stream(test);
|
sp = test->new_stream(test);
|
||||||
|
if (!sp)
|
||||||
|
return (-1);
|
||||||
sp->socket = s;
|
sp->socket = s;
|
||||||
iperf_init_stream(sp, test);
|
if (iperf_init_stream(sp, test) < 0)
|
||||||
|
return (-1);
|
||||||
iperf_add_stream(test, sp);
|
iperf_add_stream(test, sp);
|
||||||
|
|
||||||
connect_msg(sp);
|
connect_msg(sp);
|
||||||
@ -1000,20 +1024,24 @@ iperf_handle_message_client(struct iperf_test *test)
|
|||||||
|
|
||||||
if ((rval = read(test->ctrl_sck, &test->state, sizeof(char))) <= 0) {
|
if ((rval = read(test->ctrl_sck, &test->state, sizeof(char))) <= 0) {
|
||||||
if (rval == 0) {
|
if (rval == 0) {
|
||||||
fprintf(stderr, "The server has unexpectedly closed the connection. Exiting...\n");
|
// fprintf(stderr, "The server has unexpectedly closed the connection. Exiting...\n");
|
||||||
exit(1);
|
i_errno = IECTRLCLOSE;
|
||||||
|
return (-1);
|
||||||
} else {
|
} else {
|
||||||
perror("read ctrl_sck");
|
// perror("read ctrl_sck");
|
||||||
return -1;
|
i_errno = IERECVMESSAGE;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (test->state) {
|
switch (test->state) {
|
||||||
case PARAM_EXCHANGE:
|
case PARAM_EXCHANGE:
|
||||||
iperf_exchange_parameters(test);
|
if (iperf_exchange_parameters(test) < 0)
|
||||||
|
return (-1);
|
||||||
break;
|
break;
|
||||||
case CREATE_STREAMS:
|
case CREATE_STREAMS:
|
||||||
iperf_create_streams(test);
|
if (iperf_create_streams(test) < 0)
|
||||||
|
return (-1);
|
||||||
break;
|
break;
|
||||||
case TEST_START:
|
case TEST_START:
|
||||||
iperf_init_test(test);
|
iperf_init_test(test);
|
||||||
@ -1021,7 +1049,8 @@ iperf_handle_message_client(struct iperf_test *test)
|
|||||||
case TEST_RUNNING:
|
case TEST_RUNNING:
|
||||||
break;
|
break;
|
||||||
case EXCHANGE_RESULTS:
|
case EXCHANGE_RESULTS:
|
||||||
iperf_exchange_results(test);
|
if (iperf_exchange_results(test) < 0)
|
||||||
|
return (-1);
|
||||||
break;
|
break;
|
||||||
case DISPLAY_RESULTS:
|
case DISPLAY_RESULTS:
|
||||||
iperf_client_end(test);
|
iperf_client_end(test);
|
||||||
@ -1029,15 +1058,18 @@ iperf_handle_message_client(struct iperf_test *test)
|
|||||||
case IPERF_DONE:
|
case IPERF_DONE:
|
||||||
break;
|
break;
|
||||||
case SERVER_TERMINATE:
|
case SERVER_TERMINATE:
|
||||||
fprintf(stderr, "The server has terminated. Exiting...\n");
|
// fprintf(stderr, "The server has terminated. Exiting...\n");
|
||||||
exit(1);
|
i_errno = IESERVERTERM;
|
||||||
|
return (-1);
|
||||||
case ACCESS_DENIED:
|
case ACCESS_DENIED:
|
||||||
fprintf(stderr, "The server is busy running a test. Try again later.\n");
|
// fprintf(stderr, "The server is busy running a test. Try again later.\n");
|
||||||
exit(0);
|
// exit(0);
|
||||||
|
i_errno = IEACCESSDENIED;
|
||||||
|
return (-1);
|
||||||
default:
|
default:
|
||||||
// XXX: This needs to be removed from the production version
|
// printf("How did you get here? test->state = %d\n", test->state);
|
||||||
printf("How did you get here? test->state = %d\n", test->state);
|
i_errno = IEMESSAGE;
|
||||||
break;
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1057,12 +1089,13 @@ iperf_connect(struct iperf_test *test)
|
|||||||
/* Create and connect the control channel */
|
/* Create and connect the control channel */
|
||||||
test->ctrl_sck = netdial(Ptcp, test->server_hostname, test->server_port);
|
test->ctrl_sck = netdial(Ptcp, test->server_hostname, test->server_port);
|
||||||
if (test->ctrl_sck < 0) {
|
if (test->ctrl_sck < 0) {
|
||||||
return -1;
|
i_errno = IECONNECT;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Nwrite(test->ctrl_sck, test->default_settings->cookie, COOKIE_SIZE, Ptcp) < 0) {
|
if (Nwrite(test->ctrl_sck, test->default_settings->cookie, COOKIE_SIZE, Ptcp) < 0) {
|
||||||
perror("Nwrite COOKIE\n");
|
i_errno = IECTRLWRITE; // XXX: should this set IECONNECT instead?
|
||||||
return -1;
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
FD_SET(test->ctrl_sck, &test->read_set);
|
FD_SET(test->ctrl_sck, &test->read_set);
|
||||||
@ -1324,7 +1357,8 @@ iperf_new_stream(struct iperf_test *testp)
|
|||||||
|
|
||||||
sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream));
|
sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream));
|
||||||
if (!sp) {
|
if (!sp) {
|
||||||
perror("malloc");
|
// perror("malloc");
|
||||||
|
i_errno = IECREATESTREAM;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
memset(sp, 0, sizeof(struct iperf_stream));
|
memset(sp, 0, sizeof(struct iperf_stream));
|
||||||
@ -1334,16 +1368,19 @@ iperf_new_stream(struct iperf_test *testp)
|
|||||||
sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));
|
sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));
|
||||||
|
|
||||||
if (!sp->buffer) {
|
if (!sp->buffer) {
|
||||||
perror("Malloc sp->buffer");
|
// perror("Malloc sp->buffer");
|
||||||
return NULL;
|
i_errno = IECREATESTREAM;
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
if (!sp->settings) {
|
if (!sp->settings) {
|
||||||
perror("Malloc sp->settings");
|
// perror("Malloc sp->settings");
|
||||||
return NULL;
|
i_errno = IECREATESTREAM;
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
if (!sp->result) {
|
if (!sp->result) {
|
||||||
perror("Malloc sp->result");
|
// perror("Malloc sp->result");
|
||||||
return NULL;
|
i_errno = IECREATESTREAM;
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make a per stream copy of default_settings in each stream structure */
|
/* Make a per stream copy of default_settings in each stream structure */
|
||||||
@ -1379,7 +1416,7 @@ iperf_new_stream(struct iperf_test *testp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void
|
int
|
||||||
iperf_init_stream(struct iperf_stream * sp, struct iperf_test * testp)
|
iperf_init_stream(struct iperf_stream * sp, struct iperf_test * testp)
|
||||||
{
|
{
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
@ -1387,24 +1424,30 @@ iperf_init_stream(struct iperf_stream * sp, struct iperf_test * testp)
|
|||||||
len = sizeof(struct sockaddr_in);
|
len = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
if (getsockname(sp->socket, (struct sockaddr *) &sp->local_addr, &len) < 0) {
|
if (getsockname(sp->socket, (struct sockaddr *) &sp->local_addr, &len) < 0) {
|
||||||
perror("getsockname");
|
i_errno = IEINITSTREAM;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
if (getpeername(sp->socket, (struct sockaddr *) &sp->remote_addr, &len) < 0) {
|
if (getpeername(sp->socket, (struct sockaddr *) &sp->remote_addr, &len) < 0) {
|
||||||
perror("getpeername");
|
i_errno = IEINITSTREAM;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
if (testp->protocol == Ptcp) {
|
if (testp->protocol == Ptcp) {
|
||||||
|
// XXX: This property is for all sockets, not just TCP
|
||||||
if (set_tcp_windowsize(sp->socket, testp->default_settings->socket_bufsize,
|
if (set_tcp_windowsize(sp->socket, testp->default_settings->socket_bufsize,
|
||||||
testp->role == 's' ? SO_RCVBUF : SO_SNDBUF) < 0)
|
testp->role == 's' ? SO_RCVBUF : SO_SNDBUF) < 0) {
|
||||||
fprintf(stderr, "unable to set window size\n");
|
i_errno = IESETWINDOWSIZE;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
/* set TCP_NODELAY and TCP_MAXSEG if requested */
|
/* set TCP_NODELAY and TCP_MAXSEG if requested */
|
||||||
set_tcp_options(sp->socket, testp->no_delay, testp->default_settings->mss);
|
// XXX: This has been moved
|
||||||
|
// set_tcp_options(sp->socket, testp->no_delay, testp->default_settings->mss);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
int
|
void
|
||||||
iperf_add_stream(struct iperf_test * test, struct iperf_stream * sp)
|
iperf_add_stream(struct iperf_test * test, struct iperf_stream * sp)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -1413,15 +1456,11 @@ iperf_add_stream(struct iperf_test * test, struct iperf_stream * sp)
|
|||||||
if (!test->streams) {
|
if (!test->streams) {
|
||||||
test->streams = sp;
|
test->streams = sp;
|
||||||
sp->id = 1;
|
sp->id = 1;
|
||||||
return 1;
|
|
||||||
} else {
|
} else {
|
||||||
for (n = test->streams, i = 2; n->next; n = n->next, ++i);
|
for (n = test->streams, i = 2; n->next; n = n->next, ++i);
|
||||||
n->next = sp;
|
n->next = sp;
|
||||||
sp->id = i;
|
sp->id = i;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1471,12 +1510,15 @@ iperf_run_client(struct iperf_test * test)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: Do we need to check signal() for errors?
|
||||||
signal(SIGINT, sig_handler);
|
signal(SIGINT, sig_handler);
|
||||||
if (setjmp(env)) {
|
if (setjmp(env)) {
|
||||||
fprintf(stderr, "Exiting...\n");
|
fprintf(stderr, "Exiting...\n");
|
||||||
test->state = CLIENT_TERMINATE;
|
test->state = CLIENT_TERMINATE;
|
||||||
if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
|
if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
|
||||||
fprintf(stderr, "Unable to send CLIENT_TERMINATE message to server\n");
|
i_errno = IESENDMESSAGE;
|
||||||
|
return (-1);
|
||||||
|
// fprintf(stderr, "Unable to send CLIENT_TERMINATE message to server\n");
|
||||||
}
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -1490,21 +1532,25 @@ iperf_run_client(struct iperf_test * test)
|
|||||||
|
|
||||||
result = select(test->max_fd + 1, &temp_read_set, &temp_write_set, NULL, &tv);
|
result = select(test->max_fd + 1, &temp_read_set, &temp_write_set, NULL, &tv);
|
||||||
if (result < 0 && errno != EINTR) {
|
if (result < 0 && errno != EINTR) {
|
||||||
perror("select");
|
// perror("select");
|
||||||
exit(1);
|
i_errno = IESELECT;
|
||||||
|
return (-1);
|
||||||
} else if (result > 0) {
|
} else if (result > 0) {
|
||||||
if (FD_ISSET(test->ctrl_sck, &temp_read_set)) {
|
if (FD_ISSET(test->ctrl_sck, &temp_read_set)) {
|
||||||
iperf_handle_message_client(test);
|
if (iperf_handle_message_client(test) < 0)
|
||||||
|
return (-1);
|
||||||
FD_CLR(test->ctrl_sck, &temp_read_set);
|
FD_CLR(test->ctrl_sck, &temp_read_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test->state == TEST_RUNNING) {
|
if (test->state == TEST_RUNNING) {
|
||||||
if (test->reverse) {
|
if (test->reverse) {
|
||||||
// Reverse mode. Client receives.
|
// Reverse mode. Client receives.
|
||||||
iperf_recv(test);
|
if (iperf_recv(test) < 0)
|
||||||
|
return (-1);
|
||||||
} else {
|
} else {
|
||||||
// Regular mode. Client sends.
|
// Regular mode. Client sends.
|
||||||
iperf_send(test);
|
if (iperf_send(test) < 0)
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform callbacks */
|
/* Perform callbacks */
|
||||||
@ -1522,8 +1568,9 @@ iperf_run_client(struct iperf_test * test)
|
|||||||
test->stats_callback(test);
|
test->stats_callback(test);
|
||||||
test->state = TEST_END;
|
test->state = TEST_END;
|
||||||
if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
|
if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
|
||||||
perror("Nwrite TEST_END");
|
// perror("Nwrite TEST_END");
|
||||||
return -1;
|
i_errno = IESENDMESSAGE;
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,15 +98,14 @@ struct iperf_stream *iperf_new_udp_stream(struct iperf_test * testp);
|
|||||||
/**
|
/**
|
||||||
* iperf_add_stream -- add a stream to a test
|
* iperf_add_stream -- add a stream to a test
|
||||||
*
|
*
|
||||||
* returns 1 on success 0 on failure
|
|
||||||
*/
|
*/
|
||||||
int iperf_add_stream(struct iperf_test * test, struct iperf_stream * stream);
|
void iperf_add_stream(struct iperf_test * test, struct iperf_stream * stream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iperf_init_stream -- init resources associated with test
|
* iperf_init_stream -- init resources associated with test
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void iperf_init_stream(struct iperf_stream * sp, struct iperf_test * testp);
|
int iperf_init_stream(struct iperf_stream * sp, struct iperf_test * testp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iperf_free_stream -- free resources associated with test
|
* iperf_free_stream -- free resources associated with test
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <string.h>
|
||||||
#include "iperf.h"
|
#include "iperf.h"
|
||||||
#include "iperf_error.h"
|
#include "iperf_error.h"
|
||||||
|
|
||||||
@ -9,41 +10,161 @@ int i_errno;
|
|||||||
void
|
void
|
||||||
ierror(char *estr)
|
ierror(char *estr)
|
||||||
{
|
{
|
||||||
if (errno) {
|
fprintf(stderr, "%s: ", estr);
|
||||||
perror(estr);
|
|
||||||
} else if (h_errno) {
|
|
||||||
herror(estr);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "%s: ", estr);
|
|
||||||
|
|
||||||
switch (i_errno) {
|
switch (i_errno) {
|
||||||
case IESERVCLIENT:
|
case IESERVCLIENT:
|
||||||
fprintf(stderr, "iperf cannot be both server and client\n");
|
fprintf(stderr, "iperf cannot be both server and client\n");
|
||||||
break;
|
break;
|
||||||
case IENOROLE:
|
case IENOROLE:
|
||||||
fprintf(stderr, "iperf instance must either be a client (-c) or server (-s)\n");
|
fprintf(stderr, "iperf instance must either be a client (-c) or server (-s)\n");
|
||||||
break;
|
break;
|
||||||
case IECLIENTONLY:
|
case IECLIENTONLY:
|
||||||
fprintf(stderr, "some option you are trying to set is client only\n");
|
fprintf(stderr, "some option you are trying to set is client only\n");
|
||||||
break;
|
break;
|
||||||
case IEDURATION:
|
case IEDURATION:
|
||||||
fprintf(stderr, "test duration too long (maximum = %d seconds)\n", MAX_TIME);
|
fprintf(stderr, "test duration too long (maximum = %d seconds)\n", MAX_TIME);
|
||||||
break;
|
break;
|
||||||
case IENUMSTREAMS:
|
case IENUMSTREAMS:
|
||||||
fprintf(stderr, "number of parallel streams too large (maximum = %d)\n", MAX_STREAMS);
|
fprintf(stderr, "number of parallel streams too large (maximum = %d)\n", MAX_STREAMS);
|
||||||
break;
|
break;
|
||||||
case IEBLOCKSIZE:
|
case IEBLOCKSIZE:
|
||||||
fprintf(stderr, "block size too large (maximum = %d bytes)\n", MAX_BLOCKSIZE);
|
fprintf(stderr, "block size too large (maximum = %d bytes)\n", MAX_BLOCKSIZE);
|
||||||
break;
|
break;
|
||||||
case IEBUFSIZE:
|
case IEBUFSIZE:
|
||||||
fprintf(stderr, "socket buffer size too large (maximum = %d bytes)\n", MAX_TCP_BUFFER);
|
fprintf(stderr, "socket buffer size too large (maximum = %d bytes)\n", MAX_TCP_BUFFER);
|
||||||
break;
|
break;
|
||||||
case IEINTERVAL:
|
case IEINTERVAL:
|
||||||
fprintf(stderr, "report interval too large (maximum = %d seconds)\n", MAX_INTERVAL);
|
fprintf(stderr, "report interval too large (maximum = %d seconds)\n", MAX_INTERVAL);
|
||||||
break;
|
break;
|
||||||
case IEMSS:
|
case IEMSS:
|
||||||
fprintf(stderr, "TCP MSS too large (maximum = %d bytes)\n", MAX_MSS);
|
fprintf(stderr, "TCP MSS too large (maximum = %d bytes)\n", MAX_MSS);
|
||||||
break;
|
break;
|
||||||
}
|
case IECTRLWRITE:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to write to the control socket: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to write to the control socket\n");
|
||||||
|
break;
|
||||||
|
case IECTRLREAD:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to read from the control socket: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to read from the control socket\n");
|
||||||
|
break;
|
||||||
|
case IECTRLCLOSE:
|
||||||
|
fprintf(stderr, "control socket has closed unexpectedly\n");
|
||||||
|
break;
|
||||||
|
case IESTREAMWRITE:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to write to stream socket: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to write to stream socket\n");
|
||||||
|
break;
|
||||||
|
case IESTREAMREAD:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to read from stream socket: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to read from stream socket\n");
|
||||||
|
break;
|
||||||
|
case IESTREAMCLOSE:
|
||||||
|
fprintf(stderr, "stream socket has closed unexpectedly\n");
|
||||||
|
break;
|
||||||
|
case IENEWTEST:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to create a new test: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to create a new test\n");
|
||||||
|
break;
|
||||||
|
case IECONNECT:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to connect to server: %s\n", strerror(errno));
|
||||||
|
else if (h_errno)
|
||||||
|
fprintf(stderr, "unable to connect to server: %s\n", hstrerror(h_errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to connect to server\n");
|
||||||
|
break;
|
||||||
|
case IESELECT:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "select failed: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "select failed\n");
|
||||||
|
break;
|
||||||
|
case IESENDPARAMS:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to send parameters to server: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to send parameters to server\n");
|
||||||
|
break;
|
||||||
|
case IERECVPARAMS:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to receive parameters from client: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to receive parameters from client\n");
|
||||||
|
break;
|
||||||
|
case IECREATESTREAM:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to create a new stream: %s\n", strerror(errno));
|
||||||
|
else if (h_errno)
|
||||||
|
fprintf(stderr, "unable to create a new stream: %s\n", hstrerror(h_errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to create a new stream\n");
|
||||||
|
break;
|
||||||
|
case IEINITSTREAM:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to initialize stream: %s\n", strerror(errno));
|
||||||
|
else if (h_errno)
|
||||||
|
fprintf(stderr, "unable to initialize stream: %s\n", hstrerror(h_errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to initialize stream\n");
|
||||||
|
break;
|
||||||
|
case IESETWINDOWSIZE:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to set socket window size: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to set socket window size\n");
|
||||||
|
break;
|
||||||
|
case IEPACKAGERESULTS:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to package results: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to package results\n");
|
||||||
|
break;
|
||||||
|
case IESENDRESULTS:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to send results: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to send results\n");
|
||||||
|
break;
|
||||||
|
case IERECVRESULTS:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to receive results: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to receive results\n");
|
||||||
|
break;
|
||||||
|
case IESTREAMID:
|
||||||
|
fprintf(stderr, "stream has an invalid id\n");
|
||||||
|
break;
|
||||||
|
case IESERVERTERM:
|
||||||
|
fprintf(stderr, "the server has terminated\n");
|
||||||
|
break;
|
||||||
|
case IEACCESSDENIED:
|
||||||
|
fprintf(stderr, "the server is busy running a test. try again later.\n");
|
||||||
|
break;
|
||||||
|
case IEMESSAGE:
|
||||||
|
fprintf(stderr, "received an unknown control message\n");
|
||||||
|
break;
|
||||||
|
case IESENDMESSAGE:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to send control message: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to send control message\n");
|
||||||
|
break;
|
||||||
|
case IERECVMESSAGE:
|
||||||
|
if (errno)
|
||||||
|
fprintf(stderr, "unable to receive control message: %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
fprintf(stderr, "unable to receive control message\n");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,29 @@ enum {
|
|||||||
IEBUFSIZE = 7, // Socket buffer size too large. Maximum value = %dMAX_TCP_BUFFER
|
IEBUFSIZE = 7, // Socket buffer size too large. Maximum value = %dMAX_TCP_BUFFER
|
||||||
IEINTERVAL = 8, // Report interval too large. Maxumum value = %dMAX_INTERVAL
|
IEINTERVAL = 8, // Report interval too large. Maxumum value = %dMAX_INTERVAL
|
||||||
IEMSS = 9, // MSS too large. Maximum value = %dMAX_MSS
|
IEMSS = 9, // MSS too large. Maximum value = %dMAX_MSS
|
||||||
IECTRLWRITE = 10, // Unable to write to the control socket (check perror)
|
IECTRLWRITE = 10, // Unable to write to the control socket (check perror)
|
||||||
IECTRLREAD = 11, // Unable to read from the control socket (check perror)
|
IECTRLREAD = 11, // Unable to read from the control socket (check perror)
|
||||||
IESOCKWRITE
|
IECTRLCLOSE = 12, // Control socket has closed unexpectedly
|
||||||
|
IESTREAMWRITE = 13, // Unable to write to stream socket (check perror)
|
||||||
|
IESTREAMREAD = 14, // Unable to read from stream (check perror)
|
||||||
|
IESTREAMCLOSE = 15, // Stream has closed unexpectedly
|
||||||
|
IENEWTEST = 16, // Unable to create a new test (check perror)
|
||||||
|
IECONNECT = 17, // Unable to connect to server (check herror/perror) [from netdial]
|
||||||
|
IESELECT = 18, // Select failed (check perror)
|
||||||
|
IESENDPARAMS = 19, // Unable to send parameters to server (check perror)
|
||||||
|
IERECVPARAMS = 20, // Unable to receive parameters from client (check perror)
|
||||||
|
IECREATESTREAM = 21, // Unable to create a new stream (check herror/perror)
|
||||||
|
IEINITSTREAM = 22, // Unable to initialize stream (check herror/perror)
|
||||||
|
IESETWINDOWSIZE = 23, // Unable to set socket window size (check perror)
|
||||||
|
IEPACKAGERESULTS = 24, // Unable to package results (check perror)
|
||||||
|
IESENDRESULTS = 25, // Unable to send results to client/server (check perror)
|
||||||
|
IERECVRESULTS = 26, // Unable to receive results from client/server (check perror)
|
||||||
|
IESTREAMID = 27, // Stream has invalid ID
|
||||||
|
IESERVERTERM = 28, // The server has terminated
|
||||||
|
IEACCESSDENIED = 29, // The server is busy running a test. Try again later.
|
||||||
|
IEMESSAGE = 30, // Received an unknown message
|
||||||
|
IESENDMESSAGE = 31, // Unable to send control message to client/server (check perror)
|
||||||
|
IERECVMESSAGE = 32, // Unable to receive control message from client/server (check perror)
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -90,7 +90,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (iperf_run(test) < 0) {
|
if (iperf_run(test) < 0) {
|
||||||
fprintf(stderr, "An error occurred. Exiting...\n");
|
ierror("error");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,13 +29,13 @@ netdial(int proto, char *client, int port)
|
|||||||
|
|
||||||
/* XXX: This is not working for non-fully qualified host names use getaddrinfo() instead? */
|
/* XXX: This is not working for non-fully qualified host names use getaddrinfo() instead? */
|
||||||
if ((hent = gethostbyname(client)) == 0) {
|
if ((hent = gethostbyname(client)) == 0) {
|
||||||
perror("gethostbyname");
|
// perror("gethostbyname");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
s = socket(AF_INET, proto, 0);
|
s = socket(AF_INET, proto, 0);
|
||||||
if (s < 0) {
|
if (s < 0) {
|
||||||
perror("socket");
|
// perror("socket");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ netdial(int proto, char *client, int port)
|
|||||||
sa.sin_family = AF_INET;
|
sa.sin_family = AF_INET;
|
||||||
|
|
||||||
if (connect(s, (struct sockaddr *) & sa, sizeof sa) < 0 && errno != EINPROGRESS) {
|
if (connect(s, (struct sockaddr *) & sa, sizeof sa) < 0 && errno != EINPROGRESS) {
|
||||||
perror("netdial: connect error");
|
// perror("netdial: connect error");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ netdial(int proto, char *client, int port)
|
|||||||
|
|
||||||
// XXX: Is there a reason to call getpeername() if none of the return values are used?
|
// XXX: Is there a reason to call getpeername() if none of the return values are used?
|
||||||
if (getpeername(s, (struct sockaddr *) & sa, &sn) < 0) {
|
if (getpeername(s, (struct sockaddr *) & sa, &sn) < 0) {
|
||||||
perror("getpeername error");
|
// perror("getpeername error");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Загрузка…
Ссылка в новой задаче
Block a user