From a2970cf7c18df09f24912bd339cb593f28dc5b14 Mon Sep 17 00:00:00 2001
From: Zooko O'Whielacronx <zooko@zooko.com>
Date: Tue, 22 May 2007 14:01:40 -0700
Subject: [PATCH] fix handling of local_ip file and rename it to
 advertised_ip_addresses and document it in README

---
 README                |  8 ++++++++
 src/allmydata/node.py | 43 ++++++++++++++++++++++++++-----------------
 2 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/README b/README
index 7fe024cb..75a268e1 100644
--- a/README
+++ b/README
@@ -229,6 +229,14 @@ RUNNING:
  To stop it again, use 'make stop-client'.  Similar makefile targets exist
  for making and running an introducer node.
 
+ If you are behind a firewall and you can configure your firewall to forward
+ TCP connections on a port to the computer running your Tahoe node, then you
+ can configure the Tahoe node to announce itself as being available on that
+ IP address and port.  The way to do this is to create a file named
+ $HERE/advertised_ip_addresses, in which you can put IP addresses and port numbers in
+ "dotted-quad:port" form, e.g. "209.97.232.113:1345".  You can put multiple
+ IP-address-and-port-number entries into this file, on separate lines.
+
  There is a public grid available for testing.  Look at the wiki page
  (http://allmydata.org) for the necessary .furl data.
 
diff --git a/src/allmydata/node.py b/src/allmydata/node.py
index b70a4a19..c0c89159 100644
--- a/src/allmydata/node.py
+++ b/src/allmydata/node.py
@@ -1,5 +1,6 @@
 
-import os.path
+import os.path, re
+
 from twisted.python import log
 from twisted.application import service
 from twisted.internet import defer
@@ -12,13 +13,16 @@ import allmydata
 import zfec
 import foolscap
 
+# group 1 will be addr (dotted quad string), group 3 if any will be portnum (string)
+ADDR_RE=re.compile("^([1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*)(:([1-9][0-9]*))?$")
+
 class Node(service.MultiService):
     # this implements common functionality of both Client nodes, Introducer 
     # nodes, and Vdrive nodes
     NODETYPE = "unknown NODETYPE"
     PORTNUMFILE = None
     CERTFILE = None
-    LOCAL_IP_FILE = "local_ip"
+    LOCAL_IP_FILE = "advertised_ip_addresses"
     NODEIDFILE = "my_nodeid"
 
     def __init__(self, basedir="."):
@@ -105,21 +109,26 @@ class Node(service.MultiService):
         # running, which means after startService.
         l = self.tub.getListeners()[0]
         portnum = l.getPortnum()
-        local_ip_filename = os.path.join(self.basedir, self.LOCAL_IP_FILE)
-        if os.path.exists(local_ip_filename):
-            f = open(local_ip_filename, "r")
-            local_ip = f.read()
-            f.close()
-            if local_ip not in local_addresses:
-                local_addresses.append(local_ip)
-        if not os.path.exists(self._portnumfile):
-            # record which port we're listening on, so we can grab the same
-            # one next time
-            f = open(self._portnumfile, "w")
-            f.write("%d\n" % portnum)
-            f.close()
-        location = ",".join(["%s:%d" % (ip, portnum)
-                             for ip in local_addresses])
+        # record which port we're listening on, so we can grab the same one next time
+        open(self._portnumfile, "w").write("%d\n" % portnum)
+
+        local_addresses = [ "%s:%d" % (addr, portnum,) for addr in local_addresses ]
+
+        addresses = []
+        try:
+            for addrline in open(os.path.join(self.basedir, self.LOCAL_IP_FILE), "rU"):
+                mo = ADDR_RE.search(addrline)
+                if mo:
+                    (addr, dummy, aportnum,) = mo.groups()
+                    if aportnum is None:
+                        aportnum = portnum
+                    addresses.append("%s:%d" % (addr, aportnum,))
+        except EnvironmentError:
+            pass
+
+        addresses.extend(local_addresses)
+
+        location = ",".join(addresses)
         self.log("Tub location set to %s" % location)
         self.tub.setLocation(location)
         return self.tub
-- 
2.45.2