Unverified Commit 88d8c865 authored by Dennis Jenkins's avatar Dennis Jenkins Committed by GitHub

Merge pull request #388 from hydratim/IPv6

IPv6 Bug Fix
parents 6124c84c a3537f57
......@@ -49,6 +49,8 @@ public:
int backlog = Const::MaxBacklog);
void setHandler(const std::shared_ptr<Handler>& handler);
static bool systemSupportsIpv6();
void bind();
void bind(const Address& address);
......
......@@ -52,6 +52,7 @@ public:
Ipv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d);
static Ipv4 any();
static Ipv4 loopback();
std::string toString() const;
void toNetwork(in_addr_t*) const;
......@@ -67,6 +68,8 @@ public:
Ipv6(uint16_t a, uint16_t b, uint16_t c, uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h);
static Ipv6 any();
static Ipv6 loopback();
std::string toString() const;
void toNetwork(in6_addr*) const;
......
......@@ -50,6 +50,12 @@ Ipv4::any() {
return Ipv4(0, 0, 0, 0);
}
Ipv4
Ipv4::loopback() {
return Ipv4(127, 0, 0, 1);
}
std::string
Ipv4::toString() const {
......@@ -86,6 +92,11 @@ Ipv6::any() {
return Ipv6(0, 0, 0, 0, 0, 0, 0, 0);
}
Ipv6
Ipv6::loopback() {
return Ipv6(0, 0, 0, 0, 0, 0, 0, 1);
}
std::string
Ipv6::toString() const {
......@@ -97,7 +108,7 @@ Ipv6::toString() const {
inet_ntop(AF_INET6, &addr, buff6, INET6_ADDRSTRLEN);
return std::string("[") + std::string(buff6) + std::string("]");
return std::string(buff6);
}
void Ipv6::toNetwork(in6_addr *addr6) const {
......@@ -196,7 +207,8 @@ Address::init(const std::string& addr) {
unsigned long s_pos = addr.find('[');
if (pos != std::string::npos && s_pos != std::string::npos) {
//IPv6 address
host_ = addr.substr(s_pos, pos+1);
host_ = addr.substr(s_pos+1, pos-1);
family_ = AF_INET6;
try {
in6_addr addr6;
char buff6[INET6_ADDRSTRLEN+1];
......@@ -212,6 +224,7 @@ Address::init(const std::string& addr) {
if (pos == std::string::npos)
throw std::invalid_argument("Invalid address");
host_ = addr.substr(0, pos);
family_ = AF_INET;
if (host_ == "*") {
host_ = "0.0.0.0";
}
......
......@@ -14,6 +14,8 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
......@@ -145,6 +147,29 @@ Listener::pinWorker(size_t worker, const CpuSet& set)
#endif
}
bool
Listener::systemSupportsIpv6(){
struct ifaddrs *ifaddr, *ifa;
int family, n;
bool supportsIpv6 = false;
if (getifaddrs(&ifaddr) == -1) {
throw std::runtime_error("Call to getifaddrs() failed");
}
for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
if (ifa->ifa_addr == NULL)
continue;
family = ifa->ifa_addr->sa_family;
if (family == AF_INET6) {
supportsIpv6 = true;
continue;
}
}
freeifaddrs(ifaddr);
return supportsIpv6;
}
void
Listener::bind() {
bind(addr_);
......
......@@ -123,6 +123,7 @@ TEST(listener_test, listener_bind_port_free) {
ASSERT_TRUE(true);
}
// Listener should not crash if an additional member is added to the listener class. This test
// is there to prevent regression for PR 303
TEST(listener_test, listener_uses_default) {
......@@ -180,6 +181,7 @@ TEST(listener_test, listener_bind_port_not_free_throw_runtime) {
}
}
// Listener should be able to bind port 0 directly to get an ephemeral port.
TEST(listener_test, listener_bind_ephemeral_port) {
Pistache::Port port(0);
......@@ -192,3 +194,20 @@ TEST(listener_test, listener_bind_ephemeral_port) {
Pistache::Port bound_port = listener.getPort();
ASSERT_TRUE(bound_port > (uint16_t)0);
}
TEST(listener_test, listener_bind_ephemeral_v6_port) {
Pistache::Port port(0);
Pistache::Address address(Pistache::Ipv6::any(), port);
Pistache::Tcp::Listener listener;
if (not listener.systemSupportsIpv6()) {
Pistache::Flags<Pistache::Tcp::Options> options;
listener.setHandler(Pistache::Http::make_handler<DummyHandler>());
listener.bind(address);
Pistache::Port bound_port = listener.getPort();
ASSERT_TRUE(bound_port > (uint16_t)0);
}
ASSERT_TRUE(true);
}
......@@ -50,29 +50,37 @@ TEST(net_test, address_creation)
ASSERT_EQ(address5.port(), 8080);
Address address6("[::1]:8080");
ASSERT_EQ(address6.host(), "[::1]");
ASSERT_EQ(address6.host(), "::1");
ASSERT_EQ(address6.port(), 8080);
std::string addr2 = "[::1]";
Address address7(addr2, Port(8080));
ASSERT_EQ(address7.host(), "[::1]");
ASSERT_EQ(address7.host(), "::1");
ASSERT_EQ(address7.port(), 8080);
Address address8(Ipv6(0, 0, 0, 0, 0, 0, 0, 1), Port(8080));
ASSERT_EQ(address8.host(), "[::1]");
ASSERT_EQ(address8.host(), "::1");
ASSERT_EQ(address8.port(), 8080);
Address address9(Ipv6::any(), Port(8080));
ASSERT_EQ(address9.host(), "[::]");
ASSERT_EQ(address9.host(), "::");
ASSERT_EQ(address9.port(), 8080);
Address address10("[::]:8080");
ASSERT_EQ(address10.host(), "[::]");
ASSERT_EQ(address10.host(), "::");
ASSERT_EQ(address10.port(), 8080);
Address address11("[2001:0DB8:AABB:CCDD:EEFF:0011:2233:4455]:8080");
ASSERT_EQ(address11.host(), "[2001:0DB8:AABB:CCDD:EEFF:0011:2233:4455]");
ASSERT_EQ(address11.host(), "2001:0DB8:AABB:CCDD:EEFF:0011:2233:4455");
ASSERT_EQ(address11.port(), 8080);
Address address12(Ipv4::loopback(), Port(8080));
ASSERT_EQ(address12.host(), "127.0.0.1");
ASSERT_EQ(address12.port(), 8080);
Address address13(Ipv6::loopback(), Port(8080));
ASSERT_EQ(address13.host(), "::1");
ASSERT_EQ(address13.port(), 8080);
}
TEST(net_test, invalid_address)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment