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

[minion-cvs] Flesh out inline documentation



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

Modified Files:
	EventStats.py MMTPServer.py Modules.py PacketHandler.py 
	ServerMain.py ServerQueue.py 
Log Message:
Flesh out inline documentation

Index: EventStats.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/EventStats.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- EventStats.py	15 Jul 2003 04:41:18 -0000	1.8
+++ EventStats.py	25 Aug 2003 21:05:34 -0000	1.9
@@ -56,17 +56,17 @@
         """Called whenever a packet is received via MMTP."""
         self._log("ReceivedPacket", arg)
     def receivedConnection(self, arg=None):
-        """DOCDOC"""
+        """Called whenever we get an incoming MMTP connection."""
         self._log("ReceivedConnection", arg)
 
     def attemptedConnect(self, arg=None):
-        """DOCDOC"""
+        """Called whenever we try to connect to an MMTP server."""
         self._log("AttemptedConnect", arg)
     def successfulConnect(self, arg=None):
-        """DOCDOC"""
+        """Called whenever we successfully connect to an MMTP server."""
         self._log("SuccessfulConnect", arg)
     def failedConnect(self, arg=None):
-        """DOCDOC"""
+        """Called whenever we fail to connect to an MMTP server."""
         self._log("FailedConnect", arg)
 
     def attemptedRelay(self, arg=None):

Index: MMTPServer.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/MMTPServer.py,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -d -r1.47 -r1.48
--- MMTPServer.py	21 Aug 2003 21:34:03 -0000	1.47
+++ MMTPServer.py	25 Aug 2003 21:05:34 -0000	1.48
@@ -43,7 +43,8 @@
 warn = LOG.warn
 error = LOG.error
 
-#DOCDOC
+# For windows -- list of errno values that we can expect when blocking IO
+# blocks on a connect.
 IN_PROGRESS_ERRNOS = [ getattr(errno, ename) 
    for ename in [ "EINPROGRESS", "WSAEWOULDBLOCK"]
    if hasattr(errno,ename) ]
@@ -81,7 +82,9 @@
         writefds = self.writers.keys()
  
         if not (readfds or writefds):
-            #DOCDOC
+            # Windows 'select' doesn't timeout properly when we aren't
+            # selecting on any FDs.  This should never happen to us,
+            # but we'll check for it anyway.
             time.sleep(timeout)
             return
    
@@ -352,9 +355,21 @@
         # needs to be retried till the other guy sends an 'ack'
         # back... but we don't want to keep retrying indefinitely, or
         # else we can deadlock on a connection from ourself to
-        # ourself.
+        # ourself.  Thus, we do the following:
+        #
+
+        # We try to shutdown.  This either acknowledges the other
+        # side's attempt to close the stream, or sends a request to
+        # close the stream.
+        #      - If OpenSSL says we're finished, great!
+        #      - If not, and we've already tried to shutdown, then freak out;
+        #        that's not supposed to happen.
+        #      - If we're not finished, and this *is* our first time trying,
+        #        then start *reading* from the incoming socket.  We should
+        #        get an acknowledgement for our close request soon when read
+        #        returns a 0.  Then, calling shutdown again should mean we're
+        #        done.
 
-        #DOCDOC this insanity.
         while 1:
             done = self.__con.shutdown() # may throw want*
             if not done and self.__awaitingShutdown:
@@ -377,8 +392,10 @@
                 raise _ml.TLSWantRead()
 
     def __readTooMuch(self):
-        """DOCDOC"""
-        print "AAAARGH."
+        """Helper function -- called if we read too much data while we're
+           shutting down."""
+        LOG.error("Read over 128 bytes of unexpected data from closing "
+                  "connection to %s", self.address)
         self.__sock.close()
         self.state = None
 
@@ -1013,6 +1030,8 @@
 
     def shutdown(self, err=0, retriable=0):
         self.active = 0
+        if err and self.finished == self.__setupFinished:
+            EventStats.log.failedConnect()
         SimpleTLSConnection.shutdown(self, err=err, retriable=retriable)
 
     def remove(self):

Index: Modules.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/Modules.py,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- Modules.py	21 Aug 2003 21:34:03 -0000	1.50
+++ Modules.py	25 Aug 2003 21:05:34 -0000	1.51
@@ -128,10 +128,10 @@
         raise NotImplementedError("processMessage")
 
     def sync(self):
-        """DOCDOC"""
+        """Flush all pending data held by this module to disk."""
 
     def close(self):
-        """DOCDOC"""
+        """Release all resources held by this module."""
         pass
 
 class ImmediateDeliveryQueue:
@@ -459,19 +459,20 @@
             queue.sendReadyMessages()
 
     def getServerInfoBlocks(self):
-        """DOCDOC"""
+        """Return a list of strings that should be appended to the server
+           descriptor of this server, based on the configuration of its
+           modules.
+        """
         return [ m.getServerInfoBlock() for m in self.modules
                        if self.enabled.get(m.getName(),0) ]
 
     def close(self):
-        """DOCDOC"""
-        #XXXX005 this method must be called on shutdown!
+        """Release all resources held by all modules."""
         for module in self.enabled:
             module.close()
 
     def sync(self):
-        """DOCDOC"""
-        #XXXX005 this method must be called on reset!
+        """Flush all state held by all modules to disk."""
         for module in self.enabled:
             module.sync()
 
@@ -591,7 +592,12 @@
         
 
 class _FragmentedDeliveryMessage:
+    """Helper class: obeys the interface of mixminion.server.PacketHandler.
+       DeliveryMessage, but contains a long message reassembled from
+       fragments."""
     def __init__(self, ssfm):
+        """Create a _FragmentedDeliveryMessage object from an instance of
+           mixminion.Packet.ServerSideFragmentedMessage."""
         self.m = ssfm
         self.contents = None
     def __getstate__(self):
@@ -624,7 +630,6 @@
         else:
             return encodeBase64(self.contents)
     def getHeaders(self):
-        """DOCDOC"""
         if self.contents is None:
             self.decode()
         assert self.headers is not None
@@ -779,11 +784,24 @@
 
 #----------------------------------------------------------------------
 class MailBase:
-    """DOCDOC"""
+    """Implementation class: contains code shared by modules that send email
+       messages (such as mbox and smtp)."""
+    ## Fields: (to be set by subclass)
+    # subject: Default subject to use for outgoing mail, if none is given
+    #    in the message.
+    # fromTag: String to prepend to from name.
+    # returnAddress: Return address for mail; should be an rfc822-style 
+    #    mailbox.
+    # header: Text that should be appended after the headers and before
+    #    the message itself.  It must include the empty line that separates
+    #    headers from body.
+    # maxMessageSize: Largest allowable size (after decompression, before
+    #   base64) for outgoing messages.
     def _formatEmailMessage(self, address, packet):
-        """DOCDOC"""
-        #DOCDOC implied fields
-        #   subject, fromTag, returnAddress, header, maxMessageSize
+        """Given a RFC822 mailbox (delivery address), and an instance of
+           DeliveryMessage, return a string containing a message to be sent
+           to a recipient, adding headers as needed.
+        """
 
         if len(packet.getContents()) > self.maxMessageSize:
             LOG.warn("Dropping over-long message (message is %sb; max is %sb)",
@@ -844,8 +862,6 @@
         return self.retrySchedule
 
     def getConfigSyntax(self):
-        # Validate returnaddress! XXXX005
-
         # FFFF There should be some way to say that fields are required
         # FFFF if the module is enabled.
         return { "Delivery/MBOX" :
@@ -972,8 +988,7 @@
 
 #----------------------------------------------------------------------
 class SMTPModule(DeliveryModule, MailBase):
-    """Placeholder for real exit node implementation.
-       For now, use MixmasterSMTPModule DOCDOC"""
+    """Common base class for SMTP mail."""
     def __init__(self):
         DeliveryModule.__init__(self)
     def getServerInfoBlock(self):
@@ -1003,8 +1018,6 @@
         return self.retrySchedule
 
     def getConfigSyntax(self):
-        # Validate returnaddress! XXXX005
-        
         return { "Delivery/SMTP" :
                  { 'Enabled' : ('REQUIRE', _parseBoolean, "no"),
                    'Retry': ('ALLOW', _parseIntervalList,
@@ -1205,7 +1218,8 @@
 
 MAIL_HEADERS = ["SUBJECT", "FROM", "IN-REPLY-TO", "REFERENCES"]
 def checkMailHeaders(headers):
-    """DOCDOC"""
+    """Check whether the decoded headers in a provided dict are permissible
+       for an outgoing email message.  Raise ParseError if they are not."""
     for k in headers.keys():
         if k not in MAIL_HEADERS:
             #XXXX this should raise parse error instead.

Index: PacketHandler.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/PacketHandler.py,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- PacketHandler.py	21 Aug 2003 21:34:03 -0000	1.21
+++ PacketHandler.py	25 Aug 2003 21:05:34 -0000	1.22
@@ -262,8 +262,12 @@
     # type -- until decode is called, None.  After decode is called,
     #     one of 'plain' (plaintext message), 'long' (overcompressed message),
     #     'enc' (encrypted message), or 'err' (malformed message).
-    # isfrag -- DOCDOC
-    # dPayload -- DOCDOC
+    # headers -- a map from key to value for the delivery headers in
+    #     this message's payload.  In the case of a fragment, or a
+    #     non-plaintext message, the map is empty.
+    # isfrag -- Is this packet a fragment of a complete message?  If so, the
+    #     type must be 'plain'.
+    # dPayload -- An instance of mixminion.Packet.Payload for this object.
     def __init__(self, routingType, routingInfo, applicationKey,
                  tag, payload):
         """Construct a new DeliveryPacket."""
@@ -278,7 +282,7 @@
         self.payload = payload
         self.contents = None
         self.type = None
-        self.headers = None#DOCDOC
+        self.headers = None
         self.isfrag = 0
         self.dPayload = None
 
@@ -298,7 +302,7 @@
         return self.contents
 
     def getDecodedPayload(self):
-        """DOCDOC"""
+        """Return an instance of mixminion.Packet.Payload for this packet."""
         if self.type is None: self.decode()
         return self.dPayload
 
@@ -314,7 +318,7 @@
         return self.type == 'long'
 
     def isFragment(self):
-        """DOCDOC"""
+        """Return true iff this packet is part of a fragmented message."""
         if self.type is None: self.decode()
         return self.isfrag
 
@@ -384,7 +388,7 @@
             return encodeBase64(self.contents)
 
     def getHeaders(self):
-        """DOCDOC"""
+        """Return a dict containing the headers for this message."""
         if self.type is None:
             self.decode()
         assert self.headers is not None
@@ -413,4 +417,3 @@
             tp = 'BIN'
 
         return Packet.TextEncodedMessage(self.contents, tp, tag)
-

Index: ServerMain.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/ServerMain.py,v
retrieving revision 1.88
retrieving revision 1.89
diff -u -d -r1.88 -r1.89
--- ServerMain.py	21 Aug 2003 21:34:03 -0000	1.88
+++ ServerMain.py	25 Aug 2003 21:05:34 -0000	1.89
@@ -848,6 +848,7 @@
         LOG.info("Checking for key rotation")
         self.keyring.checkKeys()
         self.generateKeys()
+        self.moduleManager.sync()
 
     def doMix(self):
         """Called when the server's mix is about to fire.  Picks some
@@ -900,8 +901,9 @@
         self.cleaningThread.join()
         self.processingThread.join()
         self.moduleManager.join()
-
+        
         self.packetHandler.close()
+        self.moduleManager.close()
 
         EventStats.log.save()
 

Index: ServerQueue.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/ServerQueue.py,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- ServerQueue.py	21 Aug 2003 21:34:03 -0000	1.31
+++ ServerQueue.py	25 Aug 2003 21:05:34 -0000	1.32
@@ -3,8 +3,7 @@
 
 """mixminion.server.ServerQueue
 
-   Facility for fairly secure, directory-based, unordered queues.
-   DOCDOC not any more.
+   Facilities for retriable delivery queues, and for mix pools.
    """
 
 import os
@@ -23,16 +22,6 @@
 __all__ = [ 'DeliveryQueue', 'TimedMixPool', 'CottrellMixPool',
             'BinomialCottrellMixPool' ]
 
-# Mode to pass to open(2) for creating a new file, and dying if it already
-# exists.
-_NEW_MESSAGE_FLAGS = os.O_WRONLY+os.O_CREAT+os.O_EXCL
-# On windows or mac, binary != text.
-_NEW_MESSAGE_FLAGS += getattr(os, 'O_BINARY', 0)
-
-# Any inp_* files older than INPUT_TIMEOUT seconds old are assumed to be
-# trash.
-INPUT_TIMEOUT = 6000
-
 class _DeliveryState:
     """Helper class: holds the state needed to schedule delivery or
        eventual abandonment of a message in a DeliveryQueue."""
@@ -62,23 +51,25 @@
         self.pending = None
         self.nextAttempt = None
         self.remove = 0
-
+        
     def isPending(self):
-        """DOCDOC"""
+        """Return true iff we are currently trying to deliver this message."""
         return self.pending is not None
 
     def setPending(self, now=None):
-        """DOCDOC"""
+        """Note that we are now trying to deliver this message, so that we
+           don't try to deliver it twice at the same time."""
         if now is None:
             now = time.time()
         self.pending = now
 
     def setNonPending(self):
-        """DOCDOC"""
+        """Note that we are no longer trying to deliver this message, so that
+           we can try it again later."""
         self.pending = None
 
     def isRemovable(self):
-        """DOCDOC"""
+        """Return true iff this message is old enough to be removed."""
         return self.remove
     
     def __getstate__(self):
@@ -263,7 +254,9 @@
 
     def _rescan(self, now=None):
         """Helper: Rebuild the internal state of this queue from the
-           underlying directory. DOCDOC trashes .pending and .sendable."""
+           underlying directory.  After calling 'rescan',
+           _rebuildNextAttempt must be called to recalculate our
+           delivery schedule."""
         try:
             self._lock.acquire()
             self.store.loadAllMetadata(lambda h: _DeliveryState())
@@ -273,11 +266,11 @@
             self._lock.release()
 
     def getAllMessages(self):
-        """DOCDOC"""
+        """Return handles for all messages in the store."""
         return self.store.getAllMessages()
 
     def count(self):
-        """DOCDOC"""
+        """Return the number of messages in the store."""
         return self.store.count()
 
     def _rebuildNextAttempt(self, now=None):