瀏覽代碼

2009-12-24 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Use AI_ADDRCONFIG flag if it is available. Refactored so that
	getaddrinfo calls are not scattered around. Unset AI_ADDRCONFIG
	when conducting unit tests because they fail if networking
	interface is not configured with IPv4 address.
	* src/NameResolver.cc
	* src/SocketCore.cc
	* src/SocketCore.h
	* src/a2netcompat.h
	* test/AllTest.cc
Tatsuhiro Tsujikawa 16 年之前
父節點
當前提交
88bcc6e681
共有 6 個文件被更改,包括 77 次插入39 次删除
  1. 12 0
      ChangeLog
  2. 3 8
      src/NameResolver.cc
  3. 41 31
      src/SocketCore.cc
  4. 12 0
      src/SocketCore.h
  5. 6 0
      src/a2netcompat.h
  6. 3 0
      test/AllTest.cc

+ 12 - 0
ChangeLog

@@ -1,3 +1,15 @@
+2009-12-24  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Use AI_ADDRCONFIG flag if it is available. Refactored so that
+	getaddrinfo calls are not scattered around. Unset AI_ADDRCONFIG
+	when conducting unit tests because they fail if networking
+	interface is not configured with IPv4 address.
+	* src/NameResolver.cc
+	* src/SocketCore.cc
+	* src/SocketCore.h
+	* src/a2netcompat.h
+	* test/AllTest.cc
+
 2009-12-24  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Fixed unit test error

+ 3 - 8
src/NameResolver.cc

@@ -40,6 +40,7 @@
 #include "message.h"
 #include "StringFormat.h"
 #include "util.h"
+#include "SocketCore.h"
 
 namespace aria2 {
 
@@ -48,26 +49,20 @@ NameResolver::NameResolver():_socktype(0), _family(AF_UNSPEC) {}
 void NameResolver::resolve(std::deque<std::string>& resolvedAddresses,
 			   const std::string& hostname)
 {
-  struct addrinfo hints;
   struct addrinfo* res;
-  memset(&hints, 0, sizeof(hints));
-  hints.ai_family = _family;
-  hints.ai_socktype = _socktype;
-  hints.ai_flags = 0;
-  hints.ai_protocol = 0;
   int s;
-  s = getaddrinfo(hostname.c_str(), 0, &hints, &res);
+  s = callGetaddrinfo(&res, hostname.c_str(), 0, _family, _socktype, 0, 0);
   if(s) {
     throw DL_ABORT_EX(StringFormat(EX_RESOLVE_HOSTNAME,
 				 hostname.c_str(), gai_strerror(s)).str());
   }
+  auto_delete<struct addrinfo*> resDeleter(res, freeaddrinfo);
   struct addrinfo* rp;
   for(rp = res; rp; rp = rp->ai_next) {
     std::pair<std::string, uint16_t> addressPort
       = util::getNumericNameInfo(rp->ai_addr, rp->ai_addrlen);
     resolvedAddresses.push_back(addressPort.first);
   }
-  freeaddrinfo(res);
 }
 
 void NameResolver::setSocktype(int socktype)

+ 41 - 31
src/SocketCore.cc

@@ -191,14 +191,9 @@ static sock_t bindTo
 (const char* host, uint16_t port, int family, int sockType,
  int getaddrinfoFlags, std::string& error)
 {
-  struct addrinfo hints;
   struct addrinfo* res;
-  memset(&hints, 0, sizeof(hints));
-  hints.ai_family = family;
-  hints.ai_socktype = sockType;
-  hints.ai_flags = getaddrinfoFlags;
-  hints.ai_protocol = 0;
-  int s = getaddrinfo(host, uitos(port).c_str(), &hints, &res);
+  int s = callGetaddrinfo(&res, host, uitos(port).c_str(), family, sockType,
+			  getaddrinfoFlags, 0);  
   if(s) {
     error = gai_strerror(s);
     return -1;
@@ -307,19 +302,15 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port)
 {
   closeConnection();
 
-  struct addrinfo hints;
   struct addrinfo* res;
-  memset(&hints, 0, sizeof(hints));
-  hints.ai_family = _protocolFamily;
-  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);
+  s = callGetaddrinfo(&res, host.c_str(), uitos(port).c_str(), _protocolFamily,
+		      _sockType, 0, 0);
   if(s) {
     throw DL_ABORT_EX(StringFormat(EX_RESOLVE_HOSTNAME,
 				 host.c_str(), gai_strerror(s)).str());
   }
+  auto_delete<struct addrinfo*> resDeleter(res, freeaddrinfo);
   struct addrinfo* rp;
   for(rp = res; rp; rp = rp->ai_next) {
     sock_t fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
@@ -362,7 +353,6 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port)
     // later. In such case, next ai_addr should be tried.
     break;
   }
-  freeaddrinfo(res);
   if(sockfd == (sock_t) -1) {
     throw DL_ABORT_EX(StringFormat(EX_SOCKET_CONNECT, host.c_str(),
 				   strerror(errno)).str());
@@ -1058,18 +1048,14 @@ ssize_t SocketCore::writeData(const char* data, size_t len,
   _wantRead = false;
   _wantWrite = false;
 
-  struct addrinfo hints;
   struct addrinfo* res;
-  memset(&hints, 0, sizeof(hints));
-  hints.ai_family = _protocolFamily;
-  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);
+  s = callGetaddrinfo(&res, host.c_str(), uitos(port).c_str(), _protocolFamily,
+		      _sockType, 0, 0);
   if(s) {
     throw DL_ABORT_EX(StringFormat(EX_SOCKET_SEND, gai_strerror(s)).str());
   }
+  auto_delete<struct addrinfo*> resDeleter(res, freeaddrinfo);
   struct addrinfo* rp;
   ssize_t r = -1;
   for(rp = res; rp; rp = rp->ai_next) {
@@ -1083,7 +1069,6 @@ ssize_t SocketCore::writeData(const char* data, size_t len,
       break;
     }
   }
-  freeaddrinfo(res);
   if(r == -1) {
     throw DL_ABORT_EX(StringFormat(EX_SOCKET_SEND, errorMsg()).str());
   }
@@ -1200,15 +1185,10 @@ void SocketCore::bindAddress(const std::string& interface)
   }
 #endif // HAVE_GETIFADDRS
   if(bindAddrs.empty()) {
-    struct addrinfo hints;
-    struct addrinfo* res = 0;
-    memset(&hints, 0, sizeof(hints));
-    hints.ai_family = _protocolFamily;
-    hints.ai_socktype = SOCK_STREAM;
-    hints.ai_flags = 0;
-    hints.ai_protocol = 0;
+    struct addrinfo* res;
     int s;
-    s = getaddrinfo(interface.c_str(), 0, &hints, &res);
+    s = callGetaddrinfo(&res, interface.c_str(), 0, _protocolFamily,
+			SOCK_STREAM, 0, 0);
     if(s) {
       throw DL_ABORT_EX
 	(StringFormat(MSG_INTERFACE_NOT_FOUND,
@@ -1255,4 +1235,34 @@ void SocketCore::bindAddress(const std::string& interface)
   }
 }
 
+namespace {
+
+int defaultAIFlags = DEFAULT_AI_FLAGS;
+
+int getDefaultAIFlags()
+{
+  return defaultAIFlags;
+}
+
+}
+
+void setDefaultAIFlags(int flags)
+{
+  defaultAIFlags = flags;
+}
+
+int callGetaddrinfo
+(struct addrinfo** resPtr, const char* host, const char* service, int family,
+ int sockType, int flags, int protocol)
+{
+  struct addrinfo hints;
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = family;
+  hints.ai_socktype = sockType;
+  hints.ai_flags = getDefaultAIFlags();
+  hints.ai_flags |= flags;
+  hints.ai_protocol = protocol;
+  return getaddrinfo(host, service, &hints, resPtr);  
+}
+
 } // namespace aria2

+ 12 - 0
src/SocketCore.h

@@ -363,6 +363,18 @@ public:
   static void bindAddress(const std::string& interface);
 };
 
+// Set default ai_flags. hints.ai_flags is initialized with this
+// value.
+void setDefaultAIFlags(int flags);
+
+// Wrapper function for getaddrinfo(). The value
+// flags|DEFAULT_AI_FLAGS is used as ai_flags.  You can override
+// DEFAULT_AI_FLAGS value by calling setDefaultAIFlags() with new
+// flags.
+int callGetaddrinfo
+(struct addrinfo** resPtr, const char* host, const char* service, int family,
+ int sockType, int flags, int protocol);
+
 } // namespace aria2
 
 #endif // _D_SOCKET_CORE_H_

+ 6 - 0
src/a2netcompat.h

@@ -97,4 +97,10 @@
 # define sock_t int
 #endif
 
+#ifdef AI_ADDRCONFIG
+# define DEFAULT_AI_FLAGS AI_ADDRCONFIG
+#else // !AI_ADDRCONFIG
+# define DEFAULT_AI_FLAGS 0
+#endif // !AI_ADDRCONFIG
+
 #endif // _D_A2NETCOMPAT_H_

+ 3 - 0
test/AllTest.cc

@@ -24,6 +24,9 @@ int main(int argc, char* argv[]) {
   // and latter cannot connect to former. To avoid this situation, we
   // limit protocol family to AF_INET for unit tests.
   aria2::SocketCore::setProtocolFamily(AF_INET);
+  // If AI_ADDRCONFIG is set, tests fail if IPv4 address is not
+  // configured.
+  aria2::setDefaultAIFlags(0);
 
   CppUnit::Test* suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
   CppUnit::TextUi::TestRunner runner;