Browse Source

Use same port number for IPv4 and IPv6 DHT

Tatsuhiro Tsujikawa 12 years ago
parent
commit
4ac4fdf1e9
2 changed files with 23 additions and 9 deletions
  1. 2 1
      src/BtRegistry.h
  2. 21 8
      src/DHTSetup.cc

+ 2 - 1
src/BtRegistry.h

@@ -81,7 +81,8 @@ class BtRegistry {
 private:
   std::map<a2_gid_t, SharedHandle<BtObject> > pool_;
   uint16_t tcpPort_;
-  // This is IPv4 port for DHT and UDP tracker. No IPv6 udpPort atm.
+  // This is UDP port for DHT and UDP tracker. But currently UDP
+  // tracker is not supported in IPv6.
   uint16_t udpPort_;
   SharedHandle<LpdMessageReceiver> lpdMessageReceiver_;
   SharedHandle<UDPTrackerClient> udpTrackerClient_;

+ 21 - 8
src/DHTSetup.cc

@@ -112,16 +112,27 @@ void DHTSetup::setup
       localNode.reset(new DHTNode());
     }
 
+    uint16_t port;
     SharedHandle<DHTConnectionImpl> connection(new DHTConnectionImpl(family));
     {
-      SegList<int> sgl;
-      util::parseIntSegments(sgl, e->getOption()->get(PREF_DHT_LISTEN_PORT));
-      sgl.normalize();
-      uint16_t port;
+      port = e->getBtRegistry()->getUdpPort();
       const std::string& addr =
-        e->getOption()->get(family == AF_INET?PREF_DHT_LISTEN_ADDR:
+        e->getOption()->get(family == AF_INET ? PREF_DHT_LISTEN_ADDR:
                             PREF_DHT_LISTEN_ADDR6);
-      if(!connection->bind(port, addr, sgl)) {
+      // If UDP port is already used, use the same port
+      // number. Normally IPv4 port is available, then IPv6 port is
+      // (especially for port >= 1024). We don't loose much by doing
+      // this. We did the same thing in TCP socket. See BtSetup.cc.
+      bool rv;
+      if(port == 0) {
+        SegList<int> sgl;
+        util::parseIntSegments(sgl, e->getOption()->get(PREF_DHT_LISTEN_PORT));
+        sgl.normalize();
+        rv = connection->bind(port, addr, sgl);
+      } else {
+        rv = connection->bind(port, addr);
+      }
+      if(!rv) {
         throw DL_ABORT_EX("Error occurred while binding UDP port for DHT");
       }
       localNode->setPort(port);
@@ -192,7 +203,6 @@ void DHTSetup::setup
       DHTRegistry::getMutableData().messageReceiver = receiver;
       DHTRegistry::getMutableData().messageFactory = factory;
       e->getBtRegistry()->setUDPTrackerClient(udpTrackerClient);
-      e->getBtRegistry()->setUdpPort(localNode->getPort());
     } else {
       DHTRegistry::getMutableData6().localNode = localNode;
       DHTRegistry::getMutableData6().routingTable = routingTable;
@@ -290,6 +300,10 @@ void DHTSetup::setup
     }
     commands.insert(commands.end(), tempCommands->begin(), tempCommands->end());
     tempCommands->clear();
+    if(e->getBtRegistry()->getUdpPort() == 0) {
+      // We assign port last so that no exception gets in the way
+      e->getBtRegistry()->setUdpPort(port);
+    }
   } catch(RecoverableException& ex) {
     A2_LOG_ERROR_EX(fmt("Exception caught while initializing DHT functionality."
                         " DHT is disabled."),
@@ -298,7 +312,6 @@ void DHTSetup::setup
       DHTRegistry::clearData();
       e->getBtRegistry()->setUDPTrackerClient
         (SharedHandle<UDPTrackerClient>());
-      e->getBtRegistry()->setUdpPort(0);
     } else {
       DHTRegistry::clearData6();
     }