[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[minion-cvs] Print useful server names for incoming connections.



Update of /home/minion/cvsroot/src/minion/lib/mixminion
In directory moria.mit.edu:/tmp/cvs-serv11868/lib/mixminion

Modified Files:
	ClientDirectory.py ClientMain.py ClientUtils.py MMTPClient.py 
	NetUtils.py Packet.py ServerInfo.py test.py 
Log Message:
Print useful server names for incoming connections.

Index: ClientDirectory.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/ClientDirectory.py,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- ClientDirectory.py	27 Jan 2004 05:55:54 -0000	1.29
+++ ClientDirectory.py	2 Feb 2004 07:05:49 -0000	1.30
@@ -60,7 +60,9 @@
     # byNickname: Map from nickname.lower() to list of (ServerInfo, source)
     #   tuples.
     # byKeyID: Map from desc.getKeyDigest() to list of (ServerInfo,source)
-    # allServers: DOCDOC
+    # blockedNickname: Map from nickname to list of '*' (blocked in every
+    #   position), 'entry' (blocked as entry node), 'exit' (blocked as exit
+    #   node).
     # __scanning: Flag to prevent recursive invocation of self.rescan().
     # __downloading: Flag to prevent simultaneous invocation of
     #    downloadDirectory()
@@ -99,7 +101,7 @@
         self.__downloading = 0
         self._lock = RWLock()
         self.config = None
-        self.blockedNicknames = {} #nickname->['*','entry','exit']
+        self.blockedNicknames = {}
         if diskLock is None:
             self._diskLock = threading.RLock()
         else:
@@ -112,7 +114,7 @@
             self._diskLock.release()
 
     def configure(self, config):
-        """DOCDOC"""
+        """Adjust this ClientDirectory to account for blocked servers."""
         sec = config.get("Security", {})
         blocked = {}
         for lst in sec.get("BlockServers", []):
@@ -127,6 +129,7 @@
         self._lock.write_in()
         try:
             self.blockedNicknames = blocked
+            self.__rebuildTables()
         finally:
             self._lock.write_out()
 
@@ -388,8 +391,9 @@
 
     def _installAsKeyIDResolver(self):
         """Use this ClientDirectory to identify servers in calls to
-           ServerInfo.displayServer."""
+           ServerInfo.displayServer*."""
         mixminion.ServerInfo._keyIDToNicknameFn = self.getNicknameByKeyID
+        mixminion.ServerInfo._addressToNicknameFn = self.getNicknameByAddress
 
     def importFromFile(self, filename):
         """Import a new server descriptor stored in 'filename'"""
@@ -484,18 +488,15 @@
         return len(badSources)
 
     def __rebuildTables(self):
-        """Helper method.  Reconstruct byNickname, byKeyID, and allServers
-           from the internal state of this object.  Caller must hold write
-           lock."""
+        """Helper method.  Reconstruct byNickname and byKeyIDk from the
+           internal state of this object.  Caller must hold write lock.
+        """
         self.byNickname = {}
         self.byKeyID = {}
-        self.allServers = []
-        self.byCapability = { } #DOCDOC disused
         self.goodServerNicknames = {}
 
         for info, where in self.serverList:
             nn = info.getNickname().lower()
-            self.allServers.append((info,where))
             self.goodServerNicknames[nn] = 1
 
         for info, where in self.fullServerList:
@@ -600,7 +601,10 @@
         return u.values()
 
     def __nicknameIsBlocked(self, nn, isEntry=0, isExit=0):
-        """DOCDOC"""
+        """Return true iff 'nn' is blocked.  By default, check for nicknames
+           blocked in every position.  If isEntry is true, also check for
+           nicknames blocked as entries; and if isExit is true, also check
+           for nicknames blocked as exits."""
         b = self.blockedNicknames.get(nn.lower(), None)
         if b is None:
             return 0
@@ -614,20 +618,26 @@
             return 0
 
     def __excludeBlocked(self, lst, isEntry=0, isExit=0):
-        """DOCDOC"""
+        """Given a list of ServerInfo, return a new list with all the
+           blocked servers removed.  'isEntry' and 'isExit' are as for
+           __nicknameIsBlocked.
+        """
         res = []
         for info in lst:
             if not self.__nicknameIsBlocked(info.getNickname(),isEntry,isExit):
                 res.append(info)
         return res
 
-    def getNicknameByIP(self, ip):
-        """DOCDOC"""
+    def getNicknameByAddress(self, addr):
+        """Given an address (IP or hostname) return the nickname of
+           the server with that hostname.  Return None if no such
+           server is known, and a slash-separated string if multiple
+           servers are known."""
         self._lock.read_in()
         try:
             nicknames = []
             for desc,where in self.fullServerList:
-                if desc.getIP() == ip:
+                if addr in (desc.getIP(), desc.getHostname()):
                     if desc.getNickname() not in nicknames:
                         nicknames.append(desc.getNickname())
             return "/".join(nicknames)
@@ -635,8 +645,9 @@
             self._lock.read_out()
 
     def getNicknameByKeyID(self, keyid):
-        """Given a keyid, return the nickname of the server with that keyid.
-           Return None if no such server is known."""
+        """Given a keyid, return the nickname of the server with that
+           keyid.  Return None if no such server is known, and a
+           slash-separated string if multiple servers are known."""
         self._lock.read_in()
         try:
             s = self.byKeyID.get(keyid)
@@ -651,7 +662,8 @@
             self._lock.read_out()
 
     def getKeyIDByNickname(self, nickname):
-        """DOCDOC"""
+        """Given the nickname of the server, return the corresponding
+           keyid, or None if the nickname is not recognized."""
         self._lock.read_in()
         try:
             s = self.byNickname.get(nickname.lower())
@@ -677,9 +689,10 @@
     def getLiveServers(self, startAt=None, endAt=None, isEntry=0, isExit=0):
         """Return a list of all server desthat are live from startAt through
            endAt.  The list is in the standard (ServerInfo,where) format,
-           as returned by __find.
-           DOCDOC no blocked or notrecommended
-           """
+           as returned by __find.  If 'isEntry' or 'isExit' is true, return
+           servers suitable as entries or exits.  Exclude servers in
+           the not-recommended or blocked lists.
+        """
         if startAt is None:
             startAt = time.time()
         if endAt is None:
@@ -687,7 +700,7 @@
         self._lock.read_in()
         try:
             return self.__excludeBlocked(
-                self.__find(self.allServers, startAt, endAt),
+                self.__find(self.serverList, startAt, endAt),
                 isEntry=isEntry, isExit=isExit)
         finally:
             self._lock.read_out()
@@ -739,7 +752,7 @@
                         LOG.info("Couldn't remove %s: %s", s[2:], e)
             finally:
                 self._diskLock.release()
-            for field in 'fullServerList', 'serverList', 'allServers':
+            for field in 'fullServerList', 'serverList':
                 val = getattr(self, field)
                 val = [ (i,w) for i,w in val if not badSources.has_key(w) ]
                 setattr(self,field,val)
@@ -931,7 +944,7 @@
                 servers.append(self.getServerInfo(name, startAt, endAt, 1))
 
         # Now figure out which relays we haven't used yet.
-        relays = self.__find(self.allServers, startAt, endAt)
+        relays = self.__find(self.serverList, startAt, endAt)
         relays = self.__excludeBlocked(relays)
         if not relays:
             raise UIError("No relays known")

Index: ClientMain.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/ClientMain.py,v
retrieving revision 1.152
retrieving revision 1.153
diff -u -d -r1.152 -r1.153
--- ClientMain.py	27 Jan 2004 05:57:59 -0000	1.152
+++ ClientMain.py	2 Feb 2004 07:05:49 -0000	1.153
@@ -30,7 +30,7 @@
      parseReplyBlocks, parseSMTPInfo, parseTextEncodedMessages, \
      parseTextReplyBlocks, ReplyBlock, parseMessageAndHeaders
 
-from mixminion.ServerInfo import displayServer, ServerInfo
+from mixminion.ServerInfo import displayServerByRouting, ServerInfo
 
 #----------------------------------------------------------------------
 # Global variable; holds an instance of Common.Lockfile used to prevent
@@ -572,13 +572,13 @@
         sentSome = 0; sentAll = 1
         for routing, packets in self._sortPackets(packets):
             LOG.info("Sending %s packets to %s...",
-                     len(packets), displayServer(routing))
+                     len(packets), displayServerByRouting(routing))
             try:
                 self.sendPackets(packets, routing, noQueue=1, warnIfLost=0)
                 sentSome = 1
             except MixError, e:
                 LOG.error("Can't deliver packets to %s: %s; leaving in queue",
-                          displayServer(routing), str(e))
+                          displayServerByRouting(routing), str(e))
                 sentAll = 0
 
         if sentAll:
@@ -596,7 +596,8 @@
             byRouting = self._sortPackets(
                 [ (h, self.queue.getRouting(h)) for h in handles ],
                 shuffle = 0)
-            byName = [ (displayServer(ri), lst) for ri,lst in byRouting ]
+            byName = [ (displayServerByRouting(ri), lst)
+                       for ri,lst in byRouting ]
             byName.sort()
             if not byName:
                 LOG.info("No packets removed.")
@@ -1868,7 +1869,7 @@
         print "(No packets in queue)"
         return
 
-    res_items = [ (displayServer(ri),count,date)
+    res_items = [ (displayServerByRouting(ri),count,date)
                   for ri,(count,date) in res.items() ]
     res_items.sort()
     now = time.time()

Index: ClientUtils.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/ClientUtils.py,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- ClientUtils.py	17 Jan 2004 04:24:57 -0000	1.18
+++ ClientUtils.py	2 Feb 2004 07:05:49 -0000	1.19
@@ -25,7 +25,6 @@
      succeedingMidnight, writeFile, armorText, unarmorText
 from mixminion.Crypto import sha1, ctr_crypt, DIGEST_LEN, AES_KEY_LEN, \
      getCommonPRNG, trng
-from mixminion.ServerInfo import displayServer
 
 #----------------------------------------------------------------------
 class BadPassword(MixError):

Index: MMTPClient.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/MMTPClient.py,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -d -r1.51 -r1.52
--- MMTPClient.py	27 Jan 2004 05:58:46 -0000	1.51
+++ MMTPClient.py	2 Feb 2004 07:05:49 -0000	1.52
@@ -90,7 +90,7 @@
         if context is None:
             context = _ml.TLSContext_new()
         if serverName is None:
-            serverName = mixminion.ServerInfo.displayServer(
+            serverName = mixminion.ServerInfo.displayServerByRouting(
                 IPV4Info(targetAddr, targetPort, targetKeyID))
         if certCache is None:
             certCache = PeerCertificateCache()
@@ -393,7 +393,7 @@
            after each successful packet delivery.
     """
     # Find out where we're connecting to.
-    serverName = mixminion.ServerInfo.displayServer(routing)
+    serverName = mixminion.ServerInfo.displayServerByRouting(routing)
     if isinstance(routing, IPV4Info):
         family, addr = socket.AF_INET, routing.ip
     else:

Index: NetUtils.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/NetUtils.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- NetUtils.py	12 Jan 2004 04:48:16 -0000	1.10
+++ NetUtils.py	2 Feb 2004 07:05:49 -0000	1.11
@@ -40,8 +40,8 @@
 
 #======================================================================
 def optimizeThroughput(sock):
-    """DOCDOC"""
-    if not IPTOS_THROUGHPUT: 
+    """Set the socket options on 'sock' to maximize throughput."""
+    if not IPTOS_THROUGHPUT:
         return
     if sys.platform in ('cygwin', 'dgux', 'sni-sysv'):
         # According to rumor, these platforms handle socket.IP_TOS

Index: Packet.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Packet.py,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -d -r1.72 -r1.73
--- Packet.py	7 Jan 2004 02:50:08 -0000	1.72
+++ Packet.py	2 Feb 2004 07:05:49 -0000	1.73
@@ -530,7 +530,7 @@
         self.encryptionKey = key
 
     def format(self):
-        from mixminion.ServerInfo import displayServer
+        import mixminion.ServerInfo
         digest = binascii.b2a_hex(sha1(self.pack()))
         expiry = formatTime(self.timestamp)
         if self.routingType == SWAP_FWD_IPV4_TYPE:
@@ -539,9 +539,10 @@
             routing = parseMMTPHostInfo(self.routingInfo)
         else:
             routing = None
+        server = mixminion.ServerInfo.displayServerByRouting(routing)
         return """Reply block hash: %s
 Expires at: %s GMT
-First server is: %s""" % (digest, expiry, displayServer(routing))
+First server is: %s""" % (digest, expiry, server)
 
     def pack(self):
         """Returns the external representation of this reply block"""

Index: ServerInfo.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/ServerInfo.py,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -d -r1.78 -r1.79
--- ServerInfo.py	27 Jan 2004 05:55:54 -0000	1.78
+++ ServerInfo.py	2 Feb 2004 07:05:49 -0000	1.79
@@ -8,7 +8,7 @@
    descriptors.
    """
 
-__all__ = [ 'ServerInfo', 'ServerDirectory', 'displayServer' ]
+__all__ = [ 'ServerInfo', 'ServerDirectory', 'displayServerByRouting' ]
 
 import re
 import time
@@ -40,55 +40,65 @@
 MMTP_KEY_BYTES = 1024 >> 3
 
 # ----------------------------------------------------------------------
-def displayServer(s):
-    """Return the best possible human-readable name for a server 's'.
-       's' must be one of: None, IPV4Info, MMTPHostInfo, ServerInfo,
-       string.
+def displayServerByRouting(s):
+    """Return the best possible human-readable name for a server with
+       routinginfo 's'.  's' must be one of: IPV4Info, MMTPHostInfo.
     """
-    if isinstance(s, types.StringType):
-        return s
-    elif isinstance(s, ServerInfo):
-        if s.getHostname():
-            addr = "%s:%s" % (s.getHostname(), s.getPort())
-        else:
-            addr = "%s:%s" % (s.getIP(), s.getPort())
-        nickname = "'%s'" % s.getNickname()
-    elif (isinstance(s, mixminion.Packet.IPV4Info) or
-          isinstance(s, mixminion.Packet.MMTPHostInfo)):
-        nickname = getNicknameByKeyID(s.keyinfo)
-        if nickname:
-            nickname = "'%s'" % nickname
-        else:
-            nickname = 'server'
-        if isinstance(s, mixminion.Packet.IPV4Info):
-            addr = "%s:%s" % (s.ip, s.port)
-        else:
-            addr = "%s:%s" % (s.hostname, s.port)
-    elif s is None:
-        return "unknown server"
+    assert (isinstance(s, mixminion.Packet.IPV4Info) or
+            isinstance(s, mixminion.Packet.MMTPHostInfo))
+    nickname = getNicknameByKeyID(s.keyinfo)
+    if isinstance(s, mixminion.Packet.IPV4Info):
+        addr = "%s:%s" % (s.ip, s.port)
     else:
-        raise AssertionError # unreached
-
+        addr = "%s:%s" % (s.hostname, s.port)
+    if nickname:
+        nickname = "'%s'"%nickname
+    else:
+        nickname = "server"
     return "%s at %s" % (nickname, addr)
 
+def displayServerByAddress(ip, port, hostname=None):
+    """Return the best human-reasable name for a server at IP 'ip', hostname
+       'hostname', connecting from port 'port'.  Note that because reverse
+       caching is unreliable, and IP-based authentication is a lie, any
+       inferred nicknames are displayed as questionable.
+    """
+    nickname = None
+    if hostname is not None:
+        nickname = getNicknameByAddress(hostname)
+    if nickname is None:
+        nickname = getNicknameByAddress(ip)
+    if nickname is None:
+        nickname = ""
+    else:
+        nickname = " ('%s'?)" % nickname
+    return "server at %s:%s%s" %(ip, port, nickname)
+
 def getNicknameByKeyID(keyid):
     """Given a 20-byte keyid, look up the nickname of the corresponding
-       server.  Return the nickname on success and None if we don't recognize
-       the server.
-
-       FFFF Right now, this is not supported for servers, since they don't
-       FFFF download directories.
+       server.  Return the nickname on success and None if we don't
+       recognize the server.  If multiple servers match, return their
+       nicknames separated by slashes.
     """
     #FFFF Be cleverer with all-zero keyids.
-    if _keyIDToNicknameFn:
+    if _keyIDToNicknameFn is not None:
         return _keyIDToNicknameFn(keyid)
     else:
         return None
 
-# This variable should hold None, or a function that maps from keyids to
-# nicknames, and returns None on failure.  Currently set by
-# ClientDirectory.ClientDirectory._installAsKeyIDResolver().
+def getNicknameByAddress(address):
+    """Given an IP or hostname, look up the nickname of the corresponding
+       server.  Returns as for getNicknameByKeyID.
+    """
+    if _addressToNicknameFn is not None:
+        return _addressToNicknameFn(address)
+    else:
+        return None
+
+# These variables should hold None, or functions that implement getNicknameBy*.
+# Currently set by ClientDirectory.ClientDirectory._installAsKeyIDResolver().
 _keyIDToNicknameFn = None
+_addressToNicknameFn = None
 
 # ----------------------------------------------------------------------
 

Index: test.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/test.py,v
retrieving revision 1.180
retrieving revision 1.181
diff -u -d -r1.180 -r1.181
--- test.py	27 Jan 2004 05:14:31 -0000	1.180
+++ test.py	2 Feb 2004 07:05:49 -0000	1.181
@@ -4461,38 +4461,44 @@
 
 class ServerInfoTests(TestCase):
     def test_displayServer(self):
-        ds = mixminion.ServerInfo.displayServer
+        dsbr = mixminion.ServerInfo.displayServerByRouting
+        dsba = mixminion.ServerInfo.displayServerByAddress
         eq = self.assertEquals
-        eq(ds(None), "unknown server")
-        eq(ds("Fred"), "Fred")
 
         # Test without keyid resolver
-        eq(ds(IPV4Info("1.2.3.4", 48099, "x"*20)),
+        eq(dsbr(IPV4Info("1.2.3.4", 48099, "x"*20)),
            "server at 1.2.3.4:48099")
-
-        eq(ds(MMTPHostInfo("a.b.com", 48099, "x"*20)),
+        eq(dsbr(MMTPHostInfo("a.b.com", 48099, "x"*20)),
            "server at a.b.com:48099")
+        eq(dsba("1.2.3.4",48099), "server at 1.2.3.4:48099")
+        eq(dsba("1.2.3.4",48099, "X.Y"), "server at 1.2.3.4:48099")
 
         # Test with keyid resolver
         def resolver(keyid):
             if keyid[0] == 'a': return "Kenichi"
             elif keyid[1] == 'b': return "Tima"
             else: return None
+        def reverseResolver(addr):
+            if addr == "1.2.3.4": return "Each"
+            elif addr == "a.b.c.d": return "Peach"
+            else: return None
         try:
             mixminion.ServerInfo._keyIDToNicknameFn = resolver
-            eq(ds(IPV4Info("1.2.3.4", 48099, "b"*20)),
+            mixminion.ServerInfo._addressToNicknameFn = reverseResolver
+            eq(dsbr(IPV4Info("1.2.3.4", 48099, "b"*20)),
                "'Tima' at 1.2.3.4:48099")
-            eq(ds(IPV4Info("1.2.3.4", 48099, "x"*20)),
+            eq(dsbr(IPV4Info("1.2.3.4", 48099, "x"*20)),
                "server at 1.2.3.4:48099")
-            eq(ds(MMTPHostInfo("ken.com", 48099, "a"*20)),
+            eq(dsbr(MMTPHostInfo("ken.com", 48099, "a"*20)),
                "'Kenichi' at ken.com:48099")
+            eq(dsba("1.2.3.4",48099), "server at 1.2.3.4:48099 ('Each'?)")
+            eq(dsba("1.2.3.4",48099,"a.b.c.d"),
+               "server at 1.2.3.4:48099 ('Peach'?)")
+            eq(dsba("3.4.5.6",48099,"x.y.z"),
+               "server at 3.4.5.6:48099")
         finally:
             mixminion.ServerInfo._keyIDToNicknameFn = None
-
-            # Test serverinfos
-        examples = getExampleServerDescriptors()
-        eq(ds(mixminion.ServerInfo.ServerInfo(string=examples["Fred"][0])),
-           "'Fred' at Fred:48099")
+            mixminion.ServerInfo._addressToNicknameFn = None
 
     def test_ServerInfo(self):
         # Try generating a serverinfo and see if its values are as expected.
@@ -7537,7 +7543,7 @@
     tc = loader.loadTestsFromTestCase
 
     if 0:
-        suite.addTest(tc(MMTPTests))
+        suite.addTest(tc(ServerInfoTests))
         return suite
     testClasses = [MiscTests,
                    MinionlibCryptoTests,