Author: dbkr
Date: 2006-08-04 16:29:28 +0000 (Fri, 04 Aug 2006)
New Revision: 9884

Modified:
   trunk/apps/Freemail/src/freemail/AccountManager.java
   trunk/apps/Freemail/src/freemail/InboundContact.java
   trunk/apps/Freemail/src/freemail/MessageSender.java
   trunk/apps/Freemail/src/freemail/OutboundContact.java
Log:
Fix stuff relating to ACKs, and fights between long addresses and short ones 
for the same outbound contact.


Modified: trunk/apps/Freemail/src/freemail/AccountManager.java
===================================================================
--- trunk/apps/Freemail/src/freemail/AccountManager.java        2006-08-04 
15:47:27 UTC (rev 9883)
+++ trunk/apps/Freemail/src/freemail/AccountManager.java        2006-08-04 
16:29:28 UTC (rev 9884)
@@ -212,6 +212,8 @@

                PropsFile accfile = getAccountFile(accountdir);

+               alias = alias.toLowerCase();
+               
                MailSite ms = new MailSite(accfile);

                if (ms.insertAlias(alias)) {

Modified: trunk/apps/Freemail/src/freemail/InboundContact.java
===================================================================
--- trunk/apps/Freemail/src/freemail/InboundContact.java        2006-08-04 
15:47:27 UTC (rev 9883)
+++ trunk/apps/Freemail/src/freemail/InboundContact.java        2006-08-04 
16:29:28 UTC (rev 9884)
@@ -134,6 +134,13 @@
                        }
                        System.out.println("You've got mail!");
                        sm.slotUsed();
+                       String ack_key = this.ibct_props.get("ackssk");
+                       if (ack_key == null) {
+                               System.out.println("Warning! Can't send message 
acknowledgement - don't have an 'ackssk' entry! This message will eventually 
bounce, even though you've received it.");
+                               continue;
+                       }
+                       ack_key += "ack-"+id;
+                       AckProcrastinator.put(ack_key);
                }
        }


Modified: trunk/apps/Freemail/src/freemail/MessageSender.java
===================================================================
--- trunk/apps/Freemail/src/freemail/MessageSender.java 2006-08-04 15:47:27 UTC 
(rev 9883)
+++ trunk/apps/Freemail/src/freemail/MessageSender.java 2006-08-04 16:29:28 UTC 
(rev 9884)
@@ -15,6 +15,7 @@
        public static final String OUTBOX_DIR = "outbox";
        private static final int MIN_RUN_TIME = 60000;
        public static final String NIM_KEY_PREFIX = "KSK at freemail-nim-";
+       private static final int MAX_TRIES = 10;
        private final File datadir;
        private Thread senderthread;

@@ -35,7 +36,7 @@
                this.senderthread.interrupt();
        }

-       private synchronized void copyToOutbox(File src, File outbox, String 
to) throws IOException {
+       private void copyToOutbox(File src, File outbox, String to) throws 
IOException {
                File tempfile = File.createTempFile("fmail-msg-tmp", null, 
Freemail.getTempDir());

                FileOutputStream fos = new FileOutputStream(tempfile);
@@ -49,15 +50,22 @@
                fis.close();
                fos.close();

+               this.moveToOutbox(tempfile, 0, to, outbox);
+       }
+       
+       // save a file to the outbox handling name collisions and atomicity
+       private void moveToOutbox(File f, int tries, String to, File outbox) {
                File destfile;
                int prefix = 1;
-               do {
-                       String filename = prefix + ":" + to;
-                       destfile = new File(outbox, filename);
-                       prefix++;
-               } while (destfile.exists());
+               synchronized (this.senderthread) {
+                       do {
+                               String filename = prefix + ":" + tries + ":" + 
to;
+                               destfile = new File(outbox, filename);
+                               prefix++;
+                       } while (destfile.exists());

-               tempfile.renameTo(destfile);
+                       f.renameTo(destfile);
+               }
        }

        public void run() {
@@ -100,12 +108,16 @@
        }

        private void sendSingle(File accdir, File msg) {
-               String parts[] = msg.getName().split(":", 2);
+               String parts[] = msg.getName().split(":", 3);
                EmailAddress addr;
-               if (parts.length < 2) {
-                       addr = new EmailAddress(parts[0]);
+               int tries;
+               if (parts.length < 3) {
+                       System.out.println("Warning invalid file in outbox - 
deleting.");
+                       msg.delete();
+                       return;
                } else {
-                       addr = new EmailAddress(parts[1]);
+                       tries = Integer.parseInt(parts[1]);
+                       addr = new EmailAddress(parts[2]);
                }

                if (addr.domain == null || addr.domain.length() == 0) {
@@ -122,6 +134,15 @@
                } else {
                        if (this.sendSecure(accdir, addr, msg)) {
                                msg.delete();
+                       } else {
+                               tries++;
+                               if (tries > MAX_TRIES) {
+                                       if (Postman.bounceMessage(msg, new 
MessageBank(accdir.getName()), "Tried too many times to deliver this message, 
but it doesn't apear that this address even exists. If you're sure that it 
does, check your Freenet connection.")) {
+                                               msg.delete();
+                                       }
+                               } else {
+                                       this.moveToOutbox(msg, tries, parts[2], 
msg.getParentFile());
+                               }
                        }
                }
        }
@@ -134,6 +155,13 @@
                } catch (BadFreemailAddressException bfae) {
                        // bounce
                        return Postman.bounceMessage(msg, new 
MessageBank(accdir.getName()), "The address that this message was destined for 
("+addr+") is not a valid Freemail address.");
+               } catch (OutboundContactFatalException obfe) {
+                       // bounce
+                       return Postman.bounceMessage(msg, new 
MessageBank(accdir.getName()), obfe.getMessage());
+               } catch (IOException ioe) {
+                       // couldn't get the mailsite - try again if you're not 
ready
+                       //to give up yet
+                       return false;
                }

                return ct.sendMessage(msg);

Modified: trunk/apps/Freemail/src/freemail/OutboundContact.java
===================================================================
--- trunk/apps/Freemail/src/freemail/OutboundContact.java       2006-08-04 
15:47:27 UTC (rev 9883)
+++ trunk/apps/Freemail/src/freemail/OutboundContact.java       2006-08-04 
16:29:28 UTC (rev 9884)
@@ -8,6 +8,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
 import java.math.BigInteger;
 import java.security.SecureRandom;

@@ -52,10 +53,10 @@
        private static final int AES_KEY_LENGTH = 256 / 8;
        // this is defined in the AES standard (although the Rijndael
        // algorithm does support other block sizes.
-       // we read 128 bytes for our IV, so it needs to be constant.
+       // we read 128 bytes for our IV, so it needs to be constant.)
        private static final int AES_BLOCK_LENGTH = 128 / 8;

-       public OutboundContact(File accdir, EmailAddress a) throws 
BadFreemailAddressException {
+       public OutboundContact(File accdir, EmailAddress a) throws 
BadFreemailAddressException, IOException, OutboundContactFatalException {
                this.address = a;

                this.accdir = accdir;
@@ -72,8 +73,23 @@
                        if (!outbounddir.exists())
                                outbounddir.mkdir();

-                       File obctdir = new File(outbounddir, 
this.address.getSubDomain());
+                       if (!this.address.is_ssk_address()) {
+                               String ssk_mailsite = 
this.fetchKSKRedirect(this.address.getMailpageKey());
+                               
+                               if (ssk_mailsite == null) throw new 
IOException();
+                               
+                               FreenetURI furi;
+                               try {
+                                       furi = new FreenetURI(ssk_mailsite);
+                               } catch (MalformedURLException mfue) {
+                                       throw new 
OutboundContactFatalException("The Freemail address points to an invalid 
redirect, and is therefore useless.");
+                               }
+                               
+                               this.address.domain = 
Base32.encode(furi.getKeyBody().getBytes())+".freemail";
+                       }

+                       File obctdir = new File(outbounddir, 
this.address.getSubDomain().toLowerCase());
+                       
                        if (!obctdir.exists())
                                obctdir.mkdir();

@@ -111,7 +127,7 @@
                        if (ctskey == null) {
                                this.init();
                        }
-                       ctskey += "ack";
+                       ctskey += "cts";

                        HighLevelFCPClient fcpcli = new HighLevelFCPClient();

@@ -369,6 +385,43 @@
                return true;
        }

+       // fetch the redirect (assumes that this is a KSK address)
+       private String fetchKSKRedirect(String key) throws 
OutboundContactFatalException {
+               HighLevelFCPClient cli = new HighLevelFCPClient();
+               
+               System.out.println("Attempting to fetch mailsite redirect 
"+key);
+               File result = cli.fetch(key);
+               
+               if (result == null) {
+                       System.out.println("Failed to retrieve mailsite 
redirect "+key);
+                       return null;
+               }
+               
+               if (result.length() > 512) {
+                       System.out.println("Fatal: mailsite redirect too long. 
Ignoring.");
+                       result.delete();
+                       throw new OutboundContactFatalException("Mailsite 
redirect too long.");
+               }
+               
+               BufferedReader br = null;
+               try {
+                       br = new BufferedReader(new FileReader(result));
+               } catch (FileNotFoundException fnfe) {
+                       // impossible
+               }
+               
+               String addr;
+               try {
+                       addr = br.readLine();
+                       br.close();
+               } catch (IOException ioe) {
+                       System.out.println("Warning: IO exception whilst 
reading mailsite redirect file: "+ioe.getMessage());
+                       return null;
+               }
+               result.delete();
+               return addr;
+       }
+       
        private boolean fetchMailSite() throws OutboundContactFatalException {
                HighLevelFCPClient cli = new HighLevelFCPClient();

@@ -380,36 +433,6 @@
                        return false;
                }

-               if (!this.address.is_ssk_address()) {
-                       // presumably a KSK 'redirect'. Follow it.
-                       BufferedReader br = null;
-                       try {
-                               br = new BufferedReader(new 
FileReader(mailsite_file));
-                       } catch (FileNotFoundException fnfe) {
-                               // impossible
-                       }
-                       
-                       if (mailsite_file.length() > 512) {
-                               System.out.println("Fatal: mailsite redirect 
too long. Ignoring.");
-                               throw new 
OutboundContactFatalException("Mailsite redirect too long.");
-                       }
-                       
-                       String addr;
-                       try {
-                               addr = br.readLine();
-                               br.close();
-                       } catch (IOException ioe) {
-                               System.out.println("Warning: IO exception 
whilst reading mailsite redirect file: "+ioe.getMessage());
-                               return false;
-                       }
-                       mailsite_file.delete();
-                       mailsite_file = cli.fetch(addr);
-                       if (mailsite_file == null) {
-                               System.out.println("Failed to retrieve 
redirected mailsite "+addr);
-                               return false;
-                       }
-               }
-               
                System.out.println("got mailsite");

                PropsFile mailsite = new PropsFile(mailsite_file);
@@ -610,8 +633,10 @@
                                continue;
                        }

-                       key += msgs[i].uid;
+                       key += "ack-"+msgs[i].uid;

+                       System.out.println("Looking for message ack on "+key);
+                       
                        File ack = fcpcli.fetch(key);
                        if (ack != null) {
                                System.out.println("Ack received for message 
"+msgs[i].uid+" on contact "+this.address.domain+". Now that's a job well 
done.");
@@ -622,6 +647,7 @@
                                // delete inital slot for forward secrecy
                                this.contactfile.remove("initialslot");
                        } else {
+                               System.out.println("Failed to receive ack on 
"+key);
                                if (System.currentTimeMillis() > 
msgs[i].first_send_time + FAIL_DELAY) {
                                        // give up and bounce the message
                                        File m = msgs[i].getMessageFile();


Reply via email to