UDPSingleServer();
#endif
} else {
- bool client = false,
+ bool client = (mSettings->mHost != NULL),
mCount = (mSettings->mThreads != 0);
thread_Settings *tempSettings = NULL;
Iperf_ListEntry *exist, *listtemp;
client_hdr* hdr;
-
- if ( mSettings->mHost != NULL ) {
- client = true;
- SockAddr_remoteAddr( mSettings );
- }
Settings_Copy( mSettings, &server );
server->mThreadMode = kMode_Server;
-
-
+
// Accept each packet,
// If there is no existing client, then start
// a new thread to service the new client
close( server->mSock );
break;
}
+
// Reset Single Client Stuff
if ( isSingleClient( mSettings ) && clients == NULL ) {
- mSettings->peer = server->peer;
mClients--;
client = true;
// Once all the server threads exit then quit
mClients = 1;
}
}
- // Verify that it is allowed
- if ( client ) {
- if ( !SockAddr_Hostare_Equal( (sockaddr*) &mSettings->peer,
- (sockaddr*) &server->peer ) ) {
- // Not allowed try again
- close( server->mSock );
- if ( isConnectionLess( mSettings ) ) {
- mSettings->mSock = -1;
- Listen();
- }
- continue;
- }
- }
+ // Copy peer address for individual/bidirectional dual-test
+ // NOTE: There is no longer a reverse-lookup for the peer to
+ // check if it is allowed. The reason is that it simply
+ // gets too complex: compare v4/v6, v4/v4, v6/v4, v6/v6
+ if (client)
+ mSettings->peer = server->peer;
// Create an entry for the connection list
listtemp = new Iperf_ListEntry;
- memcpy(listtemp, &server->peer, sizeof(iperf_sockaddr));
+ memcpy(listtemp, &server->peer, sizeof(server->peer));
listtemp->next = NULL;
// See if we need to do summing
* ------------------------------------------------------------------- */
void Listener::Listen()
{
- int rc;
- int boolean = 1;
- Socklen_t len = sizeof(boolean);
-
- SockAddr_localAddr( mSettings );
- MakeSocket( mSettings );
-
- SetSocketOptions( mSettings );
-
- // reuse the address, so we can run if a former server was killed off
- setsockopt( mSettings->mSock, SOL_SOCKET, SO_REUSEADDR, (char*) &boolean, len );
-
- // listen for connections (TCP/DCCP only).
- rc = bind( mSettings->mSock, (sockaddr*) &mSettings->local, mSettings->size_local );
- WARN_errno( rc == SOCKET_ERROR, "bind" );
+ MakeSocket(mSettings);
// default backlog traditionally 5
- if ( !isConnectionLess( mSettings ) ) {
- rc = listen( mSettings->mSock, 5 );
- WARN_errno( rc == SOCKET_ERROR, "listen" );
- }
+ if (!isConnectionLess(mSettings) && listen(mSettings->mSock, 5) < 0)
+ WARN_errno( 1, "listen" );
- // if multicast, join the group
- if ( SockAddr_isMulticast( &mSettings->local ) ) {
- McastJoin( );
- }
-} // end Listen
+ // if multicast, join the group specified earlier via -B
+ if (isMulticast(mSettings))
+ McastJoin();
+}
/* -------------------------------------------------------------------
* Joins the multicast group, with the default interface.
* ------------------------------------------------------------------- */
-void Listener::McastJoin( ) {
-#ifdef HAVE_MULTICAST
- if ( !SockAddr_isIPv6( &mSettings->local ) ) {
- struct ip_mreq mreq;
+void Listener::McastJoin()
+{
+ if (SockAddr_isIPv6(&mSettings->local)) {
+ struct ipv6_mreq mreq;
- memcpy( &mreq.imr_multiaddr, SockAddr_get_in_addr( &mSettings->local ),
- sizeof(mreq.imr_multiaddr));
+ memset(&mreq, 0, sizeof(mreq));
+ memcpy(&mreq.ipv6mr_multiaddr, &((struct sockaddr_in6*)&mSettings->local)->sin6_addr,
+ sizeof(mreq.ipv6mr_multiaddr));
- mreq.imr_interface.s_addr = htonl( INADDR_ANY );
+ mreq.ipv6mr_interface = mSettings->mMcastIface;
- int rc = setsockopt( mSettings->mSock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (char*) &mreq, sizeof(mreq));
- WARN_errno( rc == SOCKET_ERROR, "multicast join" );
- }
-#ifdef HAVE_IPV6_MULTICAST
- else {
- struct ipv6_mreq mreq;
+ if (setsockopt(mSettings->mSock, IPPROTO_IPV6,
+ IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
+ die("IPv6 multicast join failed: did you use -j/-J?");
- memcpy( &mreq.ipv6mr_multiaddr, SockAddr_get_in6_addr( &mSettings->local ),
- sizeof(mreq.ipv6mr_multiaddr));
+ } else {
+ struct ip_mreqn mreq;
- mreq.ipv6mr_interface = 0;
+ memset(&mreq, 0, sizeof(mreq));
+ memcpy(&mreq.imr_multiaddr, &((struct sockaddr_in*)&mSettings->local)->sin_addr,
+ sizeof(mreq.imr_multiaddr));
+
+ mreq.imr_ifindex = mSettings->mMcastIface;
- int rc = setsockopt( mSettings->mSock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
- (char*) &mreq, sizeof(mreq));
- WARN_errno( rc == SOCKET_ERROR, "multicast join" );
+ if (setsockopt(mSettings->mSock, IPPROTO_IP,
+ IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
+ die("IPv4 multicast join failed: did you use -j/-J?");
}
-#endif
-#endif
}
-// end McastJoin
/* -------------------------------------------------------------------
* Sets the Multicast TTL for outgoing packets.
void Listener::Accept( thread_Settings *server )
{
- server->size_peer = sizeof(iperf_sockaddr);
+ socklen_t socklen = sizeof(server->peer);
if ( isConnectionLess( server ) ) {
/* -------------------------------------------------------------------
server->mSock = INVALID_SOCKET;
while ( server->mSock == INVALID_SOCKET ) {
rc = recvfrom( mSettings->mSock, mBuf, mSettings->mBufLen, 0,
- (struct sockaddr*) &server->peer, &server->size_peer );
+ (struct sockaddr *)&server->peer, &socklen );
FAIL_errno( rc == SOCKET_ERROR, "recvfrom", mSettings );
Mutex_Lock( &clients_mutex );
datagramID = ntohl( ((dgram_record*) mBuf)->id );
if ( exist == NULL && datagramID >= 0 ) {
server->mSock = mSettings->mSock;
- int rc = connect( server->mSock, (struct sockaddr*) &server->peer,
- server->size_peer );
+ int rc = connect(server->mSock, (struct sockaddr *)&server->peer, socklen);
FAIL_errno( rc == SOCKET_ERROR, "datagram-based connect", mSettings );
} else {
server->mSock = INVALID_SOCKET;
}
} else {
// Handles interupted accepts. Returns the newly connected socket.
- server->mSock = INVALID_SOCKET;
-
- while ( server->mSock == INVALID_SOCKET ) {
- // accept a connection
- server->mSock = accept( mSettings->mSock,
- (sockaddr*) &server->peer, &server->size_peer );
- if ( server->mSock == INVALID_SOCKET && errno == EINTR ) {
- continue;
- }
- }
+ do {
+ server->mSock = accept(mSettings->mSock, (struct sockaddr *)&server->peer, &socklen);
+ } while (server->mSock == INVALID_SOCKET);
}
- server->size_local = sizeof(iperf_sockaddr);
- getsockname( server->mSock, (sockaddr*) &server->local,
- &server->size_local );
-} // end Accept
+ // find out which local interface the connection uses
+ socklen = sizeof(server->local);
+ getsockname(server->mSock, (struct sockaddr *)&server->local, &socklen);
+}
void Listener::UDPSingleServer( ) {
- bool client = false, mCount = (mSettings->mThreads != 0);
+ bool client = (mSettings->mHost != NULL),
+ mCount = (mSettings->mThreads != 0);
thread_Settings *tempSettings = NULL;
Iperf_ListEntry *exist, *listtemp;
int rc;
int32_t datagramID;
+ socklen_t socklen = sizeof(server->peer);
ReportStruct *reportstruct = new ReportStruct;
dgram_record *dgram_hdr = (dgram_record *)mBuf;
-
assert( isPacketOriented( mSettings ) );
- if ( mSettings->mHost != NULL ) {
- client = true;
- SockAddr_remoteAddr( mSettings );
- }
Settings_Copy( mSettings, &server );
server->mThreadMode = kMode_Server;
-
// Accept each packet,
// If there is no existing client, then start
// a new report to service the new client
do {
// Get next packet
while ( sInterupted == 0) {
- server->size_peer = sizeof( iperf_sockaddr );
- rc = recvfrom( mSettings->mSock, mBuf, mSettings->mBufLen, 0,
- (struct sockaddr*) &server->peer, &server->size_peer );
- WARN_errno( rc == SOCKET_ERROR, "recvfrom" );
- if ( rc == SOCKET_ERROR ) {
+ rc = recvfrom(mSettings->mSock, mBuf, mSettings->mBufLen, 0,
+ (struct sockaddr *)&server->peer, &socklen);
+ if (rc == SOCKET_ERROR) {
+ WARN_errno( 1, "recvfrom" );
return;
}
-
// Handle connection for datagram-based sockets.
exist = Iperf_present( &server->peer, clients);
datagramID = ntohl( dgram_hdr->id );
groupID--;
server->mSock = -groupID;
Mutex_Unlock( &groupCond );
- server->size_local = sizeof(iperf_sockaddr);
- getsockname( mSettings->mSock, (sockaddr*) &server->local,
- &server->size_local );
+ // make this a connected socket and determine local interface
+ connect(mSettings->mSock, (sockaddr *)&server->peer, socklen);
+ socklen = sizeof(server->local);
+ getsockname(mSettings->mSock, (sockaddr *)&server->local, &socklen);
break;
}
} else {
server_hdr *hdr = (server_hdr *) (dgram_hdr + 1);
hdr->flags = htonl( 0 );
}
- sendto( mSettings->mSock, mBuf, mSettings->mBufLen, 0,
- (struct sockaddr*) &server->peer, server->size_peer);
+ if (write(mSettings->mSock, mBuf, mSettings->mBufLen) < 0)
+ WARN_errno(1, "UDPSingleServer write");
}
}
if ( server->mSock == INVALID_SOCKET ) {
}
// Reset Single Client Stuff
if ( isSingleClient( mSettings ) && clients == NULL ) {
- mSettings->peer = server->peer;
mClients--;
client = true;
// Once all the server threads exit then quit
mClients = 1;
}
}
- // Verify that it is allowed
- if ( client ) {
- if ( !SockAddr_Hostare_Equal( (sockaddr*) &mSettings->peer,
- (sockaddr*) &server->peer ) ) {
- // Not allowed try again
- connect( mSettings->mSock,
- (sockaddr*) &server->peer,
- server->size_peer );
- close( mSettings->mSock );
- mSettings->mSock = -1;
- Listen( );
- continue;
- }
- }
+ // Copy peer address (see note in Listener::Run())
+ if (client)
+ mSettings->peer = server->peer;
// Create an entry for the connection list
listtemp = new Iperf_ListEntry;
- memcpy(listtemp, &server->peer, sizeof(iperf_sockaddr));
+ memcpy(listtemp, &server->peer, sizeof(server->peer));
listtemp->server = server;
listtemp->next = NULL;