[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r11736: refactored a lot of things to make old and new parts (RMI, n (in puppetor/trunk/src/de/uniba/wiai/lspi/puppetor: . examples groovy impl)
Author: kloesing
Date: 2007-10-01 17:59:35 -0400 (Mon, 01 Oct 2007)
New Revision: 11736
Added:
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/HiddenService.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/HiddenServiceEventType.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/PuppeTorException.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/LongRunningNetwork.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/MergingProxiesWithLongRunningNetwork.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/MergingRoutersWithLongRunningNetwork.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/HiddenServiceImpl.java
Removed:
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/AliceEventType.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/BobEventType.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/MiscEventType.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkState.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/TorProcessException.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/rmi/
Modified:
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ClientApplication.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ClientEventType.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/DirectoryNode.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Event.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/EventManager.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/EventType.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Network.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkFactory.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NodeEventType.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NodeState.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ProxyNode.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/RouterNode.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ServerApplication.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ServerEventType.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AccessingPublicWebServerOverTor.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPrivateTorNetwork.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPublicTorNetwork.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingHiddenServiceToPublicTorNetwork.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/groovy/RmiPuppetzShell.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ClientApplicationImpl.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/DirectoryNodeImpl.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/EventImpl.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/EventManagerImpl.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java
puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ServerApplicationImpl.java
Log:
refactored a lot of things to make old and new parts (RMI, network merging, Groovy shell) better fit together
Deleted: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/AliceEventType.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/AliceEventType.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/AliceEventType.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2007, Karsten Loesing
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * Neither the names of the copyright owners nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package de.uniba.wiai.lspi.puppetor;
-
-public class AliceEventType implements EventType{
-
- /**
- * Alice has received an onion request; this event is parsed from a log
- * statement in connection_ap_handshake_rewrite_and_attach().
- */
- public static final AliceEventType ALICE_ONION_REQUEST_RECEIVED = new AliceEventType();
-
- /**
- * Alice sends a fetch request for a hidden service descriptor to a
- * directory server; this event is parsed from a log statement in
- * rend_client_refetch_renddesc().
- */
- public static final AliceEventType ALICE_SENDING_FETCH_DESC = new AliceEventType();
-
- /**
- * Alice receives a reply to a previous fetch request for a hidden service
- * descriptors from a directory server; this event is parsed from a log
- * statement in connection_dir_client_reached_eof().
- */
- public static final AliceEventType ALICE_DESC_FETCHED_RECEIVED = new AliceEventType();
-
- /**
- * Alice has built a circuit to a rendezvous point and sends an
- * ESTABLISH_RENDEZVOUS cell; this event is parsed from a log statement in
- * rend_client_send_establish_rendezvous().
- */
- public static final AliceEventType ALICE_BUILT_REND_CIRC_SENDING_ESTABLISH_RENDEZVOUS = new AliceEventType();
-
- /**
- * Alice receives a RENDEZVOUS_ESTABLISHED cell from a rendezvous point;
- * this event is parsed from a log statement in
- * rend_client_rendezvous_acked().
- */
- public static final AliceEventType ALICE_RENDEZVOUS_ESTABLISHED_RECEIVED = new AliceEventType();
-
- /**
- * Alice has built a circuit to an introduction point (which does not
- * automatically lead to sending an INTRODUCE1 cell, because the rendezvous
- * circuit might not be ready); this event is parsed from a log statement in
- * rend_client_introcirc_has_opened().
- */
- public static final AliceEventType ALICE_BUILT_INTRO_CIRC = new AliceEventType();
-
- /**
- * Alice sends an INTRODUCE1 cell to an introduction point; this event is
- * parsed from a log statement in rend_client_send_introduction().
- */
- public static final AliceEventType ALICE_SENDING_INTRODUCE1 = new AliceEventType();
-
- /**
- * Alice has received an INTRODUCE_ACK cell as an acknowledgement to the
- * previous INTRODUCE1 cell; this event is parsed from a log statement in
- * rend_client_introduction_acked().
- */
- public static final AliceEventType ALICE_INTRODUCE_ACK_RECEIVED = new AliceEventType();
-
- /**
- * Alice has received a RENDEZVOUS2 cell and can now open an application
- * connection to the client; this event is parsed from a log statement in
- * rend_client_receive_rendezvous().
- */
- public static final AliceEventType ALICE_RENDEZVOUS2_RECEIVED_APP_CONN_OPENED = new AliceEventType();
-}
\ No newline at end of file
Deleted: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/BobEventType.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/BobEventType.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/BobEventType.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2007, Karsten Loesing
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * Neither the names of the copyright owners nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package de.uniba.wiai.lspi.puppetor;
-
-public class BobEventType implements EventType{
-
- /**
- * Bob has built a circuit to an introduction point and sends an
- * ESTABLISH_INTRO cell; this event is parsed from a log statement in
- * rend_service_intro_has_opened().
- */
- public static final BobEventType BOB_BUILT_INTRO_CIRC_SENDING_ESTABLISH_INTRO = new BobEventType();
-
- /**
- * Bob has received an INTRO_ESTABLISHED cell, i.e. a node has confirmed to
- * work as introduction point; this event is parsed from a log statement in
- * rend_service_intro_established().
- */
- public static final BobEventType BOB_INTRO_ESTABLISHED_RECEIVED = new BobEventType();
-
- /**
- * Bob posts a hidden service descriptor to the directory servers (or to
- * hidden service directories in a modified Tor); this event is parsed from
- * a log statement in upload_service_descriptor().
- */
- public static final BobEventType BOB_SENDING_PUBLISH_DESC = new BobEventType();
-
- /**
- * Bob received a response from a directory server (or from a hidden service
- * directory in a modified Tor) to a previous publish request; this event is
- * parsed from a log statement in connection_dir_client_reached_eof().
- */
- public static final BobEventType BOB_DESC_PUBLISHED_RECEIVED = new BobEventType();
-
- /**
- * Bob has received an INTRODUCE2 cell, i.e. a node wants to establish a
- * connection, and will now try to establish a circuit to the client's
- * rendezvous point; this event is parsed from a log statement in
- * rend_service_introduce().
- */
- public static final BobEventType BOB_INTRODUCE2_RECEIVED = new BobEventType();
-
- /**
- * Bob has built a circuit to a rendezvous point and sends an RENDEZVOUS1
- * cell; this event is parsed from a log statement in
- * rend_service_rendezvous_has_opened().
- */
- public static final BobEventType BOB_BUILT_REND_CIRC_SENDING_RENDEZVOUS1 = new BobEventType();
-
- /**
- * Bob opens a connection to the actual hidden server; this event is parsed
- * from a log statement in connection_exit_begin_conn().
- */
- public static final BobEventType BOB_APP_CONN_OPENED = new BobEventType();
-
-}
\ No newline at end of file
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ClientApplication.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ClientApplication.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ClientApplication.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -46,21 +46,22 @@
* <p>
* Performs one or more HTTP requests to a previously provided address and
* port. All requests are performed by a thread in the background, so that
- * this method may return immediately. That thread will try for
+ * this method returns immediately. That thread will try for
* <code>retries</code> times to make the request with a timeout of
- * <code>timeoutForEachRetry</code> millis each. If an attempt is not
- * successful, the thread nevertheless waits for the timeout to expire. If
- * <code>stopOnSuccess</code> is set to <code>true</code>, the thread
- * will quit performing requests after the first successful request.
+ * <code>timeoutForEachRetry</code> milliseconds each. If an attempt is not
+ * successful, the thread nevertheless waits for the timeout to expire
+ * before performing the next attempt. If <code>stopOnSuccess</code> is
+ * set to <code>true</code>, the thread will quit performing requests
+ * immediately after the first successful request.
* </p>
*
* <p>
- * For each sent request the application fires an
- * <event>EventType.APPLICATION_SENDING_REQUEST</code> event. On receiving
- * a reply it fires an event of type <code>EventType.APPLICATION_REPLY_RECEIVED</code>,
- * if a request is not successful or times out, an <code>EventType.APPLICATION_GAVE_UP_REQUEST</code>
+ * For each sent request the application fires a
+ * <event>ClientEventType.CLIENT_SENDING_REQUEST</code> event. On receiving
+ * a reply it fires an event of type <code>ClientEventType.CLIENT_REPLY_RECEIVED</code>,
+ * if a request is not successful or times out, a <code>ClientEventType.CLIENT_GAVE_UP_REQUEST</code>
* event is fired. After all requests have been performed (either
- * successfully, or not) an event of type <code>EventType.APPLICATION_REQUESTS_PERFORMED</code>
+ * successfully, or not) an event of type <code>ClientEventType.CLIENT_REQUESTS_PERFORMED</code>
* is fired.
* </p>
*
@@ -82,7 +83,7 @@
* Thrown if an invalid value is given for either of the
* parameters.
*/
- public abstract void performRequest(int retries, long timeoutForEachRetry,
+ public abstract void startRequests(int retries, long timeoutForEachRetry,
boolean stopOnSuccess);
/**
@@ -92,7 +93,6 @@
* Thrown if no requests have been started before.
*/
public abstract void stopRequest();
-
/**
* Returns the name of this client.
@@ -100,4 +100,27 @@
* @return The name of this client.
*/
public abstract String getClientApplicationName();
+
+ /**
+ * Returns the SOCKS port of the local Tor node to which requests are sent.
+ *
+ * @return The SOCKS port of the local Tor node to which requests are sent.
+ */
+ public abstract int getSocksPort();
+
+ /**
+ * Returns the target name for the requests sent by this client; can be
+ * either a server name/address or an onion address.
+ *
+ * @return The target name for the requests sent by this client.
+ */
+ public abstract String getTargetName();
+
+ /**
+ * Returns the target port for the requests sent by this client; can be
+ * either a server port or a virtual port of a hidden service.
+ *
+ * @return The target port for the requests sent by this client.
+ */
+ public abstract int getTargetPort();
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ClientEventType.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ClientEventType.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ClientEventType.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -31,32 +31,59 @@
*/
package de.uniba.wiai.lspi.puppetor;
-public class ClientEventType implements EventType{
-
+/**
+ * Event types that can be fired by a client application running as thread in
+ * the background.
+ */
+public class ClientEventType implements EventType {
+
/**
+ * String identifying the type of the event type.
+ */
+ String typeString;
+
+ /**
+ * Creates a new event type with the given type string.
+ *
+ * @param typeString
+ * String identifying the type of the event type.
+ */
+ public ClientEventType(String typeString) {
+ this.typeString = typeString;
+ }
+
+ public String getTypeName() {
+ return this.typeString;
+ }
+
+ /**
* The client application is sending a request; this event is fired
* internally and not parsed from a log statement from Tor.
*/
- public static final ClientEventType CLIENT_SENDING_REQUEST = new ClientEventType();
+ public static final ClientEventType CLIENT_SENDING_REQUEST = new ClientEventType(
+ "CLIENT_SENDING_REQUEST");
/**
* The client application has received a reply to a previously sent request;
* this event is fired internally and not parsed from a log statement from
* Tor.
*/
- public static final ClientEventType CLIENT_REPLY_RECEIVED = new ClientEventType();
+ public static final ClientEventType CLIENT_REPLY_RECEIVED = new ClientEventType(
+ "CLIENT_REPLY_RECEIVED");
/**
* The client application has given up waiting for the reply to a previously
* sent request; this event is fired internally and not parsed from a log
* statement from Tor.
*/
- public static final ClientEventType CLIENT_GAVE_UP_REQUEST = new ClientEventType();
+ public static final ClientEventType CLIENT_GAVE_UP_REQUEST = new ClientEventType(
+ "CLIENT_GAVE_UP_REQUEST");
/**
* The client application has completed a series of requests, whether they
* were successful or not; this event is fired internally and not parsed
* from a log statement from Tor.
*/
- public static final ClientEventType CLIENT_REQUESTS_PERFORMED = new ClientEventType();
+ public static final ClientEventType CLIENT_REQUESTS_PERFORMED = new ClientEventType(
+ "CLIENT_REQUESTS_PERFORMED");
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/DirectoryNode.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/DirectoryNode.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/DirectoryNode.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -52,56 +52,31 @@
*
* @return <code>DirServer</code> string to configure a node to use this
* node as directory server.
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if a problem occurs when determining the fingerprint
* of this node.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract String determineDirServerString()
- throws TorProcessException, RemoteException;
+ public abstract String getDirServerString() throws PuppeTorException,
+ RemoteException;
/**
- * Writes the given (possibly empty) set of onion router fingerprints to the
- * <code>approved-routers</code> file of this node. This will confirm to
- * directory clients, that the given routers can be trusted.
+ * Adds the given (possibly empty) set of onion router fingerprints to the
+ * set of approved routers to confirm to directory clients, that the given
+ * routers can be trusted. Changes are only stored locally and not written
+ * to the <code>approved-routers</code> file to disk which will be done
+ * when writing the configuration of this node.
*
* @param approvedRouters
- * The set of approved routers to be written. Each provided
- * string must be formatted as
- * <code>nickname 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000</code>.
- * @throws IllegalArgumentException
- * Thrown if <code>null</code> is passed as parameter;
- * however, if an empty set is passed, an empty
- * <code>approved-routers</code> file will be written.
- * @throws TorProcessException
- * Thrown if the <code>approved-routers</code> file cannot be
- * written to disk.
- * @throws RemoteException
- * Thrown if an error occurs when accessed remotely.
- */
- public void writeApprovedRouters(Set<String> approvedRouters)
- throws TorProcessException, RemoteException;
-
- /**
- * Adds the given set of onion router fingerprints to the
- * <code>approved-routers</code> file of this node. This will confirm to
- * directory clients, that the given routers can be trusted.
- *
- * @param approvedRouters
* The set of approved routers to be added. Each provided string
* must be formatted as
* <code>nickname 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000</code>.
* @throws IllegalArgumentException
- * Thrown if <code>null</code> is passed as parameter;
- * however, if an empty set is passed, the
- * <code>approved-routers</code> file will not be changed.
- * @throws TorProcessException
- * Thrown if the <code>approved-routers</code> file cannot be
- * written to disk.
+ * Thrown if <code>null</code> is passed as parameter.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
public void addApprovedRouters(Set<String> approvedRouters)
- throws TorProcessException, RemoteException;
+ throws RemoteException;
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Event.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Event.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Event.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -36,12 +36,12 @@
/**
* An <code>Event</code> is created for every state change of an asynchronous
* system component, e.g. a Tor process or a client/server application running
- * as thread in the background. In contrast to <code>NodeState</code> or
- * <code>NetworkState</code> an <code>Event</code> cannot be a pre- or
- * postconditions for a method invocation. There is no prescribed order in which
- * events are fired by a certain process or application. Some events can be
- * fired only once, others possibly multiple times. All management operations
- * for events are contained in the <code>EventManager</code>.
+ * as thread in the background. In contrast to <code>NodeState</code> an
+ * <code>Event</code> cannot be a pre- or postconditions for a method
+ * invocation. There is no prescribed order in which events are fired by a
+ * certain process or application. Some events can be fired only once, others
+ * possibly multiple times. All management operations for events are contained
+ * in the <code>EventManager</code>.
*
* @author kloesing
*/
@@ -56,7 +56,7 @@
public abstract String getSource();
/**
- * Returns the type of this event.
+ * Returns the event type.
*
* @return The event type.
*/
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/EventManager.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/EventManager.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/EventManager.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -40,7 +40,7 @@
* asynchronous events by Tor processes and client or server applications
* running as threads in the background. A test application can either register
* event listeners to be notified asynchronously about events when they occur,
- * or synchronize with an event by being blocked until the certain event occurs.
+ * or synchronize with an event by being blocked until a certain event occurs.
*
* @author kloesing
*/
@@ -54,7 +54,7 @@
* signalized in a later invocation on the event listener, but not in both.
* This prevents race conditions by eliminating the gap between registration
* of an event handler and asking if an event has been fired before
- * registering. This method can be invoked in any node or network state.
+ * registering.
*
* @param source
* The name of the source of events that the listener is
@@ -72,7 +72,7 @@
* empty list is returned instead of <code>null</code>.
* @throws IllegalArgumentException
* Thrown if <code>null</code> is passed for either of the
- * parameters or if <code>source</code> is not known.
+ * parameters or if the <code>source</code> is unknown.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
@@ -81,16 +81,14 @@
/**
* Registers the given <code>listener</code> as event listener for future
- * events originating from any source. This method can be invoked in any
- * node or network state.
+ * events originating from any source.
*
* @param listener
* The listener that wants to be notified about events from the
* given <code>source</code>. If the <code>listener</code>
- * is already registered for the same <code>source</code>,
- * nothing happens, i.e. the <code>listener</code> will not
- * receive multiple invocations for the same event. May not be
- * <code>null</code>.
+ * is already registered for all sources, nothing happens, i.e.
+ * the <code>listener</code> will not receive multiple
+ * invocations for the same event. May not be <code>null</code>.
* @throws IllegalArgumentException
* Thrown if <code>null</code> is passed for the parameter.
* @throws RemoteException
@@ -107,11 +105,11 @@
* The source of the events that the invoking thread is
* interested in. May not be <code>null</code> and must be the
* name of a previously created node, client, or server.
- * @throws IllegalArgumentException
- * Thrown if <code>null</code> is passed as parameter or if
- * <code>source</code> is unknown.
* @return List of all previously observed events from the given
* <code>source</code>.
+ * @throws IllegalArgumentException
+ * Thrown if <code>null</code> is passed as parameter or if
+ * the <code>source</code> is unknown.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
@@ -119,16 +117,16 @@
throws RemoteException;
/**
- * Returns whether the given <code>event</code> has been observed from the
- * given <code>source</code> before, or not.
+ * Returns whether the given <code>eventType</code> has been observed from
+ * the given <code>source</code> before, or not.
*
* @param source
* The source of the event that the invoking thread is interested
* in. May not be <code>null</code> and must be the name of a
* previously created node, client, or server.
- * @param event
- * The event that the invoking thread is interested int. May not
- * be <code>null</code>.
+ * @param eventType
+ * The event type that the invoking thread is interested in. May
+ * not be <code>null</code>.
* @throws IllegalArgumentException
* Thrown if <code>null</code> is passed for either of the
* parameters or if <code>source</code> is unknown.
@@ -137,19 +135,14 @@
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract boolean hasEventOccured(String source, EventType event)
+ public abstract boolean hasEventOccured(String source, EventType eventType)
throws RemoteException;
/**
* Removes the given <code>listener</code> as event listener from all
* previously registered sources. If this listener is not registered for any
- * source, nothing happens. This method can be invoked in any node or
- * network state.
+ * source, nothing happens.
*
- * TODO should we include the source as parameter, too, to have even more
- * control over removing listeners from sources? Or should we overload the
- * method?
- *
* @param listener
* The listener that shall be removed from the list of registered
* listeners. May not be <code>null</code>.
@@ -162,125 +155,130 @@
throws RemoteException;
/**
- * Checks if the given <code>event</code> has been observed from the given
- * <code>source</code> before; if not, blocks the invoking thread until
- * the next event is fired from that source. Note that this method does not
- * restrict waiting to a timeout, so that it could potentially block
- * forever! This method can be invoked in any node or network state.
+ * Checks if the given <code>eventType</code> has been observed from the
+ * given <code>source</code> before; if not, blocks the invoking thread
+ * until the next event of this type is fired from that source. Note that
+ * this method does not restrict waiting to a timeout, so that it could
+ * potentially block forever!
*
* @param source
* The source of the event that the invoking thread is willing to
* wait for. May not be <code>null</code> and must be the name
* of a previously created node, client, or server.
- * @param event
- * The event that the invoking thread is willing to wait for from
- * the given <code>source</code>. May not be <code>null</code>.
+ * @param eventType
+ * The event type that the invoking thread is willing to wait for
+ * from the given <code>source</code>. May not be
+ * <code>null</code>.
* @throws IllegalArgumentException
* Thrown if <code>null</code> is passed for either of the
- * parameters or if <code>source</code> is unknown.
+ * parameters or if the <code>source</code> is unknown.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract void waitForAnyOccurence(String source, EventType event)
+ public abstract void waitForAnyOccurence(String source, EventType eventType)
throws RemoteException;
/**
- * Checks if the given <code>event</code> has been observed from the given
- * <code>source</code> before; if not, blocks the invoking thread until
- * the next event is fired from that source or the given timeout of
- * <code>maximumTimeToWaitInMillis</code> millis has expired. This method
- * can be invoked in any node or network state.
+ * Checks if the given <code>eventType</code> has been observed from the
+ * given <code>source</code> before; if not, blocks the invoking thread
+ * until the next event of this type is fired from that source or the given
+ * timeout of <code>maximumTimeToWaitInMillis</code> milliseconds has
+ * expired.
*
* @param source
* The source of the event that the invoking thread is willing to
* wait for. May not be <code>null</code> and must be the name
* of a previously created node, client, or server.
- * @param event
- * The event that the invoking thread is willing to wait for from
- * the given <code>source</code>. May not be <code>null</code>.
+ * @param eventType
+ * The event type that the invoking thread is willing to wait for
+ * from the given <code>source</code>. May not be
+ * <code>null</code>.
* @param maximumTimeToWaitInMillis
* The maximum time to wait in milliseconds. A positive value or
* zero restricts waiting to this time. If this value is
* negative, we will wait potentially forever.
* @return <code>true</code> if an event of the given type has been fired
- * by the source within the given timeout, <code>false</code>
- * otherwise.
+ * by the <code>source</code> within the given timeout,
+ * <code>false</code> otherwise.
* @throws IllegalArgumentException
* Thrown if an invalid value is passed for either of the
- * parameters or if <code>source</code> is unknown.
+ * parameters or if the <code>source</code> is unknown.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract boolean waitForAnyOccurence(String source, EventType event,
- long maximumTimeToWaitInMillis) throws RemoteException;
+ public abstract boolean waitForAnyOccurence(String source,
+ EventType eventType, long maximumTimeToWaitInMillis)
+ throws RemoteException;
/**
* Blocks the invoking thread until the next <code>event</code> is fired
* from the given <code>source</code>. This method only waits for the
* next occurence of an event, regardless of previous occurrences. Note that
* this method does not restrict waiting to a timeout, so that it could
- * potentially block forever! This method can be invoked in any node or
- * network state.
+ * potentially block forever!
*
* @param source
* The source of the event that the invoking thread is willing to
* wait for. May not be <code>null</code> and must be the name
* of a previously created node, client, or server.
- * @param event
- * The event that the invoking thread is willing to wait for from
- * the given <code>source</code>. May not be <code>null</code>.
+ * @param eventType
+ * The event type that the invoking thread is willing to wait for
+ * from the given <code>source</code>. May not be
+ * <code>null</code>.
* @throws IllegalArgumentException
* Thrown if <code>null</code> is passed for either of the
- * parameters or if <code>source</code> is unknown.
+ * parameters or if the <code>source</code> is unknown.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract void waitForNextOccurence(String source, EventType event)
+ public abstract void waitForNextOccurence(String source, EventType eventType)
throws RemoteException;
/**
* Blocks the invoking thread until the next <code>event</code> is fired
* from the given <code>source</code> or the given timeout of
- * <code>maximumTimeToWaitInMillis</code> millis has expired. This method
+ * <code>maximumTimeToWaitInMillis</code> milliseconds has expired. This method
* only waits for the next occurence of an event, regardless of previous
- * occurrences. This method can be invoked in any node or network state.
+ * occurrences.
*
* @param source
* The source of the event that the invoking thread is willing to
* wait for. May not be <code>null</code> and must be the name
* of a previously created node, client, or server.
- * @param event
- * The event that the invoking thread is willing to wait for from
- * the given <code>source</code>. May not be <code>null</code>.
+ * @param eventType
+ * The event type that the invoking thread is willing to wait for
+ * from the given <code>source</code>. May not be
+ * <code>null</code>.
* @param maximumTimeToWaitInMillis
* The maximum time to wait in milliseconds. A positive value or
* zero restricts waiting to this time. If this value is
* negative, we will wait potentially forever.
* @return <code>true</code> if an event of the given type has been fired
- * by the source within the given timeout, <code>false</code>
- * otherwise.
+ * by the <code>source</code> within the given timeout,
+ * <code>false</code> otherwise.
* @throws IllegalArgumentException
* Thrown if an invalid value is passed for either of the
- * parameters or if <code>source</code> is unknown.
+ * parameters or if the <code>source</code> is unknown.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
public abstract boolean waitForNextOccurence(String source,
- EventType event, long maximumTimeToWaitInMillis)
+ EventType eventType, long maximumTimeToWaitInMillis)
throws RemoteException;
/**
* Registers a new event type by passing a pattern string that can be
* applied to a regular expression when parsing Tor log statements. This is
* useful for log statements that are only included in modified Tor
- * versions.
+ * versions. Therefore, the event type may be an instance of a self-defined
+ * class that implements <code>EventType</code>.
*
* @param patternString
* The pattern string that will be used for parsing Tor log
* statements; the syntax corresponds to java.util.regex.Pattern.
* @param eventType
- * The event type that will be fired when a log statement was
- * parsed that includes the given pattern.
+ * The event type of the event that will be fired when a log
+ * statement was parsed that includes the given pattern.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/EventType.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/EventType.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/EventType.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -40,4 +40,11 @@
*/
public interface EventType {
+ /**
+ * Returns a string representation of the event type name for display
+ * purposes.
+ *
+ * @return String representation of the event type name.
+ */
+ public abstract String getTypeName();
}
Added: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/HiddenService.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/HiddenService.java (rev 0)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/HiddenService.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -0,0 +1,56 @@
+package de.uniba.wiai.lspi.puppetor;
+
+/**
+ * A <code>HiddenService</code> instance contains all configurations of a
+ * hidden service that is registered at a node.
+ *
+ * @author kloesing
+ */
+public interface HiddenService {
+
+ /**
+ * Determines the onion address for a previously added hidden service with
+ * name <code>serviceName</code>. Requires that the node has been
+ * started, i.e. is in state <code>NodeState.RUNNING</code>, and is
+ * configured to provide this hidden service.
+ *
+ * @return The onion address string consisting of 16 base32 chars plus
+ * ".onion" for hidden service versions 0 and 1 or 16 base32 chars
+ * plus "." plus 24 base32 chars plus ".onion" for hidden service
+ * version 2.
+ * @throws IllegalArgumentException
+ * Thrown if <code>null</code> or a zero-length string is
+ * passed as parameter.
+ * @throws IllegalStateException
+ * Thrown if the node at which this hidden service is configured
+ * is not in state <code>NodeState.RUNNING</code>.
+ * @throws PuppeTorException
+ * Thrown if the onion address of this hidden service could not
+ * be read, which is also the case when the node's configuration
+ * has not been written and the node has not been HUP'ed after
+ * configuring the hidden service.
+ */
+ public abstract String determineOnionAddress() throws PuppeTorException;
+
+ /**
+ * Returns the name of the hidden service.
+ *
+ * @return The name of the hidden service.
+ */
+ public String getServiceName();
+
+ /**
+ * Returns the port on which the service listens for requests.
+ *
+ * @return The port on which the service listens for requests.
+ */
+ public int getServicePort();
+
+ /**
+ * Returns the virtual port that this hidden service runs on as it is
+ * announced to clients.
+ *
+ * @return The virtual port of this hidden service.
+ */
+ public int getVirtualPort();
+}
Copied: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/HiddenServiceEventType.java (from rev 11669, puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/AliceEventType.java)
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/HiddenServiceEventType.java (rev 0)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/HiddenServiceEventType.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2007, Karsten Loesing
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the names of the copyright owners nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package de.uniba.wiai.lspi.puppetor;
+
+/**
+ * Event types that can be fired by all Tor processes performing hidden-service
+ * operations.
+ */
+public class HiddenServiceEventType implements EventType {
+
+ /**
+ * String identifying the type of the event type.
+ */
+ String typeString;
+
+ /**
+ * Creates a new event type with the given type string.
+ *
+ * @param typeString
+ * String identifying the type of the event type.
+ */
+ public HiddenServiceEventType(String typeString) {
+ this.typeString = typeString;
+ }
+
+ public String getTypeName() {
+ return this.typeString;
+ }
+
+ /**
+ * Alice has received an onion request; this event is parsed from a log
+ * statement in connection_ap_handshake_rewrite_and_attach().
+ */
+ public static final HiddenServiceEventType ALICE_ONION_REQUEST_RECEIVED = new HiddenServiceEventType(
+ "ALICE_ONION_REQUEST_RECEIVED");
+
+ /**
+ * Alice sends a fetch request for a hidden service descriptor to a
+ * directory server; this event is parsed from a log statement in
+ * rend_client_refetch_renddesc().
+ */
+ public static final HiddenServiceEventType ALICE_SENDING_FETCH_DESC = new HiddenServiceEventType(
+ "ALICE_SENDING_FETCH_DESC");
+
+ /**
+ * Alice receives a reply to a previous fetch request for a hidden service
+ * descriptors from a directory server; this event is parsed from a log
+ * statement in connection_dir_client_reached_eof().
+ */
+ public static final HiddenServiceEventType ALICE_DESC_FETCHED_RECEIVED = new HiddenServiceEventType(
+ "ALICE_DESC_FETCHED_RECEIVED");
+
+ /**
+ * Alice has built a circuit to a rendezvous point and sends an
+ * ESTABLISH_RENDEZVOUS cell; this event is parsed from a log statement in
+ * rend_client_send_establish_rendezvous().
+ */
+ public static final HiddenServiceEventType ALICE_BUILT_REND_CIRC_SENDING_ESTABLISH_RENDEZVOUS = new HiddenServiceEventType(
+ "ALICE_BUILT_REND_CIRC_SENDING_ESTABLISH_RENDEZVOUS");
+
+ /**
+ * Alice receives a RENDEZVOUS_ESTABLISHED cell from a rendezvous point;
+ * this event is parsed from a log statement in
+ * rend_client_rendezvous_acked().
+ */
+ public static final HiddenServiceEventType ALICE_RENDEZVOUS_ESTABLISHED_RECEIVED = new HiddenServiceEventType(
+ "ALICE_RENDEZVOUS_ESTABLISHED_RECEIVED");
+
+ /**
+ * Alice has built a circuit to an introduction point (which does not
+ * automatically lead to sending an INTRODUCE1 cell, because the rendezvous
+ * circuit might not be ready); this event is parsed from a log statement in
+ * rend_client_introcirc_has_opened().
+ */
+ public static final HiddenServiceEventType ALICE_BUILT_INTRO_CIRC = new HiddenServiceEventType(
+ "ALICE_BUILT_INTRO_CIRC");
+
+ /**
+ * Alice sends an INTRODUCE1 cell to an introduction point; this event is
+ * parsed from a log statement in rend_client_send_introduction().
+ */
+ public static final HiddenServiceEventType ALICE_SENDING_INTRODUCE1 = new HiddenServiceEventType(
+ "ALICE_SENDING_INTRODUCE1");
+
+ /**
+ * Alice has received an INTRODUCE_ACK cell as an acknowledgement to a
+ * previously sent INTRODUCE1 cell; this event is parsed from a log
+ * statement in rend_client_introduction_acked().
+ */
+ public static final HiddenServiceEventType ALICE_INTRODUCE_ACK_RECEIVED = new HiddenServiceEventType(
+ "ALICE_INTRODUCE_ACK_RECEIVED");
+
+ /**
+ * Alice has received a RENDEZVOUS2 cell and can now open an application
+ * connection to the client; this event is parsed from a log statement in
+ * rend_client_receive_rendezvous().
+ */
+ public static final HiddenServiceEventType ALICE_RENDEZVOUS2_RECEIVED_APP_CONN_OPENED = new HiddenServiceEventType(
+ "ALICE_RENDEZVOUS2_RECEIVED_APP_CONN_OPENED");
+
+ /**
+ * Bob has built a circuit to an introduction point and sends an
+ * ESTABLISH_INTRO cell; this event is parsed from a log statement in
+ * rend_service_intro_has_opened().
+ */
+ public static final HiddenServiceEventType BOB_BUILT_INTRO_CIRC_SENDING_ESTABLISH_INTRO = new HiddenServiceEventType(
+ "BOB_BUILT_INTRO_CIRC_SENDING_ESTABLISH_INTRO");
+
+ /**
+ * Bob has received an INTRO_ESTABLISHED cell, i.e. a node has confirmed to
+ * work as introduction point; this event is parsed from a log statement in
+ * rend_service_intro_established().
+ */
+ public static final HiddenServiceEventType BOB_INTRO_ESTABLISHED_RECEIVED = new HiddenServiceEventType(
+ "BOB_INTRO_ESTABLISHED_RECEIVED");
+
+ /**
+ * Bob posts a hidden service descriptor to the directory servers; this
+ * event is parsed from a log statement in upload_service_descriptor().
+ */
+ public static final HiddenServiceEventType BOB_SENDING_PUBLISH_DESC = new HiddenServiceEventType(
+ "BOB_SENDING_PUBLISH_DESC");
+
+ /**
+ * Bob received a response from a directory server to a previous publish
+ * request; this event is parsed from a log statement in
+ * connection_dir_client_reached_eof().
+ */
+ public static final HiddenServiceEventType BOB_DESC_PUBLISHED_RECEIVED = new HiddenServiceEventType(
+ "BOB_DESC_PUBLISHED_RECEIVED");
+
+ /**
+ * Bob has received an INTRODUCE2 cell, i.e. a node wants to establish a
+ * connection, and will now try to establish a circuit to the client's
+ * rendezvous point; this event is parsed from a log statement in
+ * rend_service_introduce().
+ */
+ public static final HiddenServiceEventType BOB_INTRODUCE2_RECEIVED = new HiddenServiceEventType(
+ "BOB_INTRODUCE2_RECEIVED");
+
+ /**
+ * Bob has built a circuit to a rendezvous point and sends a RENDEZVOUS1
+ * cell; this event is parsed from a log statement in
+ * rend_service_rendezvous_has_opened().
+ */
+ public static final HiddenServiceEventType BOB_BUILT_REND_CIRC_SENDING_RENDEZVOUS1 = new HiddenServiceEventType(
+ "BOB_BUILT_REND_CIRC_SENDING_RENDEZVOUS1");
+
+ /**
+ * Bob opens a connection to the actual hidden server; this event is parsed
+ * from a log statement in connection_exit_begin_conn().
+ */
+ public static final HiddenServiceEventType BOB_APP_CONN_OPENED = new HiddenServiceEventType(
+ "BOB_APP_CONN_OPENED");
+
+ /**
+ * The directory server has received a descriptor post request; this event
+ * is parsed from a log statement in directory_handle_command_post().
+ */
+ public static final HiddenServiceEventType DIR_PUBLISH_DESC_RECEIVED = new HiddenServiceEventType(
+ "DIR_PUBLISH_DESC_RECEIVED");
+
+ /**
+ * The directory server has received a descriptor fetch request; this event
+ * is parsed from a log statement in directory_handle_command_get().
+ */
+ public static final HiddenServiceEventType DIR_FETCH_DESC_RECEIVED = new HiddenServiceEventType(
+ "DIR_FETCH_DESC_RECEIVED");
+
+ /**
+ * The node received an ESTABLISH_INTRO cell, i.e. was requested to work as
+ * introduction point, and replies with an INTRO_ESTABLISHED cell; this
+ * event is parsed from a log statement in rend_mid_establish_intro().
+ */
+ public static final HiddenServiceEventType IPO_RECEIVED_ESTABLISH_INTRO_SENDING_INTRO_ESTABLISHED = new HiddenServiceEventType(
+ "IPO_RECEIVED_ESTABLISH_INTRO_SENDING_INTRO_ESTABLISHED");
+
+ /**
+ * The introduction point received an INTRODUCE1 cell and reacts by sending
+ * an INTRODUCE2 cell to Bob and an INTRODUCE_ACK cell to Alice; this event
+ * is parsed from a log statement in rend_mid_introduce().
+ */
+ public static final HiddenServiceEventType IPO_RECEIVED_INTRODUCE1_SENDING_INTRODUCE2_AND_INTRODUCE_ACK = new HiddenServiceEventType(
+ "IPO_RECEIVED_INTRODUCE1_SENDING_INTRODUCE2_AND_INTRODUCE_ACK");
+
+ /**
+ * The node received an ESTABLISH_RENDEZVOUS cell, i.e. was requested to
+ * work as rendezvous point, and replies with a RENDEZVOUS_ESTABLISHED cell;
+ * this event is parsed from a log statement in
+ * rend_mid_establish_rendezvous().
+ */
+ public static final HiddenServiceEventType RPO_RECEIVED_ESTABLISH_RENDEZVOUS_SENDING_RENDEZVOUS_ESTABLISHED = new HiddenServiceEventType(
+ "RPO_RECEIVED_ESTABLISH_RENDEZVOUS_SENDING_RENDEZVOUS_ESTABLISHED");
+
+ /**
+ * The rendezvous point received a RENDEZVOUS1 cell and reacts by sending a
+ * RENDEZVOUS2 cell to Alice; this event is parsed from a log statement in
+ * rend_mid_rendezvous().
+ */
+ public static final HiddenServiceEventType RPO_RECEIVING_RENDEZVOUS1_SENDING_RENDEZVOUS2 = new HiddenServiceEventType(
+ "RPO_RECEIVING_RENDEZVOUS1_SENDING_RENDEZVOUS2");
+
+}
\ No newline at end of file
Deleted: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/MiscEventType.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/MiscEventType.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/MiscEventType.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2007, Karsten Loesing
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * Neither the names of the copyright owners nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package de.uniba.wiai.lspi.puppetor;
-
-public class MiscEventType implements EventType {
-
- /**
- * The hidden service directory has stored a v2 descriptor; this event can
- * only be parsed from a log statement in a modified Tor!
- */
- public static final MiscEventType HSDIR_DESC_STORED = new MiscEventType();
-
- /**
- * The directory server has received a descriptor post request; this event
- * is parsed from a log statement in directory_handle_command_post().
- */
- public static final MiscEventType DIR_PUBLISH_DESC_RECEIVED = new MiscEventType();
-
- /**
- * The directory server has received a descriptor fetch request; this event
- * is parsed from a log statement in directory_handle_command_get().
- */
- public static final MiscEventType DIR_FETCH_DESC_RECEIVED = new MiscEventType();
-
- /**
- * The node received an ESTABLISH_INTRO cell, i.e. was requested to work as
- * introduction point, and replies with an INTRO_ESTABLISHED cell; this
- * event is parsed from a log statement in rend_mid_establish_intro().
- */
- public static final MiscEventType IPO_RECEIVED_ESTABLISH_INTRO_SENDING_INTRO_ESTABLISHED = new MiscEventType();
-
- /**
- * The introduction point received an INTRODUCE1 cell and reacts by sending
- * an INTRODUCE2 cell to Bob and an INTRODUCE_ACK cell to Alice; this event
- * is parsed from a log statement in rend_mid_introduce().
- */
- public static final MiscEventType IPO_RECEIVED_INTRODUCE1_SENDING_INTRODUCE2_AND_INTRODUCE_ACK = new MiscEventType();
-
- /**
- * The node received an ESTABLISH_RENDEZVOUS cell, i.e. was requested to
- * work as rendezvous point, and replies with an RENDEZVOUS_ESTABLISHED
- * cell; this event is parsed from a log statement in
- * rend_mid_establish_rendezvous().
- */
- public static final MiscEventType RPO_RECEIVED_ESTABLISH_RENDEZVOUS_SENDING_RENDEZVOUS_ESTABLISHED = new MiscEventType();
-
- /**
- * The rendezvous point received a RENDEZVOUS1 cell and reacts by sending a
- * RENDEZVOUS2 cell to Alice; this event is parsed from a log statement in
- * rend_mid_rendezvous().
- */
- public static final MiscEventType RPO_RECEIVING_RENDEZVOUS1_SENDING_RENDEZVOUS2 = new MiscEventType();
-}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Network.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Network.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Network.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -32,13 +32,9 @@
package de.uniba.wiai.lspi.puppetor;
import java.io.File;
-import java.net.MalformedURLException;
-import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
-import java.util.List;
import java.util.Map;
-import java.util.Set;
/**
* A Network instance constitutes the central object of any test run and is
@@ -53,76 +49,119 @@
/**
* <p>
- * Configures the nodes in this network so that they can run in a private
- * network and don't require public directory servers or onion routers from
- * the Internet. This configuration should be done after configuring the
- * nodes and before writing configurations to disk. This operation can only
- * be invoked, if network status is
- * <code>NetworkState.CONFIGURING_NODES</code>.
+ * Configures this network as private Tor network by exchanging directory
+ * strings and router fingerprints between the nodes of this network.
+ * Afterwards, the nodes will be able to run a private Tor network,
+ * separated from public directory servers and onion routers.
* </p>
*
* <p>
- * The main requirement for this method lies in the fact that all nodes need
- * to be configured so that they accept our own directory nodes instead of
- * the pre-configured directory nodes from the public Tor network. This
- * configuration requires the fingerprints of all directory nodes. These
- * fingerprints are written to disk by the directory nodes as soon as they
- * are started. But the directories need to be configured before being
- * started, too, in order to prevent them from becoming part of the public
- * Tor network. And now we have the chicken or the egg dilemma.
+ * The configuration is done in two steps:
+ * <ol>
+ * <li>Directory strings of directory nodes are added to the configurations
+ * of all nodes in the other network.</li>
+ * <li>Router fingerprints of all router and directory nodes are added to
+ * the <code>approved-routers</code> files of the directory nodes.</li>
+ * </ol>
* </p>
*
* <p>
- * The non-trivial solution is to configure the directory nodes with a fake
- * directory configuration and start them using the
- * <code>--list-fingerprint</code> option. Hence they write a
- * <code>fingerprint</code> file to disk and shut down immediately. This
- * fingerprint can be read, and all nodes can be configured to use the
- * directory using this fingerprint.
+ * This operation may be invoked in any state of the contained nodes.
+ * However, a network that does not have directory nodes of its own but
+ * relies on directory nodes of a merged network <b>should not be started
+ * before being configured as private network!</b> Otherwise it would
+ * connect to the public Tor network before being merged with the other
+ * private Tor network. However, it may also be invoked at a later time,
+ * e.g. to admit new nodes.
* </p>
*
* <p>
- * A second, non-trivial task is to authorize routers and directory nodes.
- * Therefore, an authoritative directory needs to know all fingerprints of
- * authorized nodes. They are stored in the <code>approved-routers</code>
- * file in the working directory of the directory node.
+ * This operation does not write any configurations to disk and neither
+ * starts a nodes nor sends HUP signals to running nodes. These operations
+ * are left to the application, so that they have more control over the
+ * network behavior.
* </p>
*
* <p>
- * The complete task is encapsulated in this method for convenience.
- * However, all operations could also be performed directly on the nodes, if
- * required.
+ * Applications need to ensure that there are enough directory nodes (2) and
+ * router nodes (3) in the network to allow normal operation.
* </p>
*
- * TODO check if we have enough directory and router nodes to build a
- * private network? How many are required? 2 dirs and 3 routers?
+ * @throws PuppeTorException
+ * Thrown if an I/O problem occurs while determining the nodes'
+ * fingerprints.
+ * @throws RemoteException
+ * Thrown if an error occurs when accessed remotely.
+ */
+ public abstract void configureAsPrivateNetwork() throws PuppeTorException,
+ RemoteException;
+
+ /**
+ * <p>
+ * Merges this network with another private Tor network by exchanging
+ * directory strings and router fingerprints. Afterwards, the nodes in both
+ * networks will consider the two networks a single, larger private Tor
+ * network.
+ * </p>
*
- * @throws IllegalStateException
- * Thrown if network is not in state
- * <code>NetworkState.CONFIGURING_NODES</code>.
- * @throws TorProcessException
- * Thrown if an I/O problem occurs while starting nodes with the
- * <code>--list-fingerprint</code> option, reading files from
- * the nodes' working directories, or writing the
- * <code>approved-routers</code> files.
+ * <p>
+ * The configuration is done in two steps:
+ * <ol>
+ * <li>Directory strings of all directory nodes in this network are added
+ * to the configurations of all nodes in the other network and vice versa.</li>
+ * <li>Router fingerprints of all router and directory nodes in this
+ * network are added to the <code>approved-routers</code> files of all
+ * directory nodes in the other network and vice versa.</li>
+ * </ol>
+ * </p>
+ *
+ * <p>
+ * This operation may be invoked in any state of the contained nodes.
+ * However, a network that does not have directory nodes of its own but
+ * relies on directory nodes of a merged network <b>should not be started
+ * before merging!</b> Otherwise it would connect to the public Tor network
+ * before being merged with the other private Tor network. However, it may
+ * also be invoked at a later time, e.g. to admit new nodes.
+ * </p>
+ *
+ * <p>
+ * This operation does not write any configurations to disk and neither
+ * starts a nodes nor sends HUP signals to running nodes. These operations
+ * are left to the application, so that they have more control over the
+ * network behavior.
+ * </p>
+ *
+ * <p>
+ * Note that this operation is only effective if there are directory nodes
+ * in either of the two networks. Otherwise, no information will be
+ * exchanged between the two networks. Applications need to ensure that
+ * there are in total enough directory nodes (2) and router nodes (3) in
+ * both networks to allow normal operation.
+ * </p>
+ *
+ * @param remoteNetwork
+ * The remote network to merge this network with.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
+ * @throws PuppeTorException
+ * Thrown if an I/O problem occurs while reading directory
+ * strings or router fingerprints, while writing the new
*/
- public abstract void configureAsPrivateNetwork()
- throws TorProcessException, RemoteException;
+ public abstract void configureAsInterconnectedPrivateNetwork(
+ Network remoteNetwork) throws RemoteException, PuppeTorException;
/**
* Creates a new client application, but does not yet perform a request.
*
* @param clientApplicationName
* The name for this client application, which is used for
- * logging purposes only. May neither be <code>null</code> or a
- * zero-length string. The name needs to be unique in this
- * network.
+ * logging purposes and as event source. May neither be
+ * <code>null</code> or a zero-length string. The name needs to
+ * be unique in this network.
* @param targetAddress
* The target for requests sent by this client application. Can
- * be an IP address, a domain name, or an onion address. May
- * neither be <code>null</code> or a zero-length string.
+ * be a publicly available URL or an onion address. May neither
+ * be <code>null</code> or a zero-length string.
* @param targetPort
* The TCP port for requests sent by this client application. If
* the target address is an onion address, this port is the
@@ -146,19 +185,15 @@
/**
* Creates a new directory node with automatically assigned ports and adds
* it to the network, but does not yet write its configuration to disk or
- * start the corresponding Tor process. This operation can only be invoked,
- * if network status is <code>NetworkState.CONFIGURING_NODES</code>.
+ * start the corresponding Tor process.
*
* @param nodeName
* The name for this node, which is used as name for the working
- * directory, for logging purposes, and as node nickname. May
- * neither be <code>null</code> or have zero or more than 19
- * alpha-numeric characters. The node name needs to be unique in
- * this network.
+ * directory, for logging purposes, as node nickname, and as
+ * event source. May neither be <code>null</code> or have zero
+ * or more than 19 alpha-numeric characters. The node name needs
+ * to be unique in this network.
* @return Reference to the created directory node.
- * @throws IllegalStateException
- * Thrown if network is not in state
- * <code>NetworkState.CONFIGURING_NODES</code>.
* @throws IllegalArgumentException
* Thrown if an invalid value is given as node name.
* @throws RemoteException
@@ -171,23 +206,19 @@
* Creates a new directory node with automatically assigned ports that will
* listen on the given IP address and adds it to the network, but does not
* yet write its configuration to disk or start the corresponding Tor
- * process. This operation can only be invoked, if network status is
- * <code>NetworkState.CONFIGURING_NODES</code>.
+ * process.
*
* @param nodeName
* The name for this node, which is used as name for the working
- * directory, for logging purposes, and as node nickname. May
- * neither be <code>null</code> or have zero or more than 19
- * alpha-numeric characters. The node name needs to be unique in
- * this network.
+ * directory, for logging purposes, as node nickname, and as
+ * event source. May neither be <code>null</code> or have zero
+ * or more than 19 alpha-numeric characters. The node name needs
+ * to be unique in this network.
* @param serverIpAddress
* The IP address on which the node will listen. Must be a valid
* IP v4 address in dotted decimal notation. May not be
* <code>null</code>.
* @return Reference to the created directory node.
- * @throws IllegalStateException
- * Thrown if network is not in state
- * <code>NetworkState.CONFIGURING_NODES</code>.
* @throws IllegalArgumentException
* Thrown if an invalid value is given as node name.
* @throws RemoteException
@@ -199,15 +230,13 @@
/**
* Creates a new directory node and adds it to the network, but does not yet
* write its configuration to disk or start the corresponding Tor process.
- * This operation can only be invoked, if network status is
- * <code>NetworkState.CONFIGURING_NODES</code>.
*
* @param nodeName
* The name for this node, which is used as name for the working
- * directory, for logging purposes, and as node nickname. May
- * neither be <code>null</code> or have zero or more than 19
- * alpha-numeric characters. The node name needs to be unique in
- * this network.
+ * directory, for logging purposes, as node nickname, and as
+ * event source. May neither be <code>null</code> or have zero
+ * or more than 19 alpha-numeric characters. The node name needs
+ * to be unique in this network.
* @param controlPort
* The TCP port on which the corresponding Tor process will wait
* for a controller. May not be negative or greater than 65535.
@@ -224,9 +253,6 @@
* for incoming directory requests. May not be negative or
* greater than 65535.
* @return Reference to the created directory node.
- * @throws IllegalStateException
- * Thrown if network is not in state
- * <code>NetworkState.CONFIGURING_NODES</code>.
* @throws IllegalArgumentException
* Thrown if an invalid value is given for either of the
* parameters.
@@ -240,15 +266,14 @@
/**
* Creates a new directory node that will listen on the given IP address and
* adds it to the network, but does not yet write its configuration to disk
- * or start the corresponding Tor process. This operation can only be
- * invoked, if network status is <code>NetworkState.CONFIGURING_NODES</code>.
+ * or start the corresponding Tor process.
*
* @param nodeName
* The name for this node, which is used as name for the working
- * directory, for logging purposes, and as node nickname. May
- * neither be <code>null</code> or have zero or more than 19
- * alpha-numeric characters. The node name needs to be unique in
- * this network.
+ * directory, for logging purposes, as node nickname, and as
+ * event source. May neither be <code>null</code> or have zero
+ * or more than 19 alpha-numeric characters. The node name needs
+ * to be unique in this network.
* @param controlPort
* The TCP port on which the corresponding Tor process will wait
* for a controller. May not be negative or greater than 65535.
@@ -269,9 +294,6 @@
* IP v4 address in dotted decimal notation. May not be
* <code>null</code>.
* @return Reference to the created directory node.
- * @throws IllegalStateException
- * Thrown if network is not in state
- * <code>NetworkState.CONFIGURING_NODES</code>.
* @throws IllegalArgumentException
* Thrown if an invalid value is given for either of the
* parameters.
@@ -288,10 +310,11 @@
* disk or start the corresponding Tor process.
*
* @param nodeName
- * The name for this node, which is only used as name for the
- * working directory and for logging purposes. May neither be
- * <code>null</code> or have zero or more than 19 alpha-numeric
- * characters. The node name needs to be unique in this network.
+ * The name for this node, which is used as name for the working
+ * directory, for logging purposes, and as event source. May
+ * neither be <code>null</code> or have zero or more than 19
+ * alpha-numeric characters. The node name needs to be unique in
+ * this network.
* @return Reference to the created proxy node.
* @throws IllegalArgumentException
* Thrown if an invalid value is given as node name.
@@ -307,10 +330,11 @@
* Tor process.
*
* @param nodeName
- * The name for this node, which is only used as name for the
- * working directory and for logging purposes. May neither be
- * <code>null</code> or have zero or more than 19 alpha-numeric
- * characters. The node name needs to be unique in this network.
+ * The name for this node, which is used as name for the working
+ * directory, for logging purposes, and as event source. May
+ * neither be <code>null</code> or have zero or more than 19
+ * alpha-numeric characters. The node name needs to be unique in
+ * this network.
* @param controlPort
* The TCP port on which the corresponding Tor process will wait
* for a controller. May not be negative or greater than 65535.
@@ -335,10 +359,10 @@
*
* @param nodeName
* The name for this node, which is used as name for the working
- * directory, for logging purposes, and as node nickname. May
- * neither be <code>null</code> or have zero or more than 19
- * alpha-numeric characters. The node name needs to be unique in
- * this network.
+ * directory, for logging purposes, as node nickname, and as
+ * event source. May neither be <code>null</code> or have zero
+ * or more than 19 alpha-numeric characters. The node name needs
+ * to be unique in this network.
* @return Reference to the created router node.
* @throws IllegalArgumentException
* Thrown if an invalid value is given as node name.
@@ -355,10 +379,10 @@
*
* @param nodeName
* The name for this node, which is used as name for the working
- * directory, for logging purposes, and as node nickname. May
- * neither be <code>null</code> or have zero or more than 19
- * alpha-numeric characters. The node name needs to be unique in
- * this network.
+ * directory, for logging purposes, as node nickname, and as
+ * event source. May neither be <code>null</code> or have zero
+ * or more than 19 alpha-numeric characters. The node name needs
+ * to be unique in this network.
* @param controlPort
* The TCP port on which the corresponding Tor process will wait
* for a controller. May not be negative or greater than 65535.
@@ -393,10 +417,10 @@
*
* @param nodeName
* The name for this node, which is used as name for the working
- * directory, for logging purposes, and as node nickname. May
- * neither be <code>null</code> or have zero or more than 19
- * alpha-numeric characters. The node name needs to be unique in
- * this network.
+ * directory, for logging purposes, as node nickname, and as
+ * event source. May neither be <code>null</code> or have zero
+ * or more than 19 alpha-numeric characters. The node name needs
+ * to be unique in this network.
* @param serverIpAddress
* The IP address on which the node will listen. Must be a valid
* IP v4 address in dotted decimal notation. May not be
@@ -417,10 +441,10 @@
*
* @param nodeName
* The name for this node, which is used as name for the working
- * directory, for logging purposes, and as node nickname. May
- * neither be <code>null</code> or have zero or more than 19
- * alpha-numeric characters. The node name needs to be unique in
- * this network.
+ * directory, for logging purposes, as node nickname, and as
+ * event source. May neither be <code>null</code> or have zero
+ * or more than 19 alpha-numeric characters. The node name needs
+ * to be unique in this network.
* @param controlPort
* The TCP port on which the corresponding Tor process will wait
* for a controller. May not be negative or greater than 65535.
@@ -458,9 +482,9 @@
*
* @param serverApplicationName
* The name for this server application, which is used for
- * logging purposes only. May neither be <code>null</code> or a
- * zero-length string. The name needs to be unique in this
- * network.
+ * logging purposes and as event source. May neither be
+ * <code>null</code> or a zero-length string. The name needs to
+ * be unique in this network.
* @return Reference to the created server application.
* @throws IllegalArgumentException
* Thrown if an invalid value is given as server application
@@ -477,9 +501,9 @@
*
* @param serverApplicationName
* The name for this server application, which is used for
- * logging purposes only. May neither be <code>null</code> or a
- * zero-length string. The name needs to be unique in this
- * network.
+ * logging purposes and as event source. May neither be
+ * <code>null</code> or a zero-length string. The name needs to
+ * be unique in this network.
* @param serverPort
* The TCP port on which the server will wait for incoming
* requests. May not be negative or greater than 65535.
@@ -504,15 +528,6 @@
public abstract EventManager getEventManager() throws RemoteException;
/**
- * Returns the current network state.
- *
- * @return Current network state.
- * @throws RemoteException
- * Thrown if an error occurs when accessed remotely.
- */
- public abstract NetworkState getNetworkState() throws RemoteException;
-
- /**
* Returns (a copy of) the map containing the names of all directory nodes
* as keys and the corresponding directory nodes as values.
*
@@ -528,65 +543,46 @@
* (only those that are not acting as directory nodes at the same time) as
* keys and the corresponding router nodes as values.
*
- * TODO is this important: returns the stubs for remote access.
- *
* @return Map containing all router nodes.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public Map<String, RouterNode> getAllRouterNodes() throws RemoteException;
+ public abstract Map<String, RouterNode> getAllRouterNodes()
+ throws RemoteException;
/**
* Returns (a copy of) the map containing the names of all proxy nodes (only
* those that are not acting as router or directory nodes at the same time)
* as keys and the corresponding proxy nodes as values.
*
- * TODO is this important: returns the stubs for remote access.
- *
* @return Map containing all proxy nodes.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public Map<String, ProxyNode> getAllProxyNodes() throws RemoteException;
-
- /**
- * Returns the <code>ProxyNode</code> with name <code>nodeName</code> or
- * <code>null</code> if no such node exists.
- *
- * @param nodeName
- * The node name to look up.
- * @return The <code>ProxyNode</code> with name <code>nodeName</code>.
- * @throws RemoteException
- * Thrown if an error occurs when accessed remotely.
- */
- public abstract ProxyNode getProxyNode(String nodeName)
+ public abstract Map<String, ProxyNode> getAllProxyNodes()
throws RemoteException;
/**
- * Returns the <code>RouterNode</code> with name <code>nodeName</code>
- * or <code>null</code> if no such node exists.
+ * Returns (a copy of) the map containing the names of all nodes as keys and
+ * the corresponding proxy nodes as values.
*
- * @param nodeName
- * The node name to look up.
- * @return The <code>RouterNode</code> with name <code>nodeName</code>.
+ * @return Map containing all nodes.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract RouterNode getRouterNode(String nodeName)
- throws RemoteException;
+ public abstract Map<String, ProxyNode> getAllNodes() throws RemoteException;
/**
- * Returns the <code>DirectoryNode</code> with name <code>nodeName</code>
- * or <code>null</code> if no such node exists.
+ * Returns the node with name <code>nodeName</code> or <code>null</code>
+ * if no such node exists.
*
* @param nodeName
* The node name to look up.
- * @return The <code>DirectoryNode</code> with name <code>nodeName</code>.
+ * @return The node with name <code>nodeName</code>.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract DirectoryNode getDirectoryNode(String nodeName)
- throws RemoteException;
+ public abstract ProxyNode getNode(String nodeName) throws RemoteException;
/**
* <p>
@@ -596,37 +592,37 @@
* </p>
*
* <p>
- * First, the method waits for <code>hupInterval</code> millis for the
- * nodes to have successfully opened a circuit. If they do not succeed
+ * First, the method waits for <code>hupInterval</code> milliseconds for
+ * the nodes to have successfully opened a circuit. If they do not succeed
* within this time, a HUP signal is sent to all nodes and the method waits
- * for another <code>hupInterval</code> millis. In total, the method sends
- * at most <code>tries</code> HUP signals before giving up and returning
- * with <code>false</code>. Thus, the maximum waiting time is
+ * for another <code>hupInterval</code> milliseconds. In total, the method
+ * sends at most <code>tries</code> HUP signals before giving up and
+ * returning with <code>false</code>. Thus, the maximum waiting time is
* <code>(tries + 1)</code> times <code>hupInterval</code>. As soon as
* all nodes have successfully opened circuits, the method returns with
- * <code>true</code>. This operation can only be invoked, if network
- * status is <code>NetworkState.NODES_STARTED</code>.
+ * <code>true</code>. This operation can only be invoked, if all nodes in
+ * the network are in state <code>NodeState.RUNNING</code>.
* </p>
*
* @param tries
* The maximum number of HUP signals that are sent to the Tor
* processes. Negative values are not allowed. A value of zero
* means to wait only for the given time of
- * <code>hupInterval</code> millis without sending a HUP
+ * <code>hupInterval</code> milliseconds without sending a HUP
* signal. Typical values depend on the network being a public or
* private Tor network and range about 3 to 5 tries.
* @param hupInterval
- * The time in millis that the method will wait between sending
- * HUP signals. Negative values are not allowed. Typically,
- * values should not be smaller than 10 seconds to permit Tor to
- * stabilize.
+ * The time in milliseconds that the method will wait between
+ * sending HUP signals. Negative values are not allowed.
+ * Typically, values should not be smaller than 5 seconds to
+ * permit Tor to stabilize.
* @throws IllegalStateException
- * Thrown if network is not in state
- * <code>NetworkState.NODES_STARTED</code>.
+ * Thrown if at least one node is not in state
+ * <code>NodeState.RUNNING</code>.
* @throws IllegalArgumentException
* Thrown if a negative value is given for either
* <code>tries</code> or <code>hupInterval</code>.
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if an I/O problem occurs while sending HUP signals.
* @return <code>true</code> if all nodes have reported to have
* successfully opened a circuit, <code>false</code> otherwise.
@@ -634,35 +630,48 @@
* Thrown if an error occurs when accessed remotely.
*/
public abstract boolean hupUntilUp(int tries, long hupInterval)
- throws TorProcessException, RemoteException;
+ throws PuppeTorException, RemoteException;
/**
+ * Sends a HUP signal to all nodes in the network once. This operation can
+ * only be invoked, if all nodes in the network are in state
+ * <code>NodeState.RUNNING</code>.
+ *
+ * @throws IllegalStateException
+ * Thrown if at least one node is not in state
+ * <code>NodeState.RUNNING</code>.
+ * @throws PuppeTorException
+ * Thrown if an I/O problem occurs while sending HUP signals.
+ * @throws RemoteException
+ * Thrown if an error occurs when accessed remotely.
+ */
+ public abstract void hupAllNodes() throws PuppeTorException,
+ RemoteException;
+
+ /**
* Attempts to shut down all running nodes. The method blocks until all
* shutdown requests have been sent and either returns, or throws the first
* exception that has been observed when shutting down nodes. The method can
- * be assumed to return very quickly. This operation can only be invoked, if
- * network status is <code>NetworkState.NODES_STARTED</code>.
+ * be assumed to return very quickly. If there are no running nodes in this
+ * network, this operation has no effect.
*
- * @throws IllegalStateException
- * Thrown if network is not in state
- * <code>NetworkState.NODES_STARTED</code>.
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if an I/O problem occurs while shutting down the
* nodes.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract void shutdownNodes() throws TorProcessException,
+ public abstract void shutdownNodes() throws PuppeTorException,
RemoteException;
/**
* Attempts to start all nodes within a given timeout of
- * <code>maximumTimeToWaitInMillis</code> millis. The method returns as
- * soon as all nodes have started and opened their control port so that we
- * can connect to them. It returns a boolean that states whether the
+ * <code>maximumTimeToWaitInMillis</code> milliseconds. The method returns
+ * as soon as all nodes have started and opened their control port so that
+ * we can connect to them. It returns a boolean that states whether the
* operation was either successful or has timed out. This operation can only
- * be invoked, if network status is
- * <code>NetworkState.CONFIGURATIONS_WRITTEN</code>.
+ * be invoked, if all nodes in the network have written their configuration,
+ * i.e. are not in state <code>NodeState.CONFIGURING</code> anymore.
*
* @param maximumTimeToWaitInMillis
* The maximum time to wait in milliseconds. A positive value or
@@ -670,41 +679,39 @@
* allowed. Typical values are in the range of a few seconds.
* @return <code>true</code> if all nodes could be started successfully,
* <code>false</code> if a timeout has occured.
+ * @throws IllegalStateException
+ * Thrown if at least one node in the network is still in state
+ * <code>NodeState.CONFIGURING</code>.
* @throws IllegalArgumentException
* Thrown if a negative value is given for
* <code>maximumTimeToWaitInMillis</code>.
- * @throws IllegalStateException
- * Thrown if network is not in state
- * <code>NetworkState.CONFIGURATIONS_WRITTEN</code>.
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if an I/O problem occurs while starting the nodes.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
public abstract boolean startNodes(long maximumTimeToWaitInMillis)
- throws TorProcessException, RemoteException;
+ throws PuppeTorException, RemoteException;
/**
* Writes the configurations for all nodes in the network to disk, including
* <code>torrc</code> and <code>approved-routers</code> files. This
* method is assumed to return very quickly. In case of a private network,
- * <code>configureAsPrivateNetwork</code> must be invoked in advance to
- * this method! If network status is
- * <code>NetworkState.CONFIGURING_NODES</code>, it will be changed to
- * <code>NetworkState.CONFIGURATIONS_WRITTEN</code>.
+ * <code>configureAsPrivateNetwork</code> should be invoked in advance to
+ * this method!
*
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if an I/O problem occurs while writing to the nodes'
* working directories.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract void writeConfigurations() throws TorProcessException,
+ public abstract void writeConfigurations() throws PuppeTorException,
RemoteException;
/**
* Returns the working directory of this network configuration which is in
- * test-env/networkName/.
+ * <code>test-env/networkName/</code>.
*
* @return Working directory of this network.
* @throws RemoteException
@@ -713,100 +720,43 @@
public abstract File getWorkingDirectory() throws RemoteException;
/**
- * Returns whether all nodes in this network are up, or not.
+ * Adds a configuration string to the template of a node class, so that it
+ * will be added to future instances of this node class and its subclasses.
*
- * @return <code>true</code> if all nodes are up, <code>false</code> if
- * at least one node is not up.
- */
- public abstract boolean allNodesUp() throws RemoteException;
-
- /**
- * Appends the given directory server strings to the configurations of all
- * nodes in this network. This enables the nodes to use the directories of a
- * remote network.
- *
- * TODO when is the TorProcessException thrown?
- *
- * TODO in which state is this method permitted?
- *
- * @param dirServerStrings
- * A list containing the directory server strings of the nodes
- * which should be added to the network.
+ * @param nodeClass
+ * The class of nodes of which future instances will have the
+ * given configuration string.
+ * @param templateConfigurationString
+ * The configuration string.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract void addDirectoryStrings(List<String> dirServerStrings)
- throws RemoteException, TorProcessException;
+ public abstract void addTemplateConfiguration(
+ Class<? extends ProxyNode> nodeClass,
+ String templateConfigurationString) throws RemoteException;
/**
- * Appends the fingerprints of the given routers to the approved routers
- * file of all directory nodes of this network, thereby approving these
- * router nodes.
+ * Returns the name of this network.
*
- * TODO in which state is this method permitted?
- *
- * @param approvedRoutersStrings
- * A set containing the fingerprints of the router nodes which
- * should be approved by the Network.
+ * @return The name of this network.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
- * @throws TorProcessException
- * Thrown if an <code>approved-routers</code> file cannot be
- * written to disk.
*/
- public abstract void addApprovedRouters(Set<String> approvedRoutersStrings)
- throws RemoteException, TorProcessException;
+ public abstract String getNetworkName() throws RemoteException;
/**
- * TODO Unconfirmed!
+ * Binds the network at the local <code>rmiregistry</code> to make it
+ * remotely available and returns whether binding was successful.
*
- * Enables to bind a network to the groovy shell.
- *
- * @param remoteHost
- * The IpAddress where the RMI registry is running.
- * @param bindingName
- * The name whereby the stub is bound.
- * @return Network Stub
- * @throws MalformedURLException
- * Thrown to indicate that a malformed URL has occurred. Either
- * no legal protocol could be found in a specification string or
- * the string could not be parsed.
+ * @return <code>true</code> if binding was successful, <code>false</code>
+ * otherwise.
+ * @throws PuppeTorException
+ * Thrown if an error occurs while binding to the
+ * <code>rmiregistry</code>.
* @throws RemoteException
- * Thrown if an error occurs when accessed remotely.
- * @throws NotBoundException
- * A NotBoundException is thrown if an attempt is made to lookup
- * or unbind in the registry a name that has no associated
- * binding.
+ * Thrown if an error occurs when accessed remotely (though this
+ * might never happen as the object is not bound, yet).
*/
- public abstract Network connectNetwork(String remoteHost, String bindingName)
- throws MalformedURLException, RemoteException, NotBoundException;
+ public abstract boolean bindAtRmiregistry() throws RemoteException;
- /**
- * TODO Unconfirmed!
- *
- * Merges two separate networks.
- *
- * @param remoteNetwork
- * The stub of the network to merge.
- * @throws RemoteException
- * Thrown if an error occurs when accessed remotely.
- */
- public abstract void mergeNetworks(Network remoteNetwork)
- throws RemoteException;
-
- /**
- * Adds a configuration string to the template of a node class, so that it
- * will be added to future instances of this node class.
- *
- * @param nodeClass
- * The class of nodes of which future instances will have the
- * given configuration string.
- * @param templateConfigurationString
- * The configuration string.
- * @throws RemoteException
- * Thrown if an error occurs when accessed remotely.
- */
- public abstract void addTemplateConfiguration(
- Class<? extends ProxyNode> nodeClass,
- String templateConfigurationString) throws RemoteException;
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkFactory.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkFactory.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkFactory.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -31,12 +31,15 @@
*/
package de.uniba.wiai.lspi.puppetor;
+import java.net.MalformedURLException;
+import java.rmi.Naming;
+import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import de.uniba.wiai.lspi.puppetor.impl.NetworkImpl;
/**
- * The <code>NetworkFactory</code> is an abstract factory that can create
+ * The <code>NetworkFactory</code> is a concrete factory that can create
* <code>Network</code> instances.
*
* TODO At the moment, this class uses the concrete class NetworkImpl to
@@ -53,7 +56,8 @@
/**
* Creates a new network that is required for a test run. The new network is
* initially unpopulated and creates its own working directory at
- * test-env/randomTestID/.
+ * test-env/randomTestID/. The network automatically assigns port numbers to
+ * newly created nodes starting at <code>7000</code>.
*
* @param networkName
* Name of this network configuration.
@@ -69,14 +73,18 @@
/**
* Creates a new network that is required for a test run. The new network is
* initially unpopulated and creates its own working directory at
- * test-env/randomTestID/.
+ * test-env/randomTestID/. The network automatically assigns port numbers to
+ * newly created nodes starting at <code>startPort</code>.
*
* @param networkName
* Name of this network configuration.
* @param startPort
* The initial value for automatically assigned port numbers of
* nodes created by this <code>Network</code>; must be a value
- * between 1024 and 65535.
+ * between <code>1024</code> and <code>65535</code>.
+ * Applications need to ensure that there are enough ports left
+ * to the maximum number port <code>65535</code> for all
+ * created nodes.
* @return A new network instance.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
@@ -85,4 +93,37 @@
throws RemoteException {
return new NetworkImpl(networkName, startPort);
}
+
+ /**
+ * Connects to a remote network and returns a reference on it.
+ *
+ * @param remoteHost
+ * The IP address and port of the remote <code>rmiregistry</code>.
+ * @param bindingName
+ * The name under which the other network is bound at the remote
+ * <code>rmiregistry</code>.
+ * @return Reference on the remote network.
+ * @throws PuppeTorException
+ * Thrown if an error occurs when looking up the remote network
+ * at the remote <code>rmiregistry</code>.
+ * @throws RemoteException
+ * Thrown if an error occurs when accessed remotely.
+ */
+ public static Network connectToNetwork(String remoteHost, String bindingName)
+ throws PuppeTorException, RemoteException {
+ Network remoteNetwork = null;
+ try {
+ remoteNetwork = (Network) Naming.lookup("rmi://" + remoteHost + "/"
+ + bindingName);
+ } catch (MalformedURLException e) {
+ PuppeTorException ex = new PuppeTorException(
+ "Cannot connect to remote network!", e);
+ throw ex;
+ } catch (NotBoundException e) {
+ PuppeTorException ex = new PuppeTorException(
+ "Cannot connect to remote network!", e);
+ throw ex;
+ }
+ return remoteNetwork;
+ }
}
Deleted: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkState.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkState.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkState.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2007, Karsten Loesing
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * Neither the names of the copyright owners nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package de.uniba.wiai.lspi.puppetor;
-
-/**
- * The <code>NetworkState</code> constitutes the single state of a network
- * that is the result of the <code>NodeState</code>s of all nodes in the
- * network. In contrast to <code>EventType</code> the network (and node)
- * states depend only on the methods that have been invoked on these objects,
- * and not on asynchronous state changes. Most operations of
- * <code>Network</code> require a certain <code>NetworkState</code> as
- * precondition and may ensure another <code>NetworkState</code> as
- * postcondition. There is a prescribed order of states.
- *
- * @author kloesing
- */
-public enum NetworkState {
-
- /**
- * The configurations of the nodes in the network have not been written to
- * disk and can be changed. This is the initial state of a
- * <code>Network</code>.
- */
- CONFIGURING_NODES,
-
- /**
- * The configurations of all nodes in the network have been written to disk
- * and cannot be changed anymore, but the Tor processes have not been
- * started, yet. This state could be useful to review the configurations
- * that have been written to disk.
- */
- CONFIGURATIONS_WRITTEN,
-
- /**
- * The nodes in the network have been started and are running.
- */
- NODES_STARTED,
-
- /**
- * The nodes in the network had been started and shut down.
- */
- NODES_SHUT_DOWN
-
-}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NodeEventType.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NodeEventType.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NodeEventType.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -31,36 +31,55 @@
*/
package de.uniba.wiai.lspi.puppetor;
-public class NodeEventType implements EventType{
+/**
+ * Event types that can be fired by all Tor processes.
+ */
+public class NodeEventType implements EventType {
/**
- * The node has reported that its routing table for v2 hidden services has
- * changed; this event can only be parsed from a log statement in a modified
- * Tor!
+ * String identifying the type of the event type.
*/
- public static final NodeEventType NODE_ROUTING_TABLE_CHANGED = new NodeEventType();
-
+ String typeString;
+
/**
+ * Creates a new event type with the given type string.
+ *
+ * @param typeString
+ * String identifying the type of the event type.
+ */
+ public NodeEventType(String typeString) {
+ this.typeString = typeString;
+ }
+
+ public String getTypeName() {
+ return this.typeString;
+ }
+
+ /**
* The node was started and we managed to connect to its control port; this
* event is fired internally and not parsed from a log statement from Tor.
*/
- public static final NodeEventType NODE_STARTED = new NodeEventType();
-
+ public static final NodeEventType NODE_STARTED = new NodeEventType(
+ "NODE_STARTED");
+
/**
* The node has opened its control port; this event is parsed from a log
* statement in connection_create_listener().
*/
- public static final NodeEventType NODE_CONTROL_PORT_OPENED = new NodeEventType();
-
+ public static final NodeEventType NODE_CONTROL_PORT_OPENED = new NodeEventType(
+ "NODE_CONTROL_PORT_OPENED");
+
/**
* The node which has successfully opened a circuit; this event is parsed
* from a log statement in circuit_send_next_onion_skin().
*/
- public static final NodeEventType NODE_CIRCUIT_OPENED = new NodeEventType();
-
+ public static final NodeEventType NODE_CIRCUIT_OPENED = new NodeEventType(
+ "NODE_CIRCUIT_OPENED");
+
/**
* The node was stopped; this event is fired internally and not parsed from
* a log statement from Tor.
*/
- public static final NodeEventType NODE_STOPPED = new NodeEventType();
+ public static final NodeEventType NODE_STOPPED = new NodeEventType(
+ "NODE_STOPPED");
}
\ No newline at end of file
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NodeState.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NodeState.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NodeState.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -33,29 +33,27 @@
/**
* The <code>NodeState</code> constitutes the state of a single Tor node. In
- * contrast to <code>EventType</code> the node (and network) states depend
- * only on the methods that have been invoked on these objects, and not on
- * asynchronous state changes. Most operations of <code>ProxyNode</code> and
- * its subclasses require a certain <code>NodeState</code> as precondition and
- * may ensure another <code>NodeState</code> as postcondition. There is a
- * prescribed order of states.
+ * contrast to <code>EventType</code> the node states depend only on the
+ * methods that have been invoked on these objects, and not on asynchronous
+ * state changes. Most operations of <code>ProxyNode</code> and its subclasses
+ * require a certain <code>NodeState</code> as precondition and may ensure
+ * another <code>NodeState</code> as postcondition. There is a prescribed
+ * order of states.
*
* @author kloesing
*/
public enum NodeState {
/**
- * The configuration of this node has not been written to disk and can be
- * changed. This is the initial state of a <code>ProxyNode</code> or one
- * of its subclasses.
+ * The configuration of this node has not been written to disk. This is the
+ * initial state of a <code>ProxyNode</code> or one of its subclasses.
*/
CONFIGURING,
/**
- * The configuration of this node has been written to disk and cannot be
- * changed anymore, but the Tor process has not been started, yet. This
- * state could be useful to review the configuration that has been written
- * to disk.
+ * The configuration of this node has been written to disk, but the Tor
+ * process has not been started, yet. This state could be useful to review
+ * the configuration that has been written to disk.
*/
CONFIGURATION_WRITTEN,
@@ -65,7 +63,8 @@
RUNNING,
/**
- * The node had been started and shut down.
+ * The node had been started and shut down. It cannot be started at a later
+ * time anymore.
*/
SHUT_DOWN
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ProxyNode.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ProxyNode.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ProxyNode.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -34,7 +34,6 @@
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.List;
-import java.util.Set;
/**
* <p>
@@ -64,9 +63,9 @@
* <li>start proxy nodes with a delay of at least 10 minutes to be sure that
* the router descriptors stored at directory authorities will be accepted by
* directory clients, or</li>
- * <li>change the constants ESTIMATED_PROPAGATION_TIME and
- * NETWORKSTATUS_CLIENT_DL_INTERVAL in Tor to values smaller than your overall
- * HUP time for starting the network.</li>
+ * <li>change the constants <code>ESTIMATED_PROPAGATION_TIME</code> and
+ * <code>NETWORKSTATUS_CLIENT_DL_INTERVAL</code> in Tor to values smaller than
+ * your overall HUP time for starting the network.</li>
* </ul>
*
* @author kloesing
@@ -75,12 +74,7 @@
/**
* Adds the entries for a hidden service to the configuration of this node.
- * This method can only be invoked while the node is in state
- * <code>NodeState.CONFIGURING</code>.
*
- * TODO Should this operation also be possible while the process is running?
- * We could easily change the configuration via the controller.
- *
* @param serviceName
* Name of the hidden service that will be used as name for the
* hidden service directory. May neither be <code>null</code>
@@ -94,37 +88,60 @@
* The virtual TCP port that this hidden service runs on as it is
* announced to clients. May not be negative or greater than
* 65535.
- * @throws IllegalStateException
- * Thrown if node is not in state
- * <code>NodeState.CONFIGURING</code>.
+ * @return <code>HiddenService</code> object containing the configuration
+ * of the created hidden service.
* @throws IllegalArgumentException
* Thrown if an invalid value is given for either of the
* parameters.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract void addHiddenService(String serviceName, int servicePort,
- int virtualPort) throws RemoteException;
+ public abstract HiddenService addHiddenService(String serviceName,
+ int servicePort, int virtualPort) throws RemoteException;
/**
- * Adds the given set of DirServer configuration entries to the
- * configuration of this node. Note that as soon as one DirServer is
- * configured, the node does not connect to an outside directory server of
- * the public network any more!
+ * Adds the entries for a hidden service with virtual port 80 to the
+ * configuration of this node.
*
- * TODO allow invocation of this method only in correct state
+ * @param serviceName
+ * Name of the hidden service that will be used as name for the
+ * hidden service directory. May neither be <code>null</code>
+ * or a zero-length string.
+ * @param servicePort
+ * The TCP port on which the service will be available for
+ * requests. This can, but need not be different from the virtual
+ * port that is announced to clients. May not be negative or
+ * greater than 65535.
+ * @return <code>HiddenService</code> object containing the configuration
+ * of the created hidden service.
+ * @throws IllegalArgumentException
+ * Thrown if an invalid value is given for either of the
+ * parameters.
+ * @throws RemoteException
+ * Thrown if an error occurs when accessed remotely.
+ */
+ public abstract HiddenService addHiddenService(String serviceName,
+ int servicePort) throws RemoteException;
+
+ /**
+ * Adds the entries for a hidden service with an automatically assigned
+ * service port and virtual port 80 to the configuration of this node.
*
- * @param authorizedDirServerStrings
- * A set of DirServer configuration entries that each contain one
- * directory server that this node shall connect to. May not be
- * <code>null</code>, but may be an empty set.
+ * service port automatically assigned virtual port 80
+ *
+ * @param serviceName
+ * Name of the hidden service that will be used as name for the
+ * hidden service directory. May neither be <code>null</code>
+ * or a zero-length string.
+ * @return <code>HiddenService</code> object containing the configuration
+ * of the created hidden service.
* @throws IllegalArgumentException
- * Thrown if <code>null</code> is passed as parameter.
+ * Thrown if an invalid value is given for the parameter.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract void configureDirServers(
- Set<String> authorizedDirServerStrings) throws RemoteException;
+ public abstract HiddenService addHiddenService(String serviceName)
+ throws RemoteException;
/**
* Adds the given configuration string, consisting of "<configuration key>
@@ -165,17 +182,14 @@
* <code>configurationString</code> by this new configuration string; if
* multiple occurrences of the given configuration key are found, only the
* first occurrence is replaced; if no configuration can be found, the
- * configuration string is added.
+ * configuration string is appended.
*
* @param configurationString
* The replacing configuration string.
* @throws IllegalArgumentException
- * Thrown if the given configurationString is either
+ * Thrown if the given configuration string is either
* <code>null</code>, a zero-length string, or does not
* consist of configuration key and value.
- * @throws IllegalStateException
- * Thrown if not invoked in state
- * <code>NodeState.CONFIGURING</code>.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
@@ -183,6 +197,22 @@
throws RemoteException;
/**
+ * Removes all configuration strings containing the given configuration key
+ * in "<configuration key> <configuration value>", regardless of their
+ * configuration value.
+ *
+ * @param configurationKey
+ * The configuration key to remove.
+ * @throws IllegalArgumentException
+ * Thrown if the given configuration key is either
+ * <code>null</code> or a zero-length key.
+ * @throws RemoteException
+ * Thrown if an error occurs when accessed remotely.
+ */
+ public abstract void deleteConfiguration(String configurationKey)
+ throws RemoteException;
+
+ /**
* Returns the name of this node.
*
* @return The name of this node.
@@ -201,48 +231,18 @@
public abstract NodeState getNodeState() throws RemoteException;
/**
- * Determines the onion address for a previously added hidden service with
- * name <code>serviceName</code>. Requires that the node has been
- * started, i.e. is in state <code>NodeState.RUNNING</code>.
- *
- * @param serviceName
- * Name of the hidden service that has been used before to add
- * the hidden service. May neither be <code>null</code> or a
- * zero-length string.
- * @param version
- * Hidden service version; can be either 0, 1, or 2. Note that
- * version 2 may not be implemented in the regular Tor sources!
- * @return The onion address string consisting of 16 base32 chars plus
- * ".onion" for hidden service versions 0 and 1 or 16 base32 chars
- * plus "." plus 24 base32 chars plus ".onion" for hidden service
- * version 2.
- * @throws IllegalArgumentException
- * Thrown if <code>null</code> or a zero-length string is
- * passed as parameter.
- * @throws TorProcessException
- * Thrown if either there does not exist a hidden service with
- * the given <code>serviceName</code> as directory, if the
- * given <code>version</code> is invalid, or if the
- * <code>hostname</code> file could not be read.
- * @throws RemoteException
- * Thrown if an error occurs when accessed remotely.
- */
- public abstract String getOnionAddress(String serviceName, int version)
- throws TorProcessException, RemoteException;
-
- /**
* Sends a HUP command to the process via its control port to restart it;
* can only be done if the node has already been started, i.e. is in state
* <code>NodeState.RUNNING</code>!
*
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if an I/O problem occurs while sending the HUP signal.
* @throws IllegalStateException
* Thrown if node is not in state <code>NodeState.RUNNING</code>.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract void hup() throws TorProcessException, RemoteException;
+ public abstract void hup() throws PuppeTorException, RemoteException;
/**
* Shuts down the Tor process corresponding to this node immediately. This
@@ -253,13 +253,13 @@
* @throws IllegalStateException
* Thrown if this node is not in state
* <code>NodeState.RUNNING</code>.
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if an I/O problem occurs while sending the
* <code>SHUTDOWN</code> signal.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract void shutdown() throws TorProcessException, RemoteException;
+ public abstract void shutdown() throws PuppeTorException, RemoteException;
/**
* Starts the Tor process for this node and connects to the control port as
@@ -269,12 +269,9 @@
* output is parsed to see when the control port is opened.</b>
*
* @param maximumTimeToWaitInMillis
- * Maximum time in millis we will wait for the Tor process to be
- * started and the control port being opened. If this value is
- * negative or zero, we will wait potentially forever. TODO
- * should we normalize behavior for negative timeouts to either
- * throw an exception or wait forever consistently for the whole
- * framework?
+ * Maximum time in milliseconds we will wait for the Tor process
+ * to be started and the control port being opened. If this value
+ * is negative or zero, we will wait potentially forever.
* @return <code>true</code> if the node could be started successfully,
* <code>false</code> otherwise.
* @throws IllegalStateException
@@ -282,14 +279,14 @@
* <code>NodeState.CONFIGURATION_WRITTEN</code>, i.e. if
* either configuration has not been written or the process has
* already been started.
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if either the process could not be started, or the
* connection to the control port could not be established.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
public abstract boolean startNode(long maximumTimeToWaitInMillis)
- throws TorProcessException, RemoteException;
+ throws PuppeTorException, RemoteException;
/**
* Writes the configuration of this node to the <code>torrc</code> file in
@@ -297,13 +294,13 @@
* <code>NodeState.CONFIGURATION_WRITTEN</code>, if it was in state
* <code>NodeState.CONFIGURING</code> before.
*
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if the configuration file <code>torrc</code> cannot
* be written to disk.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract void writeConfiguration() throws TorProcessException,
+ public abstract void writeConfiguration() throws PuppeTorException,
RemoteException;
/**
Copied: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/PuppeTorException.java (from rev 11669, puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/TorProcessException.java)
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/PuppeTorException.java (rev 0)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/PuppeTorException.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2007, Karsten Loesing
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the names of the copyright owners nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package de.uniba.wiai.lspi.puppetor;
+
+/**
+ * The <code>PuppeTorException</code> comprises all kinds of checked
+ * exceptions that occur when interacting with the JVM-external Tor processes or
+ * with the local file system. Any occurence of this exception denotes either a
+ * configuration problem that can only be solved outside of the JVM, or an
+ * unexpected problem. In contrast to this, all kinds of programming errors of
+ * an application using this API (invoking a method with wrong parameter values,
+ * in wrong state, etc.) will instead cause appropriate runtime exceptions from
+ * the Java API.
+ *
+ * @author kloesing
+ */
+@SuppressWarnings("serial")
+public class PuppeTorException extends Exception {
+
+ /**
+ * Creates a <code>PuppeTorException</code> without detail message or
+ * cause.
+ */
+ public PuppeTorException() {
+ super();
+ }
+
+ /**
+ * Creates a <code>PuppeTorException</code> with the given detail
+ * <code>message</code> and <code>cause</code>.
+ *
+ * @param message
+ * The detail message of this exception.
+ * @param cause
+ * The cause for this exception.
+ */
+ public PuppeTorException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a <code>PuppeTorException</code> with the given detail
+ * <code>message</code>, but without a <code>cause</code>.
+ *
+ * @param message
+ * The detail message of this exception.
+ */
+ public PuppeTorException(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a <code>PuppeTorException</code> with the given
+ * <code>cause</code>, but without a detail message.
+ *
+ * @param cause
+ * The cause for this exception.
+ */
+ public PuppeTorException(Throwable cause) {
+ super(cause);
+ }
+}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/RouterNode.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/RouterNode.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/RouterNode.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -45,64 +45,6 @@
public interface RouterNode extends ProxyNode {
/**
- * <p>
- * Determines the directory fingerprint of this node. If the Tor process has
- * not been started before, it is started and immediately stopped
- * afterwards, so that the Tor process creates a new onion key pair and
- * fingerprint for it. This is done using a temporary configuration file and
- * with the command-line option <code>--list-fingerprint</code>. Tor then
- * generates a new onion key and writes its fingerprint to the
- * <code>fingerprint</code> file in its working directory, but does not
- * start routing traffic.
- * </p>
- *
- * <p>
- * The temporary <code>torrc</code> file contains a fake entry as
- * DirServer, so that the node thinks that it is in a private network. The
- * reason for this is that some configuration entries might only work in a
- * private network, but the node cannot be configured with valid DirServer
- * entries that would make it believe to be in a private network, because
- * they can only be generated after invoking this method. Therefore, a
- * single DirServer entry is configured with this node as directory server
- * having a fingerprint of
- * <code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000</code>.
- * </p>
- *
- * <p>
- * The fingerprint is returned and locally stored so that further
- * invocations of this method can be answered immediately. This method can
- * only be invoked in state <code>NodeState.CONFIGURING</code> and does
- * not change this state. It should be invoked after most of the other
- * configurations for this node have been completed, but can be invoked
- * before specifying directory servers for this node.
- * </p>
- *
- * @return The content of the fingerprint file of this node.
- * @throws TorProcessException
- * Thrown if either the temporary <code>torrc</code>
- * configuration file cannot be written, the Tor process cannot
- * be started temporarily, or the fingerprint file cannot be
- * read.
- * @throws RemoteException
- * Thrown if an error occurs when accessed remotely.
- */
- public abstract String determineFingerprint() throws TorProcessException,
- RemoteException;
-
- /**
- * Returns the base32-encoded fingerprint of this node.
- *
- * @return The base32-encoded fingerprint of this node.
- * @throws IllegalStateException
- * Thrown if node is neither in state
- * <code>NodeState.RUNNING</code> or
- * <code>NodeState.SHUT_DOWN</code>.
- * @throws RemoteException
- * Thrown if an error occurs when accessed remotely.
- */
- public abstract String getFingerprintBase32() throws RemoteException;
-
- /**
* Returns the dir port of this node.
*
* @return The dir port of this node.
@@ -121,16 +63,28 @@
public abstract int getOrPort() throws RemoteException;
/**
- * Returns the fingerprint of this node formatted like
- * <code>0000 0000 0000 0000 0000 0000 0000 0000 0000 0000</code>.
+ * <p>
+ * Returns the fingerprint string of this node, formatted like
+ * <code>nickname 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000</code>.
+ * </p>
*
+ * <p>
+ * The fingerprint is determined by a background thread that is started as
+ * soon as the node is instantiated. If this background thread has not
+ * finished when this method is invoked, the invoking thread will be blocked
+ * until the fingerprint is available (or determining it has failed,
+ * whereupon an exception will be thrown).
+ * </p>
+ *
* @return The fingerprint of this node.
- * @throws IllegalStateException
- * Thrown if node is neither in state
- * <code>NodeState.RUNNING</code> or
- * <code>NodeState.SHUT_DOWN</code>.
+ * @throws PuppeTorException
+ * Thrown if either the temporary <code>torrc.temp</code>
+ * configuration file cannot be written, the Tor process cannot
+ * be started temporarily, or the fingerprint file cannot be
+ * read.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public abstract String getFingerprint() throws RemoteException;
+ public abstract String getFingerprint() throws PuppeTorException,
+ RemoteException;
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ServerApplication.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ServerApplication.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ServerApplication.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -44,26 +44,41 @@
/**
* Starts listening for incoming <code>HTTP GET</code> requests from
* clients. Any incoming request is answered by an empty
- * <code>HTTP OK</code> reply. This method may only be invoked once!
+ * <code>HTTP OK</code> reply. This method may only be invoked when the
+ * server is currently not in listening state!
*
* @throws IllegalStateException
- * Thrown if <code>listen</code> has already been invoked
- * before.
+ * Thrown if the server is currently not in listening state.
*/
- public abstract void listen();
+ public abstract void startListening();
/**
- * Stops listening for requests.
+ * Stops listening for requests. This method may only be invoked when the
+ * server is currently in listening state!
*
* @throws IllegalStateException
- * Thrown if <code>listen</code> has not been invoked before.
+ * Thrown if the server is currently in listening state.
*/
public abstract void stopListening();
/**
+ * Returns whether this server is currently in listening state.
+ *
+ * @return The listening state of this server.
+ */
+ public abstract boolean isListening();
+
+ /**
* Returns the name of this server.
*
* @return The name of this server.
*/
public abstract String getServerApplicationName();
+
+ /**
+ * Returns the port on which this server listens.
+ *
+ * @return The port on which this server listens.
+ */
+ public abstract int getServerPort();
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ServerEventType.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ServerEventType.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ServerEventType.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -31,12 +31,36 @@
*/
package de.uniba.wiai.lspi.puppetor;
-public class ServerEventType implements EventType{
+/**
+ * Event types that can be fired by a server application running as thread in
+ * the background.
+ */
+public class ServerEventType implements EventType {
/**
+ * String identifying the type of the event type.
+ */
+ String typeString;
+
+ /**
+ * Creates a new event type with the given type string.
+ *
+ * @param typeString
+ * String identifying the type of the event type.
+ */
+ public ServerEventType(String typeString) {
+ this.typeString = typeString;
+ }
+
+ public String getTypeName() {
+ return this.typeString;
+ }
+
+ /**
* The server application has received a request and sent a reply to it;
* this event is fired internally and not parsed from a log statement from
* Tor.
*/
- public static final ServerEventType SERVER_RECEIVING_REQUEST_SENDING_REPLY = new ServerEventType();
+ public static final ServerEventType SERVER_RECEIVING_REQUEST_SENDING_REPLY = new ServerEventType(
+ "SERVER_RECEIVING_REQUEST_SENDING_REPLY");
}
\ No newline at end of file
Deleted: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/TorProcessException.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/TorProcessException.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/TorProcessException.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2007, Karsten Loesing
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * * Neither the names of the copyright owners nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package de.uniba.wiai.lspi.puppetor;
-
-/**
- * The <code>TorProcessException</code> comprises all kinds of checked
- * exceptions that occur when interacting with the JVM-external Tor processes or
- * with the local file system. Any occurence of this exception denotes either a
- * configuration problem that can only be solved outside of the JVM, or an
- * unexpected problem. In contrast to this, all kinds of programming errors of
- * an application using this API (invoking a method with wrong parameter values,
- * in wrong state, etc.) will instead cause appropriate runtime exceptions from
- * the Java API.
- *
- * @author kloesing
- */
-@SuppressWarnings("serial")
-public class TorProcessException extends Exception {
-
- /**
- * Creates a <code>TorProcessException</code> without detail message or
- * cause.
- */
- public TorProcessException() {
- super();
- }
-
- /**
- * Creates a <code>TorProcessException</code> with the given detail
- * <code>message</code> and <code>cause</code>.
- *
- * @param message
- * The detail message of this exception.
- * @param cause
- * The cause for this exception.
- */
- public TorProcessException(String message, Throwable cause) {
- super(message, cause);
- }
-
- /**
- * Creates a <code>TorProcessException</code> with the given detail
- * <code>message</code>, but without a <code>cause</code>.
- *
- * @param message
- * The detail message of this exception.
- */
- public TorProcessException(String message) {
- super(message);
- }
-
- /**
- * Creates a <code>TorProcessException</code> with the given
- * <code>cause</code>, but without a detail message.
- *
- * @param cause
- * The cause for this exception.
- */
- public TorProcessException(Throwable cause) {
- super(cause);
- }
-
-}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AccessingPublicWebServerOverTor.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AccessingPublicWebServerOverTor.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AccessingPublicWebServerOverTor.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -41,11 +41,11 @@
import de.uniba.wiai.lspi.puppetor.Network;
import de.uniba.wiai.lspi.puppetor.NetworkFactory;
import de.uniba.wiai.lspi.puppetor.ProxyNode;
-import de.uniba.wiai.lspi.puppetor.TorProcessException;
+import de.uniba.wiai.lspi.puppetor.PuppeTorException;
/**
- * Example for accessing a public Web server (here: <code>www.google.com</code>)
- * over Tor to measure access times.
+ * Example for accessing a public web server (here: <code>www.google.com</code>)
+ * over Tor to measure the access time.
*
* @author kloesing
*/
@@ -56,23 +56,19 @@
*
* @param args
* Command-line arguments (ignored).
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if there is a problem with the JVM-external Tor
* processes that we cannot handle.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public static void main(String[] args) throws TorProcessException,
+ public static void main(String[] args) throws PuppeTorException,
RemoteException {
// though we only need a single proxy, we always need to create a
// network to initialize a test case.
Network network = NetworkFactory.createNetwork("example1");
- // configure firewall restrictions for all newly created nodes
- network.addTemplateConfiguration(ProxyNode.class,
- "ReachableAddresses accept *:80, accept *:443, reject *:*");
-
// create a single proxy node with name "proxy"
ProxyNode proxy = network.createProxy("proxy");
@@ -84,16 +80,20 @@
if (!network.startNodes(5000)) {
// failed to start the proxy
+ System.out.println("Failed to start the node!");
return;
}
+ System.out.println("Successfully started the node!");
// hup until proxy has built circuits (5 retries, 10 seconds timeout
// each)
if (!network.hupUntilUp(5, 10000)) {
// failed to build circuits
+ System.out.println("Failed to build circuits!");
return;
}
+ System.out.println("Successfully built circuits!");
// create client application
ClientApplication client = network.createClient("client",
@@ -109,10 +109,9 @@
if (event.getType() == ClientEventType.CLIENT_SENDING_REQUEST) {
before = System.currentTimeMillis();
} else if (event.getType() == ClientEventType.CLIENT_REPLY_RECEIVED) {
- System.out
- .println("Request took "
- + (System.currentTimeMillis() - before)
- + " millis");
+ System.out.println("Request took "
+ + (System.currentTimeMillis() - before)
+ + " milliseconds");
}
}
};
@@ -125,7 +124,7 @@
clientEventListener);
// perform at most three request with a timeout of 20 seconds each
- client.performRequest(3, 20000, true);
+ client.startRequests(3, 20000, true);
// block this thread as long as client requests are running
manager.waitForAnyOccurence(client.getClientApplicationName(),
@@ -146,5 +145,8 @@
} catch (InterruptedException e) {
}
+ // Shut down the JVM
+ System.out.println("Goodbye.");
+ System.exit(0);
}
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPrivateTorNetwork.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPrivateTorNetwork.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPrivateTorNetwork.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -33,17 +33,18 @@
import java.rmi.RemoteException;
-import de.uniba.wiai.lspi.puppetor.BobEventType;
import de.uniba.wiai.lspi.puppetor.ClientApplication;
import de.uniba.wiai.lspi.puppetor.ClientEventType;
import de.uniba.wiai.lspi.puppetor.Event;
import de.uniba.wiai.lspi.puppetor.EventListener;
import de.uniba.wiai.lspi.puppetor.EventManager;
+import de.uniba.wiai.lspi.puppetor.HiddenService;
+import de.uniba.wiai.lspi.puppetor.HiddenServiceEventType;
import de.uniba.wiai.lspi.puppetor.Network;
import de.uniba.wiai.lspi.puppetor.NetworkFactory;
+import de.uniba.wiai.lspi.puppetor.PuppeTorException;
import de.uniba.wiai.lspi.puppetor.RouterNode;
import de.uniba.wiai.lspi.puppetor.ServerApplication;
-import de.uniba.wiai.lspi.puppetor.TorProcessException;
/**
* Example for advertising and accessing a hidden service over a private Tor
@@ -58,13 +59,13 @@
*
* @param args
* Command-line arguments (ignored).
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if there is a problem with the JVM-external Tor
* processes that we cannot handle.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public static void main(String[] args) throws TorProcessException,
+ public static void main(String[] args) throws PuppeTorException,
RemoteException {
// create a network to initialize a test case
@@ -72,18 +73,17 @@
// create three router nodes with parameters (router name, control port,
// SOCKS port, OR port, dir mirror port)
- RouterNode router1 = network.createRouter("router1", 7021, 7022, 7023,
- 7024);
- network.createRouter("router2", 7031, 7032, 7033, 7034);
- network.createRouter("router3", 7041, 7042, 7043, 7044);
+ RouterNode router1 = network.createRouter("router1");
+ network.createRouter("router2");
+ RouterNode router3 = network.createRouter("router3");
// create two directory nodes with parameters (router name, control
// port, SOCKS port, OR port, dir port)
- network.createDirectory("dir1", 7051, 7052, 7053, 7054);
- network.createDirectory("dir2", 7061, 7062, 7063, 7064);
+ network.createDirectory("dir1");
+ network.createDirectory("dir2");
// add hidden service
- router1.addHiddenService("hidServ", 7025, 80);
+ HiddenService hidServ1 = router1.addHiddenService("hidServ");
// configure nodes of this network to be part of a private network
network.configureAsPrivateNetwork();
@@ -95,7 +95,7 @@
// timeout of 15 seconds
if (!network.startNodes(15000)) {
- // failed to start the proxy
+ // failed to start the nodes
System.out.println("Failed to start nodes!");
return;
}
@@ -115,28 +115,29 @@
EventManager manager = network.getEventManager();
// wait for 3 minutes that the proxy has published its first RSD
-
if (!manager.waitForAnyOccurence(router1.getNodeName(),
- BobEventType.BOB_DESC_PUBLISHED_RECEIVED, 3L * 60L * 1000L)) {
+ HiddenServiceEventType.BOB_DESC_PUBLISHED_RECEIVED,
+ 3L * 60L * 1000L)) {
// failed to publish an RSD
System.out.println("Failed to publish an RSD!");
return;
}
- System.out.println("All RSDs published!");
+ System.out.println("Successfully published an RSD!");
+ // create server application
+ ServerApplication server = network.createServer("server", hidServ1
+ .getServicePort());
+
// determine onion address for hidden service
- String onionAddress = router1.getOnionAddress("hidServ", 1);
+ String onionAddress = hidServ1.determineOnionAddress();
- // create server application
- ServerApplication server = network.createServer("server", 7025);
-
// start server
- server.listen();
+ server.startListening();
System.out.println("Started server");
// create client application
ClientApplication client = network.createClient("client", onionAddress,
- 80, 7042);
+ hidServ1.getVirtualPort(), router3.getSocksPort());
// register event listener
EventListener clientAndServerEventListener = new EventListener() {
@@ -152,7 +153,7 @@
clientAndServerEventListener);
// perform at most five request with a timeout of 45 seconds each
- client.performRequest(5, 45000, true);
+ client.startRequests(5, 45000, true);
// wait for request to be performed
manager.waitForAnyOccurence(client.getClientApplicationName(),
@@ -161,5 +162,8 @@
// shut down nodes
network.shutdownNodes();
+ // Shut down the JVM
+ System.out.println("Goodbye.");
+ System.exit(0);
}
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPublicTorNetwork.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPublicTorNetwork.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPublicTorNetwork.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -33,18 +33,19 @@
import java.rmi.RemoteException;
-import de.uniba.wiai.lspi.puppetor.BobEventType;
import de.uniba.wiai.lspi.puppetor.ClientApplication;
import de.uniba.wiai.lspi.puppetor.ClientEventType;
import de.uniba.wiai.lspi.puppetor.Event;
import de.uniba.wiai.lspi.puppetor.EventListener;
import de.uniba.wiai.lspi.puppetor.EventManager;
+import de.uniba.wiai.lspi.puppetor.HiddenService;
+import de.uniba.wiai.lspi.puppetor.HiddenServiceEventType;
import de.uniba.wiai.lspi.puppetor.Network;
import de.uniba.wiai.lspi.puppetor.NetworkFactory;
import de.uniba.wiai.lspi.puppetor.ProxyNode;
+import de.uniba.wiai.lspi.puppetor.PuppeTorException;
import de.uniba.wiai.lspi.puppetor.ServerApplication;
import de.uniba.wiai.lspi.puppetor.ServerEventType;
-import de.uniba.wiai.lspi.puppetor.TorProcessException;
/**
* Example for advertising and accessing a hidden service over the public Tor
@@ -59,25 +60,24 @@
*
* @param args
* Command-line arguments (ignored).
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if there is a problem with the JVM-external Tor
* processes that we cannot handle.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public static void main(String[] args) throws TorProcessException,
+ public static void main(String[] args) throws PuppeTorException,
RemoteException {
// create a network to initialize a test case
Network network = NetworkFactory.createNetwork("example3");
- // create two proxy nodes with names "proxy1"/"proxy2", control ports
- // 7001/7011, and SOCKS ports 7002/7012
- ProxyNode proxy1 = network.createProxy("proxy1", 7001, 7002);
- network.createProxy("proxy2", 7011, 7012);
+ // create two proxy nodes
+ ProxyNode proxy1 = network.createProxy("proxy1");
+ ProxyNode proxy2 = network.createProxy("proxy2");
// add hidden service to the configuration of proxy1
- proxy1.addHiddenService("hidServ", 7005, 80);
+ HiddenService hidServ1 = proxy1.addHiddenService("hidServ");
// write configuration of proxy node
network.writeConfigurations();
@@ -87,11 +87,12 @@
if (!network.startNodes(5000)) {
// failed to start the proxy
- System.out.println("Failed to start the proxy!");
+ System.out.println("Failed to start nodes!");
return;
}
+ System.out.println("Successfully started nodes!");
- // hup until proxy has built circuits (5 retries, 10 seconds timeout
+ // hup until nodes have built circuits (5 retries, 10 seconds timeout
// each)
if (!network.hupUntilUp(5, 10000)) {
@@ -99,28 +100,32 @@
System.out.println("Failed to build circuits!");
return;
}
+ System.out.println("Successfully built circuits!");
// obtain reference to event manager to be able to respond to events
EventManager manager = network.getEventManager();
// wait for 3 minutes that the proxy has published its first RSD
if (!manager.waitForAnyOccurence(proxy1.getNodeName(),
- BobEventType.BOB_DESC_PUBLISHED_RECEIVED, 3L * 60L * 1000L)) {
+ HiddenServiceEventType.BOB_DESC_PUBLISHED_RECEIVED,
+ 3L * 60L * 1000L)) {
// failed to publish an RSD
System.out.println("Failed to publish an RSD!");
return;
}
+ System.out.println("Successfully published an RSD!");
// create server application
- ServerApplication server = network.createServer("server", 7005);
+ ServerApplication server = network.createServer("server", hidServ1
+ .getServicePort());
// determine onion address for hidden service
- String onionAddress = proxy1.getOnionAddress("hidServ", 1);
+ String onionAddress = hidServ1.determineOnionAddress();
// create client application
ClientApplication client = network.createClient("client", onionAddress,
- 80, 7012);
+ hidServ1.getVirtualPort(), proxy2.getSocksPort());
// create event listener to listen for client and server application
// events
@@ -138,14 +143,14 @@
requestReceivedAtServer = event.getOccurrenceTime();
System.out.println("Request took "
+ (requestReceivedAtServer - requestSentFromClient)
- + " millis from client to server!");
+ + " milliseconds from client to server!");
} else if (event.getType() == ClientEventType.CLIENT_REPLY_RECEIVED) {
System.out
.println("Request took "
+ (event.getOccurrenceTime() - requestSentFromClient)
- + " millis for the round-trip and "
+ + " milliseconds for the round-trip and "
+ (event.getOccurrenceTime() - requestReceivedAtServer)
- + " millis from server to client!");
+ + " milliseconds from server to client!");
}
}
};
@@ -157,10 +162,10 @@
clientAndServerEventListener);
// start server
- server.listen();
+ server.startListening();
// perform at most five request with a timeout of 45 seconds each
- client.performRequest(5, 45000, true);
+ client.startRequests(5, 45000, true);
// block this thread as long as client requests are running
manager.waitForAnyOccurence(client.getClientApplicationName(),
@@ -169,6 +174,8 @@
// shut down proxy
network.shutdownNodes();
- System.out.println("Exiting...");
+ // Shut down the JVM
+ System.out.println("Goodbye.");
+ System.exit(0);
}
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingHiddenServiceToPublicTorNetwork.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingHiddenServiceToPublicTorNetwork.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingHiddenServiceToPublicTorNetwork.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -33,19 +33,19 @@
import java.rmi.RemoteException;
-import de.uniba.wiai.lspi.puppetor.BobEventType;
import de.uniba.wiai.lspi.puppetor.Event;
import de.uniba.wiai.lspi.puppetor.EventListener;
import de.uniba.wiai.lspi.puppetor.EventManager;
+import de.uniba.wiai.lspi.puppetor.HiddenServiceEventType;
import de.uniba.wiai.lspi.puppetor.Network;
import de.uniba.wiai.lspi.puppetor.NetworkFactory;
import de.uniba.wiai.lspi.puppetor.NodeEventType;
import de.uniba.wiai.lspi.puppetor.ProxyNode;
-import de.uniba.wiai.lspi.puppetor.TorProcessException;
+import de.uniba.wiai.lspi.puppetor.PuppeTorException;
/**
* Example for advertising a hidden service to the public Tor network and
- * observe publication of rendezvous service descriptors.
+ * observing the publication of rendezvous service descriptors.
*
* @author kloesing
*/
@@ -56,22 +56,21 @@
*
* @param args
* Command-line arguments (ignored).
- * @throws TorProcessException
+ * @throws PuppeTorException
* Thrown if there is a problem with the JVM-external Tor
* processes that we cannot handle.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
*/
- public static void main(String[] args) throws TorProcessException,
+ public static void main(String[] args) throws PuppeTorException,
RemoteException {
// though we only need one proxy, we always need to create a network
// to initialize a test case
Network network = NetworkFactory.createNetwork("example2");
- // create a single proxy node with name "proxy", control port 7001,
- // and SOCKS port 7002
- ProxyNode proxy = network.createProxy("proxy", 7001, 7002);
+ // create a single proxy node
+ ProxyNode proxy = network.createProxy("proxy");
// add hidden service to the configuration
proxy.addHiddenService("hidServ", 7005, 80);
@@ -90,10 +89,10 @@
if (circuitOpened == -1) {
circuitOpened = System.currentTimeMillis();
}
- } else if (event.getType() == BobEventType.BOB_DESC_PUBLISHED_RECEIVED) {
+ } else if (event.getType() == HiddenServiceEventType.BOB_DESC_PUBLISHED_RECEIVED) {
System.out.println("RSD published "
+ (System.currentTimeMillis() - circuitOpened)
- + " millis after first circuit was opened");
+ + " milliseconds after first circuit was opened");
}
}
};
@@ -109,9 +108,10 @@
if (!network.startNodes(5000)) {
// failed to start the proxy
- System.out.println("Failed to start the proxy!");
+ System.out.println("Failed to start the node!");
return;
}
+ System.out.println("Successfully started the node!");
// hup until proxy has built circuits (5 retries, 10 seconds timeout
// each)
@@ -121,6 +121,7 @@
System.out.println("Failed to build circuits!");
return;
}
+ System.out.println("Successfully built circuits!");
// let it run for 2 minutes and observe when RSDs are published...
System.out
@@ -135,6 +136,8 @@
// shut down proxy
network.shutdownNodes();
- System.out.println("Exiting...");
+ // Shut down the JVM
+ System.out.println("Goodbye.");
+ System.exit(0);
}
}
Added: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/LongRunningNetwork.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/LongRunningNetwork.java (rev 0)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/LongRunningNetwork.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2007, Patrick Geyer, Johannes Jungkunst, Karsten Loesing,
+ * Stefan Schilling
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the names of the copyright owners nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package de.uniba.wiai.lspi.puppetor.examples;
+
+import java.rmi.RemoteException;
+
+import de.uniba.wiai.lspi.puppetor.Event;
+import de.uniba.wiai.lspi.puppetor.EventListener;
+import de.uniba.wiai.lspi.puppetor.EventManager;
+import de.uniba.wiai.lspi.puppetor.Network;
+import de.uniba.wiai.lspi.puppetor.NetworkFactory;
+import de.uniba.wiai.lspi.puppetor.PuppeTorException;
+
+/**
+ * Example for starting and running a private network of routers and directories
+ * that may be accessed via RMI, e.g. to be merged with another network. Note
+ * that the <code>rmiregistry</code> must be running in order to run this
+ * example.
+ *
+ * @author pgeyer, jjungkunst, sschilling
+ */
+public class LongRunningNetwork {
+
+ /**
+ * Sets up and runs the test.
+ *
+ * @param args
+ * Command-line arguments (ignored).
+ * @throws PuppeTorException
+ * Thrown if there is a problem with the JVM-external Tor
+ * processes that we cannot handle.
+ * @throws RemoteException
+ * Thrown if an error occurs when accessed remotely.
+ */
+ public static void main(String[] args) throws PuppeTorException,
+ RemoteException {
+
+ // create a network to initialize a test case (networkName, startPort)
+ Network network = NetworkFactory.createNetwork("longRunning");
+
+ // create two directory nodes
+ network.createDirectory("dir1");
+ network.createDirectory("dir2");
+
+ // create six router nodes
+ network.createRouter("router1");
+ network.createRouter("router2");
+ network.createRouter("router3");
+ network.createRouter("router4");
+ network.createRouter("router5");
+ network.createRouter("router6");
+
+ // obtain reference to event manager to be able to respond to events
+ EventManager manager = network.getEventManager();
+ EventListener listener = new EventListener() {
+ public void handleEvent(Event event) {
+ System.out.println(event);
+ }
+ };
+ manager.addEventListener(listener);
+
+ // configure nodes of this network to be part of a private network
+ network.configureAsPrivateNetwork();
+ System.out.println("Network written ...");
+
+ // write configuration of proxy node
+ network.writeConfigurations();
+ System.out.println("Config written ...");
+
+ // start proxy node and wait until it has opened a circuit with a
+ // timeout of 5 seconds
+ if (!network.startNodes(5000)) {
+ System.out.println("Failed to start the nodes!");
+ return;
+ }
+ System.out.println("Nodes started ...");
+
+ // hup until the nodes have built circuits (5 retries, 10 seconds timeout
+ // each)
+ if (!network.hupUntilUp(5, 10000)) {
+
+ // failed to build circuits
+ System.out.println("Failed to build circuits!");
+ return;
+ }
+ System.out.println("Successfully built circuits!");
+
+ // bind the network to rmiregistry
+ if (!network.bindAtRmiregistry()) {
+
+ // failed to bind at rmiregistry
+ System.out.println("Failed to bind at rmiregistry! "
+ + "Is rmiregistry running?");
+ return;
+ }
+ System.out.println("Bound at rmiregistry to name \""
+ + network.getNetworkName() + "\"!");
+
+ // wait until the end of time
+ System.out.println("Waiting until the end of time... "
+ + "Interrupt with Ctrl-C!");
+ try {
+ Thread.sleep(Long.MAX_VALUE);
+ } catch (InterruptedException e) {
+ // do nothing
+ }
+ }
+}
\ No newline at end of file
Added: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/MergingProxiesWithLongRunningNetwork.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/MergingProxiesWithLongRunningNetwork.java (rev 0)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/MergingProxiesWithLongRunningNetwork.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2007, Patrick Geyer, Johannes Jungkunst, Karsten Loesing,
+ * Stefan Schilling
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the names of the copyright owners nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *
+ * WARNING! This class is untested, yet! Don't rely on it!
+ *
+ */
+
+package de.uniba.wiai.lspi.puppetor.examples;
+
+import java.rmi.RemoteException;
+
+import de.uniba.wiai.lspi.puppetor.Event;
+import de.uniba.wiai.lspi.puppetor.EventListener;
+import de.uniba.wiai.lspi.puppetor.EventManager;
+import de.uniba.wiai.lspi.puppetor.Network;
+import de.uniba.wiai.lspi.puppetor.NetworkFactory;
+import de.uniba.wiai.lspi.puppetor.PuppeTorException;
+
+/**
+ * Example for a private network containing only proxies that is merged with
+ * another, long-running private network that contains routers and directories.
+ * Note that <code>LongRunningNetwork</code> must be running in order to run
+ * this example.
+ *
+ * @author pgeyer, jjungkunst, sschilling
+ */
+public class MergingProxiesWithLongRunningNetwork {
+
+ /**
+ * Sets up and runs the test.
+ *
+ * @param args
+ * Command-line arguments (ignored).
+ * @throws PuppeTorException
+ * Thrown if there is a problem with the JVM-external Tor
+ * processes that we cannot handle.
+ * @throws RemoteException
+ * Thrown if an error occurs when accessed remotely.
+ */
+ public static void main(String[] args) throws PuppeTorException,
+ RemoteException {
+
+ // create a network to initialize a test case
+ Network network = NetworkFactory.createNetwork("proxies", 8000);
+
+ // create two proxy nodes
+ network.createProxy("client", 9001, 9050);
+ network.createProxy("server", 9051, 9002);
+
+ // obtain reference to event manager to be able to respond to events
+ EventManager manager = network.getEventManager();
+ EventListener listener = new EventListener() {
+ public void handleEvent(Event event) {
+ System.out.println(event);
+ }
+ };
+ manager.addEventListener(listener);
+
+ // obtain a reference on the remote long-running network
+ Network remoteNetwork = NetworkFactory.connectToNetwork("127.0.0.1",
+ "longRunning");
+
+ // merge configuration with long-running network
+ System.out.println("Merging network configurations...");
+ network.configureAsInterconnectedPrivateNetwork(remoteNetwork);
+ System.out.println("Network configurations merged!");
+
+ // write configuration of proxy node
+ network.writeConfigurations();
+ System.out.println("Config written ...");
+
+ // start proxy node and wait until it has opened a circuit with a
+ // timeout of 5 seconds
+ if (!network.startNodes(5000)) {
+ System.out.println("Failed to start the nodes!");
+ return;
+ }
+ System.out.println("Nodes started ...");
+
+ // hup until proxy has built circuits (20 retries, 5 seconds timeout
+ // each)
+ if (!network.hupUntilUp(20, 5000)) {
+
+ // failed to build circuits
+ System.out.println("Failed to build circuits!");
+ return;
+ }
+ System.out.println("Successfully built circuits!");
+
+ // wait for an hour
+ try {
+ Thread.sleep(60 * 60 * 1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // shutdown after hours
+ network.shutdownNodes();
+
+ // Shut down the JVM
+ System.out.println("Goodbye.");
+ System.exit(0);
+ }
+}
\ No newline at end of file
Added: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/MergingRoutersWithLongRunningNetwork.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/MergingRoutersWithLongRunningNetwork.java (rev 0)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/MergingRoutersWithLongRunningNetwork.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2007, Patrick Geyer, Johannes Jungkunst, Karsten Loesing,
+ * Stefan Schilling
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the names of the copyright owners nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package de.uniba.wiai.lspi.puppetor.examples;
+
+import java.rmi.RemoteException;
+
+import de.uniba.wiai.lspi.puppetor.Event;
+import de.uniba.wiai.lspi.puppetor.EventListener;
+import de.uniba.wiai.lspi.puppetor.EventManager;
+import de.uniba.wiai.lspi.puppetor.Network;
+import de.uniba.wiai.lspi.puppetor.NetworkFactory;
+import de.uniba.wiai.lspi.puppetor.PuppeTorException;
+
+/**
+ * Example for a private network of routers without directories that is merged
+ * with another, long-running private network that contains routers and
+ * directories. Note that <code>LongRunningNetwork</code> must be running in
+ * order to run this example.
+ *
+ * @author pgeyer, jjungkunst, sschilling
+ */
+public class MergingRoutersWithLongRunningNetwork {
+
+ /**
+ * Sets up and runs the test.
+ *
+ * @param args
+ * Command-line arguments (ignored).
+ * @throws PuppeTorException
+ * Thrown if there is a problem with the JVM-external Tor
+ * processes that we cannot handle.
+ * @throws RemoteException
+ * Thrown if an error occurs when accessed remotely.
+ */
+ public static void main(String[] args) throws PuppeTorException,
+ RemoteException {
+
+ // create a network to initialize a test case (networkName)
+ Network network = NetworkFactory.createNetwork("routers", 9000);
+
+ // create six router nodes
+ network.createRouter("router10");
+ network.createRouter("router11");
+ network.createRouter("router12");
+ network.createRouter("router13");
+ network.createRouter("router14");
+ network.createRouter("router15");
+
+ // obtain reference to event manager to be able to respond to events
+ EventManager manager = network.getEventManager();
+ EventListener listener = new EventListener() {
+ public void handleEvent(Event event) {
+ System.out.println(event);
+ }
+ };
+ manager.addEventListener(listener);
+
+ // configure nodes of this network to be part of a private network
+ network.configureAsPrivateNetwork();
+ System.out.println("Network written ...");
+
+ // obtain a reference on the remote long-running network
+ Network remoteNetwork = NetworkFactory.connectToNetwork("127.0.0.1",
+ "longRunning");
+
+ // merge configuration with long-running network
+ network.configureAsInterconnectedPrivateNetwork(remoteNetwork);
+ System.out.println("Network configurations merged ...");
+
+ // write configurations and hup all nodes in the other network
+ remoteNetwork.writeConfigurations();
+ remoteNetwork.hupAllNodes();
+
+ // write configuration of proxy node
+ network.writeConfigurations();
+ System.out.println("Config written ...");
+
+ // start proxy node and wait until it has opened a circuit with a
+ // timeout of 5 seconds
+ if (!network.startNodes(5000)) {
+ System.out.println("Failed to start the nodes!");
+ return;
+ }
+ System.out.println("Nodes started ...");
+
+ // hup until proxy has built circuits (20 retries, 5 seconds timeout
+ // each)
+ if (!network.hupUntilUp(20, 5000)) {
+
+ // failed to build circuits
+ System.out.println("Failed to build circuits!");
+ return;
+ }
+ System.out.println("Successfully built circuits!");
+
+ // bind the network to rmiregistry
+ if (!network.bindAtRmiregistry()) {
+
+ // failed to bind at rmiregistry
+ System.out.println("Failed to bind at rmiregistry! "
+ + "Is rmiregistry running?");
+ return;
+ }
+ System.out.println("Bound at rmiregistry to name \""
+ + network.getNetworkName() + "\"!");
+
+ // wait for an hour
+ try {
+ Thread.sleep(60 * 60 * 1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // shutdown after hours
+ network.shutdownNodes();
+
+ // Shut down the JVM
+ System.out.println("Goodbye.");
+ System.exit(0);
+ }
+}
\ No newline at end of file
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/groovy/RmiPuppetzShell.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/groovy/RmiPuppetzShell.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/groovy/RmiPuppetzShell.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -30,16 +30,6 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
-/*
- *
- * WARNING! This class is untested, yet! Don't rely on it!
- *
- */
-
-/**
- * @author pgeyer, jjungkunst, sschilling
- */
package de.uniba.wiai.lspi.puppetor.groovy;
import groovy.lang.GroovyShell;
@@ -49,6 +39,10 @@
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
@@ -59,6 +53,7 @@
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.LinkedList;
+import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -69,155 +64,135 @@
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
+import javax.swing.JTextField;
import de.uniba.wiai.lspi.puppetor.Event;
import de.uniba.wiai.lspi.puppetor.EventListener;
import de.uniba.wiai.lspi.puppetor.Network;
-@SuppressWarnings("serial")
/**
- * A <code>RmiPuppetzShell</code> represents a command shell to PuppeTor. By
- * the use of a groovy interpreter, the different nodes of a Tor network can be
- * manipulated.
+ * The <code>RmiPuppetzShell</code> constitutes a simple graphical interface
+ * to PuppeTor networks. It can connect to already running PuppeTor networks via
+ * RMI and inspect or manipulate those networks using the Java-based script
+ * language Groovy.
*
* @author pgeyer, jjungkunst, sschilling
*/
+@SuppressWarnings("serial")
public class RmiPuppetzShell extends JFrame {
/**
- * The shell that evaluates the groovy commands.
+ * Main method to start the GUI.
+ *
+ * @param args
+ * (ignored)
*/
- private GroovyShell shell;
+ public static void main(String args[]) {
+ new RmiPuppetzShell();
+ }
- private Logger logger;
-
/**
- * The ContentPane to which all other graphical components are added.
+ * The southern panel for the buttons.
*/
- private JPanel jContentPane = null;
+ private JPanel buttonJPanel = null;
/**
- * The text area to which the groovy commands are entered
+ * Command history.
*/
- private JTextArea inputJTextArea = null;
+ private LinkedList<String> commandHistory = null;
/**
- * The OK button
+ * Counter that referes to the current entry in the command history.
*/
- private JButton okJButton = null;
+ private int commandHistoryIndex = 0;
/**
- * The sothern panel for the buttons
+ * Scroll pane for the output text area.
*/
- private JPanel buttonJPanel = null;
+ private JScrollPane ConsoleJScrollPane = null;
/**
- * The Console where local evants can be printed to.
+ * The console where local events can be printed to.
*/
private JTextArea consoleJTextArea = null;
/**
- * Splitpane to devide the main window into a input field for groovy
- * commands and an output area for the different networks.
+ * Map to store the EventListeners under the corresponding network name.
*/
- private JSplitPane jSplitPane = null;
+ private Map<String, EventListener> eventListeners;
/**
- * The tabbedpane that provides tabs for the different networks and the
- * console
+ * Scroll pane for the input text field for Groovy commands.
*/
- private JTabbedPane jTabbedPane = null;
+ private JScrollPane inputJScrollPane = null;
/**
- * Scrollpane for the input jTextArea for the goovy commands
+ * The text field to which Groovy commands may be entered.
*/
- private JScrollPane inputJScrollPane = null;
+ private JTextField inputJTextField = null;
/**
- * Scrollpane for the output jTextArea.
+ * The 'next' button.
*/
- private JScrollPane ConsoleJScrollPane = null;
+ private JButton jButtonNext = null;
/**
- * A hash map to store the EventListeners with the coresponding network name
+ * The 'previous' button.
*/
- private HashMap<String, EventListener> eventListeners = new HashMap<String, EventListener>();
+ private JButton jButtonPrevious = null;
/**
- * A hash map to store the entiries that have been entered into the shell.
+ * The content pane to which all other graphical components are added.
*/
- private LinkedList<String> shellEntries = null; // @jve:decl-index=0:
+ private JPanel jContentPane = null;
- private int listCounter = 0;
+ /**
+ * Splitpane to divide the main window into an input field for Groovy
+ * commands and an output area for the different networks.
+ */
+ private JSplitPane jSplitPane = null;
- private JButton jButtonNext = null;
+ /**
+ * The tabbed pane that provides tabs for the different networks and the
+ * console.
+ */
+ private JTabbedPane jTabbedPane = null;
- private JButton jButtonPrevious = null;
-
/**
- * This method initializes jButtonNext
- *
- * @return javax.swing.JButton
+ * Logger for this shell which is simply called "shell".
*/
- private JButton getJButtonNext() {
- if (jButtonNext == null) {
- jButtonNext = new JButton();
- jButtonNext.setText(">");
- jButtonNext.addMouseListener(new java.awt.event.MouseAdapter() {
- public void mouseReleased(java.awt.event.MouseEvent e) {
- displayNextInput();
- }
- });
- }
- return jButtonNext;
- }
+ private Logger logger;
/**
- * This method initializes jButtonPrevious
- *
- * @return javax.swing.JButton
+ * The 'OK' button.
*/
- private JButton getJButtonPrevious() {
- if (jButtonPrevious == null) {
- jButtonPrevious = new JButton();
- jButtonPrevious.setText("<");
- jButtonPrevious.addMouseListener(new java.awt.event.MouseAdapter() {
- public void mouseReleased(java.awt.event.MouseEvent e) {
- displayPreviousInput();
- }
- });
- }
- return jButtonPrevious;
- }
+ private JButton okJButton = null;
/**
- * Main method to start the Gui.
- *
- * @param args
+ * The shell that executes Groovy commands.
*/
- public static void main(String args[]) {
+ private GroovyShell shell;
- new RmiPuppetzShell();
- }
-
/**
- * Initializes the Gui and registers it as a listener to the netaNetwork
+ * Creates a new instance and initializes the GUI.
*/
- public RmiPuppetzShell() {
+ private RmiPuppetzShell() {
// create logger
- this.logger = Logger.getLogger("RmiPuppetzShell" + "."
- + this.getClass().getName());
-
+ this.logger = Logger.getLogger("shell");
this.logger.setLevel(Level.ALL);
// log entering
- this.logger.entering(this.getClass().getName(), "RmiPuppetzShell",
- new Object[] {});
+ this.logger.entering(this.getClass().getName(), "RmiPuppetzShell");
+ // initialize data structures
+ this.eventListeners = new HashMap<String, EventListener>();
+ this.commandHistory = new LinkedList<String>();
+
+ // initialize the GUI
initialize();
- // binds network on the shell
+ // bind this instance to the shell
try {
shell.setVariable("shell", this);
consoleJTextArea.append("Welcome, type \"shell.[method]\" to use!"
@@ -233,12 +208,58 @@
}
/**
- * Lookup an already running network.
+ * Adds a tab to the network.
*
+ * A tab is created in the lower area of the Gui that is supposed to print
+ * the output of an <code>EventManager<code> of a Network. To do this an
+ * <code>EventListener<code> is created and its stub is returned.
+ *
+ * @param tabName The name of the new tab.
+ * @return The RMI stub of the event listener added to the output tab.
+ */
+ public EventListener addLogTab(String tabName) {
+
+ // log entering
+ this.logger.entering(this.getClass().getName(), "addLogTab", tabName);
+
+ // create a scroll pane containing a text area
+ JScrollPane jScrollPane = new JScrollPane();
+ final JTextArea jTextArea = new JTextArea();
+ jScrollPane.getViewport().add(jTextArea);
+
+ // add the scroll pane to the tabbed pane
+ jTabbedPane.add(tabName, jScrollPane);
+
+ // Creating EventListener
+ EventListener el = new EventListener() {
+ public void handleEvent(Event event) {
+ jTextArea.append(event.getMessage() + "\n");
+ }
+ };
+ this.eventListeners.put(tabName, el);
+
+ // creating an EventListener stub
+ EventListener elStub = null;
+ try {
+ elStub = (EventListener) UnicastRemoteObject.exportObject(el, 0);
+ } catch (RemoteException e) {
+ this.logger.throwing(this.getClass().getName(), "addLogTab", e);
+ e.printStackTrace();
+ }
+
+ // log exiting and return stub
+ this.logger.exiting(this.getClass().getName(), "addLogTab");
+ return elStub;
+ }
+
+ /**
+ * Lookup an already running PuppeTor network.
+ *
* @param remoteHost
- * The IpAddress where the RMI registry is running.
+ * The IP address where the RMI registry is running.
* @param bindingName
- * The name whereby the stub is bound.
+ * The name to which the network is bound.
+ * @return Network reference.
* @throws MalformedURLException
* Thrown to indicate that a malformed URL has occurred. Either
* no legal protocol could be found in a specification string or
@@ -246,11 +267,10 @@
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
* @throws NotBoundException
- * A NotBoundException is thrown if an attempt is made to lookup
- * or unbind in the registry a name that has no associated
- * binding.
+ * Thrown if an attempt is made to lookup a name that has no
+ * associated binding.
*/
- public void connectNetwork(String remoteHost, String bindingName)
+ public Network connectNetwork(String remoteHost, String bindingName)
throws MalformedURLException, RemoteException, NotBoundException {
// log entering
@@ -264,7 +284,7 @@
// register eventlistener
network.getEventManager().addEventListener(addLogTab(bindingName));
- // binds network on the shell
+ // binds network to its name on the shell
try {
shell.setVariable(bindingName, network);
getConsoleJTextArea().append(
@@ -275,249 +295,214 @@
e.printStackTrace();
}
- // log exiting
- this.logger.exiting(this.getClass().getName(), "connectNetwork");
+ // log exiting and return reference to the network
+ this.logger.exiting(this.getClass().getName(), "connectNetwork",
+ network);
+ return network;
}
/**
- * An output stream that writes its output to a javax.swing.JTextArea
- * control.
+ * Displays the next command in the command area.
*/
- private class TextAreaOutputStream extends OutputStream {
- private JTextArea textControl;
-
- /**
- * Creates a new instance of TextAreaOutputStream which writes to the
- * specified instance of javax.swing.JTextArea control.
- *
- * @param control
- * A reference to the javax.swing.JTextArea control to which
- * the output must be redirected to.
- */
- public TextAreaOutputStream(JTextArea control) {
- textControl = control;
+ private void displayNextInput() {
+ if (!(commandHistory.size() == 0)) {
+ commandHistoryIndex--;
+ if (commandHistoryIndex < 0) {
+ commandHistoryIndex = commandHistory.size() - 1;
+ }
+ inputJTextField.setText(commandHistory.get(commandHistoryIndex));
}
+ }
- /**
- * Writes the specified byte as a character to the
- * javax.swing.JTextArea.
- *
- * @param b
- * The byte to be written as character to the JTextArea.
- */
- public void write(int b) throws IOException {
- // append the data as characters to the JTextArea control
- textControl.append(String.valueOf((char) b));
+ /**
+ * Displays the previous command in the command area.
+ */
+ private void displayPreviousInput() {
+ if (!(commandHistory.size() == 0)) {
+ commandHistoryIndex++;
+ if (commandHistoryIndex >= commandHistory.size()) {
+ commandHistoryIndex = 0;
+ }
+ inputJTextField.setText(commandHistory.get(commandHistoryIndex));
}
}
/**
- * This method initializes the window.
+ * Executes the command that is written to the command text field.
*/
- private void initialize() {
+ private void executeCommand() {
- // log entering
- this.logger.entering(this.getClass().getName(), "initialize");
- this.shellEntries = new LinkedList<String>();
- this.setSize(new Dimension(531, 256));
- this.setPreferredSize(new Dimension(100, 150));
- this.setContentPane(getJContentPane());
- this.setTitle("Rmi-Puppetz Shell");
- this.setVisible(true);
- this.setDefaultCloseOperation(EXIT_ON_CLOSE);
- shell = new GroovyShell();
+ Thread evaluationThread = new Thread() {
+ @Override
+ public void run() {
- // Create Printstream that writes to JTextArea
- PrintStream out = new PrintStream(new TextAreaOutputStream(
- getConsoleJTextArea()));
+ // log entering
+ logger.entering(this.getClass().getName(), "run");
- // redirect standard output stream to the TextAreaOutputStream
- System.setOut(out);
+ Script script = null;
+ try {
+ String input = inputJTextField.getText();
+ commandHistoryIndex = 0;
+ commandHistory.addFirst(input);
+ script = shell.parse(input);
+ } catch (Exception e1) {
+ consoleJTextArea.append("In correct input\n");
+ e1.printStackTrace();
+ logger.log(Level.WARNING, e1.getMessage());
+ return;
+ }
+ try {
+ script.run();
+ } catch (Exception e2) {
+ consoleJTextArea
+ .append("An error occured while performing script"
+ + "\n");
+ e2.printStackTrace();
+ logger.log(Level.WARNING, e2.getMessage());
+ return;
+ }
- // redirect error output stream to the TextAreaOutputStream
- System.setErr(out);
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "initialize");
+ // log exiting
+ logger.exiting(this.getClass().getName(), "run");
+ }
+ };
+ evaluationThread.setName("evaluationThread");
+ evaluationThread.start();
}
/**
- * This method initializes jContentPane
+ * This method initializes ConsoleJScrollPane
*
- * @return javax.swing.JPanel
+ * @return JScrollPane
*/
- private JPanel getJContentPane() {
- // log entering
- this.logger.entering(this.getClass().getName(), "getJContentPane");
- if (jContentPane == null) {
- jContentPane = new JPanel();
- jContentPane.setLayout(new BorderLayout());
- jContentPane.add(getJPanel(), BorderLayout.SOUTH);
- jContentPane.add(getJSplitPane(), BorderLayout.CENTER);
+ private JScrollPane getConsoleJScrollPane() {
+ if (ConsoleJScrollPane == null) {
+ ConsoleJScrollPane = new JScrollPane();
+ ConsoleJScrollPane.getViewport().add(getConsoleJTextArea());
}
+ return ConsoleJScrollPane;
+ }
- // log exiting
- this.logger.exiting(this.getClass().getName(), "getJContentPane");
- return jContentPane;
+ /**
+ * This method initializes consoleJTextArea
+ *
+ * @return JTextArea
+ */
+ private JTextArea getConsoleJTextArea() {
+ if (consoleJTextArea == null) {
+ consoleJTextArea = new JTextArea();
+ consoleJTextArea.setEditable(false);
+ consoleJTextArea.setName("Console");
+ }
+ return consoleJTextArea;
}
/**
* This method initializes inputJScrollPane
*
- * @return javax.swing.JTextArea
+ * @return JTextArea
*/
private JScrollPane getInputJScrollPane() {
- // log entering
- this.logger.entering(this.getClass().getName(), "getInputJScrollPane");
if (inputJScrollPane == null) {
inputJScrollPane = new JScrollPane();
inputJScrollPane.getViewport().add(getInputJTextArea());
}
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "getInputJScrollPane");
-
return inputJScrollPane;
}
/**
- * This method initializes inputJTextArea
+ * This method initializes inputJTextField
*
- * @return javax.swing.JTextArea
+ * @return JTextArea
*/
- private JTextArea getInputJTextArea() {
-
- // log entering
- this.logger.entering(this.getClass().getName(), "getInputJTextArea");
- if (inputJTextArea == null) {
- inputJTextArea = new JTextArea();
- inputJTextArea.setEditable(true);
+ private JTextField getInputJTextArea() {
+ if (inputJTextField == null) {
+ inputJTextField = new JTextField();
+ inputJTextField.setEditable(true);
+ inputJTextField.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ executeCommand();
+ }
+ });
}
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "getInputJTextArea");
- return inputJTextArea;
+ return inputJTextField;
}
/**
- * This method initializes ConsoleJScrollPane
+ * This method initializes okJButton.
*
- * @return javax.swing.JScrollPane
+ * @return JButton
*/
- private JScrollPane getConsoleJScrollPane() {
-
- // log entering
- this.logger.entering(this.getClass().getName(),
- "getConsoleJScrollPane", new Object[] {});
-
- if (ConsoleJScrollPane == null) {
- ConsoleJScrollPane = new JScrollPane();
- ConsoleJScrollPane.getViewport().add(getConsoleJTextArea());
+ private JButton getJButton() {
+ if (okJButton == null) {
+ okJButton = new JButton();
+ okJButton.setText("OK");
+ okJButton.addMouseListener(new MouseAdapter() {
+ public void mouseReleased(MouseEvent e) {
+ executeCommand();
+ }
+ });
}
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "getConsoleJScrollPane");
-
- return ConsoleJScrollPane;
+ return okJButton;
}
/**
- * This method initializes consoleJTextArea
+ * This method initializes jButtonNext
*
- * @return javax.swing.JTextArea
+ * @return JButton
*/
- private JTextArea getConsoleJTextArea() {
-
- // log entering
- this.logger.entering(this.getClass().getName(), "getConsoleJTextArea");
-
- if (consoleJTextArea == null) {
- consoleJTextArea = new JTextArea();
- consoleJTextArea.setEditable(false);
- consoleJTextArea.setName("Console");
+ private JButton getJButtonNext() {
+ if (jButtonNext == null) {
+ jButtonNext = new JButton();
+ jButtonNext.setText(">");
+ jButtonNext.addMouseListener(new MouseAdapter() {
+ public void mouseReleased(MouseEvent e) {
+ displayNextInput();
+ }
+ });
}
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "getConsoleJTextArea");
-
- return consoleJTextArea;
+ return jButtonNext;
}
/**
- * This method initializes okJButton.
+ * This method initializes jButtonPrevious
*
- * It also creates and adds an EventListener that evaluates the content of
- * the inputJTextArea in groovy shell.
- *
* @return javax.swing.JButton
*/
- private JButton getJButton() {
-
- // log entering
- this.logger.entering(this.getClass().getName(), "getJButton");
-
- if (okJButton == null) {
- okJButton = new JButton();
- okJButton.setText("OK");
- okJButton.addMouseListener(new java.awt.event.MouseAdapter() {
- public void mouseReleased(java.awt.event.MouseEvent e) {
-
- Thread evaluationThread = new Thread() {
- @Override
- public void run() {
- // log entering
- logger.entering(this.getClass().getName(), "run");
- Script script = null;
- try {
- String input = inputJTextArea.getText();
- listCounter = 0;
- shellEntries.addFirst(input);
- script = shell.parse(input);
- } catch (Exception e1) {
- consoleJTextArea.append("In correct input"
- + "\n");
- e1.printStackTrace();
- logger.log(Level.WARNING, e1.getMessage());
- return;
- }
- try {
- script.run();
- } catch (Exception e2) {
- consoleJTextArea
- .append("An error occured while performing script"
- + "\n");
- e2.printStackTrace();
- logger.log(Level.WARNING, e2.getMessage());
- return;
- }
-
- // log exiting
- logger.exiting(this.getClass().getName(), "run");
- }
- };
- evaluationThread.setName("evaluationThread");
- evaluationThread.start();
-
+ private JButton getJButtonPrevious() {
+ if (jButtonPrevious == null) {
+ jButtonPrevious = new JButton();
+ jButtonPrevious.setText("<");
+ jButtonPrevious.addMouseListener(new MouseAdapter() {
+ public void mouseReleased(MouseEvent e) {
+ displayPreviousInput();
}
});
}
+ return jButtonPrevious;
+ }
- // log exiting
- this.logger.exiting(this.getClass().getName(), "getJButton");
-
- return okJButton;
+ /**
+ * This method initializes jContentPane
+ *
+ * @return JPanel
+ */
+ private JPanel getJContentPane() {
+ if (jContentPane == null) {
+ jContentPane = new JPanel();
+ jContentPane.setLayout(new BorderLayout());
+ jContentPane.add(getJPanel(), BorderLayout.SOUTH);
+ jContentPane.add(getJSplitPane(), BorderLayout.CENTER);
+ }
+ return jContentPane;
}
/**
* This method initializes buttonJPanel
*
- * @return javax.swing.JPanel
+ * @return JPanel
*/
private JPanel getJPanel() {
-
- // log entering
- this.logger.entering(this.getClass().getName(), "getJPanel");
-
if (buttonJPanel == null) {
GridBagConstraints gridBagConstraints2 = new GridBagConstraints();
gridBagConstraints2.gridx = 0;
@@ -535,130 +520,70 @@
buttonJPanel.add(getJButtonNext(), gridBagConstraints1);
buttonJPanel.add(getJButtonPrevious(), gridBagConstraints2);
}
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "getJPanel");
-
return buttonJPanel;
}
/**
* This method initializes jSplitPane
*
- * @return javax.swing.JSplitPane
+ * @return JSplitPane
*/
private JSplitPane getJSplitPane() {
-
- // log entering
- this.logger.entering(this.getClass().getName(), "getJSplitPane");
-
if (jSplitPane == null) {
jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
getInputJScrollPane(), getJTabbedPane());
jSplitPane.setContinuousLayout(true);
}
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "getJSplitPane");
-
return jSplitPane;
}
/**
* This method initializes jTabbedPane
*
- * @return javax.swing.JTabbedPane
+ * @return JTabbedPane
*/
private JTabbedPane getJTabbedPane() {
-
- // log entering
- this.logger.entering(this.getClass().getName(), "getJTabbedPane");
-
if (jTabbedPane == null) {
jTabbedPane = new JTabbedPane();
jTabbedPane.add("Console", getConsoleJScrollPane());
}
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "getJTabbedPane");
-
return this.jTabbedPane;
}
/**
- * Adds a tab to the network.
- *
- * A tab is created in the lower area of the Gui that is supposed to print
- * the output of an <code>EventManager<code> of a Network. To do this an
- * <code>EventListener<code> is created and its stub is returned.
- *
- * @return the stub of the event Listener added to the output tab of a
- * registered network
+ * This method initializes the main window.
*/
- public EventListener addLogTab(String tabName) {
+ private void initialize() {
// log entering
- this.logger.entering(this.getClass().getName(), "addLogTab", tabName);
+ this.logger.entering(this.getClass().getName(), "initialize");
- // Creating ScrollPane & TextArea
- JScrollPane jScrollPane = new JScrollPane();
- final JTextArea jTextArea = new JTextArea();
- // Adding TextArea to ScrollPane's Viewport
- jScrollPane.getViewport().add(jTextArea);
- // add ScrollPane to TabbedPane
- jTabbedPane.add(tabName, jScrollPane);
- // Creating EventListener
- EventListener el = new EventListener() {
+ // initialize GUI elements
+ this.setSize(new Dimension(531, 256));
+ this.setPreferredSize(new Dimension(100, 150));
+ this.setContentPane(getJContentPane());
+ this.setTitle("Rmi-Puppetz Shell");
+ this.setVisible(true);
+ this.setDefaultCloseOperation(EXIT_ON_CLOSE);
- public void handleEvent(Event event) {
+ this.shell = new GroovyShell();
- jTextArea.append(event.getMessage() + "\n");
+ // create Printstream that writes to JTextArea
+ final JTextArea textArea = getConsoleJTextArea();
+ PrintStream out = new PrintStream(new OutputStream() {
+ @Override
+ public void write(int b) throws IOException {
+ textArea.append(String.valueOf((char) b));
}
+ });
- };
- this.eventListeners.put(tabName, el);
- // creating an EventListener stub
- EventListener elStub = null;
- try {
- elStub = (EventListener) UnicastRemoteObject.exportObject(el, 0);
- } catch (RemoteException e) {
- this.logger.throwing(this.getClass().getName(), "addLogTab", e);
- e.printStackTrace();
- }
- // log exiting
- this.logger.exiting(this.getClass().getName(), "addLogTab");
+ // redirect standard output stream to our text area
+ System.setOut(out);
- return elStub;
- }
+ // redirect error output stream to our text area
+ System.setErr(out);
- /**
- * This method cycles throught the previous inputs and displays them to the
- * gui.
- */
- private void displayPreviousInput() {
-
- if (!(shellEntries.size() == 0)) {
- listCounter++;
- if (listCounter >= shellEntries.size()) {
- listCounter = 0;
- }
- inputJTextArea.setText(shellEntries.get(listCounter));
- }
+ // log exiting and return reference to the network
+ this.logger.exiting(this.getClass().getName(), "initialize");
}
-
- /**
- * This method cycles throught the previous inputs in reverse order and
- * displays them to the gui.
- */
- private void displayNextInput() {
-
- if (!(shellEntries.size() == 0)) {
- listCounter--;
- if (listCounter < 0) {
- listCounter = shellEntries.size() - 1;
- }
- inputJTextArea.setText(shellEntries.get(listCounter));
- }
- }
-
-} // @jve:decl-index=0:visual-constraint="28,41"
+}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ClientApplicationImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ClientApplicationImpl.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ClientApplicationImpl.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -311,13 +311,13 @@
private RequestThread clientThread;
/**
- * Event manager to which all events concerning this client application are
- * notified.
+ * Event manager that handles all events concerning this client application.
*/
private EventManagerImpl eventManager;
/**
- * Logger for this client.
+ * Logger for this client which is called "client." plus the name of this
+ * client application.
*/
private Logger logger;
@@ -327,8 +327,8 @@
private int socksPort;
/**
- * Target name for the requests sent by this client; can be either a server
- * name/address or an onion address.
+ * Target name for the requests sent by this client; can be a publicly
+ * available URL or an onion address.
*/
private String targetName;
@@ -370,7 +370,7 @@
}
// create logger
- this.logger = Logger.getLogger("application." + clientApplicationName);
+ this.logger = Logger.getLogger("client." + clientApplicationName);
// log entering
this.logger.entering(this.getClass().getName(),
@@ -401,7 +401,7 @@
this.logger.exiting(this.getClass().getName(), "ClientApplicationImpl");
}
- public synchronized void performRequest(int retries,
+ public synchronized void startRequests(int retries,
long timeoutForEachRetry, boolean stopOnSuccess) {
// log entering
@@ -471,4 +471,16 @@
public String getClientApplicationName() {
return clientApplicationName;
}
+
+ public int getSocksPort() {
+ return socksPort;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public int getTargetPort() {
+ return targetPort;
+ }
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/DirectoryNodeImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/DirectoryNodeImpl.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/DirectoryNodeImpl.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -41,12 +41,12 @@
import java.util.TreeSet;
import de.uniba.wiai.lspi.puppetor.DirectoryNode;
-import de.uniba.wiai.lspi.puppetor.TorProcessException;
+import de.uniba.wiai.lspi.puppetor.PuppeTorException;
/**
* Implementation of <code>DirectoryNode</code>.
*
- * @author karsten
+ * @author kloesing
*/
@SuppressWarnings("serial")
public class DirectoryNodeImpl extends RouterNodeImpl implements DirectoryNode {
@@ -90,6 +90,9 @@
* has an invalid value.
* @throws RemoteException
* Thrown if an error occurs when accessed remotely.
+ * @throws PuppeTorException
+ * Thrown if an I/O problem occurs while writing the temporary
+ * <code>approved-routers</code> file.
*/
DirectoryNodeImpl(NetworkImpl network, String nodeName, int controlPort,
int socksPort, int orPort, int dirPort, String serverIpAddress)
@@ -111,10 +114,9 @@
// configure this node as an authoritative directory
this.configuration.add("AuthoritativeDirectory 1");
- // TODO make this a little bit more configurable---same as to
- // location of tor executable?
+ // TODO make this a little bit more configurable
this.configuration
- .add("RecommendedVersions 0.1.2.12-rc,0.1.2.7-alpha-dev,0.2.0.0-alpha-dev,0.2.0.2-alpha-dev,0.2.0.4-alpha-dev,0.2.0.4-alpha");
+ .add("RecommendedVersions 0.2.0.7-alpha,0.2.0.7-alpha-dev");
this.configuration.add("VersioningAuthoritativeDirectory 1");
@@ -136,15 +138,14 @@
this.logger.exiting(this.getClass().getName(), "DirectoryNodeImpl");
}
- public synchronized String determineDirServerString()
- throws TorProcessException {
+ public synchronized String getDirServerString() throws PuppeTorException,
+ RemoteException {
// log entering
- this.logger.entering(this.getClass().getName(),
- "determineDirServerString");
+ this.logger.entering(this.getClass().getName(), "getDirServerString");
// determine fingerprint
- String fingerprint = determineFingerprint();
+ String fingerprint = this.getFingerprint();
// cut off router nickname
fingerprint = fingerprint.substring(fingerprint.indexOf(" ") + 1);
@@ -155,32 +156,14 @@
+ " " + fingerprint;
// log exiting and return dir server string
- this.logger.exiting(this.getClass().getName(),
- "determineDirServerString", dirServerString);
+ this.logger.exiting(this.getClass().getName(), "getDirServerString",
+ dirServerString);
return dirServerString;
}
- public synchronized void writeApprovedRouters(Set<String> routers)
- throws TorProcessException, RemoteException {
+ public void addApprovedRouters(Set<String> routers) throws RemoteException {
// log entering
- this.logger.entering(this.getClass().getName(), "writeApprovedRouters",
- routers);
-
- // clear the existing set of approved routers
- this.approvedRouters.clear();
-
- // invoke addApprovedRouters to perform the actual work
- this.addApprovedRouters(routers);
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "writeApprovedRouters");
- }
-
- public void addApprovedRouters(Set<String> routers)
- throws TorProcessException, RemoteException {
-
- // log entering
this.logger.entering(this.getClass().getName(), "addApprovedRouters",
routers);
@@ -196,8 +179,39 @@
// known strings (if any)
this.approvedRouters.addAll(routers);
- // store the complete set of approved router strings to file
+ // log exiting
+ this.logger.exiting(this.getClass().getName(), "addApprovedRouters");
+ }
+
+ @Override
+ protected void determineFingerprint() {
+
+ // log entering
+ this.logger.entering(this.getClass().getName(), "determineFingerprint");
+
+ // create an empty approved-routers file to make Tor happy
try {
+ new File(this.workingDir.getAbsolutePath() + File.separator
+ + "approved-routers").createNewFile();
+ } catch (IOException e) {
+ PuppeTorException ex = new PuppeTorException(
+ "Could not write empty approved-routers file!", e);
+ this.caughtException = ex;
+ return;
+ }
+
+ // invoke overwritten method
+ super.determineFingerprint();
+ }
+
+ @Override
+ public synchronized void writeConfiguration() throws PuppeTorException {
+
+ // log entering
+ this.logger.entering(this.getClass().getName(), "writeConfiguration");
+
+ // write approved-routers file
+ try {
File approvedRoutersFile = new File(this.workingDir
.getAbsolutePath()
+ File.separator + "approved-routers");
@@ -208,39 +222,16 @@
}
bw.close();
} catch (IOException e) {
- TorProcessException ex = new TorProcessException(e);
+ PuppeTorException ex = new PuppeTorException(e);
this.logger.throwing(this.getClass().getName(),
- "addApprovedRouters", ex);
+ "writeConfiguration", ex);
throw ex;
}
+ // invoke overridden method
+ super.writeConfiguration();
+
// log exiting
- this.logger.exiting(this.getClass().getName(), "addApprovedRouters");
+ this.logger.exiting(this.getClass().getName(), "writeConfiguration");
}
-
- public synchronized String determineFingerprint()
- throws TorProcessException {
-
- // log entering
- this.logger.entering(this.getClass().getName(), "determineFingerprint");
-
- // check if the fingerprint has not been determined before
- if (this.fingerprint == null) {
-
- // create an empty approved-routers file to make Tor happy
- try {
- new File(this.workingDir.getAbsolutePath() + File.separator
- + "approved-routers").createNewFile();
- } catch (IOException e) {
- TorProcessException ex = new TorProcessException(
- "Could not write empty approved-routers file!", e);
- this.logger.throwing(this.getClass().getName(),
- "determineFingerprint", ex);
- throw ex;
- }
- }
-
- // invoke overwritten method
- return super.determineFingerprint();
- }
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/EventImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/EventImpl.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/EventImpl.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -79,15 +79,27 @@
* Either the log message that led to firing this event, or an
* internal message.
*/
- EventImpl(long occurrenceTime, String source, EventType type,
- String message) {
- // time may be 0 and type null
+ EventImpl(long occurrenceTime, String source, EventType type, String message) {
this.occurrenceTime = occurrenceTime;
this.source = source;
this.type = type;
this.message = message;
}
+ /**
+ * Creates a new <code>EventImpl</code>.
+ *
+ * @param source
+ * The source of this event.
+ * @param message
+ * Either the log message that led to firing this event, or an
+ * internal message.
+ */
+ EventImpl(String source, String message) {
+ this.source = source;
+ this.message = message;
+ }
+
public String getSource() {
return this.source;
}
@@ -117,9 +129,9 @@
@Override
public String toString() {
return this.getClass().getSimpleName() + ": occurenceTime="
- + new Date(this.occurrenceTime) + ", source=\""
- + this.source.toString() + "\", type=" + this.type.toString()
- + ", message=\"" + this.message + "\"";
+ + new Date(this.occurrenceTime) + ", source=\"" + this.source
+ + "\", type=" + this.type.getTypeName() + ", message=\""
+ + this.message + "\"";
}
/**
@@ -129,7 +141,7 @@
* The occurrence time of the event or of the corresponding log
* statement.
*/
- public void setOccurenceTime(long occurrenceTime) {
+ void setOccurenceTime(long occurrenceTime) {
this.occurrenceTime = occurrenceTime;
}
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/EventManagerImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/EventManagerImpl.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/EventManagerImpl.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -42,6 +42,7 @@
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
@@ -50,17 +51,17 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import de.uniba.wiai.lspi.puppetor.AliceEventType;
-import de.uniba.wiai.lspi.puppetor.BobEventType;
import de.uniba.wiai.lspi.puppetor.Event;
import de.uniba.wiai.lspi.puppetor.EventListener;
import de.uniba.wiai.lspi.puppetor.EventManager;
import de.uniba.wiai.lspi.puppetor.EventType;
-import de.uniba.wiai.lspi.puppetor.MiscEventType;
+import de.uniba.wiai.lspi.puppetor.HiddenServiceEventType;
import de.uniba.wiai.lspi.puppetor.NodeEventType;
/**
* Implementation of <code>EventManager</code>.
+ *
+ * @author kloesing
*/
@SuppressWarnings("serial")
public class EventManagerImpl extends UnicastRemoteObject implements
@@ -77,8 +78,8 @@
private Set<EventListener> eventHandlersForAllSources;
/**
- * Logger for this <code>EventManagerImpl</code> instance which is called
- * "event." plus the name of the network.
+ * Logger for this event manager which is called "event." plus the name of
+ * the network.
*/
private Logger logger;
@@ -88,8 +89,8 @@
private Map<String, List<Event>> observedEvents;
/**
- * Set of all registered event sources. This is required to cross-check
- * requests for events from a given source to avoid typos.
+ * Set of all registered event sources. This is required to ensure that
+ * requests for events from a given source specify valid event sources.
*/
private Set<String> eventSources;
@@ -103,6 +104,8 @@
* @throws IllegalArgumentException
* Thrown if the given <code>networkName</code> is either
* <code>null</code> or a zero-length string.
+ * @throws RemoteException
+ * Thrown if an error occurs when accessed remotely.
*/
EventManagerImpl(String networkName) throws RemoteException {
@@ -266,19 +269,17 @@
}
/**
- * An ordered list of all log statements that are yet unparsed.
+ * An ordered list of all log statements that are still unparsed.
*/
private List<EventImpl> unparsedLogStatements = new LinkedList<EventImpl>();
/**
- * TODO document me
+ * Stores the occurrence of an unparsed Tor log events that might result in
+ * an event. All such unparsed events are later parsed by a background
+ * thread in invocation order. Then, the occurrence time and the event type
+ * will be parsed from the log message; if the log message does not contain
+ * anything of interest, the event will be discarded.
*
- * stores either events produced by ourself or unparsed Tor log events for
- * later parsing by a background thread in invocation order
- *
- * time and type will be parsed from Tor log message; if message does not
- * contain anything of interest, the event will be discarded
- *
* @param source
* The event source.
* @param logMessage
@@ -287,16 +288,7 @@
* Thrown if the source is unknown.
*/
synchronized void observeUnparsedEvent(String source, String logMessage) {
-
- if (!this.eventSources.contains(source)) {
- IllegalArgumentException e = new IllegalArgumentException();
- this.logger.throwing(this.getClass().getName(),
- "observeInternalEvent", e);
- throw e;
- }
-
- this.unparsedLogStatements.add(new EventImpl(0, source, null,
- logMessage));
+ this.unparsedLogStatements.add(new EventImpl(source, logMessage));
notifyAll();
}
@@ -330,10 +322,12 @@
}
/**
- * Parse a log statement coming from Tor and see if it is interesting for
- * us.
+ * Parses a log statement coming from Tor and decides whether it is
+ * interesting for us.
*/
void parseNextEvent() {
+
+ // wait for the next event in the queue
EventImpl event = null;
synchronized (this) {
while (this.unparsedLogStatements.isEmpty()) {
@@ -342,15 +336,21 @@
} catch (InterruptedException e) {
}
}
-
event = this.unparsedLogStatements.remove(0);
}
+ // does the event contain a known source? if not, discard it
+ if (!this.eventSources.contains(event.getSource())) {
+ this.logger.log(Level.WARNING,
+ "Unknown event source while parsing an event: "
+ + event.getSource());
+ return;
+ }
+
// does the event require parsing? if not, process immediately
if (event.getType() != null) {
observeEvent(event);
} else {
-
String line = event.getMessage();
/*
@@ -362,11 +362,12 @@
Calendar c = Calendar.getInstance();
int currentYear = c.get(Calendar.YEAR);
+ // try to apply one of the event type patterns
for (Entry<Pattern, EventType> entry : eventTypePatterns.entrySet()) {
Matcher matcher = entry.getKey().matcher(line);
if (matcher.find()) {
SimpleDateFormat sdf = new SimpleDateFormat(
- "MMM dd HH:mm:ss.SSS");
+ "MMM dd HH:mm:ss.SSS", Locale.US);
Date logTime = sdf.parse(line, new ParsePosition(0));
c.setTimeInMillis(logTime.getTime());
c.set(Calendar.YEAR, currentYear);
@@ -378,12 +379,12 @@
}
}
}
-
}
/**
* Map of all patterns, that should be included when parsing log statements
- * coming from Tor, and the respective event types, that should be fired.
+ * coming from Tor, and the respective event types of the events that should
+ * be fired.
*/
Map<Pattern, EventType> eventTypePatterns;
@@ -394,7 +395,7 @@
/**
* Initializes the parsing engine with the standard log message patterns
- * that should be included in current Tor. Any further patterns should be
+ * that should be included in current Tor. Any further patterns need to be
* added by the test application manually.
*/
private void initializeEventTypePatterns() {
@@ -404,60 +405,61 @@
registerEventTypePattern("Tor has successfully opened a circuit. "
+ "Looks like client functionality is working.",
NodeEventType.NODE_CIRCUIT_OPENED);
- registerEventTypePattern("Established circuit .* as introduction "
- + "point for service .*",
- BobEventType.BOB_BUILT_INTRO_CIRC_SENDING_ESTABLISH_INTRO);
+ registerEventTypePattern(
+ "Established circuit .* as introduction "
+ + "point for service .*",
+ HiddenServiceEventType.BOB_BUILT_INTRO_CIRC_SENDING_ESTABLISH_INTRO);
registerEventTypePattern("Received INTRO_ESTABLISHED cell on "
+ "circuit .* for service .*",
- BobEventType.BOB_INTRO_ESTABLISHED_RECEIVED);
+ HiddenServiceEventType.BOB_INTRO_ESTABLISHED_RECEIVED);
registerEventTypePattern("Sending publish request for hidden "
- + "service .*", BobEventType.BOB_SENDING_PUBLISH_DESC);
+ + "service .*", HiddenServiceEventType.BOB_SENDING_PUBLISH_DESC);
registerEventTypePattern("Uploaded rendezvous descriptor",
- BobEventType.BOB_DESC_PUBLISHED_RECEIVED);
+ HiddenServiceEventType.BOB_DESC_PUBLISHED_RECEIVED);
registerEventTypePattern("Received INTRODUCE2 cell for service .* "
- + "on circ .*", BobEventType.BOB_INTRODUCE2_RECEIVED);
+ + "on circ .*", HiddenServiceEventType.BOB_INTRODUCE2_RECEIVED);
registerEventTypePattern("Done building circuit .* to rendezvous "
+ "with cookie .* for service .*",
- BobEventType.BOB_BUILT_REND_CIRC_SENDING_RENDEZVOUS1);
+ HiddenServiceEventType.BOB_BUILT_REND_CIRC_SENDING_RENDEZVOUS1);
registerEventTypePattern("begin is for rendezvous",
- BobEventType.BOB_APP_CONN_OPENED);
+ HiddenServiceEventType.BOB_APP_CONN_OPENED);
registerEventTypePattern("Got a hidden service request for ID '.*'",
- AliceEventType.ALICE_ONION_REQUEST_RECEIVED);
+ HiddenServiceEventType.ALICE_ONION_REQUEST_RECEIVED);
registerEventTypePattern("Fetching rendezvous descriptor for "
- + "service .*", AliceEventType.ALICE_SENDING_FETCH_DESC);
+ + "service .*", HiddenServiceEventType.ALICE_SENDING_FETCH_DESC);
registerEventTypePattern("Received rendezvous descriptor",
- AliceEventType.ALICE_DESC_FETCHED_RECEIVED);
+ HiddenServiceEventType.ALICE_DESC_FETCHED_RECEIVED);
registerEventTypePattern(
"Sending an ESTABLISH_RENDEZVOUS cell",
- AliceEventType.ALICE_BUILT_REND_CIRC_SENDING_ESTABLISH_RENDEZVOUS);
+ HiddenServiceEventType.ALICE_BUILT_REND_CIRC_SENDING_ESTABLISH_RENDEZVOUS);
registerEventTypePattern("Got rendezvous ack. This circuit is now "
+ "ready for rendezvous",
- AliceEventType.ALICE_RENDEZVOUS_ESTABLISHED_RECEIVED);
+ HiddenServiceEventType.ALICE_RENDEZVOUS_ESTABLISHED_RECEIVED);
registerEventTypePattern("introcirc is open",
- AliceEventType.ALICE_BUILT_INTRO_CIRC);
+ HiddenServiceEventType.ALICE_BUILT_INTRO_CIRC);
registerEventTypePattern("Sending an INTRODUCE1 cell",
- AliceEventType.ALICE_SENDING_INTRODUCE1);
+ HiddenServiceEventType.ALICE_SENDING_INTRODUCE1);
registerEventTypePattern("Received ack. Telling rend circ",
- AliceEventType.ALICE_INTRODUCE_ACK_RECEIVED);
- registerEventTypePattern("Got RENDEZVOUS2 cell from hidden service",
- AliceEventType.ALICE_RENDEZVOUS2_RECEIVED_APP_CONN_OPENED);
+ HiddenServiceEventType.ALICE_INTRODUCE_ACK_RECEIVED);
+ registerEventTypePattern(
+ "Got RENDEZVOUS2 cell from hidden service",
+ HiddenServiceEventType.ALICE_RENDEZVOUS2_RECEIVED_APP_CONN_OPENED);
registerEventTypePattern("Handling rendezvous descriptor post",
- MiscEventType.DIR_PUBLISH_DESC_RECEIVED);
+ HiddenServiceEventType.DIR_PUBLISH_DESC_RECEIVED);
registerEventTypePattern("Handling rendezvous descriptor get",
- MiscEventType.DIR_FETCH_DESC_RECEIVED);
+ HiddenServiceEventType.DIR_FETCH_DESC_RECEIVED);
registerEventTypePattern(
"Received an ESTABLISH_INTRO request on circuit .*",
- MiscEventType.IPO_RECEIVED_ESTABLISH_INTRO_SENDING_INTRO_ESTABLISHED);
+ HiddenServiceEventType.IPO_RECEIVED_ESTABLISH_INTRO_SENDING_INTRO_ESTABLISHED);
registerEventTypePattern(
"Received an INTRODUCE1 request on circuit .*",
- MiscEventType.IPO_RECEIVED_INTRODUCE1_SENDING_INTRODUCE2_AND_INTRODUCE_ACK);
+ HiddenServiceEventType.IPO_RECEIVED_INTRODUCE1_SENDING_INTRODUCE2_AND_INTRODUCE_ACK);
registerEventTypePattern(
"Received an ESTABLISH_RENDEZVOUS request on circuit .*",
- MiscEventType.RPO_RECEIVED_ESTABLISH_RENDEZVOUS_SENDING_RENDEZVOUS_ESTABLISHED);
+ HiddenServiceEventType.RPO_RECEIVED_ESTABLISH_RENDEZVOUS_SENDING_RENDEZVOUS_ESTABLISHED);
registerEventTypePattern(
"Got request for rendezvous from circuit .* to cookie .*",
- MiscEventType.RPO_RECEIVING_RENDEZVOUS1_SENDING_RENDEZVOUS2);
-
+ HiddenServiceEventType.RPO_RECEIVING_RENDEZVOUS1_SENDING_RENDEZVOUS2);
}
/**
@@ -465,10 +467,8 @@
* event history and propagates its occurrence to all registered event
* handlers.
*
- * @param source
- * The source of the given event.
* @param event
- * The event type.
+ * The observed event.
*/
private synchronized void observeEvent(Event event) {
@@ -494,7 +494,6 @@
// make a copy of the event handler set, because some event handlers
// might want to remove themselves from this set while handling the
// event
-
Set<EventListener> copyOfEventHandlers = new HashSet<EventListener>(
this.eventHandlers.get(source));
@@ -711,7 +710,7 @@
&& (timeLeft = endOfTime - System.currentTimeMillis()) > 0) {
this.logger.log(Level.FINEST, "We will wait for " + timeLeft
- + " millis for the next occurence of event type "
+ + " milliseconds for the next occurence of event type "
+ type + " from source " + source + "...");
try {
@@ -744,12 +743,38 @@
}
/**
- * Adds the given <code>name</code> as possible event source.
+ * Adds the given <code>source</code> as possible event source.
*
- * @param name
+ * @param source
* The name of the node, client, or server to add.
+ * @throws IllegalArgumentException
+ * Thrown if there is already an event source with this name.
*/
- void addEventSource(String name) {
- this.eventSources.add(name);
+ void addEventSource(String source) {
+
+ // log entering
+ this.logger.entering(this.getClass().getName(), "addEventSource",
+ source);
+
+ // check if source name is unique in this network
+ if (this.eventSources.contains(source)) {
+ IllegalArgumentException e = new IllegalArgumentException(
+ "There is already an event source with name " + source
+ + " in this network!");
+ this.logger
+ .throwing(this.getClass().getName(), "addEventSource", e);
+ throw e;
+ }
+
+ // add event source name
+ this.eventSources.add(source);
+
+ // log exiting
+ this.logger.exiting(this.getClass().getName(), "addEventSource");
}
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
}
Added: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/HiddenServiceImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/HiddenServiceImpl.java (rev 0)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/HiddenServiceImpl.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -0,0 +1,167 @@
+package de.uniba.wiai.lspi.puppetor.impl;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import de.uniba.wiai.lspi.puppetor.HiddenService;
+import de.uniba.wiai.lspi.puppetor.PuppeTorException;
+
+/**
+ * Implementation of <code>HiddenService</code>.
+ *
+ * @author kloesing
+ */
+public class HiddenServiceImpl implements HiddenService {
+
+ /**
+ * Logger for this node which is called "hidserv." plus the name of this
+ * hidden service.
+ */
+ protected Logger logger;
+
+ /**
+ * The node at which this hidden service is configured.
+ */
+ private ProxyNodeImpl node;
+
+ /**
+ * Name of the hidden service that will be used as name for the hidden
+ * service directory.
+ */
+ private String serviceName;
+
+ /**
+ * The TCP port on which the service will be available for requests.
+ */
+ private int servicePort;
+
+ /**
+ * The virtual TCP port that this hidden service runs on as it is announced
+ * to clients.
+ */
+ private int virtualPort;
+
+ /**
+ * Adds the entries for a hidden service to the configuration of this node.
+ *
+ * Creates a new <code>HiddenServiceImpl</code>.
+ *
+ * @param node
+ * The node at which this hidden service is configured.
+ * @param serviceName
+ * Name of the hidden service that will be used as name for the
+ * hidden service directory. May neither be <code>null</code>
+ * or a zero-length string.
+ * @param servicePort
+ * The TCP port on which the service will be available for
+ * requests. This can, but need not be different from the virtual
+ * port that is announced to clients. May not be negative or
+ * greater than 65535.
+ * @param virtualPort
+ * The virtual TCP port that this hidden service runs on as it is
+ * announced to clients. May not be negative or greater than
+ * 65535.
+ * @throws IllegalArgumentException
+ * Thrown if an invalid value is given for either of the
+ * parameters.
+ */
+ HiddenServiceImpl(ProxyNodeImpl node, String serviceName, int servicePort,
+ int virtualPort) {
+
+ // check if networkName can be used as logger name
+ if (serviceName == null || serviceName.length() == 0) {
+ throw new IllegalArgumentException("Invalid serviceName: "
+ + serviceName);
+ }
+
+ // create logger
+ this.logger = Logger.getLogger("hidserv." + serviceName);
+
+ // log entering
+ this.logger.entering(this.getClass().getName(), "HiddenServiceImpl",
+ new Object[] { node, serviceName, servicePort, virtualPort });
+
+ // check parameters
+ if (serviceName == null || serviceName.length() == 0 || servicePort < 0
+ || servicePort > 65535 || virtualPort < 0
+ || virtualPort > 65535) {
+ this.logger.log(Level.SEVERE,
+ "Illegal argument when adding hidden service!");
+ IllegalArgumentException e = new IllegalArgumentException();
+ this.logger.throwing(this.getClass().getName(), "addHiddenService",
+ e);
+ throw e;
+ }
+
+ // store parameter values
+ this.node = node;
+ this.serviceName = serviceName;
+ this.servicePort = servicePort;
+ this.virtualPort = virtualPort;
+
+ // log exiting
+ this.logger.exiting(this.getClass().getName(), "HiddenServiceImpl");
+ }
+
+ public String determineOnionAddress() throws PuppeTorException {
+
+ // log entering
+ this.logger.entering(this.getClass().getName(), "getOnionAddress");
+
+ // check if hidden service directory exists
+ File hiddenServiceFile = new File(this.node.getWorkingDir()
+ .getAbsolutePath()
+ + File.separator
+ + this.serviceName
+ + File.separator
+ + "hostname");
+ if (!hiddenServiceFile.exists()) {
+ this.logger.log(Level.SEVERE,
+ "Hidden service directory or hostname file does not exist: "
+ + hiddenServiceFile.getAbsolutePath());
+
+ PuppeTorException e = new PuppeTorException(
+ "Hidden service directory or hostname file does not exist: "
+ + hiddenServiceFile.getAbsolutePath());
+ this.logger.throwing(this.getClass().getName(), "getOnionAddress",
+ e);
+ throw e;
+ }
+
+ // read hostname from file
+ String address = null;
+ try {
+ BufferedReader br = new BufferedReader(new FileReader(
+ hiddenServiceFile));
+ address = br.readLine();
+ br.close();
+ } catch (IOException e) {
+ PuppeTorException ex = new PuppeTorException(
+ "Could not read hostname file!", e);
+ this.logger.throwing(this.getClass().getName(), "getOnionAddress",
+ ex);
+ throw ex;
+ }
+
+ // log exiting and return address
+ this.logger.exiting(this.getClass().getName(), "getOnionAddress",
+ address);
+ return address;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public int getServicePort() {
+ return servicePort;
+ }
+
+ public int getVirtualPort() {
+ return virtualPort;
+ }
+}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -34,7 +34,7 @@
import java.io.File;
import java.net.MalformedURLException;
import java.rmi.Naming;
-import java.rmi.NotBoundException;
+import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
@@ -53,13 +53,12 @@
import de.uniba.wiai.lspi.puppetor.EventListener;
import de.uniba.wiai.lspi.puppetor.EventManager;
import de.uniba.wiai.lspi.puppetor.Network;
-import de.uniba.wiai.lspi.puppetor.NetworkState;
import de.uniba.wiai.lspi.puppetor.NodeEventType;
import de.uniba.wiai.lspi.puppetor.NodeState;
import de.uniba.wiai.lspi.puppetor.ProxyNode;
+import de.uniba.wiai.lspi.puppetor.PuppeTorException;
import de.uniba.wiai.lspi.puppetor.RouterNode;
import de.uniba.wiai.lspi.puppetor.ServerApplication;
-import de.uniba.wiai.lspi.puppetor.TorProcessException;
/**
* Implementation of <code>Network</code>.
@@ -70,67 +69,6 @@
public class NetworkImpl extends UnicastRemoteObject implements Network {
/**
- * Internal thread class that is used to determine fingerprints in parallel.
- */
- private class FingerprintThread extends Thread {
-
- /**
- * The exception, if one is caught while trying to determine the
- * fingerprint of the node.
- */
- private TorProcessException caughtException = null;
-
- /**
- * The node of which the fingerprint shall be determined.
- */
- private RouterNode node = null;
-
- /**
- * Creates a new thread to determine the fingerprint of
- * <code>node</code>.
- *
- * @param node
- * The node of which the fingerprint shall be determined.
- */
- FingerprintThread(RouterNode node) {
-
- // log entering
- logger.entering(this.getClass().getName(), "FingerprintThread");
-
- // remember node reference
- this.node = node;
-
- // log exiting
- logger.exiting(this.getClass().getName(), "FingerprintThread");
- }
-
- @Override
- public void run() {
-
- // log entering
- logger.entering(this.getClass().getName(), "run");
-
- // determine fingerprint
- try {
- node.determineFingerprint();
- } catch (TorProcessException e) {
- logger.log(Level.SEVERE,
- "Caught an exception while determining fingerprint for "
- + "node " + node.toString() + "!");
- this.caughtException = e;
- } catch (RemoteException e) {
- logger.log(Level.SEVERE,
- "Caught a remote exception while determining fingerprint for "
- + "node " + node.toString() + "!");
- // TODO handle exception appropriately
- }
-
- // log exiting
- logger.exiting(this.getClass().getName(), "run");
- }
- }
-
- /**
* Internal thread class that is used to start Tor processes in parallel.
*/
private class NodeStarter extends Thread {
@@ -138,7 +76,7 @@
/**
* The exception, if one is caught while trying to start the node.
*/
- TorProcessException caughtException;
+ Exception caughtException;
/**
* The maximum time to wait for the Tor process to start in
@@ -191,15 +129,16 @@
// try to start node
this.success = this.node
.startNode(this.maximumTimeToWaitInMillis);
- } catch (TorProcessException e) {
- // if an exception is caught, store it, but don't throw it (the
- // thread wouldn't care)
+ } catch (PuppeTorException e) {
+ logger.log(Level.SEVERE,
+ "Caught an exception while starting node "
+ + node.toString() + "!");
this.caughtException = e;
} catch (RemoteException e) {
logger.log(Level.SEVERE,
- "Caught a remote exception while starting " + "node "
+ "Caught a remote exception while starting node "
+ node.toString() + "!");
- // TODO handle exception appropriately
+ this.caughtException = e;
}
// log exiting
@@ -208,24 +147,13 @@
}
/**
- * The fingerprints of all approved routers in the network configuration.
- */
- private HashSet<String> approvedRoutersFingerprints;
-
- /**
- * The fingerprints of all authoritative directories in the network
- * configuration.
- */
- private Set<String> authorizedDirectoriesFingerprints;
-
- /**
* Event manager to which all events concerning this network are notified.
*/
private EventManagerImpl eventManager;
/**
- * Logger for this <code>NetworkImpl</code> instance which is called
- * "network." plus the name of this network.
+ * Logger for this network which is called "network." plus the name of this
+ * network.
*/
private Logger logger;
@@ -236,48 +164,11 @@
private String networkName;
/**
- * The state of this network.
+ * All nodes contained in this network.
*/
- private NetworkState networkState = NetworkState.CONFIGURING_NODES;
-
- /**
- * All clients contained in this network. It is important that we store and
- * work only with interface types to assure that all operations could also
- * be performed by the application itself.
- */
- private Map<String, ClientApplication> clients = new HashMap<String, ClientApplication>();
-
- /**
- * All servers contained in this network. It is important that we store and
- * work only with interface types to assure that all operations could also
- * be performed by the application itself.
- */
- private Map<String, ServerApplication> servers = new HashMap<String, ServerApplication>();
-
- /**
- * All nodes contained in this network. It is important that we store and
- * work only with interface types to assure that all operations could also
- * be performed by the application itself.
- */
private Map<String, ProxyNode> nodes;
/**
- * Determines if the given <code>name</code> is unique in this network
- * (including the network name).
- *
- * @param name
- * Name to look up.
- * @return <code>true</code> if no entity was created with this name,
- * <code>false</code> otherwise.
- */
- private boolean isLocallyUnique(String name) {
- return (!this.clients.containsKey(name)
- && !this.servers.containsKey(name)
- && !this.nodes.containsKey(name) && !(this.getName()
- .equals(name)));
- }
-
- /**
* Directory that contains status information of all nodes contained in this
* network.
*/
@@ -387,20 +278,19 @@
this.logger.exiting(this.getClass().getName(), "NetworkImpl");
}
- public boolean allNodesUp() throws RemoteException {
+ /**
+ * Returns whether all nodes in this network are up, or not.
+ *
+ * @return <code>true</code> if all nodes are up, <code>false</code> if
+ * at least one node is not up.
+ * @throws RemoteException
+ * Thrown if an error occurs when accessed remotely.
+ */
+ private boolean allNodesUp() throws RemoteException {
// log entering
this.logger.entering(this.getClass().getName(), "allNodesUp");
- // nodes can only be up, when network is in state
- // NetworkState.NODES_STARTED.
- if (this.networkState != NetworkState.NODES_STARTED) {
-
- // log exiting and return false
- this.logger.exiting(this.getClass().getName(), "allNodesUp");
- return false;
- }
-
// fail on first node that is not up
for (ProxyNode node : this.nodes.values()) {
if (!eventManager.hasEventOccured(node.getNodeName(),
@@ -417,87 +307,48 @@
return true;
}
- public void configureAsPrivateNetwork() throws TorProcessException,
+ public void configureAsPrivateNetwork() throws PuppeTorException,
RemoteException {
// log entering
this.logger.entering(this.getClass().getName(),
"configureAsPrivateNetwork");
- // start threads to determine fingerprints for all directories and
- // routers in parallel
- Set<FingerprintThread> fingerprintThreads = new HashSet<FingerprintThread>();
- for (ProxyNode node : nodes.values()) {
- if (node instanceof RouterNode) {
- RouterNode dirOrRouterNode = (RouterNode) node;
- FingerprintThread fingerprintThread = new FingerprintThread(
- dirOrRouterNode);
- fingerprintThread.setName(node.getNodeName()
- + " Fingerprint Resolver");
- fingerprintThreads.add(fingerprintThread);
- fingerprintThread.start();
- }
- }
-
- // wait for all fingerprints to be determined
- for (FingerprintThread fingerprintThread : fingerprintThreads) {
-
- // join fingerprint determination one after the other
- try {
- fingerprintThread.join();
- } catch (InterruptedException e) {
- // ignore; TODO really?!
- logger.log(Level.WARNING,
- "Joining fingerprint thread was interrupted.");
- }
-
- // if any thread has caught an exception, throw that exception now
- if (fingerprintThread.caughtException != null) {
- this.logger.throwing(this.getClass().getName(),
- "configureAsPrivateNetwork",
- fingerprintThread.caughtException);
- throw fingerprintThread.caughtException;
- }
- }
-
- // read DirServer strings for all directories from memory; they should
- // have been read from disk before, so that this will perform really
- // fast
- this.authorizedDirectoriesFingerprints = new HashSet<String>();
+ // read DirServer strings for all directories
+ List<String> authorizedDirectoriesFingerprints = new ArrayList<String>();
for (ProxyNode node : this.nodes.values()) {
if (node instanceof DirectoryNode) {
DirectoryNode dirNode = (DirectoryNode) node;
- this.authorizedDirectoriesFingerprints.add(dirNode
- .determineDirServerString());
+ authorizedDirectoriesFingerprints.add(dirNode
+ .getDirServerString());
}
}
// configure nodes
for (ProxyNode node : this.nodes.values()) {
if (node.getNodeState() == NodeState.CONFIGURING) {
- node
- .configureDirServers(this.authorizedDirectoriesFingerprints);
+
+ // add to configuration
+ node.addConfigurations(authorizedDirectoriesFingerprints);
}
}
- // read fingerprints for all directories and routers from memory; they
- // should have been read from disk before, so that this will perform
- // really fast
- this.approvedRoutersFingerprints = new HashSet<String>();
+ // read fingerprints for all directories and routers
+ HashSet<String> approvedRoutersFingerprints = new HashSet<String>();
for (ProxyNode node : this.nodes.values()) {
if (node instanceof RouterNode) {
RouterNode routerOrDirNode = (RouterNode) node;
- this.approvedRoutersFingerprints.add(routerOrDirNode
- .determineFingerprint());
+ approvedRoutersFingerprints.add(routerOrDirNode
+ .getFingerprint());
}
}
- // write fingerprints for all directories and routers to
+ // write fingerprints for all directories and routers to the
// approved-routers file
for (ProxyNode node : this.nodes.values()) {
if (node instanceof DirectoryNode) {
DirectoryNode dirNode = (DirectoryNode) node;
- dirNode.writeApprovedRouters(this.approvedRoutersFingerprints);
+ dirNode.addApprovedRouters(approvedRoutersFingerprints);
}
}
@@ -514,22 +365,10 @@
new Object[] { clientApplicationName, targetAddress,
targetPort, socksPort });
- // check if client name is locally unique
- if (!this.isLocallyUnique(clientApplicationName)) {
- IllegalArgumentException e = new IllegalArgumentException(
- "There is already an entity with name "
- + clientApplicationName + " in this network!");
- this.logger.throwing(this.getClass().getName(), "createClient", e);
- throw e;
- }
-
// create client; parameter checking is done in constructor
ClientApplicationImpl client = new ClientApplicationImpl(this,
clientApplicationName, targetAddress, targetPort, socksPort);
- // add new client to clients collection
- this.clients.put(clientApplicationName, client);
-
// add name to event manager as event source
this.eventManager.addEventSource(clientApplicationName);
@@ -547,24 +386,6 @@
new Object[] { nodeName, controlPort, socksPort, orPort,
dirPort, serverIpAddress });
- // check state
- if (this.networkState != NetworkState.CONFIGURING_NODES) {
- IllegalStateException e = new IllegalStateException();
- this.logger.throwing(this.getClass().getName(), "createDirectory",
- e);
- throw e;
- }
-
- // check if node name is locally unique
- if (!this.isLocallyUnique(nodeName)) {
- IllegalArgumentException e = new IllegalArgumentException(
- "There is already an entity with name " + nodeName
- + " in this network!");
- this.logger.throwing(this.getClass().getName(), "createDirectory",
- e);
- throw e;
- }
-
// create directory node; parameter checking is done in constructor
DirectoryNode dir = new DirectoryNodeImpl(this, nodeName, controlPort,
socksPort, orPort, dirPort, serverIpAddress);
@@ -635,22 +456,13 @@
return dir;
}
- public synchronized ProxyNode createProxy(String nodeName, int controlPort,
- int socksPort) throws RemoteException {
+ public ProxyNode createProxy(String nodeName, int controlPort, int socksPort)
+ throws RemoteException {
// log entering
this.logger.entering(this.getClass().getName(), "createProxy",
new Object[] { nodeName, controlPort, socksPort });
- // check if node name is locally unique
- if (!this.isLocallyUnique(nodeName)) {
- IllegalArgumentException e = new IllegalArgumentException(
- "There is already an entity with name " + nodeName
- + " in this network!");
- this.logger.throwing(this.getClass().getName(), "createProxy", e);
- throw e;
- }
-
// create proxy node; parameter checking is done in constructor
ProxyNode proxy = new ProxyNodeImpl(this, nodeName, controlPort,
socksPort);
@@ -694,14 +506,6 @@
new Object[] { nodeName, controlPort, socksPort, orPort,
dirPort, serverIpAddress });
- // check if node name is locally unique
- if (!this.isLocallyUnique(nodeName)) {
- IllegalArgumentException e = new IllegalArgumentException(
- "There is already an entity with name " + nodeName
- + " in this network!");
- this.logger.throwing(this.getClass().getName(), "createRouter", e);
- throw e;
- }
// create router node; parameter checking is done in constructor
RouterNode router = new RouterNodeImpl(this, nodeName, controlPort,
socksPort, orPort, dirPort, serverIpAddress);
@@ -778,22 +582,10 @@
this.logger.entering(this.getClass().getName(), "createServer",
new Object[] { serverApplicationName, serverPort });
- // check if server name is locally unique
- if (!this.isLocallyUnique(serverApplicationName)) {
- IllegalArgumentException e = new IllegalArgumentException(
- "There is already an entity with name "
- + serverApplicationName + " in this network!");
- this.logger.throwing(this.getClass().getName(), "createServer", e);
- throw e;
- }
-
// create server; parameter checking is done in constructor
ServerApplicationImpl server = new ServerApplicationImpl(this,
serverApplicationName, serverPort);
- // add new server to servers collection
- this.servers.put(serverApplicationName, server);
-
// add name to event manager as event source
this.eventManager.addEventSource(serverApplicationName);
@@ -830,28 +622,14 @@
return this.eventManager;
}
- public NetworkState getNetworkState() {
- return this.networkState;
- }
-
public File getWorkingDirectory() {
return this.workingDir;
}
- public ProxyNode getProxyNode(String nodeName) {
+ public ProxyNode getNode(String nodeName) {
return this.nodes.get(nodeName);
}
- public RouterNode getRouterNode(String nodeName) {
- ProxyNode node = this.nodes.get(nodeName);
- return (node instanceof RouterNode ? (RouterNode) node : null);
- }
-
- public DirectoryNode getDirectoryNode(String nodeName) {
- ProxyNode node = this.nodes.get(nodeName);
- return (node instanceof DirectoryNode ? (DirectoryNode) node : null);
- }
-
public Map<String, ProxyNode> getAllProxyNodes() {
Map<String, ProxyNode> result = new HashMap<String, ProxyNode>();
for (String nodeName : this.nodes.keySet()) {
@@ -885,18 +663,27 @@
return result;
}
+ public Map<String, ProxyNode> getAllNodes() {
+ return new HashMap<String, ProxyNode>(nodes);
+ }
+
public boolean hupUntilUp(int tries, long hupInterval)
- throws TorProcessException, RemoteException {
+ throws PuppeTorException, RemoteException {
// log entering
this.logger.entering(this.getClass().getName(), "hupUntilUp",
new Object[] { tries, hupInterval });
- // check state
- if (this.networkState != NetworkState.NODES_STARTED) {
- IllegalStateException e = new IllegalStateException();
- this.logger.throwing(this.getClass().getName(), "hupUntilUp", e);
- throw e;
+ // check if all nodes are running
+ for (ProxyNode node : this.nodes.values()) {
+ if (node.getNodeState() != NodeState.RUNNING) {
+ IllegalStateException e = new IllegalStateException(
+ "All nodes must be running before sending them HUP "
+ + "commands!");
+ this.logger
+ .throwing(this.getClass().getName(), "hupUntilUp", e);
+ throw e;
+ }
}
// check if nodes are already up; if so, return immediately
@@ -966,27 +753,49 @@
return false;
}
- public void shutdownNodes() throws TorProcessException, RemoteException {
+ public void hupAllNodes() throws PuppeTorException, RemoteException {
// log entering
- this.logger.entering(this.getClass().getName(), "shutdownNodes");
+ this.logger.entering(this.getClass().getName(), "hupAllNodes");
- // check state
- if (this.networkState != NetworkState.NODES_STARTED) {
- IllegalStateException e = new IllegalStateException();
- this.logger.throwing(this.getClass().getName(), "shutdownNodes", e);
- throw e;
+ // check if all nodes are running
+ for (ProxyNode node : this.nodes.values()) {
+ if (node.getNodeState() != NodeState.RUNNING) {
+ IllegalStateException e = new IllegalStateException(
+ "All nodes must be running before sending them HUP "
+ + "commands!");
+ this.logger
+ .throwing(this.getClass().getName(), "hupUntilUp", e);
+ throw e;
+ }
}
+ // send a HUP signal to all nodes
+ for (ProxyNode node : this.nodes.values()) {
+ this.logger.log(Level.FINE, "Sending HUP to node "
+ + node.toString());
+ node.hup();
+ }
+
+ // no retries left and not all nodes are up; log exiting and return
+ // failure
+ this.logger.exiting(this.getClass().getName(), "hupAllNodes");
+ }
+
+ public void shutdownNodes() throws PuppeTorException, RemoteException {
+
+ // log entering
+ this.logger.entering(this.getClass().getName(), "shutdownNodes");
+
// iteratively shut down all running nodes; if an exception is caught,
// continue shutting down the other nodes and throw the first exception
// subsequently
- TorProcessException firstCaughtException = null;
+ PuppeTorException firstCaughtException = null;
for (ProxyNode node : this.nodes.values()) {
if (node.getNodeState() == NodeState.RUNNING) {
try {
node.shutdown();
- } catch (TorProcessException e) {
+ } catch (PuppeTorException e) {
if (firstCaughtException != null) {
firstCaughtException = e;
}
@@ -994,9 +803,6 @@
}
}
- // change network state
- this.networkState = NetworkState.NODES_SHUT_DOWN;
-
// if an exception was caught during shutting down nodes, throw the
// first caught exception
if (firstCaughtException != null) {
@@ -1010,17 +816,22 @@
}
public boolean startNodes(long maximumTimeToWaitInMillis)
- throws TorProcessException {
+ throws PuppeTorException, RemoteException {
// log entering
this.logger.entering(this.getClass().getName(), "startNodes",
maximumTimeToWaitInMillis);
- // check state
- if (this.networkState != NetworkState.CONFIGURATIONS_WRITTEN) {
- IllegalStateException e = new IllegalStateException();
- this.logger.throwing(this.getClass().getName(), "startNodes", e);
- throw e;
+ // check node states
+ for (ProxyNode node : this.nodes.values()) {
+ if (node.getNodeState() != NodeState.CONFIGURATION_WRITTEN) {
+ IllegalStateException e = new IllegalStateException(
+ "All configurations must be written before starting "
+ + "nodes!");
+ this.logger
+ .throwing(this.getClass().getName(), "startNodes", e);
+ throw e;
+ }
}
// check parameter
@@ -1059,11 +870,16 @@
return false;
}
- // if node start threw an exception, throw that exception now
- if (nodeStarter.caughtException != null) {
+ // if any thread has caught an exception, throw that exception now
+ Exception caughtException = nodeStarter.caughtException;
+ if (caughtException != null) {
+ PuppeTorException ex = new PuppeTorException(
+ "Exception while starting node "
+ + nodeStarter.node.getNodeName(),
+ caughtException);
this.logger.throwing(this.getClass().getName(), "startNodes",
- nodeStarter.caughtException);
- throw nodeStarter.caughtException;
+ ex);
+ throw ex;
}
// if node start did not succeed in the given time, fail
@@ -1085,9 +901,6 @@
this.logger.log(Level.FINE, "Starting nodes was successful and took "
+ ((after - before) / 1000) + " seconds.", this.networkName);
- // change state
- this.networkState = NetworkState.NODES_STARTED;
-
// log exiting and return true
this.logger.exiting(this.getClass().getName(), "startNodes", true);
return true;
@@ -1096,14 +909,15 @@
@Override
public String toString() {
return this.getClass().getSimpleName() + ": networkName=\""
- + this.networkName + "\", networkState="
- + this.networkState.toString() + ", nodes.size()="
- + this.nodes.size();
+ + this.networkName;
}
- public void writeConfigurations() throws TorProcessException,
- RemoteException {
+ public String getNetworkName() {
+ return this.networkName;
+ }
+ public void writeConfigurations() throws PuppeTorException, RemoteException {
+
// log entering
this.logger.entering(this.getClass().getName(), "writeConfigurations");
@@ -1112,297 +926,77 @@
node.writeConfiguration();
}
- // change state if necessary
- if (this.networkState == NetworkState.CONFIGURING_NODES) {
- this.networkState = NetworkState.CONFIGURATIONS_WRITTEN;
- }
-
// log exiting
this.logger.exiting(this.getClass().getName(), "writeConfigurations");
}
- public String getName() {
- return this.networkName;
- }
+ public void configureAsInterconnectedPrivateNetwork(Network remoteNetwork)
+ throws PuppeTorException, RemoteException {
- public void addApprovedRouters(Set<String> approvedRoutersString)
- throws RemoteException, TorProcessException {
-
// log entering
- this.logger.entering(this.getClass().getName(), "addApprovedRouters",
- approvedRoutersString);
+ logger.entering(this.getClass().getName(), "mergeNetworks",
+ remoteNetwork);
- for (ProxyNode tempNode : nodes.values()) {
- if (tempNode instanceof DirectoryNode) {
- DirectoryNode tempDirNode = (DirectoryNode) tempNode;
- tempDirNode.addApprovedRouters(approvedRoutersString);
- }
+ // collect dir strings from this and the remote network
+ List<String> ourDirServerStrings = new ArrayList<String>();
+ for (DirectoryNode directory : this.getAllDirectoryNodes().values()) {
+ ourDirServerStrings.add(directory.getDirServerString());
}
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "addApprovedRouters");
- }
-
- public void addDirectoryStrings(List<String> dirServerStrings)
- throws RemoteException, TorProcessException {
-
- // log entering
- this.logger.entering(this.getClass().getName(), "addDirectoryStrings",
- dirServerStrings);
-
- // add configuration strings to all nodes
- for (ProxyNode node : this.nodes.values()) {
- node.addConfigurations(dirServerStrings);
+ List<String> remoteDirServerStrings = new ArrayList<String>();
+ for (DirectoryNode directory : remoteNetwork.getAllDirectoryNodes()
+ .values()) {
+ remoteDirServerStrings.add(directory.getDirServerString());
}
- // log exiting
- this.logger.exiting(this.getClass().getName(), "addDirectoryStrings");
- }
-
- /* ***** TODO The following code is still unconfirmed!! ***** */
-
- public void addEventListener(EventListener listener) throws RemoteException {
-
- // log entering
- logger.entering(this.getClass().getName(), "addEventListener");
-
- // register the listener
- this.eventManager.addEventListener(listener);
-
- // log exiting
- logger.exiting(this.getClass().getName(), "addEventListener");
- }
-
- public Network connectNetwork(String remoteHost, String bindingName)
- throws MalformedURLException, RemoteException, NotBoundException {
-
- // log entering
- logger.entering(this.getClass().getName(), "connectNetwork");
-
- // network lookup
- Network network = (Network) Naming.lookup("rmi://" + remoteHost + "/"
- + bindingName);
-
- // log exiting
- logger.exiting(this.getClass().getName(), "connectNetwork");
- return network;
- }
-
- public void mergeNetworks(Network remoteNetwork) throws RemoteException {
-
- // log entering
- logger.entering(this.getClass().getName(), "mergeNetworks");
- try {
- // lookup to recognize which network is without directories
- if (this.getAllDirectoryNodes().size() > 0) {
- if (remoteNetwork.getAllDirectoryNodes().size() > 0) {
- configureAsWithDir(this, remoteNetwork);
- // log exiting
- logger.exiting(this.getClass().getName(), "mergeNetworks");
- } else {
- configureAsWithoutDir(this, remoteNetwork);
- // log exiting
- logger.exiting(this.getClass().getName(), "mergeNetworks");
- }
- } else {
- configureAsWithoutDir(remoteNetwork, this);
- // log exiting
- logger.exiting(this.getClass().getName(), "mergeNetworks");
- }
- } catch (RemoteException e) {
- logger.log(Level.SEVERE,
- "Caught a remote exception while merging networks!");
+ // add dir strings of local directories to all nodes of the other
+ // network and vice versa
+ for (ProxyNode node : remoteNetwork.getAllNodes().values()) {
+ node.addConfigurations(ourDirServerStrings);
}
- }
-
- private void configureAsWithoutDir(Network first, Network second) {
-
- // log entering
- logger.entering(this.getClass().getName(), "configureAsWithoutDir");
-
- try {
- // adds the directory strings to the network without
- exchangeDirectories(first, second);
-
- // writes configuration to the network
- second.writeConfigurations();
-
- // starts the router in the without network
- startRouters(second);
-
- // hups the router in the without network
- hupRouters(second);
- // adds the new router fingerprints to the directories
- exchangeFingerprints(second, first);
-
- // hups the directories
- hupDirectories(first);
-
- // log exiting
- logger.exiting(this.getClass().getName(), "configureAsWithoutDir");
-
- } catch (RemoteException e) {
- logger.log(Level.SEVERE,
- "Caught a remote exception while configureAsWithoutDir!");
- } catch (TorProcessException e) {
- logger
- .log(Level.SEVERE,
- "Caught a tor process exception while configureAsWithoutDir!");
+ for (ProxyNode node : this.getAllNodes().values()) {
+ node.addConfigurations(remoteDirServerStrings);
}
- }
- private void configureAsWithDir(Network first, Network second) {
-
- // log entering
- logger.entering(this.getClass().getName(), "configureAsWithDir");
-
- try {
- // adds the directory strings to the other network
- exchangeDirectories(first, second);
- exchangeDirectories(second, first);
-
- // adds the new router fingerprints to the directories
- exchangeFingerprints(first, second);
- exchangeFingerprints(second, first);
-
- // writes configuration to files
- first.writeConfigurations();
- second.writeConfigurations();
-
- // hups the directories
- hupDirectories(first);
- hupDirectories(second);
-
- // hups the routers
- hupRouters(first);
- hupRouters(second);
-
- // log exiting
- logger.exiting(this.getClass().getName(), "configureAsWithDir");
-
- } catch (RemoteException e) {
- logger.log(Level.SEVERE,
- "Caught a remote exception while configureAsWithDir!");
- } catch (TorProcessException e) {
- logger.log(Level.SEVERE,
- "Caught a tor process exception while configureAsWithDir!");
+ // collect router fingerprints from all routers in this and the remote
+ // network
+ Set<String> ourApprovedRoutersStrings = new TreeSet<String>();
+ for (RouterNode router : this.getAllRouterNodes().values()) {
+ ourApprovedRoutersStrings.add(router.getFingerprint());
}
- }
-
- private void exchangeDirectories(Network first, Network second)
- throws RemoteException, TorProcessException {
-
- // log entering
- logger.entering(this.getClass().getName(), "exchangeDirectories");
-
- // collects all directories from network
- HashMap<String, DirectoryNode> directories = (HashMap<String, DirectoryNode>) first
- .getAllDirectoryNodes();
- List<String> dirServerStrings = new ArrayList<String>();
-
- // adds the directory strings to the collection
- for (DirectoryNode directory : directories.values()) {
- dirServerStrings.add(directory.determineDirServerString());
+ Set<String> remoteApprovedRoutersStrings = new TreeSet<String>();
+ for (RouterNode router : remoteNetwork.getAllRouterNodes().values()) {
+ remoteApprovedRoutersStrings.add(router.getFingerprint());
}
- // adds the directory strings to the routers
- second.addDirectoryStrings(dirServerStrings);
-
- // log exiting
- logger.exiting(this.getClass().getName(), "exchangeDirectories");
- }
-
- private void exchangeFingerprints(Network first, Network second)
- throws RemoteException, TorProcessException {
-
- // log entering
- logger.entering(this.getClass().getName(), "exchangeFingerprints");
-
- // collects all routers from network
- HashMap<String, RouterNode> routers = (HashMap<String, RouterNode>) first
- .getAllRouterNodes();
- Set<String> approvedRoutersStrings = new TreeSet<String>();
-
- // adds the fingerprint strings to the collection
- for (ProxyNode router : routers.values()) {
- if (router instanceof RouterNode) {
- RouterNode localRouter = (RouterNode) router;
- approvedRoutersStrings.add(localRouter.getNodeName() + " "
- + localRouter.getFingerprint());
- }
+ // add the fingerprints of local routers and directories to the
+ // directories of the other network and vice versa
+ for (DirectoryNode node : remoteNetwork.getAllDirectoryNodes().values()) {
+ node.addApprovedRouters(ourApprovedRoutersStrings);
}
-
- // adds the fingerprint strings to the directories
- second.addApprovedRouters(approvedRoutersStrings);
-
- // log exiting
- logger.exiting(this.getClass().getName(), "exchangeFingerprints");
- }
-
- private void startRouters(Network network) throws RemoteException,
- TorProcessException {
-
- // log entering
- logger.entering(this.getClass().getName(), "startRouters");
-
- // collects all routers from network
- HashMap<String, RouterNode> routers = (HashMap<String, RouterNode>) network
- .getAllRouterNodes();
-
- // starts all router
- for (RouterNode router : routers.values()) {
- router.startNode(5000);
+ for (DirectoryNode node : this.getAllDirectoryNodes().values()) {
+ node.addApprovedRouters(remoteApprovedRoutersStrings);
}
// log exiting
- logger.exiting(this.getClass().getName(), "startRouters");
+ logger.exiting(this.getClass().getName(), "mergeNetworks");
}
- private void hupDirectories(Network network) throws RemoteException,
- TorProcessException {
+ public void addTemplateConfiguration(Class<? extends ProxyNode> nodeClass,
+ String templateConfigurationString) {
// log entering
- logger.entering(this.getClass().getName(), "hupDirectories");
+ logger.entering(this.getClass().getName(), "addTemplateConfiguration",
+ new Object[] { nodeClass, templateConfigurationString });
- // collects all directories from network
- HashMap<String, DirectoryNode> directories = (HashMap<String, DirectoryNode>) network
- .getAllDirectoryNodes();
-
- // hups all directories
- for (DirectoryNode directory : directories.values()) {
- directory.hup();
- }
-
- // log exiting
- logger.exiting(this.getClass().getName(), "hupDirectories");
- }
-
- private void hupRouters(Network network) throws RemoteException,
- TorProcessException {
-
- // log entering
- logger.entering(this.getClass().getName(), "hupDirectories");
-
- // collects all routers from network
- HashMap<String, RouterNode> routers = (HashMap<String, RouterNode>) network
- .getAllRouterNodes();
-
- // hups all router
- for (RouterNode router : routers.values()) {
- router.hup();
- }
-
- // log exiting
- logger.exiting(this.getClass().getName(), "hupRouters");
- }
-
- public void addTemplateConfiguration(Class<? extends ProxyNode> nodeClass,
- String templateConfigurationString) {
+ // add template string to local map
if (!this.templateConfigurations.containsKey(nodeClass)) {
this.templateConfigurations.put(nodeClass, new ArrayList<String>());
}
this.templateConfigurations.get(nodeClass).add(
templateConfigurationString);
+
+ // log exiting
+ logger.exiting(this.getClass().getName(), "addTemplateConfiguration");
}
/**
@@ -1423,4 +1017,37 @@
}
}
}
+
+ public boolean bindAtRmiregistry() throws RemoteException {
+
+ // log entering
+ logger.entering(this.getClass().getName(), "bindAtRmiregistry");
+
+ // set the RMISecurityManager
+ System.setSecurityManager(new RMISecurityManager());
+
+ // bind the network to the rmiregistry
+ try {
+ Naming.rebind("//127.0.0.1/" + networkName, this);
+ } catch (MalformedURLException e) {
+ this.logger.log(Level.WARNING,
+ "URL to bind this network to is malformed!", e);
+ logger.exiting(this.getClass().getName(), "bindAtRmiregistry",
+ false);
+ return false;
+ }
+
+ // log exiting
+ logger.exiting(this.getClass().getName(), "bindAtRmiregistry", true);
+ return true;
+ }
+
+ /**
+ * Returns the current port number and increments it afterwards.
+ *
+ * @return The current port number.
+ */
+ int getNextPortNumber() {
+ return this.portCounter++;
+ }
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -34,7 +34,6 @@
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -44,15 +43,15 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.freehaven.tor.control.TorControlConnection;
+import de.uniba.wiai.lspi.puppetor.HiddenService;
import de.uniba.wiai.lspi.puppetor.NodeEventType;
import de.uniba.wiai.lspi.puppetor.NodeState;
import de.uniba.wiai.lspi.puppetor.ProxyNode;
-import de.uniba.wiai.lspi.puppetor.TorProcessException;
+import de.uniba.wiai.lspi.puppetor.PuppeTorException;
/**
* Implementation of <code>ProxyNode</code>.
@@ -75,7 +74,7 @@
protected File configFile;
/**
- * Collects all configuration strings for this node during configuration
+ * Collects all configuration strings for this node during the configuration
* phase in the order they are added.
*/
protected List<String> configuration;
@@ -96,8 +95,7 @@
private EventManagerImpl eventManager;
/**
- * Logger for this <code>ProxyNodeImpl</code> instance which is called
- * "node." plus the name of this node.
+ * Logger for this node which is called "node." plus the name of this node.
*/
protected Logger logger;
@@ -107,8 +105,8 @@
protected NetworkImpl network;
/**
- * Name of this node that is used as part of the working directory and as
- * logger name of this node.
+ * Name of this node that is used as part of the working directory, as
+ * logger name of this node, and as event source.
*/
protected String nodeName;
@@ -124,7 +122,7 @@
protected int socksPort;
/**
- * Handle on the running Tor process that belongs to this node.
+ * The running Tor process that belongs to this node.
*/
protected Process torProcess;
@@ -134,6 +132,15 @@
protected File workingDir;
/**
+ * Returns this node's working directory.
+ *
+ * @return This node's working directory.
+ */
+ File getWorkingDir() {
+ return this.workingDir;
+ }
+
+ /**
* Creates a new <code>ProxyNodeImpl</code> and adds it to the given
* <code>network</code>, but does not yet write its configuration to disk
* or start the corresponding Tor process.
@@ -222,9 +229,10 @@
// allow two nodes on the same circuit to be in the same /16 net
// TODO this depends in private or public network setting!!!
- // TODO even more important: this only works since Tor 0.1.2.x!!!
this.configuration.add("EnforceDistinctSubnets 0");
+ this.configuration.add("ClientDNSRejectInternalAddresses 0");
+
// don't rely on node verification, yet... TODO change?
this.configuration
.add("AllowInvalidNodes middle,rendezvous,exit,entry,introduction");
@@ -238,7 +246,6 @@
// log exiting
this.logger.exiting(this.getClass().getName(), "ProxyNodeImpl");
-
}
public void addConfiguration(String configurationString) {
@@ -292,14 +299,6 @@
this.logger.entering(this.getClass().getName(), "replaceConfiguration",
configurationString);
- // check state
- if (this.nodeState != NodeState.CONFIGURING) {
- IllegalStateException e = new IllegalStateException();
- this.logger.throwing(this.getClass().getName(),
- "replaceConfiguration", e);
- throw e;
- }
-
// check parameter
if (configurationString == null || configurationString.length() < 1
|| !configurationString.contains(" ")) {
@@ -313,7 +312,7 @@
String configurationKey = configurationString.substring(0,
configurationString.indexOf(" "));
- // iterate over existing configuration strings and replace first
+ // iterate over existing configuration strings and replace the first
// occurrence of configuration key with new configuration string
Iterator<String> it = this.configuration.listIterator();
boolean replaced = false;
@@ -337,180 +336,90 @@
this.logger.exiting(this.getClass().getName(), "replaceConfiguration");
}
- public synchronized void addHiddenService(String serviceName,
- int servicePort, int virtualPort) {
+ public void deleteConfiguration(String configurationKey)
+ throws RemoteException {
// log entering
- this.logger.entering(this.getClass().getName(), "addHiddenService",
- new Object[] { serviceName, servicePort, virtualPort });
+ this.logger.entering(this.getClass().getName(), "deleteConfiguration",
+ configurationKey);
- // check state
- if (this.nodeState != NodeState.CONFIGURING) {
- this.logger.log(Level.SEVERE,
- "Hidden service can only be added when node is in state "
- + "CONFIGURING!");
- IllegalStateException e = new IllegalStateException(
- "Hidden service can only be added when node is in state "
- + "CONFIGURING!");
- this.logger.throwing(this.getClass().getName(), "addHiddenService",
- e);
+ // check parameter
+ if (configurationKey == null || configurationKey.length() < 1) {
+ IllegalArgumentException e = new IllegalArgumentException();
+ this.logger.throwing(this.getClass().getName(),
+ "deleteConfiguration", e);
throw e;
}
- // check parameters
- if (serviceName == null || serviceName.length() == 0 || servicePort < 0
- || servicePort > 65535 || virtualPort < 0
- || virtualPort > 65535) {
- this.logger.log(Level.SEVERE,
- "Illegal argument when adding hidden service!");
- IllegalArgumentException e = new IllegalArgumentException();
- this.logger.throwing(this.getClass().getName(), "addHiddenService",
- e);
- throw e;
+ // iterate over existing configuration strings and remove all
+ // configuration strings that have the given configuration key
+ for (String currentConfigurationString : this.configuration) {
+ String currentConfigurationKey = currentConfigurationString
+ .substring(0, currentConfigurationString.indexOf(" "));
+ if (currentConfigurationKey.equals(configurationKey)) {
+ this.configuration.remove(currentConfigurationString);
+ }
}
- // add hidden service using Tor controller
- this.configuration.add("HiddenServiceDir "
- + workingDir.getAbsolutePath() + File.separator + serviceName
- + "\nHiddenServicePort " + virtualPort + " 127.0.0.1:"
- + servicePort);
-
// log exiting
- this.logger.exiting(this.getClass().getName(), "addHiddenService");
+ this.logger.exiting(this.getClass().getName(), "deleteConfiguration");
}
- /**
- * Adds a hidden service configuration to this node while the node is
- * running.
- *
- * TODO not fully implemented yet, but this should be possible both, during
- * configuration and when running a network...
- *
- * @param serviceName
- * Name of the hidden service that will be used as name for the
- * hidden service directory. May neither be <code>null</code>
- * or a zero-length string.
- * @param servicePort
- * The TCP port on which the service will be available for
- * requests. This can, but need not be different from the virtual
- * port that is announced to clients. May not be negative or
- * greater than 65535.
- * @param virtualPort
- * The virtual TCP port that this hidden service runs on as it is
- * announced to clients. May not be negative or greater than
- * 65535.
- * @return The onion address string consisting of 16 base32 chars plus
- * ".onion" for hidden service versions 0 and 1 or 16 base32 chars
- * plus "." plus 24 base32 chars plus ".onion" for hidden service
- * version 2.
- */
- synchronized String addHiddenServiceUsingController(String serviceName,
+ public synchronized HiddenService addHiddenService(String serviceName,
int servicePort, int virtualPort) {
- // TODO this method is not supported yet!
- if (1 != 2) {
- UnsupportedOperationException e = new UnsupportedOperationException();
- this.logger.throwing(this.getClass().getName(),
- "addHiddenServiceUsingController", e);
- throw e;
- }
-
// log entering
- this.logger.entering(this.getClass().getName(),
- "addHiddenServiceUsingController", new Object[] { serviceName,
- servicePort, virtualPort });
+ this.logger.entering(this.getClass().getName(), "addHiddenService",
+ new Object[] { serviceName, servicePort, virtualPort });
- // TODO check state
+ // create hidden service object; parameter checking is done in
+ // constructor
+ HiddenService result = new HiddenServiceImpl(this, serviceName,
+ servicePort, virtualPort);
- // check parameters
- if (serviceName == null || serviceName.length() == 0 || servicePort < 0
- || servicePort > 65535 || virtualPort < 0
- || virtualPort > 65535) {
- IllegalArgumentException e = new IllegalArgumentException();
- this.logger.throwing(this.getClass().getName(),
- "addHiddenServiceUsingController", e);
- throw e;
- }
+ // add hidden service using Tor controller
+ this.configuration.add("HiddenServiceDir "
+ + workingDir.getAbsolutePath() + File.separator + serviceName
+ + "\nHiddenServicePort " + virtualPort + " 127.0.0.1:"
+ + servicePort);
- // String serverName = server.getServerName();
- // int serverPort = server.getServerPort();
+ // log exiting and return hidden service object
+ this.logger.exiting(this.getClass().getName(), "addHiddenService",
+ result);
+ return result;
+ }
- // add hidden service using Tor controller
- this.logger.log(Level.FINE,
- "Adding hidden service using Tor controller.");
+ public synchronized HiddenService addHiddenService(String serviceName,
+ int servicePort) {
- List<String> configs = new ArrayList<String>();
- configs.add("HiddenServiceDir " + workingDir.getAbsolutePath() + "/"
- + serviceName);
- configs.add("HiddenServicePort " + virtualPort + " 127.0.0.1:"
- + servicePort);
- try {
- conn.setConf(configs);
- } catch (IOException e) {
- RuntimeException ex = new RuntimeException(
- "IOException when trying to register a new "
- + "hidden service", e);
- this.logger.throwing(this.getClass().getName(),
- "addHiddenServiceUsingController", ex);
- throw ex;
- }
- this.logger.log(Level.FINE,
- "Hidden service successfully registered at Tor proxy.");
+ // log entering
+ this.logger.entering(this.getClass().getName(), "addHiddenService",
+ new Object[] { serviceName, servicePort });
- //
- File hiddenServiceFile = new File(workingDir.getAbsolutePath() + "\\"
- + serviceName + "\\hostname");
- if (!hiddenServiceFile.exists()) {
- RuntimeException ex = new RuntimeException();
- this.logger.throwing(this.getClass().getName(),
- "addHiddenServiceUsingController", ex);
- throw ex;
- }
- // read hostname from file
- String address = null;
- try {
- BufferedReader br = new BufferedReader(new FileReader(
- hiddenServiceFile));
- address = br.readLine();
- br.close();
- } catch (IOException e) {
- RuntimeException ex = new RuntimeException(e);
- this.logger.throwing(this.getClass().getName(),
- "addHiddenServiceUsingController", ex);
- throw ex;
- }
+ // invoke overloaded method
+ HiddenService result = this.addHiddenService(serviceName, servicePort,
+ 80);
- return address;
+ // log exiting and return hidden service
+ this.logger.exiting(this.getClass().getName(), "addHiddenService",
+ result);
+ return result;
}
- public synchronized void configureDirServers(
- Set<String> authorizedDirServerStrings) {
+ public synchronized HiddenService addHiddenService(String serviceName) {
// log entering
- this.logger.entering(this.getClass().getName(), "configureDirServers",
- authorizedDirServerStrings);
+ this.logger.entering(this.getClass().getName(), "addHiddenService",
+ serviceName);
- // check parameter
- if (authorizedDirServerStrings == null) {
- IllegalArgumentException e = new IllegalArgumentException(
- "Parameter may not be null!");
- this.logger.throwing(this.getClass().getName(),
- "configureDirServers", e);
- throw e;
- }
+ // invoke overloaded method
+ HiddenService result = this.addHiddenService(serviceName, this.network
+ .getNextPortNumber(), 80);
- // add to configuration
- int entriesBefore = this.configuration.size();
- this.configuration.addAll(authorizedDirServerStrings);
- this.logger.log(Level.FINE, "Added "
- + authorizedDirServerStrings.size()
- + " DirServer entries to configuration, having "
- + entriesBefore + " entries before and "
- + this.configuration.size()
- + " entries afterwards (duplicates possible)!");
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "configureDirServers");
+ // log exiting and return hidden service
+ this.logger.exiting(this.getClass().getName(), "addHiddenService",
+ result);
+ return result;
}
public String getNodeName() {
@@ -521,62 +430,9 @@
return this.nodeState;
}
- public synchronized String getOnionAddress(String serviceName, int version)
- throws TorProcessException {
+ public synchronized void hup() throws PuppeTorException {
// log entering
- this.logger.entering(this.getClass().getName(), "getOnionAddress",
- new Object[] { serviceName, version });
-
- // check parameter
- if (serviceName == null || serviceName.length() == 0) {
- IllegalArgumentException e = new IllegalArgumentException();
- this.logger.throwing(this.getClass().getName(), "getOnionAddress",
- e);
- throw e;
- }
-
- // check if hidden service directory exists
- File hiddenServiceFile = new File(workingDir.getAbsolutePath()
- + File.separator + serviceName + File.separator + "hostname"
- + ((version <= 1) ? "" : "2"));
- if (!hiddenServiceFile.exists()) {
- this.logger.log(Level.SEVERE,
- "Hidden service directory or hostname file does not exist: "
- + hiddenServiceFile.getAbsolutePath());
-
- TorProcessException e = new TorProcessException(
- "Hidden service directory or hostname file does not exist: "
- + hiddenServiceFile.getAbsolutePath());
- this.logger.throwing(this.getClass().getName(), "getOnionAddress",
- e);
- throw e;
- }
-
- // read hostname from file
- String address = null;
- try {
- BufferedReader br = new BufferedReader(new FileReader(
- hiddenServiceFile));
- address = br.readLine();
- br.close();
- } catch (IOException e) {
- TorProcessException ex = new TorProcessException(
- "Could not read hostname file!", e);
- this.logger.throwing(this.getClass().getName(), "getOnionAddress",
- ex);
- throw ex;
- }
-
- // log exiting and return address
- this.logger.exiting(this.getClass().getName(), "getOnionAddress",
- address);
- return address;
- }
-
- public synchronized void hup() throws TorProcessException {
-
- // log entering
this.logger.entering(this.getClass().getName(), "hup");
// check state
@@ -592,7 +448,7 @@
try {
this.conn.signal("HUP");
} catch (IOException e) {
- TorProcessException ex = new TorProcessException(
+ PuppeTorException ex = new PuppeTorException(
"Could not send the command HUP to the Tor process!", e);
this.logger.throwing(this.getClass().getName(), "hup", ex);
throw ex;
@@ -610,7 +466,7 @@
this.logger.exiting(this.getClass().getName(), "hup");
}
- public synchronized void shutdown() throws TorProcessException {
+ public synchronized void shutdown() throws PuppeTorException {
// log entering
this.logger.entering(this.getClass().getName(), "shutdown");
@@ -625,12 +481,11 @@
// we cannot simply kill the Tor process, because we have established a
// controller connection to it which would interpret a closed socket as
// failure and throw a RuntimeException
- // TODO who cares?!
try {
this.conn.shutdownTor("SHUTDOWN");
this.conn.shutdownTor("SHUTDOWN");
} catch (IOException e) {
- TorProcessException ex = new TorProcessException(
+ PuppeTorException ex = new PuppeTorException(
"Could not send shutdown command to Tor process!", e);
this.logger.throwing(this.getClass().getName(), "shutdown", ex);
throw ex;
@@ -711,7 +566,7 @@
}
public synchronized boolean startNode(long maximumTimeToWaitInMillis)
- throws TorProcessException {
+ throws PuppeTorException {
// log entering
this.logger.entering(this.getClass().getName(), "startNode",
@@ -736,7 +591,7 @@
this.logger.log(Level.FINE, "Started Tor process successfully!");
} catch (IOException e) {
String reason = "Could not start Tor process!";
- TorProcessException ex = new TorProcessException(reason, e);
+ PuppeTorException ex = new PuppeTorException(reason, e);
this.logger.throwing(this.getClass().getName(), "startNode", ex);
throw ex;
}
@@ -828,7 +683,7 @@
// Tor did not open its control port
this.logger.log(Level.WARNING, "Tor node " + this.nodeName
+ " did not manage to open its control port within "
- + maximumTimeToWaitInMillis + " millis!");
+ + maximumTimeToWaitInMillis + " milliseconds!");
// log exiting
this.logger.exiting(this.getClass().getName(), "startNode", false);
@@ -847,7 +702,7 @@
} catch (IOException e) {
String reason = "Could not connect to control port " + controlPort
+ "!";
- TorProcessException ex = new TorProcessException(reason, e);
+ PuppeTorException ex = new PuppeTorException(reason, e);
this.logger.throwing(this.getClass().getName(), "startNode", ex);
throw ex;
}
@@ -872,60 +727,34 @@
+ ", socksPort=" + this.socksPort;
}
- public synchronized void writeConfiguration() throws TorProcessException {
+ public synchronized void writeConfiguration() throws PuppeTorException {
// log entering
this.logger.entering(this.getClass().getName(), "writeConfiguration");
// write config file
- this.writeConfigurationFile(this.configFile, this.configuration);
-
- // change state, if necessary
- if (this.nodeState == NodeState.CONFIGURING) {
- this.nodeState = NodeState.CONFIGURATION_WRITTEN;
- }
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "writeConfiguration");
- }
-
- /**
- * Writes the given configuration strings to the given configuration file.
- *
- * @param configurationFile
- * File to write the configuration to.
- * @param configurationStrings
- * Configuration strings to be written.
- * @throws TorProcessException
- * Thrown if the configuration file cannot be written to disk.
- */
- protected void writeConfigurationFile(File configurationFile,
- List<String> configurationStrings) throws TorProcessException {
-
- // log entering
- this.logger.entering(this.getClass().getName(),
- "writeConfigurationFile", new Object[] { configurationFile,
- configurationStrings });
-
- // write config file
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(
- configurationFile));
- for (String c : configurationStrings) {
+ this.configFile));
+ for (String c : this.configuration) {
bw.write(c + "\n");
}
bw.close();
} catch (IOException e) {
- TorProcessException ex = new TorProcessException(
+ PuppeTorException ex = new PuppeTorException(
"Could not write configuration file!", e);
this.logger.throwing(this.getClass().getName(),
"writeConfigurationFile", ex);
throw ex;
}
+ // change state, if necessary
+ if (this.nodeState == NodeState.CONFIGURING) {
+ this.nodeState = NodeState.CONFIGURATION_WRITTEN;
+ }
+
// log exiting
- this.logger
- .exiting(this.getClass().getName(), "writeConfigurationFile");
+ this.logger.exiting(this.getClass().getName(), "writeConfiguration");
}
public int getSocksPort() {
@@ -939,17 +768,4 @@
public List<String> getConfiguration() {
return new ArrayList<String>(this.configuration);
}
-
- public void replaceDirectoryServers(Set<String> dirServerString)
- throws TorProcessException {
- List<String> tempConfigurationList = new ArrayList<String>();
- for (String line : this.configuration) {
- if (!line.startsWith("DirServer")) {
- tempConfigurationList.add(line);
- }
- }
- tempConfigurationList.addAll(dirServerString);
- this.configuration = tempConfigurationList;
- this.writeConfigurationFile(configFile, this.configuration);
- }
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -32,30 +32,185 @@
package de.uniba.wiai.lspi.puppetor.impl;
import java.io.BufferedReader;
+import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
+import java.io.FileWriter;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.regex.Pattern;
-import de.uniba.wiai.lspi.puppetor.NodeState;
+import de.uniba.wiai.lspi.puppetor.PuppeTorException;
import de.uniba.wiai.lspi.puppetor.RouterNode;
-import de.uniba.wiai.lspi.puppetor.TorProcessException;
/**
* Implementation of <code>RouterNode</code>.
*
* @author kloesing
- *
*/
@SuppressWarnings("serial")
public class RouterNodeImpl extends ProxyNodeImpl implements RouterNode {
/**
+ * Internal thread class that is used to determine fingerprints in parallel,
+ * which can take a few seconds.
+ */
+ private class FingerprintThread extends Thread {
+
+ @Override
+ public void run() {
+
+ // log entering
+ logger.entering(this.getClass().getName(), "run");
+
+ // create file reference for temporary config file
+ File tempConfigFile = new File(RouterNodeImpl.this.workingDir
+ .getAbsolutePath()
+ + File.separator + "torrc.tmp");
+
+ // compose a modified config file, including a DirServer option with
+ // false fingerprint; this is necessary, because otherwise Tor
+ // would not accept that this router node might have a private IP
+ // address, but connects to the public directory servers
+ List<String> copyOfConfig = new ArrayList<String>(
+ RouterNodeImpl.this.configuration);
+ String fakeDirServerString = "DirServer "
+ + RouterNodeImpl.this.nodeName + " 127.0.0.1:"
+ + RouterNodeImpl.this.dirPort
+ + " 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000";
+ copyOfConfig.add(fakeDirServerString);
+
+ // write config file
+ try {
+ BufferedWriter bw = new BufferedWriter(new FileWriter(
+ tempConfigFile));
+ for (String c : copyOfConfig) {
+ bw.write(c + "\n");
+ }
+ bw.close();
+ } catch (IOException e) {
+ PuppeTorException ex = new PuppeTorException(
+ "Could not write configuration file!", e);
+ logger.log(Level.WARNING, "Could not start Tor process!", ex);
+ RouterNodeImpl.this.setCaughtException(ex);
+ return;
+ }
+
+ // start process with option --list-fingerprint
+ ProcessBuilder processBuilder = new ProcessBuilder(torExecutable
+ .getPath(), "--list-fingerprint", "-f", "torrc.tmp");
+ processBuilder.directory(RouterNodeImpl.this.workingDir);
+ processBuilder.redirectErrorStream(true);
+ Process tmpProcess = null;
+ try {
+ tmpProcess = processBuilder.start();
+ } catch (IOException e) {
+ PuppeTorException ex = new PuppeTorException(
+ "Could not start Tor process temporarily with "
+ + "--list-fingerprint option!", e);
+ logger.log(Level.WARNING, "Could not start Tor process!", ex);
+ RouterNodeImpl.this.setCaughtException(ex);
+ return;
+ }
+
+ // wait for process to terminate
+ int exitValue = 0;
+ try {
+ exitValue = tmpProcess.waitFor();
+ } catch (InterruptedException e) {
+ PuppeTorException ex = new PuppeTorException(
+ "Interrupted while waiting for Tor process to exit!", e);
+ logger.log(Level.WARNING,
+ "Temporary Tor process was interrupted!", ex);
+ RouterNodeImpl.this.setCaughtException(ex);
+ return;
+ }
+
+ if (exitValue != 0) {
+ PuppeTorException ex = new PuppeTorException(
+ "Could not start Tor process temporarily with "
+ + "--list-fingerprint option! Tor exited with "
+ + "exit value " + exitValue
+ + "! Please go check the config options in "
+ + tempConfigFile + " manually!");
+ logger.log(Level.WARNING, "Could not start Tor process!", ex);
+ RouterNodeImpl.this.setCaughtException(ex);
+ return;
+ }
+
+ // read fingerprint from file
+ File fingerprintFile = new File(RouterNodeImpl.this.workingDir
+ .getAbsolutePath()
+ + File.separator + "fingerprint");
+ try {
+ BufferedReader br2 = new BufferedReader(new FileReader(
+ fingerprintFile));
+ RouterNodeImpl.this.setFingerprint(br2.readLine());
+ br2.close();
+ } catch (IOException e) {
+ PuppeTorException ex = new PuppeTorException(
+ "Could not read fingerprint from file!", e);
+ logger.log(Level.WARNING, "Could not read fingerprint file!",
+ ex);
+ RouterNodeImpl.this.setCaughtException(ex);
+ return;
+ }
+
+ // delete temporary config file
+ tempConfigFile.delete();
+
+ // log exiting
+ logger.exiting(this.getClass().getName(), "run");
+ }
+ }
+
+ /**
+ * Invoked by the fingerprint thread: sets the determined fingerprint string
+ *
+ * @param fingerprint
+ * The determined fingerprint string.
+ */
+ private synchronized void setFingerprint(String fingerprint) {
+
+ // log entering
+ this.logger.entering(this.getClass().getName(), "setFingerprint",
+ fingerprint);
+
+ // remember fingerprint and notify all waiting threads
+ this.fingerprint = fingerprint;
+ this.notifyAll();
+
+ // log exiting
+ this.logger.exiting(this.getClass().getName(), "setFingerprint");
+ }
+
+ /**
+ * Invoked by the fingerprint thread: sets the exception that occurred when
+ * trying to determine the fingerprint.
+ *
+ * @param caughtException
+ * The exception that occurred when trying to determine the
+ * fingerprint.
+ */
+ private synchronized void setCaughtException(
+ PuppeTorException caughtException) {
+
+ // log entering
+ this.logger.entering(this.getClass().getName(), "setCaughtException",
+ caughtException);
+
+ // remember caught exception and notify all waiting threads
+ this.caughtException = caughtException;
+ this.notifyAll();
+
+ // log exiting
+ this.logger.exiting(this.getClass().getName(), "setCaughtException");
+ }
+
+ /**
* Port on which the Tor node will be listening for directory requests from
* other Tor nodes.
*/
@@ -68,21 +223,17 @@
protected String serverIpAddress;
/**
- * Temporary config file that is used to determine the fingerprint of this
- * node.
- */
- protected File tempConfigFile;
-
- /**
* The fingerprint of this node that is determined as hash value of its
- * onion key.
+ * onion key. It is initialized with <code>null</code> and set by the
+ * fingerprint thread as soon as it is determined.
*/
- protected String fingerprint;
+ private String fingerprint;
/**
- * The base32-encoded ID of this node.
+ * The exception that was caught when determining the fingerprint of this
+ * node, if any.
*/
- protected String fingerprintBase32;
+ protected PuppeTorException caughtException;
/**
* The pattern for valid IP v4 addresses in dotted decimal notation.
@@ -172,7 +323,8 @@
// all routers mirror the directory
this.configuration.add("DirPort " + dirPort);
- // the address of this node should be localhost and not guessed by Tor
+ // the address of this node should be manually specified and not guessed
+ // by Tor
this.configuration.add("Address " + serverIpAddress);
// the OR port may only be contacted locally
@@ -190,263 +342,47 @@
// bypass testing if we are reachable
this.configuration.add("AssumeReachable 1");
- // create file reference for temporary config file
- this.tempConfigFile = new File(this.workingDir.getAbsolutePath()
- + File.separator + "torrc.tmp");
+ // start a thread to determine the node's fingerprint in the background
+ this.determineFingerprint();
// log exiting
this.logger.exiting(this.getClass().getName(), "RouterNodeImpl");
}
- public synchronized String getFingerprintBase32() {
+ public synchronized String getFingerprint() throws PuppeTorException,
+ RemoteException {
// log entering
- this.logger.entering(this.getClass().getName(), "getFingerprintBase32");
-
- // check state
- if (this.nodeState != NodeState.RUNNING
- && this.nodeState != NodeState.SHUT_DOWN) {
- String reason = "Node is neither in state NodeState.RUNNING "
- + "nor in NodeState.SHUT_DOWN, but in state "
- + this.nodeState + "!";
- IllegalStateException e = new IllegalStateException(reason);
- this.logger.throwing(this.getClass().getName(),
- "getFingerprintBase32", e);
- throw e;
- }
-
- // log exiting
- this.logger.exiting(this.getClass().getName(), "getFingerprintBase32",
- this.fingerprintBase32);
- return this.fingerprintBase32;
- }
-
- public String getFingerprint() throws RemoteException {
-
- // log entering
this.logger.entering(this.getClass().getName(), "getFingerprint");
- // check state
- if (this.nodeState != NodeState.RUNNING
- && this.nodeState != NodeState.SHUT_DOWN) {
- String reason = "Node is neither in state NodeState.RUNNING "
- + "nor in NodeState.SHUT_DOWN, but in state "
- + this.nodeState + "!";
- IllegalStateException e = new IllegalStateException(reason);
- this.logger
- .throwing(this.getClass().getName(), "getFingerprint", e);
- throw e;
- }
- String result = this.fingerprint.substring(this.fingerprint
- .indexOf(" ") + 1);
-
- // log exiting
- this.logger
- .exiting(this.getClass().getName(), "getFingerprint", result);
- return result;
- }
-
- public synchronized String determineFingerprint()
- throws TorProcessException {
-
- // log entering
- this.logger.entering(this.getClass().getName(), "determineFingerprint");
-
- // check if we can answer the request immediately
- if (this.fingerprint != null) {
-
- // log exiting and return fingerprint
- this.logger.exiting(this.getClass().getName(),
- "determineFingerprint", this.fingerprint);
- return this.fingerprint;
- }
-
- // write modified config file, including a DirServer option with
- // false fingerprint; this is necessary, because otherwise Tor
- // would not accept that this router node has a private IP
- // address, but connects to the public directory servers; just a
- // workaround...
- List<String> copyOfConfig = new ArrayList<String>(this.configuration);
- // TODO when working dir exists, but Tor did not manage to write
- // a fingerprint file, we get a NullPointerException...
- String fakeDirServerString = "DirServer " + this.nodeName
- + " 127.0.0.1:" + this.dirPort
- + " 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000";
- copyOfConfig.add(fakeDirServerString);
- writeConfigurationFile(this.tempConfigFile, copyOfConfig);
-
- // start process with option --list-fingerprint
- // TODO make this more configurable
- ProcessBuilder processBuilder = new ProcessBuilder(torExecutable
- .getPath(), "--list-fingerprint", "-f", "torrc.tmp");
- processBuilder.directory(this.workingDir);
- processBuilder.redirectErrorStream(true);
- Process tmpProcess = null;
- try {
- tmpProcess = processBuilder.start();
- } catch (IOException e) {
- TorProcessException ex = new TorProcessException(
- "Could not start Tor process temporarily with "
- + "--list-fingerprint option!", e);
- this.logger.throwing(this.getClass().getName(),
- "determineFingerprint", ex);
- throw ex;
- }
-
- // start thread to parse output
- final BufferedReader br = new BufferedReader(new InputStreamReader(
- tmpProcess.getInputStream()));
- Thread outputThread = new Thread(new Runnable() {
- public void run() {
- try {
- // read output from tor
- String line = null;
- while ((line = br.readLine()) != null) {
- // TODO discard output?
- logger.log(Level.FINER, line);
- }
- } catch (IOException e) {
- // TODO how to handle?
- logger.log(Level.SEVERE,
- "I/O exception while parsing output of temporary "
- + "Tor process!");
- }
+ // wait until either the fingerprint has been determined or an exception
+ // was caught
+ while (this.fingerprint == null && this.caughtException == null) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ // do nothing
}
- });
- outputThread.setDaemon(true);
- outputThread.start();
-
- // wait for process to terminate (should be quite fast)
- int exitValue = 0;
- try {
- exitValue = tmpProcess.waitFor();
- } catch (InterruptedException e) {
- // TODO how to handle?
- this.logger.log(Level.WARNING,
- "Temporary Tor process was interrupted!", e);
}
- if (exitValue != 0) {
- TorProcessException ex = new TorProcessException(
- "Could not start Tor process temporarily with "
- + "--list-fingerprint option! Tor exited with "
- + "exit value " + exitValue
- + "! Please go check the config options in "
- + this.tempConfigFile + " manually!");
- this.logger.throwing(this.getClass().getName(),
- "determineFingerprint", ex);
- throw ex;
+ if (this.caughtException != null) {
+ this.logger.throwing(this.getClass().getName(), "getFingerprint",
+ this.caughtException);
+ throw this.caughtException;
}
- // read fingerprint from file
- this.readFingerprintFromFile();
-
- // log exiting and return fingerprint
- this.logger.exiting(this.getClass().getName(), "determineFingerprint",
+ // log exiting
+ this.logger.exiting(this.getClass().getName(), "getFingerprint",
this.fingerprint);
return this.fingerprint;
}
- /**
- * Reads the fingerprint from disk. This requires that the fingerprint file
- * has been written before by Tor. Otherwise, a TorProcessException is
- * thrown.
- *
- * @throws TorProcessException
- * Thrown if no fingerprint file has been written by Tor before.
- */
- private void readFingerprintFromFile() throws TorProcessException {
-
- // log entering
- this.logger.entering(this.getClass().getName(),
- "readFingerprintFromFile");
-
- // check if the fingerprint has been read before
- if (this.fingerprint != null) {
-
- // log exiting and return fingerprint
- this.logger.exiting(this.getClass().getName(),
- "readFingerprintFromFile");
- return;
- }
-
- // read fingerprint from file
- File fingerprintFile = new File(this.workingDir.getAbsolutePath()
- + File.separator + "fingerprint");
- try {
- BufferedReader br2 = new BufferedReader(new FileReader(
- fingerprintFile));
- this.fingerprint = br2.readLine();
- br2.close();
- } catch (IOException e) {
- TorProcessException ex = new TorProcessException(
- "Could not read fingerprint from file!", e);
- this.logger.throwing(this.getClass().getName(),
- "determineFingerprint", ex);
- throw ex;
- }
-
- // parse fingerprint string to base32 encoded ID
-
- // convert fingerprint string to base32 encoding
- // TODO move to separate util class, document it
- String fp = this.fingerprint;
- fp = fp.substring(fp.indexOf(' ') + 1);
- byte[] bytes = new byte[20];
- int j = 0;
- for (String part : fp.split(" ")) {
- bytes[j++] = (byte) Integer.parseInt(part.substring(0, 2), 16);
- bytes[j++] = (byte) Integer.parseInt(part.substring(2), 16);
- }
- int i = 0, index = 0, digit = 0;
- int currByte, nextByte;
- StringBuffer base32 = new StringBuffer((bytes.length + 7) * 8 / 5);
- String base32Chars = "abcdefghijklmnopqrstuvwxyz234567";
- while (i < bytes.length) {
- currByte = (bytes[i] >= 0) ? bytes[i] : (bytes[i] + 256);
- if (index > 3) {
- if ((i + 1) < bytes.length) {
- nextByte = (bytes[i + 1] >= 0) ? bytes[i + 1]
- : (bytes[i + 1] + 256);
- } else {
- nextByte = 0;
- }
- digit = currByte & (0xFF >> index);
- index = (index + 5) % 8;
- digit <<= index;
- digit |= nextByte >> (8 - index);
- i++;
- } else {
- digit = (currByte >> (8 - (index + 5))) & 0x1F;
- index = (index + 5) % 8;
- if (index == 0) {
- i++;
- }
- }
- base32.append(base32Chars.charAt(digit));
- }
- this.fingerprintBase32 = base32.toString();
-
- // log exiting
- this.logger.exiting(this.getClass().getName(),
- "readFingerprintFromFile");
- }
-
@Override
public String toString() {
return super.toString() + ", orPort=" + this.orPort + ", dirPort="
+ this.dirPort;
}
- public String getName() {
- String fp = "";
- if (this.fingerprint != null) {
- fp = this.fingerprint.substring(this.fingerprint.indexOf(" ") + 1);
- fp = fp.substring(0, 4);
- }
- return this.nodeName + " (" + fp + ")";
- }
-
public int getDirPort() {
return this.dirPort;
}
@@ -455,20 +391,21 @@
return this.orPort;
}
- public boolean startNode(long maximumTimeToWaitInMillis)
- throws TorProcessException {
+ /**
+ * Determines the fingerprint of this node by starting a background thread
+ * that performs this operation.
+ */
+ protected void determineFingerprint() {
// log entering
- this.logger.entering(this.getClass().getName(), "startNode");
+ this.logger.entering(this.getClass().getName(), "determineFingerprint");
- // before starting the node, determine its fingerprint
- this.determineFingerprint();
+ // start a thread to determine this node's fingerprint
+ FingerprintThread fingerprintThread = new FingerprintThread();
+ fingerprintThread.setName(nodeName + " Fingerprint Resolver");
+ fingerprintThread.start();
- // perform the same as a proxy node does
- boolean result = super.startNode(maximumTimeToWaitInMillis);
-
- // log exiting and return result
- this.logger.exiting(this.getClass().getName(), "startNode", result);
- return result;
+ // log exiting
+ this.logger.exiting(this.getClass().getName(), "determineFingerprint");
}
}
Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ServerApplicationImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ServerApplicationImpl.java 2007-10-01 16:25:45 UTC (rev 11735)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ServerApplicationImpl.java 2007-10-01 21:59:35 UTC (rev 11736)
@@ -231,13 +231,13 @@
}
/**
- * Event manager to which all events concerning this server application are
- * notified.
+ * Event manager that handles all events concerning this server application.
*/
private EventManagerImpl eventManager;
/**
- * Logger for this server.
+ * Logger for this server which is called "server." plus the name of this
+ * server application.
*/
private Logger logger;
@@ -282,7 +282,7 @@
}
// create logger
- this.logger = Logger.getLogger("application." + serverApplicationName);
+ this.logger = Logger.getLogger("server." + serverApplicationName);
// log entering
this.logger.entering(this.getClass().getName(),
@@ -308,7 +308,7 @@
this.logger.exiting(this.getClass().getName(), "ServerApplicationImpl");
}
- public synchronized void listen() {
+ public synchronized void startListening() {
// log entering
this.logger.entering(this.getClass().getName(), "listen");
@@ -336,10 +336,10 @@
// log entering
this.logger.entering(this.getClass().getName(), "stopListening");
- // check if a request is running
+ // check if we are listening
if (this.serverThread == null) {
IllegalStateException e = new IllegalStateException(
- "We did not start listening before!");
+ "We are not listening!");
this.logger.throwing(this.getClass().getName(), "stopListening", e);
throw e;
}
@@ -350,10 +350,17 @@
// interrupt thread
this.serverThread.interrupt();
+ // unset listening thread
+ this.serverThread = null;
+
// log exiting
this.logger.exiting(this.getClass().getName(), "stopListening");
}
+ public synchronized boolean isListening() {
+ return (this.serverThread != null);
+ }
+
@Override
public String toString() {
return this.getClass().getSimpleName() + ": serverApplicationName=\""
@@ -364,4 +371,8 @@
public String getServerApplicationName() {
return this.serverApplicationName;
}
+
+ public int getServerPort() {
+ return this.serverPort;
+ }
}