[tor-commits] [metrics-lib/master] Implement bridge network status parsing.

karsten at torproject.org karsten at torproject.org
Thu Jan 12 09:23:03 UTC 2012


commit d5ffbee290e55423e143e6eb558f2647e28b5d6a
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Thu Jan 12 09:29:11 2012 +0100

    Implement bridge network status parsing.
---
 .../impl/BridgeDescriptorReaderImpl.java           |   85 ++++++++++++++++++--
 .../descriptor/impl/BridgeNetworkStatusImpl.java   |   75 +++++++++++++++++
 .../torproject/descriptor/impl/DescriptorImpl.java |   30 +++++++
 3 files changed, 183 insertions(+), 7 deletions(-)

diff --git a/src/org/torproject/descriptor/impl/BridgeDescriptorReaderImpl.java b/src/org/torproject/descriptor/impl/BridgeDescriptorReaderImpl.java
index 09f422c..04e5d2a 100644
--- a/src/org/torproject/descriptor/impl/BridgeDescriptorReaderImpl.java
+++ b/src/org/torproject/descriptor/impl/BridgeDescriptorReaderImpl.java
@@ -2,34 +2,105 @@
  * See LICENSE for licensing information */
 package org.torproject.descriptor.impl;
 
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.Stack;
+import org.torproject.descriptor.Descriptor;
 import org.torproject.descriptor.DescriptorFile;
 import org.torproject.descriptor.BridgeDescriptorReader;
 
-public class BridgeDescriptorReaderImpl implements BridgeDescriptorReader {
+public class BridgeDescriptorReaderImpl
+    implements BridgeDescriptorReader {
 
+  private List<File> directories = new ArrayList<File>();
   public void addDirectory(File directory) {
-    /* TODO Implement me. */
+    this.directories.add(directory);
   }
 
   public void setExcludeFile(File fileToExclude) {
+    throw new UnsupportedOperationException("Not implemented yet.");
     /* TODO Implement me. */
   }
 
   public void setExcludeFiles(Set<File> filesToExclude) {
+    throw new UnsupportedOperationException("Not implemented yet.");
     /* TODO Implement me. */
   }
 
-  public void setInitialCacheLimit(long cacheLimitBytes) {
-    /* TODO Implement me. */
+  public Iterator<DescriptorFile> readDescriptors() {
+    BlockingIteratorImpl<DescriptorFile> descriptorQueue =
+        new BlockingIteratorImpl<DescriptorFile>();
+    DescriptorReader reader = new DescriptorReader(this.directories,
+        descriptorQueue);
+    new Thread(reader).start();
+    return descriptorQueue;
   }
 
-  public Iterator<DescriptorFile> readDescriptors() {
-    /* TODO Implement me. */
-    return new BlockingIteratorImpl<DescriptorFile>();
+  private static class DescriptorReader implements Runnable {
+    private List<File> directories;
+    private BlockingIteratorImpl<DescriptorFile> descriptorQueue;
+    private DescriptorReader(List<File> directories,
+        BlockingIteratorImpl<DescriptorFile> descriptorQueue) {
+      this.directories = directories;
+      this.descriptorQueue = descriptorQueue;
+    }
+    public void run() {
+      for (File directory : this.directories) {
+        try {
+          Stack<File> files = new Stack<File>();
+          files.add(directory);
+          while (!files.isEmpty()) {
+            File file = files.pop();
+            if (file.isDirectory()) {
+              files.addAll(Arrays.asList(file.listFiles()));
+            } else {
+              try {
+                List<Descriptor> parsedDescriptors = this.readFile(file);
+                DescriptorFileImpl descriptorFile =
+                    new DescriptorFileImpl();
+                descriptorFile.setDirectory(directory);
+                descriptorFile.setFile(file);
+                descriptorFile.setLastModified(file.lastModified());
+                descriptorFile.setDescriptors(parsedDescriptors);
+                this.descriptorQueue.add(descriptorFile);
+              } catch (DescriptorParseException e) {
+                /* TODO Handle me. */
+              }
+            }
+          }
+        } catch (IOException e) {
+          System.err.println("Error while reading descriptors in '"
+              + directory.getAbsolutePath() + "'.");
+          /* TODO Handle this exception somehow. */
+        } finally {
+          this.descriptorQueue.setOutOfDescriptors();
+        }
+      }
+    }
+    private List<Descriptor> readFile(File file) throws IOException,
+        DescriptorParseException {
+      FileInputStream fis = new FileInputStream(file);
+      BufferedInputStream bis = new BufferedInputStream(fis);
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      int len;
+      byte[] data = new byte[1024];
+      while ((len = bis.read(data, 0, 1024)) >= 0) {
+        baos.write(data, 0, len);
+      }
+      bis.close();
+      byte[] rawDescriptorBytes = baos.toByteArray();
+      return DescriptorImpl.parseBridgeDescriptors(rawDescriptorBytes,
+          file.getName());
+    }
   }
 }
 
diff --git a/src/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java b/src/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java
new file mode 100644
index 0000000..714f6ae
--- /dev/null
+++ b/src/org/torproject/descriptor/impl/BridgeNetworkStatusImpl.java
@@ -0,0 +1,75 @@
+/* Copyright 2012 The Tor Project
+ * See LICENSE for licensing information */
+package org.torproject.descriptor.impl;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+import org.torproject.descriptor.BridgeNetworkStatus;
+
+/* Contains a bridge network status. */
+public class BridgeNetworkStatusImpl extends NetworkStatusImpl
+    implements BridgeNetworkStatus {
+
+  protected BridgeNetworkStatusImpl(byte[] statusBytes,
+      String fileName) throws DescriptorParseException {
+    super(statusBytes);
+    this.setPublishedMillisFromFileName(fileName);
+  }
+
+  private static SimpleDateFormat fileNameFormat = new SimpleDateFormat(
+      "yyyyMMdd-HHmmss");
+  static {
+    fileNameFormat.setLenient(false);
+    fileNameFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+  }
+
+  private void setPublishedMillisFromFileName(String fileName)
+      throws DescriptorParseException {
+    if (fileName.length() == 
+        "20000101-000000-4A0CCD2DDC7995083D73F5D667100C8A5831F16D".
+        length()) {
+      String publishedString = fileName.substring(0,
+          "yyyyMMdd-HHmmss".length());
+      try {
+        this.publishedMillis = fileNameFormat.parse(publishedString).
+            getTime();
+      } catch (ParseException e) {
+      } 
+    }
+    if (this.publishedMillis == 0L) {
+      throw new DescriptorParseException("Unrecognized bridge network "
+          + "status file name '" + fileName + "'.");
+    }
+  }
+
+  protected void parseHeader(byte[] headerBytes)
+      throws DescriptorParseException {
+    throw new DescriptorParseException("No directory header expected in "
+        + "bridge network status.");
+  }
+
+  protected void parseDirSource(byte[] dirSourceBytes)
+      throws DescriptorParseException {
+    throw new DescriptorParseException("No directory source expected in "
+        + "bridge network status.");
+  }
+
+  protected void parseFooter(byte[] footerBytes)
+      throws DescriptorParseException {
+    throw new DescriptorParseException("No directory footer expected in "
+        + "bridge network status.");
+  }
+
+  protected void parseDirectorySignature(byte[] directorySignatureBytes)
+      throws DescriptorParseException {
+    throw new DescriptorParseException("No directory signature expected "
+        + "in bridge network status.");
+  }
+
+  private long publishedMillis;
+  public long getPublishedMillis() {
+    return this.publishedMillis;
+  }
+}
+
diff --git a/src/org/torproject/descriptor/impl/DescriptorImpl.java b/src/org/torproject/descriptor/impl/DescriptorImpl.java
index cade4cf..24c1fe9 100644
--- a/src/org/torproject/descriptor/impl/DescriptorImpl.java
+++ b/src/org/torproject/descriptor/impl/DescriptorImpl.java
@@ -51,6 +51,36 @@ public abstract class DescriptorImpl implements Descriptor {
     return parsedDescriptors;
   }
 
+  protected static List<Descriptor> parseBridgeDescriptors(
+      byte[] rawDescriptorBytes, String fileName)
+      throws DescriptorParseException {
+    List<Descriptor> parsedDescriptors = new ArrayList<Descriptor>();
+    byte[] first100Chars = new byte[Math.min(100,
+        rawDescriptorBytes.length)];
+    System.arraycopy(rawDescriptorBytes, 0, first100Chars, 0,
+        first100Chars.length);
+    String firstLines = new String(first100Chars);
+    if (firstLines.startsWith("r ")) {
+      parsedDescriptors.add(new BridgeNetworkStatusImpl(
+          rawDescriptorBytes, fileName));
+    } else if (firstLines.startsWith("router ") ||
+        firstLines.contains("\nrouter ")) {
+      /* TODO Implement me.
+      parsedDescriptors.addAll(BridgeServerDescriptorImpl.
+          parseDescriptors(rawDescriptorBytes)); */
+    } else if (firstLines.startsWith("extra-info ") ||
+        firstLines.contains("\nextra-info ")) {
+      /* TODO Implement me.
+      parsedDescriptors.addAll(BridgeExtraInfoDescriptorImpl.
+          parseDescriptors(rawDescriptorBytes)); */
+    } else {
+      throw new DescriptorParseException("Could not detect bridge "
+          + "descriptor type in descriptor starting with '" + firstLines
+          + "'.");
+    }
+    return parsedDescriptors;
+  }
+
   protected static List<byte[]> splitRawDescriptorBytes(
       byte[] rawDescriptorBytes, String startToken) {
     List<byte[]> rawDescriptors = new ArrayList<byte[]>();





More information about the tor-commits mailing list