summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2008-02-20 13:02:48 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2008-02-20 13:02:48 +0000
commit2cc471ebf6600f11c6af07e4e968778c2c470b0b (patch)
tree240c13bf954e4286856490e615f78d238c63f925
parent4708809094a67fd75276aed2794f14274f1122e6 (diff)
2008-02-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
IPv6 support for SocketCore class. TODO: In SocketCore::establishConnection(), this is insufficient to determin the failure of connect() here because the socket is non-blocking state. The next addresses should be tried after select(). TODO: NameResolver still uses c-ares(<= 1.4) ares_gethostbyname(). If c-ares 1.5 or newer is installed, ares_getaddrinfo() should be used instead which address family independent. TODO: DHTRoutingTable{Deserializer,Serializer} currently saves peer information in a compact peer format which is for IPv4 only. Some BitTorrent functions in PeerMessageUtil still depends on IPv4 but this is a spec of BitTorrent protocol. * src/SocketCore.{h, cc} * src/PeerMessageUtil.cc * test/SocketCoreTest.cc * test/PeerMessageUtilTest.cc * test/DHTConnectionImplTest.cc Handle IPv4-mapped addresses. * src/DHTNode.cc: Now identity is determined by node id. * src/DHTMessageTrackerEntry.cc Because now PeerMessageUtil::unpackcompact() could fail, the caller should handle it. * src/DHTRoutingTableDeserializer.cc * src/DHTMessageFactoryImpl.cc
-rw-r--r--ChangeLog29
-rw-r--r--src/DHTMessageFactoryImpl.cc3
-rw-r--r--src/DHTMessageTrackerEntry.cc15
-rw-r--r--src/DHTNode.cc3
-rw-r--r--src/DHTRoutingTableDeserializer.cc5
-rw-r--r--src/PeerMessageUtil.cc30
-rw-r--r--src/SocketCore.cc315
-rw-r--r--src/SocketCore.h8
-rw-r--r--test/DHTConnectionImplTest.cc3
-rw-r--r--test/PeerMessageUtilTest.cc13
-rw-r--r--test/SocketCoreTest.cc2
11 files changed, 249 insertions, 177 deletions
diff --git a/ChangeLog b/ChangeLog
index f3220a18..56701ee8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,34 @@
2008-02-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
+ IPv6 support for SocketCore class.
+ TODO: In SocketCore::establishConnection(), this is insufficient to
+ determin the failure of connect() here because the socket is
+ non-blocking state. The next addresses should be tried after select().
+ TODO: NameResolver still uses c-ares(<= 1.4) ares_gethostbyname().
+ If c-ares 1.5 or newer is installed, ares_getaddrinfo() should be used
+ instead which address family independent.
+ TODO: DHTRoutingTable{Deserializer,Serializer} currently saves peer
+ information in a compact peer format which is for IPv4 only.
+
+ Some BitTorrent functions in PeerMessageUtil still depends on IPv4 but
+ this is a spec of BitTorrent protocol.
+ * src/SocketCore.{h, cc}
+ * src/PeerMessageUtil.cc
+ * test/SocketCoreTest.cc
+ * test/PeerMessageUtilTest.cc
+ * test/DHTConnectionImplTest.cc
+
+ Handle IPv4-mapped addresses.
+ * src/DHTNode.cc: Now identity is determined by node id.
+ * src/DHTMessageTrackerEntry.cc
+
+ Because now PeerMessageUtil::unpackcompact() could fail, the caller
+ should handle it.
+ * src/DHTRoutingTableDeserializer.cc
+ * src/DHTMessageFactoryImpl.cc
+
+2008-02-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
+
Change the unit of --stop option from a minute to a second.
* src/usage_text.h
* src/DownloadEngineFactory.cc
diff --git a/src/DHTMessageFactoryImpl.cc b/src/DHTMessageFactoryImpl.cc
index 8eb55071..001eeae7 100644
--- a/src/DHTMessageFactoryImpl.cc
+++ b/src/DHTMessageFactoryImpl.cc
@@ -299,6 +299,9 @@ std::deque<SharedHandle<DHTNode> > DHTMessageFactoryImpl::extractNodes(const cha
SharedHandle<DHTNode> node = new DHTNode(reinterpret_cast<const unsigned char*>(src+offset));
std::pair<std::string, uint16_t> addr =
PeerMessageUtil::unpackcompact(src+offset+DHT_ID_LENGTH);
+ if(addr.first.empty()) {
+ continue;
+ }
node->setIPAddress(addr.first);
node->setPort(addr.second);
nodes.push_back(node);
diff --git a/src/DHTMessageTrackerEntry.cc b/src/DHTMessageTrackerEntry.cc
index dc7c0ecf..25204e17 100644
--- a/src/DHTMessageTrackerEntry.cc
+++ b/src/DHTMessageTrackerEntry.cc
@@ -37,6 +37,7 @@
#include "DHTMessage.h"
#include "DHTMessageCallback.h"
#include "DHTConstants.h"
+#include "Util.h"
namespace aria2 {
@@ -60,8 +61,18 @@ void DHTMessageTrackerEntry::extendTimeout()
bool DHTMessageTrackerEntry::match(const std::string& transactionID, const std::string& ipaddr, uint16_t port) const
{
- return _transactionID == transactionID &&
- _targetNode->getIPAddress() == ipaddr && _targetNode->getPort() == port;
+ if(_transactionID != transactionID || _targetNode->getPort() != port) {
+ return false;
+ }
+ if(_targetNode->getIPAddress() == ipaddr) {
+ return true;
+ }
+ if(Util::endsWith(_targetNode->getIPAddress(), ipaddr)) {
+ return _targetNode->getIPAddress() == "::ffff:"+ipaddr;
+ } else if(Util::endsWith(ipaddr, _targetNode->getIPAddress())) {
+ return ipaddr == "::ffff:"+_targetNode->getIPAddress();
+ }
+ return false;
}
SharedHandle<DHTMessageCallback> DHTMessageTrackerEntry::getCallback() const
diff --git a/src/DHTNode.cc b/src/DHTNode.cc
index c1220d76..294360e8 100644
--- a/src/DHTNode.cc
+++ b/src/DHTNode.cc
@@ -56,8 +56,7 @@ void DHTNode::generateID()
bool DHTNode::operator==(const DHTNode& node) const
{
- return memcmp(_id, node._id, DHT_ID_LENGTH) == 0 &&
- _ipaddr == node._ipaddr && _port == node._port;
+ return memcmp(_id, node._id, DHT_ID_LENGTH) == 0;
}
bool DHTNode::operator<(const DHTNode& node) const
diff --git a/src/DHTRoutingTableDeserializer.cc b/src/DHTRoutingTableDeserializer.cc
index c370ff09..da0433bf 100644
--- a/src/DHTRoutingTableDeserializer.cc
+++ b/src/DHTRoutingTableDeserializer.cc
@@ -116,6 +116,11 @@ void DHTRoutingTableDeserializer::deserialize(std::istream& in)
continue;
}
std::pair<std::string, uint16_t> peer = PeerMessageUtil::unpackcompact(buf);
+ if(peer.first.empty()) {
+ // skip this entry
+ in.read(buf, 26);
+ continue;
+ }
// 2bytes reserved
in.read(buf, 2);
// localnode ID
diff --git a/src/PeerMessageUtil.cc b/src/PeerMessageUtil.cc
index c32ac949..d12b55f5 100644
--- a/src/PeerMessageUtil.cc
+++ b/src/PeerMessageUtil.cc
@@ -127,24 +127,40 @@ void PeerMessageUtil::createPeerMessageString(unsigned char* msg,
bool PeerMessageUtil::createcompact(char* compact, const std::string& addr, uint16_t port)
{
- struct in_addr in;
- if(inet_aton(addr.c_str(), &in) == 0) {
+ struct addrinfo hints;
+ struct addrinfo* res;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET; // since compact peer format is ipv4 only.
+ hints.ai_flags = AI_NUMERICHOST;
+ if(getaddrinfo(addr.c_str(), 0, &hints, &res)) {
return false;
}
+ struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(res->ai_addr);
uint32_t* addrp = (uint32_t*)compact;
- *addrp = in.s_addr;
+ *addrp = in->sin_addr.s_addr;
uint16_t* portp = (uint16_t*)(compact+4);
*portp = htons(port);
+ freeaddrinfo(res);
return true;
}
std::pair<std::string, uint16_t> PeerMessageUtil::unpackcompact(const char* compact)
{
- struct in_addr in;
- in.s_addr = *(uint32_t*)(compact);
- std::string ipaddr = inet_ntoa(in);
+ struct sockaddr_in in;
+ memset(&in, 0, sizeof(in));
+ in.sin_family = AF_INET;
+ in.sin_addr.s_addr = *reinterpret_cast<const uint32_t*>(compact);
+ in.sin_port = 0;
+ char host[NI_MAXHOST];
+ int s;
+ s = getnameinfo(reinterpret_cast<const struct sockaddr*>(&in), sizeof(in),
+ host, NI_MAXHOST, 0, NI_MAXSERV,
+ NI_NUMERICHOST);
+ if(s) {
+ return std::pair<std::string, uint16_t>();
+ }
uint16_t port = ntohs(*(uint16_t*)(compact+sizeof(uint32_t)));
- return std::pair<std::string, uint16_t>(ipaddr, port);
+ return std::pair<std::string, uint16_t>(host, port);
}
} // namespace aria2
diff --git a/src/SocketCore.cc b/src/SocketCore.cc
index 8bbaf394..57bd3ab7 100644
--- a/src/SocketCore.cc
+++ b/src/SocketCore.cc
@@ -47,6 +47,18 @@
# define SOCKET_ERRNO (WSAGetLastError())
#endif // __MINGW32__
+#ifdef __MINGW32__
+# define A2_EINPROGRESS WSAEWOULDBLOCK
+#else
+# define A2_EINPROGRESS EINPROGRESS
+#endif // __MINGW32__
+
+#ifdef __MINGW32__
+# define CLOSE(X) ::closesocket(sockfd)
+#else
+# define CLOSE(X) while(close(X) == -1 && errno == EINTR)
+#endif // __MINGW32__
+
namespace aria2 {
SocketCore::SocketCore(int sockType):_sockType(sockType), sockfd(-1) {
@@ -83,33 +95,61 @@ SocketCore::~SocketCore() {
#endif // HAVE_LIBGNUTLS
}
-void SocketCore::bind(uint16_t port)
+template<typename T>
+std::string uitos(T value)
{
- closeConnection();
- //sockfd = socket(AF_UNSPEC, _sockType, PF_UNSPEC);
- sockfd = socket(AF_INET, _sockType, 0);
- if(sockfd == -1) {
- throw new DlAbortEx(EX_SOCKET_OPEN, errorMsg());
+ std::string str;
+ if(value == 0) {
+ str = "0";
+ return str;
}
- SOCKOPT_T sockopt = 1;
- if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(socklen_t)) < 0) {
-#ifdef __MINGW32__
- ::closesocket(sockfd);
-#else
- while(close(sockfd) == -1 && errno == EINTR);
-#endif // __MINGW32__
- sockfd = -1;
- throw new DlAbortEx(EX_SOCKET_SET_OPT, errorMsg());
+ int32_t count = 0;
+ while(value) {
+ ++count;
+ char digit = value%10+'0';
+ str.insert(str.begin(), digit);
+ value /= 10;
}
+ return str;
+}
- struct sockaddr_in sockaddr;
- memset((char*)&sockaddr, 0, sizeof(sockaddr));
- sockaddr.sin_family = AF_INET;
- sockaddr.sin_addr.s_addr = INADDR_ANY;
- sockaddr.sin_port = htons(port);
-
- if(::bind(sockfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == -1) {
- throw new DlAbortEx(EX_SOCKET_BIND, errorMsg());
+void SocketCore::bind(uint16_t port)
+{
+ closeConnection();
+
+ struct addrinfo hints;
+ struct addrinfo* res;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = _sockType;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_protocol = 0;
+ int s;
+ s = getaddrinfo(0, uitos(port).c_str(), &hints, &res);
+ if(s) {
+ throw new DlAbortEx(EX_SOCKET_BIND, gai_strerror(s));
+ }
+ struct addrinfo* rp;
+ for(rp = res; rp; rp = rp->ai_next) {
+ int fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ if(fd == -1) {
+ continue;
+ }
+ SOCKOPT_T sockopt = 1;
+ if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(socklen_t)) < 0) {
+ CLOSE(fd);
+ continue;
+ }
+ if(::bind(fd, rp->ai_addr, rp->ai_addrlen) == -1) {
+ CLOSE(fd);
+ continue;
+ }
+ sockfd = fd;
+ break;
+ }
+ freeaddrinfo(res);
+ if(sockfd == -1) {
+ throw new DlAbortEx(EX_SOCKET_BIND, "all addresses failed");
}
}
@@ -122,89 +162,95 @@ void SocketCore::beginListen()
SocketCore* SocketCore::acceptConnection() const
{
- struct sockaddr_in sockaddr;
+ struct sockaddr_storage sockaddr;
socklen_t len = sizeof(sockaddr);
- memset((char*)&sockaddr, 0, sizeof(sockaddr));
- int32_t fd;
- while((fd = accept(sockfd, (struct sockaddr*)&sockaddr, &len)) == -1 && errno == EINTR);
+ int fd;
+ while((fd = accept(sockfd, reinterpret_cast<struct sockaddr*>(&sockaddr), &len)) == -1 && errno == EINTR);
if(fd == -1) {
throw new DlAbortEx(EX_SOCKET_ACCEPT, errorMsg());
}
- SocketCore* s = new SocketCore(fd, _sockType);
- return s;
+ return new SocketCore(fd, _sockType);
+}
+
+std::pair<std::string, uint16_t>
+SocketCore::getNameInfoInNumeric(const struct sockaddr* sockaddr, socklen_t len)
+{
+ char host[NI_MAXHOST];
+ char service[NI_MAXSERV];
+ int s = getnameinfo(sockaddr, len, host, NI_MAXHOST, service, NI_MAXSERV,
+ NI_NUMERICHOST|NI_NUMERICSERV);
+ if(s != 0) {
+ throw new DlAbortEx("Failed to get hostname and port. cause: %s",
+ gai_strerror(s));
+ }
+ return std::pair<std::string, uint16_t>(host, atoi(service)); // TODO
}
void SocketCore::getAddrInfo(std::pair<std::string, int32_t>& addrinfo) const
{
- struct sockaddr_in listenaddr;
- memset((char*)&listenaddr, 0, sizeof(listenaddr));
- socklen_t len = sizeof(listenaddr);
- if(getsockname(sockfd, (struct sockaddr*)&listenaddr, &len) == -1) {
+ struct sockaddr_storage sockaddr;
+ socklen_t len = sizeof(sockaddr);
+ struct sockaddr* addrp = reinterpret_cast<struct sockaddr*>(&sockaddr);
+ if(getsockname(sockfd, addrp, &len) == -1) {
throw new DlAbortEx(EX_SOCKET_GET_NAME, errorMsg());
}
- addrinfo.first = inet_ntoa(listenaddr.sin_addr);
- addrinfo.second = ntohs(listenaddr.sin_port);
+ addrinfo = SocketCore::getNameInfoInNumeric(addrp, len);
}
void SocketCore::getPeerInfo(std::pair<std::string, int32_t>& peerinfo) const
{
- struct sockaddr_in peerin;
- memset(&peerin, 0, sizeof(peerin));
- int32_t len = sizeof(peerin);
- if(getpeername(sockfd, (struct sockaddr*)&peerin, (socklen_t*)&len) < 0) {
- throw new DlAbortEx(EX_SOCKET_GET_PEER, errorMsg());
- }
- peerinfo.first = inet_ntoa(peerin.sin_addr);
- peerinfo.second = ntohs(peerin.sin_port);
+ struct sockaddr_storage sockaddr;
+ socklen_t len = sizeof(sockaddr);
+ struct sockaddr* addrp = reinterpret_cast<struct sockaddr*>(&sockaddr);
+ if(getpeername(sockfd, addrp, &len) == -1) {
+ throw new DlAbortEx(EX_SOCKET_GET_NAME, errorMsg());
+ }
+ peerinfo = SocketCore::getNameInfoInNumeric(addrp, len);
}
void SocketCore::establishConnection(const std::string& host, int32_t port)
{
closeConnection();
- sockfd = socket(AF_INET, _sockType, 0);
- if(sockfd == -1) {
- throw new DlAbortEx(EX_SOCKET_OPEN, errorMsg());
- }
- SOCKOPT_T sockopt = 1;
- if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(socklen_t)) < 0) {
- while(close(sockfd) == -1 && errno == EINTR);
- sockfd = -1;
- throw new DlAbortEx(EX_SOCKET_SET_OPT, errorMsg());
- }
- struct sockaddr_in sockaddr;
- memset((char*)&sockaddr, 0, sizeof(sockaddr));
- sockaddr.sin_family = AF_INET;
- sockaddr.sin_port = htons(port);
- if(inet_aton(host.c_str(), &sockaddr.sin_addr)) {
- // ok
- } else {
- struct addrinfo ai;
- memset((char*)&ai, 0, sizeof(ai));
- ai.ai_flags = 0;
- ai.ai_family = PF_INET;
- ai.ai_socktype = _sockType;
- ai.ai_protocol = 0;
- struct addrinfo* res;
- int32_t ec;
- if((ec = getaddrinfo(host.c_str(), NULL, &ai, &res)) != 0) {
- throw new DlAbortEx(EX_RESOLVE_HOSTNAME,
- host.c_str(), gai_strerror(ec));
+ struct addrinfo hints;
+ struct addrinfo* res;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = _sockType;
+ hints.ai_flags = 0;
+ hints.ai_protocol = 0;
+ int s;
+ s = getaddrinfo(host.c_str(), uitos(port).c_str(), &hints, &res);
+ if(s) {
+ throw new DlAbortEx(EX_RESOLVE_HOSTNAME, host.c_str(), gai_strerror(s));
+ }
+ struct addrinfo* rp;
+ for(rp = res; rp; rp = rp->ai_next) {
+ int fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ if(fd == -1) {
+ continue;
}
- sockaddr.sin_addr = ((struct sockaddr_in*)res->ai_addr)->sin_addr;
- freeaddrinfo(res);
+ SOCKOPT_T sockopt = 1;
+ if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(socklen_t)) < 0) {
+ CLOSE(fd);
+ continue;
+ }
+ sockfd = fd;
+ // make socket non-blocking mode
+ setNonBlockingMode();
+ if(connect(fd, rp->ai_addr, rp->ai_addrlen) == -1 &&
+ SOCKET_ERRNO != A2_EINPROGRESS) {
+ CLOSE(sockfd);
+ sockfd = -1;
+ continue;
+ }
+ // TODO at this point, connection may not be established and it may fail
+ // later. In such case, next ai_addr should be tried.
+ break;
}
- // make socket non-blocking mode
- setNonBlockingMode();
- // TODO handle EINTR
- if(connect(sockfd, (struct sockaddr*)&sockaddr, (socklen_t)sizeof(sockaddr)) == -1 && SOCKET_ERRNO !=
-#ifndef __MINGW32__
-EINPROGRESS
-#else
-WSAEWOULDBLOCK
-#endif // __MINGW32__
- ) {
- throw new DlAbortEx(EX_SOCKET_CONNECT, host.c_str(), errorMsg());
+ freeaddrinfo(res);
+ if(sockfd == -1) {
+ throw new DlAbortEx(EX_SOCKET_CONNECT, host.c_str(), "all addresses failed");
}
}
@@ -254,11 +300,7 @@ void SocketCore::closeConnection()
}
#endif // HAVE_LIBGNUTLS
if(sockfd != -1) {
-#ifdef __MINGW32__
- ::closesocket(sockfd);
-#else
- while(close(sockfd) == -1 && errno == EINTR);
-#endif // __MINGW32__
+ CLOSE(sockfd);
sockfd = -1;
}
#ifdef HAVE_LIBSSL
@@ -578,94 +620,51 @@ void SocketCore::initiateSecureConnection()
#endif // __MINGW32__
}
-template<typename T>
-std::string uitos(T value)
+void SocketCore::writeData(const char* data, size_t len, const std::string& host, uint16_t port)
{
- std::string str;
- if(value == 0) {
- str = "0";
- return str;
- }
- int32_t count = 0;
- while(value) {
- ++count;
- char digit = value%10+'0';
- str.insert(str.begin(), digit);
- value /= 10;
- }
- return str;
-}
-void fillSockaddr(sockaddr* addr, int sockType, const std::string& host, uint16_t port)
-{
struct addrinfo hints;
- struct addrinfo* result;
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_INET;
- hints.ai_socktype = sockType;
+ struct addrinfo* res;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = _sockType;
hints.ai_flags = 0;
hints.ai_protocol = 0;
- {
- int r = getaddrinfo(host.c_str(), uitos(port).c_str(), &hints, &result);
- if(r != 0) {
- throw new DlAbortEx(EX_RESOLVE_HOSTNAME,
- host.c_str(), gai_strerror(r));
+ int s;
+ s = getaddrinfo(host.c_str(), uitos(port).c_str(), &hints, &res);
+ if(s) {
+ throw new DlAbortEx(EX_SOCKET_SEND, gai_strerror(s));
+ }
+ struct addrinfo* rp;
+ ssize_t r = -1;
+ for(rp = res; rp; rp = rp->ai_next) {
+ while((r = sendto(sockfd, data, len, 0, rp->ai_addr, rp->ai_addrlen)) == -1 && EINTR == errno);
+ if(r == static_cast<ssize_t>(len)) {
+ break;
}
}
- memcpy(addr, result->ai_addr, result->ai_addrlen);
- freeaddrinfo(result);
-}
-
-void SocketCore::writeData(const char* data, size_t len, const std::string& host, uint16_t port)
-{
- struct sockaddr_storage addrPeer;
- fillSockaddr((struct sockaddr*)&addrPeer, _sockType, host, port);
- ssize_t r;
- while((r = sendto(sockfd, data, len, 0, (const sockaddr*)&addrPeer, sizeof(struct sockaddr_storage))) == -1 && EINTR == errno);
+ freeaddrinfo(res);
if(r == -1) {
throw new DlAbortEx(EX_SOCKET_SEND, errorMsg());
}
}
-ssize_t SocketCore::readDataFrom(char* data, size_t len, struct sockaddr* sender, socklen_t* senderLength)
+ssize_t SocketCore::readDataFrom(char* data, size_t len,
+ std::pair<std::string /* numerichost */,
+ uint16_t /* port */>& sender)
{
+ struct sockaddr_storage sockaddr;
+ socklen_t sockaddrlen = sizeof(struct sockaddr_storage);
+ struct sockaddr* addrp = reinterpret_cast<struct sockaddr*>(&sockaddr);
ssize_t r;
- while((r = recvfrom(sockfd, data, len, 0, sender, senderLength)) == -1 &&
+ while((r = recvfrom(sockfd, data, len, 0, addrp, &sockaddrlen)) == -1 &&
EINTR == errno);
if(r == -1) {
throw new DlAbortEx(EX_SOCKET_RECV, errorMsg());
}
- return r;
-}
+ sender = SocketCore::getNameInfoInNumeric(addrp, sockaddrlen);
-ssize_t SocketCore::readDataFrom(char* data, size_t len)
-{
-
- return readDataFrom(data, len, 0, 0);
-}
-
-ssize_t SocketCore::readDataFrom(char* data, size_t len,
- std::pair<std::string /* numerichost */,
- uint16_t /* port */>& sender)
-{
- struct sockaddr_storage addrSender;
- socklen_t addrSenderLength = sizeof(struct sockaddr_storage);
- ssize_t rlength = readDataFrom(data, len, (struct sockaddr*)&addrSender, &addrSenderLength);
-
- char host[NI_MAXHOST];
- char service[NI_MAXSERV];
- {
- int s = getnameinfo((struct sockaddr*)&addrSender, addrSenderLength,
- host, NI_MAXHOST, service, NI_MAXSERV,
- NI_NUMERICHOST|NI_NUMERICSERV);
- if(s != 0) {
- throw new DlAbortEx("Failed to get peer's hostname and port. cause: %s",
- gai_strerror(s));
- }
- }
- sender.first = host;
- sender.second = atoi(service); // TODO
- return rlength;
+ return r;
}
} // namespace aria2
diff --git a/src/SocketCore.h b/src/SocketCore.h
index 77f71428..774ccab3 100644
--- a/src/SocketCore.h
+++ b/src/SocketCore.h
@@ -87,6 +87,9 @@ private:
static int error();
static const char *errorMsg();
static const char *errorMsg(const int err);
+
+ static std::pair<std::string, uint16_t>
+ getNameInfoInNumeric(const struct sockaddr* sockaddr, socklen_t len);
public:
SocketCore(int sockType = SOCK_STREAM);
~SocketCore();
@@ -206,15 +209,10 @@ public:
readData(reinterpret_cast<char*>(data), len);
}
- ssize_t readDataFrom(char* data, size_t len, struct sockaddr* sender,
- socklen_t* senderLength);
-
ssize_t readDataFrom(char*, size_t len,
std::pair<std::string /* numerichost */,
uint16_t /* port */>& sender);
- ssize_t readDataFrom(char* data, size_t len);
-
/**
* Reads up to len bytes from this socket, but bytes are not removed from
* this socket.
diff --git a/test/DHTConnectionImplTest.cc b/test/DHTConnectionImplTest.cc
index a6c8544d..7c3b6f36 100644
--- a/test/DHTConnectionImplTest.cc
+++ b/test/DHTConnectionImplTest.cc
@@ -29,14 +29,13 @@ void DHTConnectionImplTest::testWriteAndReadData()
uint16_t con2port = con2.bind(0);
std::string message1 = "hello world.";
- con1.sendMessage(message1.c_str(), message1.size(), "localhost", con2port);
+ con1.sendMessage(message1.c_str(), message1.size(), "127.0.0.1", con2port);
char readbuffer[100];
std::string remoteHost;
uint16_t remotePort;
{
ssize_t rlength = con2.receiveMessage(readbuffer, sizeof(readbuffer), remoteHost, remotePort);
- CPPUNIT_ASSERT_EQUAL(std::string("127.0.0.1"), remoteHost);
CPPUNIT_ASSERT_EQUAL((ssize_t)message1.size(), rlength);
readbuffer[rlength] = '\0';
CPPUNIT_ASSERT_EQUAL(message1, std::string(readbuffer));
diff --git a/test/PeerMessageUtilTest.cc b/test/PeerMessageUtilTest.cc
index 90be6856..4b4e8126 100644
--- a/test/PeerMessageUtilTest.cc
+++ b/test/PeerMessageUtilTest.cc
@@ -9,6 +9,7 @@ namespace aria2 {
class PeerMessageUtilTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(PeerMessageUtilTest);
+ CPPUNIT_TEST(testCreateCompact);
CPPUNIT_TEST_SUITE_END();
private:
@@ -16,6 +17,7 @@ public:
void setUp() {
}
+ void testCreateCompact();
};
@@ -37,4 +39,15 @@ void createNLengthMessage(char* msg, int msgLen, int payloadLen, int id) {
msg[4] = (char)id;
}
+void PeerMessageUtilTest::testCreateCompact()
+{
+ char compact[6];
+ CPPUNIT_ASSERT(PeerMessageUtil::createcompact(compact, "::ffff:127.0.0.1", 6881));
+
+ std::pair<std::string, uint16_t> p = PeerMessageUtil::unpackcompact(compact);
+ CPPUNIT_ASSERT_EQUAL(std::string("127.0.0.1"), p.first);
+ CPPUNIT_ASSERT_EQUAL((uint16_t)6881, p.second);
+}
+
+
} // namespace aria2
diff --git a/test/SocketCoreTest.cc b/test/SocketCoreTest.cc
index c075f113..38d7d092 100644
--- a/test/SocketCoreTest.cc
+++ b/test/SocketCoreTest.cc
@@ -47,7 +47,7 @@ void SocketCoreTest::testWriteAndReadDatagram()
CPPUNIT_ASSERT_EQUAL(message1, std::string(readbuffer));
}
{
- ssize_t rlength = s.readDataFrom(readbuffer, sizeof(readbuffer));
+ ssize_t rlength = s.readDataFrom(readbuffer, sizeof(readbuffer), peer);
CPPUNIT_ASSERT_EQUAL((ssize_t)message2.size(), rlength);
readbuffer[rlength] = '\0';
CPPUNIT_ASSERT_EQUAL(message2, std::string(readbuffer));