File rtorrent-ipv6.patch of Package rtorrent-pyro-git
diff -Naur a/AUTHORS b/AUTHORS
--- a/AUTHORS 2015-09-04 03:03:45.000000000 +0800
+++ b/AUTHORS 2015-11-06 21:12:08.793123648 +0800
@@ -1 +1 @@
-Jari Sundell <jaris@ifi.uio.no>
+Jari Sundell <sundell.software@gmail.com>
diff -Naur a/README b/README
--- a/README 2015-09-04 03:03:45.000000000 +0800
+++ b/README 2015-11-06 21:12:08.793123648 +0800
@@ -32,5 +32,10 @@
CONTACT
- Send bug reports, suggestions and patches to <jaris@ifi.uio.no> or
-to the mailinglist.
+ Jari Sundell
+
+ Skomakerveien 33
+ 3185 Skoppum, NORWAY
+
+ Send bug reports, suggestions and patches to
+<sundell.software@gmail.com> or to the mailinglist.
diff -Naur a/rak/socket_address.h b/rak/socket_address.h
--- a/rak/socket_address.h 2015-09-04 03:03:45.000000000 +0800
+++ b/rak/socket_address.h 2015-11-06 21:12:08.794123680 +0800
@@ -109,13 +109,11 @@
const sockaddr* c_sockaddr() const { return &m_sockaddr; }
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); }
const socket_address_inet6* sa_inet6() const { return reinterpret_cast<const socket_address_inet6*>(this); }
sockaddr_in6* c_sockaddr_inet6() { 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
// extranous bytes and ensure it does not go beyond the size of this
@@ -139,13 +137,11 @@
union {
sockaddr m_sockaddr;
sockaddr_in m_sockaddrInet;
-#ifdef RAK_USE_INET6
sockaddr_in6 m_sockaddrInet6;
-#endif
};
};
-// Remeber to set the AF_INET.
+// Remember to set the AF_INET.
class socket_address_inet {
public:
@@ -184,6 +180,8 @@
const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&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;
@@ -192,48 +190,47 @@
struct sockaddr_in m_sockaddr;
};
-// Unique key for the address, excluding port numbers etc.
-class socket_address_key {
+class socket_address_inet6 {
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) {
- *this = sa;
- }
+ void clear() { std::memset(this, 0, sizeof(socket_address_inet6)); set_family(); }
- socket_address_key& operator = (const socket_address& sa) {
- if (sa.family() == 0) {
- std::memset(this, 0, sizeof(socket_address_key));
+ uint16_t port() const { return ntohs(m_sockaddr.sin6_port); }
+ uint16_t port_n() const { return m_sockaddr.sin6_port; }
+ 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) {
- // Using hardware order as we use operator < to compare when
- // using inet only.
- m_addr.s_addr = sa.sa_inet()->address_h();
+ in6_addr address() const { return m_sockaddr.sin6_addr; }
+ const in6_addr* address_ptr() const { return &m_sockaddr.sin6_addr; }
+ std::string address_str() const;
+ bool address_c_str(char* buf, socklen_t size) const;
- } else {
- // When we implement INET6 handling, embed the ipv4 address in
- // the ipv6 address.
- throw std::logic_error("socket_address_key(...) received an unsupported protocol family.");
- }
+ void set_address(in6_addr a) { m_sockaddr.sin6_addr = a; }
+ bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
+ bool set_address_c_str(const char* a);
- 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 {
- // Compare the memory area instead.
- return m_addr.s_addr < sa.m_addr.s_addr;
- }
+ sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
+ sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddr; }
+
+ 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:
- union {
- in_addr m_addr;
-// #ifdef RAK_USE_INET6
-// in_addr6 m_addr6;
-// #endif
- };
+ struct sockaddr_in6 m_sockaddr;
};
inline bool
@@ -241,8 +238,8 @@
switch (family()) {
case af_inet:
return sa_inet()->is_valid();
-// case af_inet6:
-// return sa_inet6().is_valid();
+ case af_inet6:
+ return sa_inet6()->is_valid();
default:
return false;
}
@@ -253,6 +250,8 @@
switch (family()) {
case af_inet:
return !sa_inet()->is_address_any();
+ case af_inet6:
+ return !sa_inet6()->is_address_any();
default:
return false;
}
@@ -263,6 +262,8 @@
switch (family()) {
case af_inet:
return sa_inet()->is_address_any();
+ case af_inet6:
+ return sa_inet6()->is_address_any();
default:
return true;
}
@@ -273,6 +274,8 @@
switch (family()) {
case af_inet:
return sa_inet()->port();
+ case af_inet6:
+ return sa_inet6()->port();
default:
return 0;
}
@@ -283,6 +286,8 @@
switch (family()) {
case af_inet:
return sa_inet()->set_port(p);
+ case af_inet6:
+ return sa_inet6()->set_port(p);
default:
break;
}
@@ -293,6 +298,8 @@
switch (family()) {
case af_inet:
return sa_inet()->address_str();
+ case af_inet6:
+ return sa_inet6()->address_str();
default:
return std::string();
}
@@ -303,6 +310,8 @@
switch (family()) {
case af_inet:
return sa_inet()->address_c_str(buf, size);
+ case af_inet6:
+ return sa_inet6()->address_c_str(buf, size);
default:
return false;
}
@@ -314,6 +323,10 @@
sa_inet()->set_family();
return true;
+ } else if (sa_inet6()->set_address_c_str(a)) {
+ sa_inet6()->set_family();
+ return true;
+
} else {
return false;
}
@@ -325,6 +338,8 @@
switch(family()) {
case af_inet:
return sizeof(sockaddr_in);
+ case af_inet6:
+ return sizeof(sockaddr_in6);
default:
return 0;
}
@@ -349,8 +364,8 @@
switch (family()) {
case af_inet:
return *sa_inet() == *rhs.sa_inet();
-// case af_inet6:
-// return *sa_inet6() == *rhs.sa_inet6();
+ case af_inet6:
+ return *sa_inet6() == *rhs.sa_inet6();
default:
throw std::logic_error("socket_address::operator == (rhs) invalid type comparison.");
}
@@ -364,8 +379,8 @@
switch (family()) {
case af_inet:
return *sa_inet() < *rhs.sa_inet();
-// case af_inet6:
-// return *sa_inet6() < *rhs.sa_inet6();
+ case af_inet6:
+ return *sa_inet6() < *rhs.sa_inet6();
default:
throw std::logic_error("socket_address::operator < (rhs) invalid type comparison.");
}
@@ -391,6 +406,21 @@
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
socket_address_inet::operator == (const socket_address_inet& rhs) const {
return
@@ -406,6 +436,55 @@
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
diff -Naur a/src/command_download.cc b/src/command_download.cc
--- a/src/command_download.cc 2015-09-04 03:03:45.000000000 +0800
+++ b/src/command_download.cc 2015-11-06 21:12:08.794123680 +0800
@@ -308,7 +308,10 @@
if (download->download()->info()->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)
port = 6881;
@@ -318,7 +321,7 @@
if (port < 1 || port > 65535)
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
diff -Naur a/src/command_network.cc b/src/command_network.cc
--- a/src/command_network.cc 2015-09-04 03:03:45.000000000 +0800
+++ b/src/command_network.cc 2015-11-06 21:12:08.794123680 +0800
@@ -172,8 +172,9 @@
lt_log_print(torrent::LOG_RPC_EVENTS,
"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) {
- if ((err = rak::address_info::get_address_info(address, PF_INET, SOCK_STREAM, &ai)) != 0)
+ } else if (std::sscanf(arg.c_str(), "%1023[^:]:%i%c", address, &port, &dummy) == 2 ||
+ 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)) + ".");
saPtr = ai->address();
diff -Naur a/src/command_peer.cc b/src/command_peer.cc
--- a/src/command_peer.cc 2015-09-04 03:03:45.000000000 +0800
+++ b/src/command_peer.cc 2015-11-06 21:12:08.795123711 +0800
@@ -69,7 +69,12 @@
torrent::Object
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
diff -Naur a/src/core/curl_get.cc b/src/core/curl_get.cc
--- a/src/core/curl_get.cc 2015-09-04 03:03:45.000000000 +0800
+++ b/src/core/curl_get.cc 2015-11-06 21:12:08.795123711 +0800
@@ -91,9 +91,13 @@
curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL, (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_IPRESOLVE, CURL_IPRESOLVE_V4);
+
+ curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
+
curl_easy_setopt(m_handle, CURLOPT_ENCODING, "");
+ m_ipv6 = false;
+
m_stack->add_get(this);
}
@@ -111,6 +115,17 @@
}
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
CurlGet::receive_timeout() {
return m_stack->transfer_done(m_handle, "Timed out");
}
diff -Naur a/src/core/curl_get.h b/src/core/curl_get.h
--- a/src/core/curl_get.h 2015-09-04 03:03:45.000000000 +0800
+++ b/src/core/curl_get.h 2015-11-06 21:12:08.795123711 +0800
@@ -58,6 +58,9 @@
void start();
void close();
+ bool is_using_ipv6() { return m_ipv6; }
+ void retry_ipv6();
+
bool is_busy() const { return m_handle; }
bool is_active() const { return m_active; }
@@ -75,6 +78,7 @@
void receive_timeout();
bool m_active;
+ bool m_ipv6;
rak::priority_item m_taskTimeout;
diff -Naur a/src/core/curl_stack.cc b/src/core/curl_stack.cc
--- a/src/core/curl_stack.cc 2015-09-04 03:03:45.000000000 +0800
+++ b/src/core/curl_stack.cc 2015-11-06 21:12:08.795123711 +0800
@@ -131,8 +131,23 @@
if (msg->msg != CURLMSG_DONE)
throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE.");
- transfer_done(msg->easy_handle,
- msg->data.result == CURLE_OK ? NULL : curl_easy_strerror(msg->data.result));
+ if (msg->data.result == CURLE_COULDNT_RESOLVE_HOST) {
+ 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;
}
diff -Naur a/src/core/manager.cc b/src/core/manager.cc
--- a/src/core/manager.cc 2015-09-04 03:03:45.000000000 +0800
+++ b/src/core/manager.cc 2015-11-06 21:12:08.796123742 +0800
@@ -223,7 +223,8 @@
int err;
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)) + ".");
try {
@@ -257,7 +258,8 @@
int err;
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)) + ".");
try {
diff -Naur a/src/display/window_peer_list.cc b/src/display/window_peer_list.cc
--- a/src/display/window_peer_list.cc 2015-09-04 03:03:45.000000000 +0800
+++ b/src/display/window_peer_list.cc 2015-11-06 21:12:08.796123742 +0800
@@ -68,7 +68,7 @@
int x = 2;
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, "DOWN"); x += 7;
m_canvas->print(x, y, "PEER"); x += 7;
@@ -99,10 +99,16 @@
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",
range.first == *m_focus ? '*' : ' ',
- rak::socket_address::cast_from(p->address())->address_str().c_str());
- x += 18;
+ ip_address.c_str());
+ x += 27;
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;
diff -Naur a/src/main.cc b/src/main.cc
--- a/src/main.cc 2015-09-04 03:03:45.000000000 +0800
+++ b/src/main.cc 2015-11-06 21:12:08.796123742 +0800
@@ -273,6 +273,7 @@
"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.hash_done, !_timestamp, {(branch,((d.complete)),((d.timestamp.finished.set_if_z,(system.time))))}\n"
"method.insert.c_simple = group.insert_persistent_view,"
"((view.add,((argument.0)))),((view.persistent,((argument.0)))),((group.insert,((argument.0)),((argument.0))))\n"
diff -Naur a/src/utils/socket_fd.cc b/src/utils/socket_fd.cc
--- a/src/utils/socket_fd.cc 2015-09-04 03:03:45.000000000 +0800
+++ b/src/utils/socket_fd.cc 2015-11-06 21:12:08.796123742 +0800
@@ -71,7 +71,10 @@
check_valid();
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
@@ -130,12 +133,30 @@
bool
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
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
@@ -153,6 +174,11 @@
SocketFd::bind(const rak::socket_address& sa) {
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());
}
@@ -160,6 +186,11 @@
SocketFd::bind(const rak::socket_address& sa, unsigned int length) {
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);
}
@@ -167,10 +198,31 @@
SocketFd::connect(const rak::socket_address& sa) {
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;
}
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
SocketFd::listen(int size) {
check_valid();
@@ -182,7 +234,14 @@
check_valid();
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
diff -Naur a/src/utils/socket_fd.h b/src/utils/socket_fd.h
--- a/src/utils/socket_fd.h 2015-09-04 03:03:45.000000000 +0800
+++ b/src/utils/socket_fd.h 2015-11-06 21:12:08.797123773 +0800
@@ -80,6 +80,7 @@
bool bind(const rak::socket_address& sa);
bool bind(const rak::socket_address& sa, unsigned int length);
bool connect(const rak::socket_address& sa);
+ bool getsockname(rak::socket_address* sa);
bool listen(int size);
SocketFd accept(rak::socket_address* sa);
@@ -91,6 +92,7 @@
inline void check_valid() const;
int m_fd;
+ bool m_ipv6_socket;
};
}