Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fc::ip::address::is_loopback_address(), fix is_public_address() #244

Merged
merged 5 commits into from
Sep 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()