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

[minion-cvs] A few minor changes, one of them with little tentacles ...



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

Modified Files:
	BuildMessage.py ClientDirectory.py ClientMain.py Common.py 
	Main.py Packet.py test.py 
Log Message:
A few minor changes, one of them with little tentacles throughout the code.

- Make the presence/absence of a tag decided by users of
  DeliverableMessage/Subheader, not (as before) by DM/S on the basis of 
  exit types.  This allows extension types to exist without deliverhandles.

- Add a 'mixminiond' script and entrypoint.  Should work.

- Fix a bug: when no workable exit server is found, we shouldn't crash.



Index: BuildMessage.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/BuildMessage.py,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -d -r1.70 -r1.71
--- BuildMessage.py	16 Feb 2004 22:50:38 -0000	1.70
+++ BuildMessage.py	21 Feb 2004 00:02:09 -0000	1.71
@@ -89,7 +89,7 @@
     return paddingPRNG.getBytes(PAYLOAD_LEN)
 
 def buildForwardPacket(payload, exitType, exitInfo, path1, path2,
-                        paddingPRNG=None):
+                       paddingPRNG=None, suppressTag=0):
     """Construct a forward message.
             payload: The payload to deliver.  Must be exactly 28K.  If the
                   payload is None, 28K of random data is sent.
@@ -101,6 +101,8 @@
                   If None, a new PRNG is initialized.
 
         Neither path1 nor path2 may be empty.  If one is, MixError is raised.
+
+        suppressTag DOCDOC
     """
     if paddingPRNG is None:
         paddingPRNG = Crypto.getCommonPRNG()
@@ -109,11 +111,6 @@
     if not path2:
         raise MixError("Second leg of path is empty")
 
-    suppressTag = 0
-    #XXXX refactor _TYPES_WITHOUT_TAGS
-    if exitType == DROP_TYPE or mixminion.Packet._TYPES_WITHOUT_TAGS.get(exitType):
-        suppressTag = 1
-
     assert len(payload) == PAYLOAD_LEN
 
     LOG.debug("  Using path %s:%s",
@@ -126,7 +123,7 @@
         tag = _getRandomTag(paddingPRNG)
         exitInfo = tag + exitInfo
     return _buildPacket(payload, exitType, exitInfo, path1, path2,
-                        paddingPRNG)
+                        paddingPRNG,suppressTag=suppressTag)
 
 
 def buildEncryptedForwardPacket(payload, exitType, exitInfo, path1, path2,
@@ -301,11 +298,14 @@
     return _buildReplyBlockImpl(path, exitType, exitInfo, expiryTime, prng,
                                 seed)[0]
 
-def checkPathLength(path1, path2, exitType, exitInfo, explicitSwap=0):
+def checkPathLength(path1, path2, exitType, exitInfo, explicitSwap=0,
+                    suppressTag=0):
     """Given two path legs, an exit type and an exitInfo, raise an error
        if we can't build a hop with the provided legs.
 
-       The leg "path1" may be null."""
+       The leg "path1" may be null.
+
+       DOCDOC suppressTag"""
     err = 0 # 0: no error. 1: 1st leg too big. 2: 1st leg okay, 2nd too big.
     if path1 is not None:
         try:
@@ -314,8 +314,7 @@
         except MixError:
             err = 1
     # Add a dummy tag as needed to last exitinfo.
-    if (exitType != DROP_TYPE
-        and not mixminion.Packet._TYPES_WITHOUT_TAGS.get(exitType)
+    if (not suppressTag
         and exitInfo is not None):
         exitInfo += "X"*20
     else:
@@ -466,7 +465,8 @@
 
 #----------------------------------------------------------------------
 def _buildPacket(payload, exitType, exitInfo,
-                 path1, path2, paddingPRNG=None, paranoia=0):
+                 path1, path2, paddingPRNG=None, paranoia=0,
+                 suppressTag=0):
     """Helper method to create a message.
 
     The following fields must be set:
@@ -498,7 +498,7 @@
         reply = path2
         path2 = None
     else:
-        if len(exitInfo) < TAG_LEN and exitType != DROP_TYPE and not mixminion.Packet._TYPES_WITHOUT_TAGS.get(exitType):
+        if len(exitInfo) < TAG_LEN and not suppressTag:
             raise MixError("Implausibly short exit info: %r"%exitInfo)
         if exitType < MIN_EXIT_TYPE and exitType != DROP_TYPE:
             raise MixError("Invalid exit type: %4x"%exitType)
@@ -547,7 +547,7 @@
                each of the subheaders.
            exitType: The routing type for the last node in the header
            exitInfo: The routing info for the last node in the header.
-               (Must include 20-byte decoding tag.)
+               (Must include 20-byte decoding tag, if any.)
            paddingPRNG: A pseudo-random number generator to generate padding
     """
     assert len(path) == len(secrets)

Index: ClientDirectory.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/ClientDirectory.py,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- ClientDirectory.py	2 Feb 2004 07:15:18 -0000	1.31
+++ ClientDirectory.py	21 Feb 2004 00:02:09 -0000	1.32
@@ -1082,6 +1082,13 @@
             raise UIError("%s exit type expects a fixed exit server." %
                           exitAddress.getPrettyExitType())
 
+        if fs is None and lh is None:
+            for desc in self.getLiveServers(startAt, endAt, isExit=1):
+                if exitAddress.isSupportedByServer(desc):
+                    break
+            else:
+                raise UIError("No recommended server supports delivery type.")
+
         # Check for unrecommended servers
         if not warnUnrecommended:
             return
@@ -1466,6 +1473,15 @@
             rt = self.exitType
         return rt, ri, self.lastHop
 
+    def suppressTag(self):
+        """DOCDOC"""
+        if self.isSSFragmented:
+            return 1
+        elif self.exitType == 'drop':
+            return 1
+        else:
+            return 0
+
 def parseAddress(s):
     """Parse and validate an address; takes a string, and returns an
        ExitAddress object.

Index: ClientMain.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/ClientMain.py,v
retrieving revision 1.155
retrieving revision 1.156
diff -u -d -r1.155 -r1.156
--- ClientMain.py	16 Feb 2004 22:30:03 -0000	1.155
+++ ClientMain.py	21 Feb 2004 00:02:09 -0000	1.156
@@ -369,7 +369,7 @@
 
             pkt = mixminion.BuildMessage.buildForwardPacket(
                 p, routingType, routingInfo, path1, path2,
-                self.prng)
+                self.prng, suppressTag=address.suppressTag())
             r.append( (pkt, path1[0]) )
 
         return r

Index: Common.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Common.py,v
retrieving revision 1.130
retrieving revision 1.131
diff -u -d -r1.130 -r1.131
--- Common.py	6 Feb 2004 23:14:28 -0000	1.130
+++ Common.py	21 Feb 2004 00:02:09 -0000	1.131
@@ -571,7 +571,7 @@
     finally:
         f.close()
 
-def writeFile(fn, contents, mode=0600, binary=0):
+def writeFile(fn, contents, mode=0600, binary=0, fsync=0):
     """Atomically write a string <contents> into a file <file> with mode
        <mode>.  If <binary>, binary mode will be used.
 
@@ -579,12 +579,16 @@
 
        If two processes attempt to writeFile the same file at once,
        the one finishing last wins.
+
+       If fsync is true, we call fsync on the file before closing it.
        """
     tmpname = fn+".tmp"
     f, tmpname = openUnique(tmpname, ['w','wb'][binary], mode)
     try:
         try:
             f.write(contents)
+            if fsync:
+                os.fsync(f.fileno())
         finally:
             f.close()
     except:

Index: Main.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Main.py,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -d -r1.67 -r1.68
--- Main.py	15 Jan 2004 21:03:26 -0000	1.67
+++ Main.py	21 Feb 2004 00:02:09 -0000	1.68
@@ -141,6 +141,8 @@
     "dir":             ( 'mixminion.directory.DirMain', 'main'),
 
     "shell":           ( 'mixminion.Main',       'commandShell' ),
+
+    "__d":             ( 'mixminion.Main',       'mixminiondMain' ),
 }
 
 _USAGE = (
@@ -177,6 +179,18 @@
   "For help on sending a message, run 'mixminion send --help'"
 )
 
+_SERVER_USAGE = (
+    "Usage: mixminiond <command> [arguments]\n"+
+    "       start     [Begin running a Mixminion server]\n"+
+    "       stop      [Halt a running Mixminion server]\n"+
+    "       reload    [Make running Mixminion server reload its config\n"+
+    "                     (Not implemented yet; only restarts logging.)]\n"+
+    "       republish [Re-send all keys to directory server]\n"+
+    "       DELKEYS   [Remove generated keys for a Mixminion server]\n"+
+    "       stats     [List as-yet-unlogged statistics for this server]\n"+
+    "       upgrade   [Upgrade a pre-0.0.4 server homedir]\n"
+    )
+
 def printVersion(cmd,args):
     import mixminion
     print "Mixminion version %s" % mixminion.__version__
@@ -199,8 +213,11 @@
 
     sys.exit(1)
 
-def printUsage():
-    print _USAGE
+def printUsage(daemon=0):
+    if daemon:
+        print _SERVER_USAGE
+    else:
+        print _USAGE
     print "NOTE: This software is for testing only.  The user set is too small"
     print "      to be anonymous, and the code is too alpha to be reliable."
 
@@ -242,7 +259,7 @@
         except SystemExit:
             pass
 
-def main(args):
+def main(args,daemon=0):
     "Use <args> to fix path, pick a command and pass it arguments."
     # Specifically, args[0] is used to fix sys.path so we can import
     # mixminion.*; args[1] is used to select a command name from _COMMANDS,
@@ -250,16 +267,14 @@
 
     correctPath(args[0])
 
-##     if len(args) > 2 and args[1] == 'mixminiond':
-##         if _COMMANDS.has_key("server-"+args[2]):
-##             args[1:3] = "server-"+args[2]
-##         else:
-##             printUsage()
-##             sys.exit(1)
+    if daemon:
+        prefix = "server-"
+    else:
+        prefix = ""
 
     # Check whether we have a recognized command.
-    if len(args) == 1  or not _COMMANDS.has_key(args[1]):
-        printUsage()
+    if len(args) == 1  or not _COMMANDS.has_key(prefix+args[1]):
+        printUsage(daemon)
         sys.exit(1)
 
     if args[1] not in ('unittests', 'benchmarks', 'version') and \
@@ -276,7 +291,7 @@
     filePermissionErrorClass = commonModule.MixFilePermissionError
 
     # Read the module and function.
-    command_module, command_fn = _COMMANDS[args[1]]
+    command_module, command_fn = _COMMANDS[prefix+args[1]]
     mod = __import__(command_module, {}, {}, [command_fn])
     func = getattr(mod, command_fn)
 

Index: Packet.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Packet.py,v
retrieving revision 1.73
retrieving revision 1.74
diff -u -d -r1.73 -r1.74
--- Packet.py	2 Feb 2004 07:05:49 -0000	1.73
+++ Packet.py	21 Feb 2004 00:02:09 -0000	1.74
@@ -94,12 +94,6 @@
 FRAGMENT_TYPE  = 0x0103  # Find the actual delivery info in the message payload
 MAX_EXIT_TYPE  = 0xFFFF
 
-# Set of exit types that don't get tag fields.
-# XXXX007 This interface is really brittle; it needs to change.  I added it
-# XXXX007 in order to allow 'fragment' to be an exit type without adding a
-# XXXX007 needless tag field to every fragment routing info.
-_TYPES_WITHOUT_TAGS = { FRAGMENT_TYPE : 1 }
-
 def typeIsSwap(tp):
     return tp in (SWAP_FWD_IPV4_TYPE,SWAP_FWD_HOST_TYPE)
 
@@ -162,8 +156,8 @@
     underflow = ""
     if rlen < len(ri):
         ri, underflow = ri[:rlen], ri[rlen:]
-    if rt >= MIN_EXIT_TYPE and not _TYPES_WITHOUT_TAGS.get(rt) and rlen < TAG_LEN:
-        raise ParseError("Subheader missing tag")
+##     if rt >= MIN_EXIT_TYPE and not _TYPES_WITHOUT_TAGS.get(rt) and rlen < TAG_LEN:
+##         raise ParseError("Subheader missing tag")
     return Subheader(major,minor,secret,digest,rt,ri,rlen,underflow)
 
 class Subheader:
@@ -202,27 +196,25 @@
                 "routingtype=%(routingtype)r, routinginfo=%(routinginfo)r, "+
                 "routinglen=%(routinglen)r)")% self.__dict__
 
-    def getExitAddress(self):
+    def getExitAddress(self, tagged=1):
         """Return the part of the routingInfo that contains the delivery
            address.  (Requires that routingType is an exit type.)"""
         assert self.routingtype >= MIN_EXIT_TYPE
         #XXXX007 This interface is completely insane.  Change it.
-        if _TYPES_WITHOUT_TAGS.get(self.routingtype):
+        if not tagged:
             return self.routinginfo
         else:
-            assert len(self.routinginfo) >= TAG_LEN
+            if len(self.routinginfo) < TAG_LEN:
+                raise ParseError("Missing tag")
             return self.routinginfo[TAG_LEN:]
 
     def getTag(self):
         """Return the part of the routingInfo that contains the decoding
            tag. (Requires that routingType is an exit type.)"""
         assert self.routingtype >= MIN_EXIT_TYPE
-        #XXXX007 This interface is completely insane.  Change it.
-        if _TYPES_WITHOUT_TAGS.get(self.routingtype):
-            return ""
-        else:
-            assert len(self.routinginfo) >= TAG_LEN
-            return self.routinginfo[:TAG_LEN]
+        if len(self.routinginfo) < TAG_LEN:
+            raise ParseError("Missing tag")
+        return self.routinginfo[:TAG_LEN]
 
     def setRoutingInfo(self, info):
         """Change the routinginfo, and the routinglength to correspond."""

Index: test.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/test.py,v
retrieving revision 1.184
retrieving revision 1.185
diff -u -d -r1.184 -r1.185
--- test.py	15 Feb 2004 23:25:33 -0000	1.184
+++ test.py	21 Feb 2004 00:02:09 -0000	1.185
@@ -2580,6 +2580,7 @@
             else:
                 self.assert_(res.isDelivery())
                 self.assertEquals(res.getExitType(), rt)
+                res.setTagged(res.getExitType() not in (DROP_TYPE,FRAGMENT_TYPE))
                 self.assertEquals(res.getAddress(), ri)
                 if appkey:
                     self.assertEquals(res.getApplicationKey(), appkey)
@@ -5385,16 +5386,18 @@
 
 class FakeDeliveryPacket(mixminion.server.PacketHandler.DeliveryPacket):
     """Stub version of DeliveryPacket used for testing modules"""
-    def __init__(self, type, exitType, exitAddress, contents, tag=None,
+    def __init__(self, type, exitType, exitAddress, contents, tag="",
                  headers = {}):
-        if tag is None:
+        if tag == "" and exitType not in (DROP_TYPE, FRAGMENT_TYPE):
             tag = "-="*10
         mixminion.server.PacketHandler.DeliveryPacket.__init__(self,
-                        exitType, exitAddress, "Z"*16, tag, "Q"*(28*1024))
+                        exitType, tag+exitAddress, "Z"*16, "Q"*(28*1024))
         self.type = type
         self.headers = headers
         self.payload = None
         self.contents = contents
+        if tag:
+            self.setTagged(1)
 
 class ModuleTests(TestCase):
     def testEmailAddressSet(self):
@@ -5850,7 +5853,7 @@
                                   "pirates@sea","").pack())
         deliv = [ mixminion.server.PacketHandler.DeliveryPacket(
             routingType=FRAGMENT_TYPE, routingInfo="", applicationKey="X"*16,
-            tag="", payload=p) for p in payloads ]
+            payload=p) for p in payloads ]
         self.assertEquals(len(deliv), 11)
 
         replaceFunction(mixminion.server.Modules, 'sendSMTPMessage',
@@ -7543,7 +7546,7 @@
     tc = loader.loadTestsFromTestCase
 
     if 0:
-        suite.addTest(tc(MMTPTests))
+        suite.addTest(tc(ModuleTests))
         return suite
     testClasses = [MiscTests,
                    MinionlibCryptoTests,