1 /*---------------------------------------------------------------
2 * Copyright (c) 1999,2000,2001,2002,2003
3 * The Board of Trustees of the University of Illinois
5 *---------------------------------------------------------------
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software (Iperf) and associated
8 * documentation files (the "Software"), to deal in the Software
9 * without restriction, including without limitation the
10 * rights to use, copy, modify, merge, publish, distribute,
11 * sublicense, and/or sell copies of the Software, and to permit
12 * persons to whom the Software is furnished to do
13 * so, subject to the following conditions:
16 * Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and
18 * the following disclaimers.
21 * Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimers in the documentation and/or other materials
24 * provided with the distribution.
27 * Neither the names of the University of Illinois, NCSA,
28 * nor the names of its contributors may be used to endorse
29 * or promote products derived from this Software without
30 * specific prior written permission.
32 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
34 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
35 * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
36 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
37 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
38 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
39 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 * ________________________________________________________________
41 * National Laboratory for Applied Network Research
42 * National Center for Supercomputing Applications
43 * University of Illinois at Urbana-Champaign
44 * http://www.ncsa.uiuc.edu
45 * ________________________________________________________________
48 * by Mark Gates <mgates@nlanr.net>
49 * Ajay Tirumala (tirumala@ncsa.uiuc.edu>.
50 * -------------------------------------------------------------------
51 * A server thread is initiated for each connection accept() returns.
52 * Handles sending and receiving data, and then closes socket.
53 * Changes to this version : The server can be run as a daemon
54 * ------------------------------------------------------------------- */
61 #include "Extractor.h"
65 /* -------------------------------------------------------------------
66 * Stores connected socket and socket info.
67 * ------------------------------------------------------------------- */
69 Server::Server( thread_Settings *inSettings ) {
70 mSettings = inSettings;
74 mBuf = new char[ mSettings->mBufLen ];
75 FAIL_errno( mBuf == NULL, "No memory for buffer\n", mSettings );
78 /* -------------------------------------------------------------------
79 * Destructor close socket.
80 * ------------------------------------------------------------------- */
83 if ( mSettings->mSock != INVALID_SOCKET ) {
84 int rc = close( mSettings->mSock );
85 WARN_errno( rc == SOCKET_ERROR, "close" );
86 mSettings->mSock = INVALID_SOCKET;
91 void Server::Sig_Int( int inSigno ) {
94 /* -------------------------------------------------------------------
95 * Receieve data from the (connected) TCP/UDP socket.
96 * Sends termination flag several times at the end.
97 * Does not close the socket.
98 * ------------------------------------------------------------------- */
99 void Server::Run( void ) {
101 struct UDP_datagram* mBuf_UDP = (struct UDP_datagram*) mBuf;
103 ReportStruct *reportstruct = NULL;
105 reportstruct = new ReportStruct;
106 if ( reportstruct != NULL ) {
107 reportstruct->packetID = 0;
108 mSettings->reporthdr = InitReport( mSettings );
111 currLen = recv( mSettings->mSock, mBuf, mSettings->mBufLen, 0 );
113 if ( isUDP( mSettings ) ) {
114 // read the datagram ID and sentTime out of the buffer
115 reportstruct->packetID = ntohl( mBuf_UDP->id );
116 reportstruct->sentTime.tv_sec = ntohl( mBuf_UDP->tv_sec );
117 reportstruct->sentTime.tv_usec = ntohl( mBuf_UDP->tv_usec );
120 reportstruct->packetLen = currLen;
121 gettimeofday( &(reportstruct->packetTime), NULL );
123 // terminate when datagram begins with negative index
124 // the datagram ID should be correct, just negated
125 if ( reportstruct->packetID < 0 ) {
126 reportstruct->packetID = -reportstruct->packetID;
129 ReportPacket( mSettings->reporthdr, reportstruct );
130 } while ( currLen > 0 );
133 gettimeofday( &(reportstruct->packetTime), NULL );
134 CloseReport( mSettings->reporthdr, reportstruct );
136 // send a acknowledgement back only if we're NOT receiving multicast
137 if ( isUDP( mSettings ) && !isMulticast( mSettings ) ) {
138 // send back an acknowledgement of the terminating datagram
142 FAIL(1, "Out of memory! Closing server thread\n", mSettings);
145 Mutex_Lock( &clients_mutex );
146 Iperf_delete( &(mSettings->peer), &clients );
147 Mutex_Unlock( &clients_mutex );
149 DELETE_PTR( reportstruct );
150 EndReport( mSettings->reporthdr );
154 /* -------------------------------------------------------------------
155 * Send an AckFIN (a datagram acknowledging a FIN) on the socket,
156 * then select on the socket for some time. If additional datagrams
157 * come in, probably our AckFIN was lost and they are re-transmitted
158 * termination datagrams, so re-transmit our AckFIN.
159 * ------------------------------------------------------------------- */
161 void Server::write_UDP_AckFIN( ) {
168 struct timeval timeout;
171 while ( count < 10 ) {
174 UDP_datagram *UDP_Hdr;
177 UDP_Hdr = (UDP_datagram*) mBuf;
179 if ( mSettings->mBufLen > (int) ( sizeof( UDP_datagram )
180 + sizeof( server_hdr ) ) ) {
181 Transfer_Info *stats = GetReport( mSettings->reporthdr );
182 hdr = (server_hdr*) (UDP_Hdr+1);
184 hdr->flags = htonl( HEADER_VERSION1 );
185 hdr->total_len1 = htonl( (long) (stats->TotalLen >> 32) );
186 hdr->total_len2 = htonl( (long) (stats->TotalLen & 0xFFFFFFFF) );
187 hdr->stop_sec = htonl( (long) stats->endTime );
188 hdr->stop_usec = htonl( (long)((stats->endTime - (long)stats->endTime)
190 hdr->error_cnt = htonl( stats->cntError );
191 hdr->outorder_cnt = htonl( stats->cntOutofOrder );
192 hdr->datagrams = htonl( stats->cntDatagrams );
193 hdr->jitter1 = htonl( (long) stats->jitter );
194 hdr->jitter2 = htonl( (long) ((stats->jitter - (long)stats->jitter)
200 write( mSettings->mSock, mBuf, mSettings->mBufLen );
202 // wait until the socket is readable, or our timeout expires
203 FD_SET( mSettings->mSock, &readSet );
207 rc = select( mSettings->mSock+1, &readSet, NULL, NULL, &timeout );
208 FAIL_errno( rc == SOCKET_ERROR, "select", mSettings );
214 // socket ready to read
215 rc = read( mSettings->mSock, mBuf, mSettings->mBufLen );
216 WARN_errno( rc < 0, "read" );
218 // Connection closed or errored
225 fprintf( stderr, warn_ack_failed, mSettings->mSock, count );
227 // end write_UDP_AckFIN