commit d5ffbee290e55423e143e6eb558f2647e28b5d6a Author: Karsten Loesing karsten.loesing@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[]>();
tor-commits@lists.torproject.org