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: ...@@ -49,6 +49,8 @@ public:
int backlog = Const::MaxBacklog); int backlog = Const::MaxBacklog);
void setHandler(const std::shared_ptr<Handler>& handler); void setHandler(const std::shared_ptr<Handler>& handler);
static bool systemSupportsIpv6();
void bind(); void bind();
void bind(const Address& address); void bind(const Address& address);
......
...@@ -52,6 +52,7 @@ public: ...@@ -52,6 +52,7 @@ public:
Ipv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d); Ipv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d);
static Ipv4 any(); static Ipv4 any();
static Ipv4 loopback();
std::string toString() const; std::string toString() const;
void toNetwork(in_addr_t*) const; void toNetwork(in_addr_t*) const;
...@@ -67,6 +68,8 @@ public: ...@@ -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); 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 any();
static Ipv6 loopback();
std::string toString() const; std::string toString() const;
void toNetwork(in6_addr*) const; void toNetwork(in6_addr*) const;
......
...@@ -50,6 +50,12 @@ Ipv4::any() { ...@@ -50,6 +50,12 @@ Ipv4::any() {
return Ipv4(0, 0, 0, 0); return Ipv4(0, 0, 0, 0);
} }
Ipv4
Ipv4::loopback() {
return Ipv4(127, 0, 0, 1);
}
std::string std::string
Ipv4::toString() const { Ipv4::toString() const {
...@@ -86,6 +92,11 @@ Ipv6::any() { ...@@ -86,6 +92,11 @@ Ipv6::any() {
return Ipv6(0, 0, 0, 0, 0, 0, 0, 0); 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 std::string
Ipv6::toString() const { Ipv6::toString() const {
...@@ -97,7 +108,7 @@ Ipv6::toString() const { ...@@ -97,7 +108,7 @@ Ipv6::toString() const {
inet_ntop(AF_INET6, &addr, buff6, INET6_ADDRSTRLEN); 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 { void Ipv6::toNetwork(in6_addr *addr6) const {
...@@ -196,7 +207,8 @@ Address::init(const std::string& addr) { ...@@ -196,7 +207,8 @@ Address::init(const std::string& addr) {
unsigned long s_pos = addr.find('['); unsigned long s_pos = addr.find('[');
if (pos != std::string::npos && s_pos != std::string::npos) { if (pos != std::string::npos && s_pos != std::string::npos) {
//IPv6 address //IPv6 address
host_ = addr.substr(s_pos, pos+1); host_ = addr.substr(s_pos+1, pos-1);
family_ = AF_INET6;
try { try {
in6_addr addr6; in6_addr addr6;
char buff6[INET6_ADDRSTRLEN+1]; char buff6[INET6_ADDRSTRLEN+1];
...@@ -212,6 +224,7 @@ Address::init(const std::string& addr) { ...@@ -212,6 +224,7 @@ Address::init(const std::string& addr) {
if (pos == std::string::npos) if (pos == std::string::npos)
throw std::invalid_argument("Invalid address"); throw std::invalid_argument("Invalid address");
host_ = addr.substr(0, pos); host_ = addr.substr(0, pos);
family_ = AF_INET;
if (host_ == "*") { if (host_ == "*") {
host_ = "0.0.0.0"; host_ = "0.0.0.0";
} }
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netdb.h> #include <netdb.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <sys/timerfd.h> #include <sys/timerfd.h>
...@@ -145,6 +147,29 @@ Listener::pinWorker(size_t worker, const CpuSet& set) ...@@ -145,6 +147,29 @@ Listener::pinWorker(size_t worker, const CpuSet& set)
#endif #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 void
Listener::bind() { Listener::bind() {
bind(addr_); bind(addr_);
......
...@@ -123,6 +123,7 @@ TEST(listener_test, listener_bind_port_free) { ...@@ -123,6 +123,7 @@ TEST(listener_test, listener_bind_port_free) {
ASSERT_TRUE(true); ASSERT_TRUE(true);
} }
// Listener should not crash if an additional member is added to the listener class. This test // Listener should not crash if an additional member is added to the listener class. This test
// is there to prevent regression for PR 303 // is there to prevent regression for PR 303
TEST(listener_test, listener_uses_default) { TEST(listener_test, listener_uses_default) {
...@@ -180,6 +181,7 @@ TEST(listener_test, listener_bind_port_not_free_throw_runtime) { ...@@ -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. // Listener should be able to bind port 0 directly to get an ephemeral port.
TEST(listener_test, listener_bind_ephemeral_port) { TEST(listener_test, listener_bind_ephemeral_port) {
Pistache::Port port(0); Pistache::Port port(0);
...@@ -192,3 +194,20 @@ TEST(listener_test, listener_bind_ephemeral_port) { ...@@ -192,3 +194,20 @@ TEST(listener_test, listener_bind_ephemeral_port) {
Pistache::Port bound_port = listener.getPort(); Pistache::Port bound_port = listener.getPort();
ASSERT_TRUE(bound_port > (uint16_t)0); 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) ...@@ -50,29 +50,37 @@ TEST(net_test, address_creation)
ASSERT_EQ(address5.port(), 8080); ASSERT_EQ(address5.port(), 8080);
Address address6("[::1]:8080"); Address address6("[::1]:8080");
ASSERT_EQ(address6.host(), "[::1]"); ASSERT_EQ(address6.host(), "::1");
ASSERT_EQ(address6.port(), 8080); ASSERT_EQ(address6.port(), 8080);
std::string addr2 = "[::1]"; std::string addr2 = "[::1]";
Address address7(addr2, Port(8080)); Address address7(addr2, Port(8080));
ASSERT_EQ(address7.host(), "[::1]"); ASSERT_EQ(address7.host(), "::1");
ASSERT_EQ(address7.port(), 8080); ASSERT_EQ(address7.port(), 8080);
Address address8(Ipv6(0, 0, 0, 0, 0, 0, 0, 1), 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); ASSERT_EQ(address8.port(), 8080);
Address address9(Ipv6::any(), Port(8080)); Address address9(Ipv6::any(), Port(8080));
ASSERT_EQ(address9.host(), "[::]"); ASSERT_EQ(address9.host(), "::");
ASSERT_EQ(address9.port(), 8080); ASSERT_EQ(address9.port(), 8080);
Address address10("[::]:8080"); Address address10("[::]:8080");
ASSERT_EQ(address10.host(), "[::]"); ASSERT_EQ(address10.host(), "::");
ASSERT_EQ(address10.port(), 8080); ASSERT_EQ(address10.port(), 8080);
Address address11("[2001:0DB8:AABB:CCDD:EEFF:0011:2233:4455]: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); 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) 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