bool Sinful::addressPointsToMe( Sinful const &addr ) const { bool addr_matches = false; // Confirm that ports match. Don't even bother checking the addresses if ports don't match. if ( getHost() && getPort() && addr.getPort() && !strcmp(getPort(),addr.getPort()) ) { // Check if host addresses match if( addr.getHost() && !strcmp(getHost(),addr.getHost()) ) { addr_matches = true; } // We may have failed to match host addresses above, but we now need // to cover the case of the loopback interface (aka 127.0.0.1). A common // usage pattern for this method is for "this" object to represent our daemonCore // command socket. If this is the case, and the addr passed in is a loopback // address, consider the addresses to match. Note we convert to a condor_sockaddr // so we can use method is_loopback(), which correctly handles both IPv4 and IPv6. Sinful oursinful( global_dc_sinful() ); condor_sockaddr addrsock; if( !addr_matches && oursinful.getHost() && !strcmp(getHost(),oursinful.getHost()) && addr.getSinful() && addrsock.from_sinful(addr.getSinful()) && addrsock.is_loopback() ) { addr_matches = true; } } // The addrs and ports match, but if shared_port is in use, we need to confirm the // shared port id also matches. if (addr_matches) { char const *spid = getSharedPortID(); char const *addr_spid = addr.getSharedPortID(); if( (spid == NULL && addr_spid == NULL) || // case without shared port (spid && addr_spid && !strcmp(spid,addr_spid)) // case with shared port ) { return true; } } // Public address failed to match, but now need to do it all over again checking // the private address. if( getPrivateAddr() ) { Sinful private_addr( getPrivateAddr() ); return private_addr.addressPointsToMe( addr ); } return false; }
char const * SharedPortEndpoint::GetMyLocalAddress() { if( !m_listening ) { return NULL; } if( m_local_addr.IsEmpty() ) { Sinful sinful; // port 0 is used as an indicator that no SharedPortServer // address is included in this address. This address should // never be shared with anybody except for local commands // and daemons who can then form a connection to us via // direct access to our named socket. sinful.setPort("0"); sinful.setHost(my_ip_string()); sinful.setSharedPortID( m_local_id.Value() ); std::string alias; if( param(alias,"HOST_ALIAS") ) { sinful.setAlias(alias.c_str()); } m_local_addr = sinful.getSinful(); } return m_local_addr.Value(); }
int main( int, char ** ) { Sinful s; Sinful t; // // Test, for 0, 1, 2, and 3 condor_sockaddrs: that the vector is not NULL, // that the vector has the correct number of elements, that the vector's // elements values are correct (and in the correct order); and that the // string form of the sinful is correct; and that the parser correctly // handles the sinful string (by repeating the vector tests); and that // the string->sinful->string loop also works (by repeating the string // test). Then repeat the 0 test after clearing the Sinful of addrs. // // We then also test adding three condor_sockaddrs in a row, just in // case one-at-a-time testing somehow hides a problem; this also tests // that adding condor_sockaddrs after clearing the Sinful works. // std::vector< condor_sockaddr > * v = s.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 0 ); delete v; v = NULL; char const * sinfulString = NULL; sinfulString = s.getSinful(); REQUIRE( sinfulString == NULL ); REQUIRE( ! s.hasAddrs() ); condor_sockaddr sa; bool ok = sa.from_ip_and_port_string( "1.2.3.4:5" ); REQUIRE( ok ); s.addAddrToAddrs( sa ); v = s.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 1 ); REQUIRE( (*v)[0] == sa ); delete v; v = NULL; sinfulString = s.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5>" ) == 0 ); t = Sinful( sinfulString ); v = t.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 1 ); REQUIRE( (*v)[0] == sa ); delete v; v = NULL; sinfulString = t.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5>" ) == 0 ); REQUIRE( s.hasAddrs() ); condor_sockaddr sa2; ok = sa2.from_ip_and_port_string( "5.6.7.8:9" ); REQUIRE( ok ); s.addAddrToAddrs( sa2 ); v = s.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 2 ); REQUIRE( (*v)[0] == sa ); REQUIRE( (*v)[1] == sa2 ); delete v; v = NULL; sinfulString = s.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5+5.6.7.8-9>" ) == 0 ); t = Sinful( sinfulString ); v = t.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 2 ); REQUIRE( (*v)[0] == sa ); REQUIRE( (*v)[1] == sa2 ); delete v; v = NULL; sinfulString = t.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5+5.6.7.8-9>" ) == 0 ); REQUIRE( s.hasAddrs() ); condor_sockaddr sa3; ok = sa3.from_ip_and_port_string( "[1:3:5:7::a]:13" ); REQUIRE( ok ); s.addAddrToAddrs( sa3 ); v = s.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 3 ); REQUIRE( (*v)[0] == sa ); REQUIRE( (*v)[1] == sa2 ); REQUIRE( (*v)[2] == sa3 ); delete v; v = NULL; sinfulString = s.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5+5.6.7.8-9+[1-3-5-7--a]-13>" ) == 0 ); t = Sinful( sinfulString ); v = t.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 3 ); REQUIRE( (*v)[0] == sa ); REQUIRE( (*v)[1] == sa2 ); REQUIRE( (*v)[2] == sa3 ); delete v; v = NULL; sinfulString = t.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5+5.6.7.8-9+[1-3-5-7--a]-13>" ) == 0 ); REQUIRE( s.hasAddrs() ); s.clearAddrs(); v = s.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 0 ); sinfulString = s.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<>" ) == 0 ); t = Sinful( sinfulString ); v = t.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 0 ); sinfulString = t.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<>" ) == 0 ); REQUIRE( ! s.hasAddrs() ); s.addAddrToAddrs( sa ); s.addAddrToAddrs( sa2 ); s.addAddrToAddrs( sa3 ); v = s.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 3 ); REQUIRE( (*v)[0] == sa ); REQUIRE( (*v)[1] == sa2 ); REQUIRE( (*v)[2] == sa3 ); delete v; v = NULL; sinfulString = s.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5+5.6.7.8-9+[1-3-5-7--a]-13>" ) == 0 ); t = Sinful( sinfulString ); v = t.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 3 ); REQUIRE( (*v)[0] == sa ); REQUIRE( (*v)[1] == sa2 ); REQUIRE( (*v)[2] == sa3 ); delete v; v = NULL; sinfulString = t.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5+5.6.7.8-9+[1-3-5-7--a]-13>" ) == 0 ); REQUIRE( s.hasAddrs() ); // In practice, all C++03 implementations are stable with respect // to insertion order; the C++11 standard requires that they are. // This is the unit test for the former. std::multimap< int, condor_sockaddr > sortedByDesire; sortedByDesire.insert(std::make_pair( 0, sa )); sortedByDesire.insert(std::make_pair( 0, sa2 )); sortedByDesire.insert(std::make_pair( 0, sa3 )); int i = 0; std::multimap< int, condor_sockaddr >::const_iterator iter; for( iter = sortedByDesire.begin(); iter != sortedByDesire.end(); ++iter, ++i ) { switch( i ) { case 0: REQUIRE( (* iter).second == sa ); break; case 1: REQUIRE( (* iter).second == sa2 ); break; case 2: REQUIRE( (* iter).second == sa3 ); break; default: REQUIRE( false ); break; } } sortedByDesire.clear(); REQUIRE( sortedByDesire.size() == 0 ); sortedByDesire.insert(std::make_pair( 1, sa )); sortedByDesire.insert(std::make_pair( 0, sa2 )); sortedByDesire.insert(std::make_pair( 0, sa3 )); i = 0; for( iter = sortedByDesire.begin(); iter != sortedByDesire.end(); ++iter, ++i ) { switch( i ) { case 0: REQUIRE( (* iter).second == sa2 ); break; case 1: REQUIRE( (* iter).second == sa3 ); break; case 2: REQUIRE( (* iter).second == sa ); break; default: REQUIRE( false ); break; } } sortedByDesire.clear(); REQUIRE( sortedByDesire.size() == 0 ); sortedByDesire.insert(std::make_pair( 0, sa2 )); sortedByDesire.insert(std::make_pair( 1, sa )); sortedByDesire.insert(std::make_pair( 0, sa3 )); i = 0; for( iter = sortedByDesire.begin(); iter != sortedByDesire.end(); ++iter, ++i ) { switch( i ) { case 0: REQUIRE( (* iter).second == sa2 ); break; case 1: REQUIRE( (* iter).second == sa3 ); break; case 2: REQUIRE( (* iter).second == sa ); break; default: REQUIRE( false ); break; } } return 0; }