changed code for Select API
Этот коммит содержится в:
родитель
ff5411c68d
Коммит
4bd06c53f0
290
src/main.c
290
src/main.c
@ -2,7 +2,7 @@
|
||||
* iperfjd -- greatly simplified version of iperf with the same interface
|
||||
* semantics
|
||||
*
|
||||
* jdugan -- 24 Jan 2009
|
||||
* kprabhu - 29th May 2009
|
||||
*
|
||||
*/
|
||||
|
||||
@ -43,6 +43,7 @@ enum {
|
||||
|
||||
uS_TO_NS = 1000,
|
||||
|
||||
MAX_BUFFER_SIZE =10,
|
||||
DEFAULT_UDP_BUFSIZE = 1470,
|
||||
DEFAULT_TCP_BUFSIZE = 8192
|
||||
};
|
||||
@ -71,6 +72,7 @@ struct iperf_stream
|
||||
struct iperf_stream *next;
|
||||
};
|
||||
|
||||
// Run routines for TCP and UDP- will be called by pthread_create() indirectly
|
||||
void *udp_client_thread(struct iperf_stream *sp);
|
||||
void *udp_server_thread(struct iperf_stream *sp);
|
||||
void *tcp_client_thread(struct iperf_stream *sp);
|
||||
@ -124,6 +126,30 @@ default_settings(struct iperf_settings *settings)
|
||||
struct iperf_stream *streams; /* head of list of streams */
|
||||
int done = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* Displays the current list of streams
|
||||
-------------------------------------------------------*/
|
||||
void Display()
|
||||
{
|
||||
struct iperf_stream * n;
|
||||
n= streams;
|
||||
int count=1;
|
||||
while(n->next!=NULL)
|
||||
{
|
||||
printf("position-%d\tsp=%d\tsocket=%d\n",count++,(int)n,n->sock);
|
||||
n=n->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* sets the parameters for the new stream created
|
||||
-------------------------------------------------------*/
|
||||
struct iperf_stream *
|
||||
new_stream(int s, struct iperf_settings *settings)
|
||||
{
|
||||
@ -136,12 +162,14 @@ new_stream(int s, struct iperf_settings *settings)
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
//initialise sp with 0
|
||||
memset(sp, 0, sizeof(struct iperf_stream));
|
||||
|
||||
// copy settings and passed socket into stream
|
||||
sp->settings = settings;
|
||||
sp->sock = s;
|
||||
|
||||
|
||||
len = sizeof sp->local;
|
||||
if(getsockname(sp->sock, (struct sockaddr *) &sp->local, &len) < 0) {
|
||||
perror("getsockname");
|
||||
@ -149,22 +177,26 @@ new_stream(int s, struct iperf_settings *settings)
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
//converts the local ip into string address
|
||||
if(inet_ntop(AF_INET, (void *) &sp->local.sin_addr,
|
||||
(void *) &sp->local_addr, 512) == NULL) {
|
||||
perror("inet_pton");
|
||||
}
|
||||
|
||||
//stores the socket id.
|
||||
if(getpeername(sp->sock, (struct sockaddr *) &sp->peer, &len) < 0) {
|
||||
perror("getpeername");
|
||||
free(sp);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
// converts the remote ip into string address
|
||||
if(inet_ntop(AF_INET, (void *) &sp->peer.sin_addr,
|
||||
(void *) &sp->peer_addr, 512) == NULL) {
|
||||
perror("inet_pton");
|
||||
}
|
||||
|
||||
// sets appropriate function pointer
|
||||
switch (settings->proto) {
|
||||
case Ptcp:
|
||||
sp->client = (void *) tcp_client_thread;
|
||||
@ -199,6 +231,11 @@ new_stream(int s, struct iperf_settings *settings)
|
||||
return(sp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* add a stream into stream_list linked list
|
||||
-------------------------------------------------------*/
|
||||
void
|
||||
add_stream(struct iperf_stream *sp)
|
||||
{
|
||||
@ -214,12 +251,75 @@ add_stream(struct iperf_stream *sp)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* delete the stream
|
||||
-------------------------------------------------------*/
|
||||
int
|
||||
free_stream(struct iperf_stream *sp)
|
||||
{
|
||||
printf("I am in free_stream \n");
|
||||
|
||||
struct iperf_stream *prev,*start;
|
||||
prev = streams;
|
||||
start = streams;
|
||||
|
||||
if(streams->sock==sp->sock)
|
||||
{
|
||||
printf("in 1 -Deleted\n\n\n");
|
||||
streams=streams->next;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
start= streams->next;
|
||||
|
||||
if(start->sock==sp->sock)
|
||||
{
|
||||
printf("Deleting socket %d \t",sp->sock);
|
||||
prev->next = sp->next;
|
||||
printf("Deleted\n\n\n");
|
||||
free(sp);
|
||||
return 0;
|
||||
}
|
||||
prev=prev->next;
|
||||
|
||||
}while(start->next!=NULL);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* update the stream
|
||||
-------------------------------------------------------*/
|
||||
struct iperf_stream *
|
||||
find_update_stream(int j, int result)
|
||||
{
|
||||
struct iperf_stream *n;
|
||||
n=streams;
|
||||
//find the correct stream for update
|
||||
do
|
||||
{
|
||||
if(n->sock==j)
|
||||
{
|
||||
n->bytes_in+= result; //update the byte count
|
||||
break;
|
||||
}
|
||||
n = n->next;
|
||||
|
||||
}while(n->next!=NULL);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* Display connected message
|
||||
-------------------------------------------------------*/
|
||||
void connect_msg(struct iperf_stream *sp)
|
||||
{
|
||||
char *ipl, *ipr;
|
||||
@ -233,6 +333,10 @@ void connect_msg(struct iperf_stream *sp)
|
||||
sp->peer_addr, htons(sp->peer.sin_port));
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* UDP client functionality.
|
||||
-------------------------------------------------------*/
|
||||
void *
|
||||
udp_client_thread(struct iperf_stream *sp)
|
||||
{
|
||||
@ -296,6 +400,10 @@ udp_client_thread(struct iperf_stream *sp)
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* UDP Server functionality.
|
||||
-------------------------------------------------------*/
|
||||
void *
|
||||
udp_server_thread(struct iperf_stream *sp)
|
||||
{
|
||||
@ -318,16 +426,30 @@ udp_server_thread(struct iperf_stream *sp)
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* UDP Reporting routine
|
||||
-------------------------------------------------------*/
|
||||
void
|
||||
udp_report(int final)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* UDP Reporting routine
|
||||
-------------------------------------------------------*/
|
||||
void
|
||||
tcp_report(int final)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* TCP client functionality
|
||||
* -------------------------------------------------------*/
|
||||
|
||||
void *
|
||||
tcp_client_thread(struct iperf_stream *sp)
|
||||
{
|
||||
@ -361,6 +483,9 @@ tcp_client_thread(struct iperf_stream *sp)
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* TCP Server functionality
|
||||
* -------------------------------------------------------*/
|
||||
void *
|
||||
tcp_server_thread(struct iperf_stream *sp)
|
||||
{
|
||||
@ -385,6 +510,10 @@ tcp_server_thread(struct iperf_stream *sp)
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* This is code for Client
|
||||
* -------------------------------------------------------*/
|
||||
int
|
||||
client(struct iperf_settings *settings)
|
||||
{
|
||||
@ -407,14 +536,18 @@ client(struct iperf_settings *settings)
|
||||
sp = new_stream(s, settings);
|
||||
add_stream(sp);
|
||||
connect_msg(sp);
|
||||
// need to replace this with Select
|
||||
pthread_create(&sp->thread, NULL, sp->client, (void *) sp);
|
||||
}
|
||||
|
||||
timer = new_timer(settings->duration, 0);
|
||||
|
||||
// wait till the timer expires
|
||||
while(!timer->expired(timer))
|
||||
sleep(settings->duration);
|
||||
|
||||
// this is checked in UDP/TCP while loop
|
||||
// to stop sending packets. Global member
|
||||
done = 1;
|
||||
|
||||
/* XXX: report */
|
||||
@ -427,14 +560,25 @@ client(struct iperf_settings *settings)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------
|
||||
* This is code for Server
|
||||
* -------------------------------------------------------*/
|
||||
int
|
||||
server(struct iperf_settings *settings)
|
||||
{
|
||||
int s, cs, sz;
|
||||
struct iperf_stream *sp;
|
||||
struct iperf_stream *sp,*temp;
|
||||
struct sockaddr_in sa_peer;
|
||||
socklen_t len;
|
||||
char buf[settings->bufsize], ubuf[UNIT_LEN];
|
||||
fd_set readset, tempset;
|
||||
int maxfd, flags;
|
||||
int peersock, j, result, result1, sent;
|
||||
struct timeval tv;
|
||||
|
||||
char buffer[DEFAULT_TCP_BUFSIZE];
|
||||
|
||||
struct sockaddr_in addr;
|
||||
|
||||
s = netannounce(settings->proto, NULL, settings->port);
|
||||
if(s < 0)
|
||||
@ -451,42 +595,156 @@ server(struct iperf_settings *settings)
|
||||
if((x = getsock_tcp_windowsize(s, SO_RCVBUF)) < 0)
|
||||
perror("SO_RCVBUF");
|
||||
|
||||
/*
|
||||
unit_snprintf(ubuf, UNIT_LEN, (double) x, 'A');
|
||||
printf("%s: %s\n",
|
||||
settings->proto == Ptcp ? "TCP window size" : "UDP buffer size", ubuf);
|
||||
*/
|
||||
printf("-----------------------------------------------------------\n");
|
||||
|
||||
len = sizeof sa_peer;
|
||||
while(1) {
|
||||
if (Ptcp == settings->proto) {
|
||||
if( (cs = accept(s, (struct sockaddr *) &sa_peer, &len)) < 0) {
|
||||
perror("accept");
|
||||
return -1;
|
||||
|
||||
FD_ZERO(&readset);
|
||||
FD_SET(s, &readset);
|
||||
maxfd = s;
|
||||
|
||||
do {
|
||||
|
||||
memcpy(&tempset, &readset, sizeof(tempset));
|
||||
tv.tv_sec = 15; // timeout interval in seconds
|
||||
tv.tv_usec = 0;
|
||||
|
||||
// using select to check on multiple descriptors.
|
||||
result = select(maxfd + 1, &tempset, NULL, NULL, &tv);
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
printf("select() timed out!\n");
|
||||
}
|
||||
sp = new_stream(cs, settings);
|
||||
} else if (Pudp == settings->proto) {
|
||||
else if (result < 0 && errno != EINTR)
|
||||
{
|
||||
printf("Error in select(): %s\n", strerror(errno));
|
||||
}
|
||||
else if (result > 0)
|
||||
{
|
||||
|
||||
if (FD_ISSET(s, &tempset))
|
||||
{
|
||||
if(settings->proto== Ptcp) // New TCP Connection
|
||||
{
|
||||
len = sizeof(addr);
|
||||
peersock = accept(s,(struct sockaddr *) &addr, &len);
|
||||
if (peersock < 0)
|
||||
{
|
||||
printf("Error in accept(): %s\n", strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("=========================\n");
|
||||
printf("%d is the socket number\n",peersock);
|
||||
FD_SET(peersock, &readset);
|
||||
maxfd = (maxfd < peersock)?peersock:maxfd;
|
||||
// creating a new stream
|
||||
sp = new_stream(peersock, settings);
|
||||
printf(" new stream is %d \n", (int)sp);
|
||||
// need to manage the linked list of streams
|
||||
add_stream(sp);
|
||||
connect_msg(sp);
|
||||
|
||||
Display();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if ( settings->proto== Pudp) //New UDP Connection
|
||||
{
|
||||
// getting a new UDP packet
|
||||
sz = recvfrom(s, buf, settings->bufsize, 0, (struct sockaddr *) &sa_peer, &len);
|
||||
if(!sz)
|
||||
break;
|
||||
|
||||
if(connect(s, (struct sockaddr *) &sa_peer, len) < 0) {
|
||||
if(connect(s, (struct sockaddr *) &sa_peer, len) < 0)
|
||||
{
|
||||
perror("connect");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get a new socket to connect to client
|
||||
printf("=========================\n");
|
||||
sp = new_stream(s, settings);
|
||||
sp->bytes_in += sz;
|
||||
printf(" new stream is %d \n", (int)sp);
|
||||
// need to manage the linked list of streams
|
||||
add_stream(sp);
|
||||
|
||||
|
||||
s = netannounce(settings->proto, NULL, settings->port);
|
||||
if(s < 0) {
|
||||
if(s < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// same as TCP -repetation
|
||||
printf("%d is the socket number\n",s);
|
||||
FD_SET(s, &readset);
|
||||
maxfd = (maxfd < s)?s:maxfd;
|
||||
|
||||
}
|
||||
|
||||
connect_msg(sp);
|
||||
pthread_create(&sp->thread, NULL, sp->server, (void *) sp);
|
||||
FD_CLR(s, &tempset);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// scanning all socket descriptors for read
|
||||
for (j=0; j<maxfd+1; j++)
|
||||
{
|
||||
if (FD_ISSET(j, &tempset))
|
||||
{
|
||||
do
|
||||
{
|
||||
if(settings->proto==Ptcp)
|
||||
result = recv(j, buffer,DEFAULT_TCP_BUFSIZE, 0);
|
||||
else
|
||||
result = recv(j, buffer,DEFAULT_UDP_BUFSIZE, 0);
|
||||
|
||||
} while (result == -1 && errno == EINTR);
|
||||
|
||||
|
||||
if (result > 0)
|
||||
{
|
||||
sp=find_update_stream(j,result);
|
||||
|
||||
}
|
||||
else if (result == 0)
|
||||
{
|
||||
Display();
|
||||
|
||||
//just find the stream with zero update
|
||||
sp = find_update_stream(j,0);
|
||||
|
||||
if(settings->proto == Ptcp)
|
||||
{
|
||||
//printf("window: %d\n", getsock_tcp_windowsize(sp->sock, SO_RCVBUF));
|
||||
}
|
||||
|
||||
|
||||
unit_snprintf(ubuf, UNIT_LEN, (double) sp->bytes_in / sp->settings->duration, 'a');
|
||||
printf("%llu bytes received %s/sec for stream %d\n\n", sp->bytes_in, ubuf,(int)sp);
|
||||
close(j);
|
||||
FD_CLR(j, &readset);
|
||||
free_stream(sp); // this needs to be a linked list delete
|
||||
//break;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error in recv(): %s\n", strerror(errno));
|
||||
}
|
||||
} // end if (FD_ISSET(j, &tempset))
|
||||
} // end for (j=0;...)
|
||||
} // end else if (result > 0)
|
||||
} while (1);
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user