X-Git-Url: http://sjero.net/git/?p=iperf;a=blobdiff_plain;f=src%2FListener.cpp;h=8afd6aa12c58707716a53a2e04d2b382e09a7f92;hp=1cc0de944c232a316954cf712e78c36e95f2693b;hb=a5a03e6ab0fdf9c4d7d4c085fcf01436f9ba3202;hpb=90fc1e2c0c74319759b21d4a177c32691b88fdf3 diff --git a/src/Listener.cpp b/src/Listener.cpp index 1cc0de9..8afd6aa 100644 --- a/src/Listener.cpp +++ b/src/Listener.cpp @@ -128,21 +128,15 @@ void Listener::Run(void) 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 @@ -158,9 +152,9 @@ void Listener::Run(void) 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 @@ -171,23 +165,16 @@ void Listener::Run(void) 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 @@ -270,69 +257,50 @@ void Listener::Run(void) * ------------------------------------------------------------------- */ 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. @@ -363,7 +331,7 @@ void Listener::McastSetTTL( int val ) { void Listener::Accept( thread_Settings *server ) { - server->size_peer = sizeof(iperf_sockaddr); + socklen_t socklen = sizeof(server->peer); if ( isConnectionLess( server ) ) { /* ------------------------------------------------------------------- @@ -377,7 +345,7 @@ void Listener::Accept( thread_Settings *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 ); @@ -387,8 +355,7 @@ void Listener::Accept( thread_Settings *server ) 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; @@ -397,43 +364,32 @@ void Listener::Accept( thread_Settings *server ) } } 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 @@ -442,15 +398,13 @@ void Listener::UDPSingleServer( ) { 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 ); @@ -470,9 +424,10 @@ void Listener::UDPSingleServer( ) { 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 { @@ -516,8 +471,8 @@ void Listener::UDPSingleServer( ) { 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 ) { @@ -529,7 +484,6 @@ void Listener::UDPSingleServer( ) { } // Reset Single Client Stuff if ( isSingleClient( mSettings ) && clients == NULL ) { - mSettings->peer = server->peer; mClients--; client = true; // Once all the server threads exit then quit @@ -540,24 +494,13 @@ void Listener::UDPSingleServer( ) { 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;