Skip to content

Commit

Permalink
Merge pull request #244 from bitshares/update-ip
Browse files Browse the repository at this point in the history
Add fc::ip::address::is_loopback_address(), fix is_public_address()
  • Loading branch information
abitmore authored Sep 1, 2022
2 parents 7db6fba + ba21645 commit ad7b28b
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
name: Build and run tests in macOS
strategy:
matrix:
os: [macos-10.15, macos-11.0]
os: [macos-11.0]
runs-on: ${{ matrix.os }}
steps:
- name: Install dependencies
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/sonar-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ jobs:
steps:
- name: Download and install latest SonarScanner CLI tool
run: |
SONAR_SCANNER_VERSION=`curl https://github.com/SonarSource/sonar-scanner-cli/releases/latest \
2>/dev/null | cut -f2 -d'"' | cut -f8 -d'/'`
SONAR_SCANNER_VERSION=`curl -w %{redirect_url} \
https://github.com/SonarSource/sonar-scanner-cli/releases/latest \
2>/dev/null | cut -f8 -d'/'`
SONAR_DOWNLOAD_PATH=https://binaries.sonarsource.com/Distribution/sonar-scanner-cli
curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip \
$SONAR_DOWNLOAD_PATH/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip
Expand Down
47 changes: 35 additions & 12 deletions include/fc/network/ip.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ namespace fc {
namespace ip {
class address {
public:
address( uint32_t _ip = 0 );
address( const std::string& s );
explicit address( uint32_t ip = 0 );
explicit address( const std::string& s );

address& operator=( const std::string& s );
operator std::string()const;
address& operator=( uint32_t ip );
explicit operator std::string()const;
// Note: there are quite a few places where it is used implicitly, so we haven't marked it as explicit so far.
operator uint32_t()const;

friend bool operator==( const address& a, const address& b );
Expand All @@ -22,33 +24,54 @@ namespace fc {
/**
* @return true if the ip is in the following ranges:
*
* 10.0.0.0 to 10.255.255.255
* 172.16.0.0 to 172.31.255.255
* 192.168.0.0 to 192.168.255.255
* 169.254.0.0 to 169.254.255.255
* * 10.0.0.0 to 10.255.255.255
* * 172.16.0.0 to 172.31.255.255
* * 192.168.0.0 to 192.168.255.255
* * 169.254.0.0 to 169.254.255.255
*
*/
bool is_private_address()const;
/**
* 224.0.0.0 to 239.255.255.255
*/
bool is_multicast_address()const;
/**
* 127.0.0.0 to 127.255.255.255
*/
bool is_loopback_address()const;

/** !private & !multicast */
/**
* not private, not loopback, and not multicast
*
* @note technically there are some addresses that are reserved but not public
* (see https://en.wikipedia.org/wiki/Reserved_IP_addresses), but so far we haven't distinguished them.
* * 0.0.0.0–0.255.255.255
* * 100.64.0.0–100.127.255.255
* * 192.0.0.0–192.0.0.255
* * 192.0.2.0–192.0.2.255
* * 192.88.99.0–192.88.99.255
* * 198.18.0.0–198.19.255.255
* * 198.51.100.0–198.51.100.255
* * 203.0.113.0–203.0.113.255
* * 233.252.0.0-233.252.0.255 (within the range 224.0.0.0–239.255.255.255)
* * 240.0.0.0–255.255.255.254
* * 255.255.255.255
*/
bool is_public_address()const;
private:
uint32_t _ip;
};

class endpoint {
public:
endpoint();
endpoint( const address& i, uint16_t p = 0);
endpoint() = default;
explicit endpoint( const address& i, uint16_t p = 0);
explicit endpoint( uint32_t i, uint16_t p = 0);

/** Converts "IP:PORT" to an endpoint */
static endpoint from_string( const string& s );
/** returns "IP:PORT" */
operator string()const;
explicit operator string()const;

void set_port(uint16_t p ) { _port = p; }
uint16_t port()const;
Expand All @@ -66,7 +89,7 @@ namespace fc {
* otherwise 2 bytes will be 'random' and you do not know
* where they are stored.
*/
uint32_t _port;
uint32_t _port = 0;
address _ip;
};

Expand Down
2 changes: 1 addition & 1 deletion src/network/http/http_connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ fc::tcp_socket& connection::get_socket()const {

http::request connection::read_request()const {
http::request req;
req.remote_endpoint = fc::variant(get_socket().remote_endpoint()).as_string();
req.remote_endpoint = std::string(get_socket().remote_endpoint());
std::vector<char> line(1024*8);
int s = my->read_until( line.data(), line.data()+line.size(), ' ' ); // METHOD
req.method = line.data();
Expand Down
39 changes: 28 additions & 11 deletions src/network/ip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace fc { namespace ip {
address::address( uint32_t ip )
:_ip(ip){}

address::address( const std::string& s )
address::address( const std::string& s )
{
try
{
Expand All @@ -26,7 +26,7 @@ namespace fc { namespace ip {
return uint32_t(a) != uint32_t(b);
}

address& address::operator=( const std::string& s )
address& address::operator=( const std::string& s )
{
try
{
Expand All @@ -36,7 +36,13 @@ namespace fc { namespace ip {
return *this;
}

address::operator std::string()const
address& address::operator=( uint32_t ip )
{
_ip = ip;
return *this;
}

address::operator std::string()const
{
try
{
Expand All @@ -49,11 +55,12 @@ namespace fc { namespace ip {
}


endpoint::endpoint()
:_port(0){ }
endpoint::endpoint(const address& a, uint16_t p)
:_port(p),_ip(a){}

endpoint::endpoint(uint32_t a, uint16_t p)
:_port(p),_ip(a){}

bool operator==( const endpoint& a, const endpoint& b ) {
return a._port == b._port && a._ip == b._ip;
}
Expand Down Expand Up @@ -84,7 +91,7 @@ namespace fc { namespace ip {
FC_RETHROW_EXCEPTIONS(warn, "error converting string to IP endpoint")
}

endpoint::operator string()const
endpoint::operator string()const
{
try
{
Expand All @@ -93,7 +100,7 @@ namespace fc { namespace ip {
FC_RETHROW_EXCEPTIONS(warn, "error converting IP endpoint to string")
}

/**
/*
* @return true if the ip is in the following ranges:
*
* 10.0.0.0 to 10.255.255.255
Expand All @@ -119,7 +126,7 @@ namespace fc { namespace ip {
return false;
}

/**
/*
* 224.0.0.0 to 239.255.255.255
*/
bool address::is_multicast_address()const
Expand All @@ -129,10 +136,20 @@ namespace fc { namespace ip {
return _ip >= min_ip._ip && _ip <= max_ip._ip;
}

/** !private & !multicast */
/*
* 127.0.0.0 to 127.255.255.255
*/
bool address::is_loopback_address()const
{
static address min_ip("127.0.0.0");
static address max_ip("127.255.255.255");
return _ip >= min_ip._ip && _ip <= max_ip._ip;
}

// not private, not loopback, and not multicast
bool address::is_public_address()const
{
return !( is_private_address() || is_multicast_address() );
return !( is_private_address() || is_loopback_address() || is_multicast_address() );
}

} // namespace ip
Expand All @@ -155,4 +172,4 @@ namespace fc { namespace ip {
vo = ip::address(var.as_string());
}

}
}
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ add_executable( all_tests all_tests.cpp
io/stream_tests.cpp
io/tcp_test.cpp
io/varint_tests.cpp
network/ip_tests.cpp
network/http/websocket_test.cpp
thread/task_cancel.cpp
thread/thread_tests.cpp
Expand Down
100 changes: 100 additions & 0 deletions tests/network/ip_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include <boost/test/unit_test.hpp>

#include <fc/network/ip.hpp>
#include <fc/variant.hpp>

BOOST_AUTO_TEST_SUITE(fc_network)

BOOST_AUTO_TEST_CASE(ip_address_test)
{
std::vector<std::string> local_ips { "127.0.0.1", "127.20.30.40" };
std::vector<std::string> multicast_ips { "224.88.77.66", "239.11.23.45" };
std::vector<std::string> private_ips { "10.2.3.4", "169.254.7.9", "192.168.5.6", "172.30.8.10" };
std::vector<std::string> public_ips { "2.3.4.55", "200.100.50.25" };
std::vector<std::string> bad_ips { "some_string", "2.300.4.55", "200:100.50.25.1" };

for( auto& ip_str : local_ips )
{
fc::ip::address ip(ip_str);
BOOST_CHECK( ip.is_loopback_address() );
BOOST_CHECK( !ip.is_multicast_address() );
BOOST_CHECK( !ip.is_private_address() );
BOOST_CHECK( !ip.is_public_address() );
}
for( auto& ip_str : multicast_ips )
{
fc::ip::address ip;
ip = ip_str;
BOOST_CHECK( !ip.is_loopback_address() );
BOOST_CHECK( ip.is_multicast_address() );
BOOST_CHECK( !ip.is_private_address() );
BOOST_CHECK( !ip.is_public_address() );
}
for( auto& ip_str : private_ips )
{
fc::ip::address ip(ip_str);
BOOST_CHECK( !ip.is_loopback_address() );
BOOST_CHECK( !ip.is_multicast_address() );
BOOST_CHECK( ip.is_private_address() );
BOOST_CHECK( !ip.is_public_address() );
}
for( auto& ip_str : public_ips )
{
fc::ip::address ip;
ip = ip_str;
BOOST_CHECK( !ip.is_loopback_address() );
BOOST_CHECK( !ip.is_multicast_address() );
BOOST_CHECK( !ip.is_private_address() );
BOOST_CHECK( ip.is_public_address() );
}
for( auto& ip_str : bad_ips )
{
BOOST_CHECK_THROW( fc::ip::address( ip_str ).is_public_address(), fc::exception );
fc::ip::address ip;
BOOST_CHECK_THROW( ip = ip_str, fc::exception );
}

fc::ip::address ip1(100U);
fc::ip::address ip2;
ip2 = 100U;
fc::ip::address ip3("0.0.0.100");
fc::ip::address ip4;
ip4 = std::string("0.0.0.100");
std::string ip5_str("100.0.0.0");
fc::ip::address ip5("100.0.0.0");

BOOST_CHECK( ip1 == ip2 );
BOOST_CHECK( ip1 == ip3 );
BOOST_CHECK( ip1 == ip4 );
BOOST_CHECK( ip1 != ip5 );
BOOST_CHECK( uint32_t(ip1) == 100U );
BOOST_CHECK( std::string(ip1) == std::string("0.0.0.100") );
}

BOOST_AUTO_TEST_CASE(ip_endpoint_test)
{
fc::ip::address ip100("0.0.0.100");
fc::ip::endpoint ep1(ip100, 100);
fc::ip::endpoint ep2(100, 100);
fc::ip::endpoint ep3(100, 101);
fc::ip::endpoint ep4(101, 100);
BOOST_CHECK( ep1 == ep2 );
BOOST_CHECK( ep1 != ep3 );
BOOST_CHECK( ep1 < ep3 );
BOOST_CHECK( ep1 < ep4 );
BOOST_CHECK( ep3 < ep4 );

std::string ep5_str("1.2.3.4:567");
fc::ip::endpoint ep5 = fc::ip::endpoint::from_string( ep5_str );
BOOST_CHECK( std::string(ep5) == ep5_str );

fc::variant v;
fc::to_variant( ep5, v, 2 );

fc::ip::endpoint ep6;
fc::from_variant( v, ep6, 2 );

BOOST_CHECK( ep5 == ep6 );
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit ad7b28b

Please sign in to comment.