Merge pull request #507 from rakshasa/ipv6

Ipv6
This commit is contained in:
Jari Sundell
2016-10-11 06:44:15 +09:00
committed by GitHub
14 changed files with 260 additions and 63 deletions
+1 -1
View File
@@ -1 +1 @@
Jari Sundell <jaris@ifi.uio.no> Jari Sundell <sundell.software@gmail.com>
+7 -2
View File
@@ -32,5 +32,10 @@ DEPENDENCIES
CONTACT CONTACT
Send bug reports, suggestions and patches to <jaris@ifi.uio.no> or Jari Sundell
to the mailinglist.
Skomakerveien 33
3185 Skoppum, NORWAY
Send bug reports, suggestions and patches to
<sundell.software@gmail.com> or to the mailinglist.
+122 -43
View File
@@ -109,13 +109,11 @@ public:
const sockaddr* c_sockaddr() const { return &m_sockaddr; } const sockaddr* c_sockaddr() const { return &m_sockaddr; }
const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddrInet; } const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddrInet; }
#ifdef RAK_USE_INET6
socket_address_inet6* sa_inet6() { return reinterpret_cast<socket_address_inet6*>(this); } socket_address_inet6* sa_inet6() { return reinterpret_cast<socket_address_inet6*>(this); }
const socket_address_inet6* sa_inet6() const { return reinterpret_cast<const socket_address_inet6*>(this); } const socket_address_inet6* sa_inet6() const { return reinterpret_cast<const socket_address_inet6*>(this); }
sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddrInet6; } sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddrInet6; }
const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddrInet6; } const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddrInet6; }
#endif
// Copy a socket address which has the length 'length. Zero out any // Copy a socket address which has the length 'length. Zero out any
// extranous bytes and ensure it does not go beyond the size of this // extranous bytes and ensure it does not go beyond the size of this
@@ -139,13 +137,11 @@ private:
union { union {
sockaddr m_sockaddr; sockaddr m_sockaddr;
sockaddr_in m_sockaddrInet; sockaddr_in m_sockaddrInet;
#ifdef RAK_USE_INET6
sockaddr_in6 m_sockaddrInet6; sockaddr_in6 m_sockaddrInet6;
#endif
}; };
}; };
// Remeber to set the AF_INET. // Remember to set the AF_INET.
class socket_address_inet { class socket_address_inet {
public: public:
@@ -184,6 +180,8 @@ public:
const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); } const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddr; } const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddr; }
socket_address_inet6 to_mapped_address() const;
bool operator == (const socket_address_inet& rhs) const; bool operator == (const socket_address_inet& rhs) const;
bool operator < (const socket_address_inet& rhs) const; bool operator < (const socket_address_inet& rhs) const;
@@ -192,48 +190,47 @@ private:
struct sockaddr_in m_sockaddr; struct sockaddr_in m_sockaddr;
}; };
// Unique key for the address, excluding port numbers etc. class socket_address_inet6 {
class socket_address_key {
public: public:
// socket_address_host_key() {} bool is_any() const { return is_port_any() && is_address_any(); }
bool is_valid() const { return !is_port_any() && !is_address_any(); }
bool is_port_any() const { return port() == 0; }
bool is_address_any() const { return std::memcmp(&m_sockaddr.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0; }
socket_address_key(const socket_address& sa) { void clear() { std::memset(this, 0, sizeof(socket_address_inet6)); set_family(); }
*this = sa;
}
socket_address_key& operator = (const socket_address& sa) { uint16_t port() const { return ntohs(m_sockaddr.sin6_port); }
if (sa.family() == 0) { uint16_t port_n() const { return m_sockaddr.sin6_port; }
std::memset(this, 0, sizeof(socket_address_key)); void set_port(uint16_t p) { m_sockaddr.sin6_port = htons(p); }
void set_port_n(uint16_t p) { m_sockaddr.sin6_port = p; }
} else if (sa.family() == socket_address::af_inet) { in6_addr address() const { return m_sockaddr.sin6_addr; }
// Using hardware order as we use operator < to compare when const in6_addr* address_ptr() const { return &m_sockaddr.sin6_addr; }
// using inet only. std::string address_str() const;
m_addr.s_addr = sa.sa_inet()->address_h(); bool address_c_str(char* buf, socklen_t size) const;
} else { void set_address(in6_addr a) { m_sockaddr.sin6_addr = a; }
// When we implement INET6 handling, embed the ipv4 address in bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
// the ipv6 address. bool set_address_c_str(const char* a);
throw std::logic_error("socket_address_key(...) received an unsupported protocol family.");
}
return *this; void set_address_any() { set_port(0); set_address(in6addr_any); }
}
// socket_address_key& operator = (const socket_address_key& sa) { sa_family_t family() const { return m_sockaddr.sin6_family; }
// } void set_family() { m_sockaddr.sin6_family = AF_INET6; }
bool operator < (const socket_address_key& sa) const { sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
// Compare the memory area instead. sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddr; }
return m_addr.s_addr < sa.m_addr.s_addr;
} const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddr; }
socket_address normalize_address() const;
bool operator == (const socket_address_inet6& rhs) const;
bool operator < (const socket_address_inet6& rhs) const;
private: private:
union { struct sockaddr_in6 m_sockaddr;
in_addr m_addr;
// #ifdef RAK_USE_INET6
// in_addr6 m_addr6;
// #endif
};
}; };
inline bool inline bool
@@ -241,8 +238,8 @@ socket_address::is_valid() const {
switch (family()) { switch (family()) {
case af_inet: case af_inet:
return sa_inet()->is_valid(); return sa_inet()->is_valid();
// case af_inet6: case af_inet6:
// return sa_inet6().is_valid(); return sa_inet6()->is_valid();
default: default:
return false; return false;
} }
@@ -253,6 +250,8 @@ socket_address::is_bindable() const {
switch (family()) { switch (family()) {
case af_inet: case af_inet:
return !sa_inet()->is_address_any(); return !sa_inet()->is_address_any();
case af_inet6:
return !sa_inet6()->is_address_any();
default: default:
return false; return false;
} }
@@ -263,6 +262,8 @@ socket_address::is_address_any() const {
switch (family()) { switch (family()) {
case af_inet: case af_inet:
return sa_inet()->is_address_any(); return sa_inet()->is_address_any();
case af_inet6:
return sa_inet6()->is_address_any();
default: default:
return true; return true;
} }
@@ -273,6 +274,8 @@ socket_address::port() const {
switch (family()) { switch (family()) {
case af_inet: case af_inet:
return sa_inet()->port(); return sa_inet()->port();
case af_inet6:
return sa_inet6()->port();
default: default:
return 0; return 0;
} }
@@ -283,6 +286,8 @@ socket_address::set_port(uint16_t p) {
switch (family()) { switch (family()) {
case af_inet: case af_inet:
return sa_inet()->set_port(p); return sa_inet()->set_port(p);
case af_inet6:
return sa_inet6()->set_port(p);
default: default:
break; break;
} }
@@ -293,6 +298,8 @@ socket_address::address_str() const {
switch (family()) { switch (family()) {
case af_inet: case af_inet:
return sa_inet()->address_str(); return sa_inet()->address_str();
case af_inet6:
return sa_inet6()->address_str();
default: default:
return std::string(); return std::string();
} }
@@ -303,6 +310,8 @@ socket_address::address_c_str(char* buf, socklen_t size) const {
switch (family()) { switch (family()) {
case af_inet: case af_inet:
return sa_inet()->address_c_str(buf, size); return sa_inet()->address_c_str(buf, size);
case af_inet6:
return sa_inet6()->address_c_str(buf, size);
default: default:
return false; return false;
} }
@@ -314,6 +323,10 @@ socket_address::set_address_c_str(const char* a) {
sa_inet()->set_family(); sa_inet()->set_family();
return true; return true;
} else if (sa_inet6()->set_address_c_str(a)) {
sa_inet6()->set_family();
return true;
} else { } else {
return false; return false;
} }
@@ -325,6 +338,8 @@ socket_address::length() const {
switch(family()) { switch(family()) {
case af_inet: case af_inet:
return sizeof(sockaddr_in); return sizeof(sockaddr_in);
case af_inet6:
return sizeof(sockaddr_in6);
default: default:
return 0; return 0;
} }
@@ -349,8 +364,8 @@ socket_address::operator == (const socket_address& rhs) const {
switch (family()) { switch (family()) {
case af_inet: case af_inet:
return *sa_inet() == *rhs.sa_inet(); return *sa_inet() == *rhs.sa_inet();
// case af_inet6: case af_inet6:
// return *sa_inet6() == *rhs.sa_inet6(); return *sa_inet6() == *rhs.sa_inet6();
default: default:
throw std::logic_error("socket_address::operator == (rhs) invalid type comparison."); throw std::logic_error("socket_address::operator == (rhs) invalid type comparison.");
} }
@@ -364,8 +379,8 @@ socket_address::operator < (const socket_address& rhs) const {
switch (family()) { switch (family()) {
case af_inet: case af_inet:
return *sa_inet() < *rhs.sa_inet(); return *sa_inet() < *rhs.sa_inet();
// case af_inet6: case af_inet6:
// return *sa_inet6() < *rhs.sa_inet6(); return *sa_inet6() < *rhs.sa_inet6();
default: default:
throw std::logic_error("socket_address::operator < (rhs) invalid type comparison."); throw std::logic_error("socket_address::operator < (rhs) invalid type comparison.");
} }
@@ -391,6 +406,21 @@ socket_address_inet::set_address_c_str(const char* a) {
return inet_pton(AF_INET, a, &m_sockaddr.sin_addr); return inet_pton(AF_INET, a, &m_sockaddr.sin_addr);
} }
inline socket_address_inet6
socket_address_inet::to_mapped_address() const {
uint32_t addr32[4];
addr32[0] = 0;
addr32[1] = 0;
addr32[2] = htonl(0xffff);
addr32[3] = m_sockaddr.sin_addr.s_addr;
socket_address_inet6 sa;
sa.clear();
sa.set_address(*reinterpret_cast<in6_addr *>(addr32));
sa.set_port_n(m_sockaddr.sin_port);
return sa;
}
inline bool inline bool
socket_address_inet::operator == (const socket_address_inet& rhs) const { socket_address_inet::operator == (const socket_address_inet& rhs) const {
return return
@@ -406,6 +436,55 @@ socket_address_inet::operator < (const socket_address_inet& rhs) const {
m_sockaddr.sin_port < rhs.m_sockaddr.sin_port); m_sockaddr.sin_port < rhs.m_sockaddr.sin_port);
} }
inline std::string
socket_address_inet6::address_str() const {
char buf[INET6_ADDRSTRLEN];
if (!address_c_str(buf, INET6_ADDRSTRLEN))
return std::string();
return std::string(buf);
}
inline bool
socket_address_inet6::address_c_str(char* buf, socklen_t size) const {
return inet_ntop(family(), &m_sockaddr.sin6_addr, buf, size);
}
inline bool
socket_address_inet6::set_address_c_str(const char* a) {
return inet_pton(AF_INET6, a, &m_sockaddr.sin6_addr);
}
inline socket_address
socket_address_inet6::normalize_address() const {
const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(m_sockaddr.sin6_addr.s6_addr);
if (addr32[0] == 0 && addr32[1] == 0 && addr32[2] == htonl(0xffff)) {
socket_address addr4;
addr4.sa_inet()->set_family();
addr4.sa_inet()->set_address_n(addr32[3]);
addr4.sa_inet()->set_port_n(m_sockaddr.sin6_port);
return addr4;
}
return *reinterpret_cast<const socket_address*>(this);
}
inline bool
socket_address_inet6::operator == (const socket_address_inet6& rhs) const {
return
memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr)) == 0 &&
m_sockaddr.sin6_port == rhs.m_sockaddr.sin6_port;
}
inline bool
socket_address_inet6::operator < (const socket_address_inet6& rhs) const {
int addr_comp = memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr));
return
addr_comp < 0 ||
(addr_comp == 0 ||
m_sockaddr.sin6_port < rhs.m_sockaddr.sin6_port);
}
} }
#endif #endif
+5 -2
View File
@@ -308,7 +308,10 @@ apply_d_add_peer(core::Download* download, const std::string& arg) {
if (download->download()->info()->is_private()) if (download->download()->info()->is_private())
throw torrent::input_error("Download is private."); throw torrent::input_error("Download is private.");
ret = std::sscanf(arg.c_str(), "%1023[^:]:%i%c", host, &port, &dummy); ret = std::sscanf(arg.c_str(), "[%64[^]]]:%i%c", host, &port, &dummy);
if (ret < 1)
ret = std::sscanf(arg.c_str(), "%1023[^:]:%i%c", host, &port, &dummy);
if (ret == 1) if (ret == 1)
port = 6881; port = 6881;
@@ -318,7 +321,7 @@ apply_d_add_peer(core::Download* download, const std::string& arg) {
if (port < 1 || port > 65535) if (port < 1 || port > 65535)
throw torrent::input_error("Invalid port number."); throw torrent::input_error("Invalid port number.");
torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_inet, SOCK_STREAM, call_add_d_peer_t(download, port)); torrent::connection_manager()->resolver()(host, (int)rak::socket_address::pf_unspec, SOCK_STREAM, call_add_d_peer_t(download, port));
} }
torrent::Object torrent::Object
+3 -2
View File
@@ -170,8 +170,9 @@ apply_scgi(const std::string& arg, int type) {
lt_log_print(torrent::LOG_RPC_EVENTS, lt_log_print(torrent::LOG_RPC_EVENTS,
"The SCGI socket has not been bound to any address and likely poses a security risk."); "The SCGI socket has not been bound to any address and likely poses a security risk.");
} else if (std::sscanf(arg.c_str(), "%1023[^:]:%i%c", address, &port, &dummy) == 2) { } else if (std::sscanf(arg.c_str(), "%1023[^:]:%i%c", address, &port, &dummy) == 2 ||
if ((err = rak::address_info::get_address_info(address, PF_INET, SOCK_STREAM, &ai)) != 0) std::sscanf(arg.c_str(), "[%64[^]]]:%i%c", address, &port, &dummy) == 2) { // [xx::xx]:port format
if ((err = rak::address_info::get_address_info(address,PF_UNSPEC, SOCK_STREAM, &ai)) != 0)
throw torrent::input_error("Could not bind address: " + std::string(rak::address_info::strerror(err)) + "."); throw torrent::input_error("Could not bind address: " + std::string(rak::address_info::strerror(err)) + ".");
saPtr = ai->address(); saPtr = ai->address();
+6 -1
View File
@@ -69,7 +69,12 @@ retrieve_p_id_html(torrent::Peer* peer) {
torrent::Object torrent::Object
retrieve_p_address(torrent::Peer* peer) { retrieve_p_address(torrent::Peer* peer) {
return rak::socket_address::cast_from(peer->peer_info()->socket_address())->address_str(); const rak::socket_address *addr = rak::socket_address::cast_from(peer->peer_info()->socket_address());
if (addr->family() == rak::socket_address::af_inet6)
return "[" + addr->address_str() + "]";
else
return addr->address_str();
} }
torrent::Object torrent::Object
+16 -1
View File
@@ -91,9 +91,13 @@ CurlGet::start() {
curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL, (long)1); curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL, (long)1);
curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, (long)1); curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, (long)1);
curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS, (long)5); curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS, (long)5);
curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
curl_easy_setopt(m_handle, CURLOPT_ENCODING, ""); curl_easy_setopt(m_handle, CURLOPT_ENCODING, "");
m_ipv6 = false;
m_stack->add_get(this); m_stack->add_get(this);
} }
@@ -110,6 +114,17 @@ CurlGet::close() {
m_handle = NULL; m_handle = NULL;
} }
void
CurlGet::retry_ipv6() {
CURL* nhandle = curl_easy_duphandle(m_handle);
curl_easy_setopt(nhandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
curl_easy_cleanup(m_handle);
m_handle = nhandle;
m_ipv6 = true;
}
void void
CurlGet::receive_timeout() { CurlGet::receive_timeout() {
return m_stack->transfer_done(m_handle, "Timed out"); return m_stack->transfer_done(m_handle, "Timed out");
+4
View File
@@ -58,6 +58,9 @@ public:
void start(); void start();
void close(); void close();
bool is_using_ipv6() { return m_ipv6; }
void retry_ipv6();
bool is_busy() const { return m_handle; } bool is_busy() const { return m_handle; }
bool is_active() const { return m_active; } bool is_active() const { return m_active; }
@@ -75,6 +78,7 @@ private:
void receive_timeout(); void receive_timeout();
bool m_active; bool m_active;
bool m_ipv6;
rak::priority_item m_taskTimeout; rak::priority_item m_taskTimeout;
+17 -2
View File
@@ -132,8 +132,23 @@ CurlStack::process_done_handle() {
if (msg->msg != CURLMSG_DONE) if (msg->msg != CURLMSG_DONE)
throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE."); throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE.");
transfer_done(msg->easy_handle, if (msg->data.result == CURLE_COULDNT_RESOLVE_HOST) {
msg->data.result == CURLE_OK ? NULL : curl_easy_strerror(msg->data.result)); iterator itr = std::find_if(begin(), end(), rak::equal(msg->easy_handle, std::mem_fun(&CurlGet::handle)));
if (itr == end())
throw torrent::internal_error("Could not find CurlGet when calling CurlStack::receive_action.");
if (!(*itr)->is_using_ipv6()) {
(*itr)->retry_ipv6();
if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0)
throw torrent::internal_error("Error calling curl_multi_add_handle.");
}
} else {
transfer_done(msg->easy_handle,
msg->data.result == CURLE_OK ? NULL : curl_easy_strerror(msg->data.result));
}
return remaining_msgs != 0; return remaining_msgs != 0;
} }
+4 -2
View File
@@ -228,7 +228,8 @@ Manager::set_bind_address(const std::string& addr) {
int err; int err;
rak::address_info* ai; rak::address_info* ai;
if ((err = rak::address_info::get_address_info(addr.c_str(), PF_INET, SOCK_STREAM, &ai)) != 0) if ((err = rak::address_info::get_address_info(addr.c_str(), PF_INET, SOCK_STREAM, &ai)) != 0 &&
(err = rak::address_info::get_address_info(addr.c_str(), PF_INET6, SOCK_STREAM, &ai)) != 0)
throw torrent::input_error("Could not set bind address: " + std::string(rak::address_info::strerror(err)) + "."); throw torrent::input_error("Could not set bind address: " + std::string(rak::address_info::strerror(err)) + ".");
try { try {
@@ -262,7 +263,8 @@ Manager::set_local_address(const std::string& addr) {
int err; int err;
rak::address_info* ai; rak::address_info* ai;
if ((err = rak::address_info::get_address_info(addr.c_str(), PF_INET, SOCK_STREAM, &ai)) != 0) if ((err = rak::address_info::get_address_info(addr.c_str(), PF_INET, SOCK_STREAM, &ai)) != 0 &&
(err = rak::address_info::get_address_info(addr.c_str(), PF_INET6, SOCK_STREAM, &ai)) != 0)
throw torrent::input_error("Could not set local address: " + std::string(rak::address_info::strerror(err)) + "."); throw torrent::input_error("Could not set local address: " + std::string(rak::address_info::strerror(err)) + ".");
try { try {
+9 -3
View File
@@ -68,7 +68,7 @@ WindowPeerList::redraw() {
int x = 2; int x = 2;
int y = 0; int y = 0;
m_canvas->print(x, y, "IP"); x += 16; m_canvas->print(x, y, "IP"); x += 25;
m_canvas->print(x, y, "UP"); x += 7; m_canvas->print(x, y, "UP"); x += 7;
m_canvas->print(x, y, "DOWN"); x += 7; m_canvas->print(x, y, "DOWN"); x += 7;
m_canvas->print(x, y, "PEER"); x += 7; m_canvas->print(x, y, "PEER"); x += 7;
@@ -99,10 +99,16 @@ WindowPeerList::redraw() {
x = 0; x = 0;
std::string ip_address = rak::socket_address::cast_from(p->address())->address_str();
if (ip_address.size() >= 24) {
ip_address.replace(ip_address.begin() + 21, ip_address.end(), "...");
}
m_canvas->print(x, y, "%c %s", m_canvas->print(x, y, "%c %s",
range.first == *m_focus ? '*' : ' ', range.first == *m_focus ? '*' : ' ',
rak::socket_address::cast_from(p->address())->address_str().c_str()); ip_address.c_str());
x += 18; x += 27;
m_canvas->print(x, y, "%.1f", (double)p->up_rate()->rate() / 1024); x += 7; m_canvas->print(x, y, "%.1f", (double)p->up_rate()->rate() / 1024); x += 7;
m_canvas->print(x, y, "%.1f", (double)p->down_rate()->rate() / 1024); x += 7; m_canvas->print(x, y, "%.1f", (double)p->down_rate()->rate() / 1024); x += 7;
+1
View File
@@ -275,6 +275,7 @@ main(int argc, char** argv) {
"method.set_key = event.download.resumed, !_timestamp, ((d.timestamp.started.set_if_z, ((system.time)) ))\n" "method.set_key = event.download.resumed, !_timestamp, ((d.timestamp.started.set_if_z, ((system.time)) ))\n"
"method.set_key = event.download.finished, !_timestamp, ((d.timestamp.finished.set_if_z, ((system.time)) ))\n" "method.set_key = event.download.finished, !_timestamp, ((d.timestamp.finished.set_if_z, ((system.time)) ))\n"
"method.set_key = event.download.hash_done, !_timestamp, {(branch,((d.complete)),((d.timestamp.finished.set_if_z,(system.time))))}\n"
"method.insert.c_simple = group.insert_persistent_view," "method.insert.c_simple = group.insert_persistent_view,"
"((view.add,((argument.0)))),((view.persistent,((argument.0)))),((group.insert,((argument.0)),((argument.0))))\n" "((view.add,((argument.0)))),((view.persistent,((argument.0)))),((group.insert,((argument.0)),((argument.0))))\n"
+63 -4
View File
@@ -71,7 +71,10 @@ SocketFd::set_priority(priority_type p) {
check_valid(); check_valid();
int opt = p; int opt = p;
return setsockopt(m_fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) == 0; if (m_ipv6_socket)
return setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) == 0;
else
return setsockopt(m_fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) == 0;
} }
bool bool
@@ -130,12 +133,30 @@ SocketFd::get_error() const {
bool bool
SocketFd::open_stream() { SocketFd::open_stream() {
return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1; m_fd = socket(rak::socket_address::pf_inet6, SOCK_STREAM, IPPROTO_TCP);
if (m_fd == -1) {
m_ipv6_socket = false;
return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1;
}
m_ipv6_socket = true;
int zero = 0;
return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
} }
bool bool
SocketFd::open_datagram() { SocketFd::open_datagram() {
return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1; m_fd = socket(rak::socket_address::pf_inet6, SOCK_DGRAM, 0);
if (m_fd == -1) {
m_ipv6_socket = false;
return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
}
m_ipv6_socket = true;
int zero = 0;
return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
} }
bool bool
@@ -153,6 +174,11 @@ bool
SocketFd::bind(const rak::socket_address& sa) { SocketFd::bind(const rak::socket_address& sa) {
check_valid(); check_valid();
if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped));
}
return !::bind(m_fd, sa.c_sockaddr(), sa.length()); return !::bind(m_fd, sa.c_sockaddr(), sa.length());
} }
@@ -160,6 +186,11 @@ bool
SocketFd::bind(const rak::socket_address& sa, unsigned int length) { SocketFd::bind(const rak::socket_address& sa, unsigned int length) {
check_valid(); check_valid();
if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped));
}
return !::bind(m_fd, sa.c_sockaddr(), length); return !::bind(m_fd, sa.c_sockaddr(), length);
} }
@@ -167,9 +198,30 @@ bool
SocketFd::connect(const rak::socket_address& sa) { SocketFd::connect(const rak::socket_address& sa) {
check_valid(); check_valid();
if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
return !::connect(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped)) || errno == EINPROGRESS;
}
return !::connect(m_fd, sa.c_sockaddr(), sa.length()) || errno == EINPROGRESS; return !::connect(m_fd, sa.c_sockaddr(), sa.length()) || errno == EINPROGRESS;
} }
bool
SocketFd::getsockname(rak::socket_address *sa) {
check_valid();
socklen_t len = sizeof(rak::socket_address);
if (::getsockname(m_fd, sa->c_sockaddr(), &len)) {
return false;
}
if (m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) {
*sa = sa->sa_inet6()->normalize_address();
}
return true;
}
bool bool
SocketFd::listen(int size) { SocketFd::listen(int size) {
check_valid(); check_valid();
@@ -182,7 +234,14 @@ SocketFd::accept(rak::socket_address* sa) {
check_valid(); check_valid();
socklen_t len = sizeof(rak::socket_address); socklen_t len = sizeof(rak::socket_address);
return SocketFd(::accept(m_fd, sa != NULL ? sa->c_sockaddr() : NULL, &len)); if (sa == NULL) {
return SocketFd(::accept(m_fd, NULL, &len));
}
int fd = ::accept(m_fd, sa->c_sockaddr(), &len);
if (fd != -1 && m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) {
*sa = sa->sa_inet6()->normalize_address();
}
return SocketFd(fd);
} }
// unsigned int // unsigned int
+2
View File
@@ -80,6 +80,7 @@ public:
bool bind(const rak::socket_address& sa); bool bind(const rak::socket_address& sa);
bool bind(const rak::socket_address& sa, unsigned int length); bool bind(const rak::socket_address& sa, unsigned int length);
bool connect(const rak::socket_address& sa); bool connect(const rak::socket_address& sa);
bool getsockname(rak::socket_address* sa);
bool listen(int size); bool listen(int size);
SocketFd accept(rak::socket_address* sa); SocketFd accept(rak::socket_address* sa);
@@ -91,6 +92,7 @@ private:
inline void check_valid() const; inline void check_valid() const;
int m_fd; int m_fd;
bool m_ipv6_socket;
}; };
} }