From 2cc471ebf6600f11c6af07e4e968778c2c470b0b Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 20 Feb 2008 13:02:48 +0000 Subject: [PATCH] 2008-02-20 Tatsuhiro Tsujikawa 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 --- ChangeLog | 29 +++ src/DHTMessageFactoryImpl.cc | 3 + src/DHTMessageTrackerEntry.cc | 15 +- src/DHTNode.cc | 3 +- src/DHTRoutingTableDeserializer.cc | 5 + src/PeerMessageUtil.cc | 30 ++- src/SocketCore.cc | 329 ++++++++++++++--------------- src/SocketCore.h | 8 +- test/DHTConnectionImplTest.cc | 3 +- test/PeerMessageUtilTest.cc | 13 ++ test/SocketCoreTest.cc | 2 +- 11 files changed, 256 insertions(+), 184 deletions(-) diff --git a/ChangeLog b/ChangeLog index f3220a18..56701ee8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2008-02-20 Tatsuhiro Tsujikawa + + 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 Change the unit of --stop option from a minute to a second. 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 > DHTMessageFactoryImpl::extractNodes(const cha SharedHandle node = new DHTNode(reinterpret_cast(src+offset)); std::pair 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 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 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(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 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(compact); + in.sin_port = 0; + char host[NI_MAXHOST]; + int s; + s = getnameinfo(reinterpret_cast(&in), sizeof(in), + host, NI_MAXHOST, 0, NI_MAXSERV, + NI_NUMERICHOST); + if(s) { + return std::pair(); + } uint16_t port = ntohs(*(uint16_t*)(compact+sizeof(uint32_t))); - return std::pair(ipaddr, port); + return std::pair(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 } +template +std::string uitos(T value) +{ + 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 SocketCore::bind(uint16_t port) { closeConnection(); - //sockfd = socket(AF_UNSPEC, _sockType, PF_UNSPEC); - 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) { -#ifdef __MINGW32__ - ::closesocket(sockfd); -#else - while(close(sockfd) == -1 && errno == EINTR); -#endif // __MINGW32__ - 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_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()); + 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(&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 +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(host, atoi(service)); // TODO } void SocketCore::getAddrInfo(std::pair& 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(&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& 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()); + struct sockaddr_storage sockaddr; + socklen_t len = sizeof(sockaddr); + struct sockaddr* addrp = reinterpret_cast(&sockaddr); + if(getpeername(sockfd, addrp, &len) == -1) { + throw new DlAbortEx(EX_SOCKET_GET_NAME, errorMsg()); } - peerinfo.first = inet_ntoa(peerin.sin_addr); - peerinfo.second = ntohs(peerin.sin_port); + 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)); - } - sockaddr.sin_addr = ((struct sockaddr_in*)res->ai_addr)->sin_addr; - freeaddrinfo(res); + 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)); } - // 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()); + 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; + } + 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; + } + 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 -std::string uitos(T value) -{ - 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; - 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)); - } - } - 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); + + 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_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(len)) { + break; + } + } + 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 r; - while((r = recvfrom(sockfd, data, len, 0, sender, senderLength)) == -1 && - EINTR == errno); - if(r == -1) { - throw new DlAbortEx(EX_SOCKET_RECV, errorMsg()); - } - return r; -} - -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& 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)); - } + struct sockaddr_storage sockaddr; + socklen_t sockaddrlen = sizeof(struct sockaddr_storage); + struct sockaddr* addrp = reinterpret_cast(&sockaddr); + ssize_t r; + while((r = recvfrom(sockfd, data, len, 0, addrp, &sockaddrlen)) == -1 && + EINTR == errno); + if(r == -1) { + throw new DlAbortEx(EX_SOCKET_RECV, errorMsg()); } - sender.first = host; - sender.second = atoi(service); // TODO - return rlength; + sender = SocketCore::getNameInfoInNumeric(addrp, sockaddrlen); + + 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 + getNameInfoInNumeric(const struct sockaddr* sockaddr, socklen_t len); public: SocketCore(int sockType = SOCK_STREAM); ~SocketCore(); @@ -206,15 +209,10 @@ public: readData(reinterpret_cast(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& 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 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));