Bladeren bron

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
Tatsuhiro Tsujikawa 17 jaren geleden
bovenliggende
commit
2cc471ebf6

+ 29 - 0
ChangeLog

@@ -1,3 +1,32 @@
+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.

+ 3 - 0
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);

+ 13 - 2
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

+ 1 - 2
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

+ 5 - 0
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

+ 23 - 7
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

+ 157 - 158
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

+ 3 - 5
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.

+ 1 - 2
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));

+ 13 - 0
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

+ 1 - 1
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));