Index: simplerunner/src/main/java/geniusweb/simplerunner/BasicConnection.java
===================================================================
--- simplerunner/src/main/java/geniusweb/simplerunner/BasicConnection.java	(revision 53)
+++ simplerunner/src/main/java/geniusweb/simplerunner/BasicConnection.java	(revision 1)
@@ -3,10 +3,8 @@
 import java.io.IOException;
 import java.net.URI;
-import java.util.List;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.CopyOnWriteArrayList;
 
-import geniusweb.connection.ConnectionEnd;
+import geniusweb.connection.Connection;
 import geniusweb.references.Reference;
+import tudelft.utilities.listener.DefaultListenable;
 import tudelft.utilities.listener.Listener;
 
@@ -18,15 +16,10 @@
  * @param <OUT> the type of outgoing data
  */
-public class BasicConnection<IN, OUT> implements ConnectionEnd<IN, OUT> {
-	private List<Listener<IN>> listeners = new CopyOnWriteArrayList<Listener<IN>>();
-
-	private final Info<OUT> EOS = new EOS<OUT>();
+public class BasicConnection<IN, OUT> extends DefaultListenable<IN>
+		implements Connection<IN, OUT> {
 	private final Reference reference;
 	private final URI uri;
 	// to be initialized
 	private Listener<OUT> handler = null;
-	private ArrayBlockingQueue<Info<OUT>> messages = new ArrayBlockingQueue<>(
-			4);
-	private Throwable error;
 
 	/**
@@ -46,5 +39,5 @@
 	 * from us. Must be called first.
 	 * 
-	 * @param newhandler a Listener&lt;OUT&gt; that can handle send actions.
+	 * @param handler a Listener<OUT> that can handle send actions.
 	 * 
 	 */
@@ -54,38 +47,4 @@
 		}
 		this.handler = newhandler;
-
-		Thread handlerThread = new Thread(new Runnable() {
-
-			@Override
-			public void run() {
-				try {
-					while (true) {
-						Info<OUT> mess = messages.take();
-						if (mess instanceof EOS)
-							break;
-						handler.notifyChange(((Data<OUT>) mess).get());
-					}
-				} catch (Exception e) {
-					setError(e);
-				}
-				handler = null;
-				System.out.println("BasicConnection closed");
-			}
-		});
-		handlerThread.start();
-	}
-
-	/**
-	 * Error condition occurs. Record error and close connection
-	 * 
-	 * @param e
-	 */
-	protected synchronized void setError(Throwable e) {
-		if (error == null) {
-			// maybe log instead?
-			e.printStackTrace();
-			error = e;
-			close();
-		}
 	}
 
@@ -94,11 +53,7 @@
 		if (handler == null) {
 			throw new IllegalStateException(
-					"BasicConnection has not been initialized or was closed");
+					"BasicConnection has not been initialized");
 		}
-		try {
-			messages.put(new Data<OUT>(data));
-		} catch (InterruptedException e) {
-			setError(e);
-		}
+		handler.notifyChange(data);
 	}
 
@@ -115,82 +70,11 @@
 	@Override
 	public void close() {
-		System.out.println("flushing and terminating " + this);
-		if (handler == null || messages.contains(EOS))
-			return;
-		try {
-			messages.put(EOS);
-		} catch (InterruptedException e) {
-			setError(e);
-		}
+
 	}
 
 	@Override
-	public String toString() {
-		return "BasicConnection[" + reference + "]";
-	}
-
-	@Override
-	public Throwable getError() {
-		return error;
-	}
-
-	/**
-	 * 
-	 * @return true iff this connection is open. Returns false also when then
-	 *         handler is in the close-down process
-	 */
-	public boolean isOpen() {
-		return handler != null && !messages.contains(EOS);
-	}
-
-	/****************** implements listenable ****************/
-	// override because notifyListeners should throw exceptions.
-	@Override
-	public void addListener(Listener<IN> l) {
-		listeners.add(l);
-	}
-
-	@Override
-	public void removeListener(Listener<IN> l) {
-		listeners.remove(l);
-	}
-
-	public void notifyListeners(IN data) {
-		for (Listener<IN> l : listeners) {
-			l.notifyChange(data);
-		}
+	public Error getError() {
+		return null;
 	}
 
 }
-
-/**
- * Wrapper around data so that we can put Null end EOS in a
- * {@link ArrayBlockingQueue}
- *
- * @param <S> the type of contained data.
- */
-
-interface Info<S> {
-
-}
-
-class Data<S> implements Info<S> {
-	private final S data;
-
-	public Data(S data) {
-		this.data = data;
-	}
-
-	public S get() {
-		return data;
-	}
-}
-
-/**
- * End of stream.
- * 
- * @author wouter
- *
- */
-class EOS<S> implements Info<S> {
-}
Index: simplerunner/src/main/java/geniusweb/simplerunner/ClassPathConnectionFactory.java
===================================================================
--- simplerunner/src/main/java/geniusweb/simplerunner/ClassPathConnectionFactory.java	(revision 53)
+++ simplerunner/src/main/java/geniusweb/simplerunner/ClassPathConnectionFactory.java	(revision 1)
@@ -11,8 +11,8 @@
 import geniusweb.actions.Action;
 import geniusweb.actions.PartyId;
-import geniusweb.inform.Inform;
 import geniusweb.party.Party;
-import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
-import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
+import geniusweb.party.inform.Inform;
+import geniusweb.protocol.partyconnection.ConnectionWithParty;
+import geniusweb.protocol.partyconnection.ConnectionWithPartyFactory;
 import geniusweb.references.Reference;
 import tudelft.utilities.repository.NoResourcesNowException;
@@ -22,147 +22,38 @@
  * <code>classpath:org/my/package/class</code>
  * 
+ * 
+ *
  */
-public class ClassPathConnectionFactory implements ProtocolToPartyConnFactory {
-	private List<ConnectionPair> allConnections = new LinkedList<>();
-
-	/**
-	 * @param reference the party class path reference4
-	 */
-	@Override
-	public ProtocolToPartyConn connect(Reference reference) {
-		ConnectionPair connpair = new ConnectionPair(reference);
-		allConnections.add(connpair);
-		return connpair.getProtocolToPartyConn();
-	}
+public class ClassPathConnectionFactory implements ConnectionWithPartyFactory {
+	private static final String SCHEME = "classpath";
+	private static int serialcounter = 1;
+	private final static URI PROTOCOLURI = uri("protocol:protocol");
 
 	@Override
-	public List<ProtocolToPartyConn> connect(List<Reference> references)
-			throws IOException, NoResourcesNowException {
-		List<ProtocolToPartyConn> connections = new LinkedList<>();
-		for (Reference partyref : references) {
-			connections.add(connect(partyref));
-		}
-		return connections;
-	}
-
-	/**
-	 * @return list of connections that are still open.
-	 */
-	public List<BasicConnection> getOpenConnections() {
-		List<BasicConnection> open = new LinkedList<>();
-		for (ConnectionPair connpair : allConnections) {
-			open.addAll(connpair.getOpenConnections());
-		}
-		return open;
-	}
-
-}
-
-class BasicConnectionWithParty extends BasicConnection<Action, Inform>
-		implements ProtocolToPartyConn {
-
-	private PartyId id;
-
-	public BasicConnectionWithParty(Reference reference, URI uri) {
-		super(reference, uri);
-		this.id = new PartyId(uri.toString().replace("classpath:", "")
-				.replaceAll("\\.", "_"));
-	}
-
-	@Override
-	public PartyId getParty() {
-		return id;
-	}
-
-	@Override
-	public String toString() {
-		return "WP" + super.toString();
-	}
-
-}
-
-/**
- * Contains the connection from protocol to party and from party to protocol.
- * These two are dependent on each other, and must close together.
- *
- */
-class ConnectionPair {
-	private static int serialcounter = 1;
-	private static final String SCHEME = "classpath";
-	private final static URI PROTOCOLURI = uri("protocol:protocol");
-
-	private final BasicConnection<Inform, Action> party2protocol;
-	private final BasicConnectionWithParty protocol2party;
-
-	/**
-	 * 
-	 * @param reference the party class path reference4
-	 * 
-	 */
-	public ConnectionPair(Reference reference) {
+	public ConnectionWithParty connect(Reference reference) {
 		// set up the whole other party including the connection to it.
 		String classpath = getClassPath(reference.getURI());
 		Party party = instantiate(classpath);
 
-		// if call to protocol would fail, we should also close the
-		// protocol2party connection. But we assume that will work fine.
-		party2protocol = new BasicConnection<Inform, Action>(reference,
-				PROTOCOLURI) {
-
-			@Override
-			public void close() {
-				if (isOpen()) {
-					super.close();
-					protocol2party.close();
-				}
-			}
-
-		};
-
-		// if callback from protocol to party fails, then also close the
-		// other direction.
-		protocol2party = new BasicConnectionWithParty(reference,
+		BasicConnection<Inform, Action> party2protocol = new BasicConnection<Inform, Action>(
+				reference, PROTOCOLURI);
+		BasicConnectionWithParty protocol2party = new BasicConnectionWithParty(
+				reference,
 				uri("classpath:" + reference.getURI().getSchemeSpecificPart()
-						+ "." + (serialcounter++))) {
-			@Override
-			public void close() {
-				if (isOpen()) {
-					super.close();
-					party2protocol.close();
-				}
-			}
-
-		};
-
-		party2protocol.init(action -> protocol2party.notifyListeners(action));
-
-		protocol2party.init(info -> party2protocol.notifyListeners(info));
+						+ "." + (serialcounter++)));
+		party2protocol.init(action -> protocol2party.notifyChange(action));
+		protocol2party.init(info -> party2protocol.notifyChange(info));
 
 		party.connect(party2protocol);
 
-	}
-
-	/**
-	 * 
-	 * @return the open connections
-	 */
-	public List<BasicConnection> getOpenConnections() {
-		List<BasicConnection> open = new LinkedList<>();
-		if (party2protocol.isOpen())
-			open.add(party2protocol);
-		if (protocol2party.isOpen())
-			open.add(protocol2party);
-		return open;
-	}
-
-	public BasicConnectionWithParty getProtocolToPartyConn() {
 		return protocol2party;
 	}
 
-	/**
-	 * Internal use for testing
-	 */
-	protected BasicConnection getPartyToProtocolConn() {
-		return party2protocol;
+	private static URI uri(String ref) {
+		try {
+			return new URI(ref);
+		} catch (URISyntaxException e) {
+			throw new IllegalStateException("failed to create basic URI", e);
+		}
 	}
 
@@ -192,15 +83,7 @@
 				| InvocationTargetException e) {
 			throw new IllegalArgumentException(
-					"Failed to create connection to party " + classpath, e);
+					"Failed to create party connection", e);
 		}
 
-	}
-
-	private static URI uri(String ref) {
-		try {
-			return new URI(ref);
-		} catch (URISyntaxException e) {
-			throw new IllegalStateException("failed to create basic URI", e);
-		}
 	}
 
@@ -218,3 +101,31 @@
 	}
 
+	@Override
+	public List<ConnectionWithParty> connect(List<Reference> references)
+			throws IOException, NoResourcesNowException {
+		List<ConnectionWithParty> connections = new LinkedList<>();
+		for (Reference partyref : references) {
+			connections.add(connect(partyref));
+		}
+		return connections;
+	}
+
 }
+
+class BasicConnectionWithParty extends BasicConnection<Action, Inform>
+		implements ConnectionWithParty {
+
+	private PartyId id;
+
+	public BasicConnectionWithParty(Reference reference, URI uri) {
+		super(reference, uri);
+		this.id = new PartyId(uri.toString().replace("classpath:", "")
+				.replaceAll("\\.", "_"));
+	}
+
+	@Override
+	public PartyId getParty() {
+		return id;
+	}
+
+}
Index: simplerunner/src/main/java/geniusweb/simplerunner/NegoRunner.java
===================================================================
--- simplerunner/src/main/java/geniusweb/simplerunner/NegoRunner.java	(revision 53)
+++ simplerunner/src/main/java/geniusweb/simplerunner/NegoRunner.java	(revision 1)
@@ -9,6 +9,11 @@
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import geniusweb.events.ProtocolEvent;
+import geniusweb.protocol.CurrentNegoState;
+import geniusweb.protocol.NegoProtocol;
 import geniusweb.protocol.NegoSettings;
-import geniusweb.simplerunner.gui.GUI;
+import geniusweb.protocol.partyconnection.ConnectionWithPartyFactory;
+import geniusweb.protocol.session.SessionSettings;
+import tudelft.utilities.logging.ReportToLogger;
 import tudelft.utilities.logging.Reporter;
 
@@ -17,32 +22,48 @@
  * All referred files and classes need to be stored locally (or be in the
  * dependency list if you use maven).
- * <p>
- * <em>IMPORTANT</em> SimpleRunner has a number of restrictions, compared to a
- * run using a runserver and partyserver
- * <ul>
- * <li>With stand-alone runner, your parties are run together in a single
- * classloader. The main implication is that there may arise version conflicts
- * between parties.
- * <li>Stand-alone runner does NOT enforce the time deadline. Parties may
- * continue running indefinitely and thus bog down the JVM and stalling
- * tournaments.
- * </ul>
+ * 
  */
-public class NegoRunner {
+public class NegoRunner implements Runnable {
+	private final NegoSettings settings;
+	private final NegoProtocol protocol;
+	private final ConnectionWithPartyFactory connectionfactory;
+	private final Reporter log;
 	private final static ObjectMapper jackson = new ObjectMapper();
 
-	/**
-	 * The main runner
-	 * 
-	 * @param args should have 0 or 1 argument. If 0 arguments, the {@link GUI}
-	 *             is started. If one argoment, it should be a filename
-	 *             containing a settings.json file. That session is then run.
-	 * @throws IOException if problem occurs
-	 */
+	public NegoRunner(NegoSettings settings,
+			ConnectionWithPartyFactory connectionfactory, Reporter logger) {
+		if (settings == null || connectionfactory == null) {
+			throw new NullPointerException("Arguments must be not null");
+		}
+		this.settings = settings;
+		this.log = logger;
+		this.protocol = settings.getProtocol(log);
+		this.connectionfactory = connectionfactory;
+	}
+
+	@Override
+	public void run() {
+		protocol.addListener(evt -> handle(evt));
+		protocol.start(connectionfactory);
+	}
+
+	private void handle(ProtocolEvent evt) {
+		if (evt instanceof CurrentNegoState && ((CurrentNegoState) evt)
+				.getState().isFinal(System.currentTimeMillis())) {
+			stop();
+		}
+	}
+
+	protected void stop() {
+		if (protocol.getState().getError() != null) {
+			log.log(Level.WARNING, "protocol terminated abnormally",
+					protocol.getState().getError());
+		} else {
+			log.log(Level.INFO,
+					"protocol ended normally: " + protocol.getState());
+		}
+	}
+
 	public static void main(String[] args) throws IOException {
-		if (args.length == 0) {
-			GUI.main(args);
-			return;
-		}
 		if (args.length != 1) {
 			showusage();
@@ -51,14 +72,15 @@
 		String serialized = new String(Files.readAllBytes(Paths.get(args[0])),
 				StandardCharsets.UTF_8);
-		NegoSettings settings = jackson.readValue(serialized,
-				NegoSettings.class);
+		SessionSettings settings = jackson.readValue(serialized,
+				SessionSettings.class);
 
-		Runner runner = new Runner(settings, new ClassPathConnectionFactory(),
-				new StdOutReporter(), 0);
+		NegoRunner runner = new NegoRunner(settings,
+				new ClassPathConnectionFactory(),
+				new ReportToLogger("sessionrunner"));
 		runner.run();
 	}
 
 	private static void showusage() {
-		System.err.println("GeniusWeb stand-alone runner.");
+		System.err.println("GeniusWeb stand-alone runner. ");
 		System.err.println("first argument should be <settings.json>.");
 		System.err.println(
@@ -68,20 +90,3 @@
 
 	}
-
 }
-
-class StdOutReporter implements Reporter {
-	@Override
-	public void log(Level level, String msg) {
-		if (level == Level.WARNING || level == Level.SEVERE)
-			System.err.println(level + ":" + msg);
-		else
-			System.out.println(level + ":" + msg);
-	}
-
-	@Override
-	public void log(Level arg0, String msg, Throwable arg2) {
-		log(arg0, msg);
-	}
-
-}
Index: simplerunner/src/main/java/geniusweb/simplerunner/Runner.java
===================================================================
--- simplerunner/src/main/java/geniusweb/simplerunner/Runner.java	(revision 53)
+++ 	(revision )
@@ -1,139 +1,0 @@
-package geniusweb.simplerunner;
-
-import java.util.List;
-import java.util.logging.Level;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import geniusweb.events.ProtocolEvent;
-import geniusweb.protocol.CurrentNegoState;
-import geniusweb.protocol.NegoProtocol;
-import geniusweb.protocol.NegoSettings;
-import geniusweb.protocol.NegoState;
-import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
-import tudelft.utilities.logging.Reporter;
-
-/**
- * A simple tool to run a negotiation stand-alone, without starting the servers.
- * All referred files and classes need to be stored locally (or be in the
- * dependency list if you use maven).
- * <p>
- * <em>IMPORTANT</em> SimpleRunner has a number of restrictions, compared to a
- * run using a runserver and partyserver
- * <ul>
- * <li>With stand-alone runner, your parties are run together in a single
- * classloader. The main implication is that there may arise version conflicts
- * between parties.
- * <li>Stand-alone runner does NOT enforce the time deadline. Parties may
- * continue running indefinitely and thus bog down the JVM and stalling
- * tournaments.
- * </ul>
- */
-public class Runner implements Runnable {
-	private final static ObjectMapper jackson = new ObjectMapper();
-
-	private final NegoSettings settings;
-	private final NegoProtocol protocol;
-	private final ClassPathConnectionFactory connectionfactory;
-	protected final Reporter log;
-	private boolean properlyStopped = false;
-	private final int LOOPTIME = 200;// ms
-	private final int FINALWAITTIME = 5000;// ms
-	private long maxruntime;
-
-	/**
-	 * 
-	 * @param settings          the {@link NegoSettings}
-	 * @param connectionfactory the {@link ProtocolToPartyConnFactory}
-	 * @param logger            the {@link Reporter} to log problems
-	 * @param maxruntime        limit in millisecs. Ignored if 0
-	 */
-	public Runner(NegoSettings settings,
-			ClassPathConnectionFactory connectionfactory, Reporter logger,
-			long maxruntime) {
-		if (settings == null || connectionfactory == null) {
-			throw new NullPointerException("Arguments must be not null");
-		}
-		this.settings = settings;
-		this.log = logger;
-		this.protocol = settings.getProtocol(log);
-		this.connectionfactory = connectionfactory;
-		this.maxruntime = maxruntime;
-	}
-
-	/**
-	 * 
-	 * @return true if the runner has finished
-	 */
-	public boolean isProperlyStopped() {
-		return properlyStopped;
-	}
-
-	@Override
-	public void run() {
-		protocol.addListener(evt -> handle(evt));
-		protocol.start(connectionfactory);
-		long remainingtime = maxruntime;
-		while (!properlyStopped && (maxruntime == 0 || remainingtime > 0)) {
-			try {
-				Thread.sleep(LOOPTIME);
-				remainingtime -= LOOPTIME;
-			} catch (InterruptedException e) {
-				e.printStackTrace();
-			}
-		}
-		log.log(Level.INFO, "Waiting for connection closure");
-
-		remainingtime = FINALWAITTIME;
-		while (remainingtime > 0
-				&& !connectionfactory.getOpenConnections().isEmpty()) {
-			try {
-				Thread.sleep(LOOPTIME);
-				remainingtime -= LOOPTIME;
-			} catch (InterruptedException e) {
-				e.printStackTrace();
-			}
-		}
-		List<BasicConnection> openconn = connectionfactory.getOpenConnections();
-		if (!openconn.isEmpty())
-			log.log(Level.WARNING, "Connections " + openconn
-					+ " did not close properly at end of run");
-		log.log(Level.INFO, "end run");
-	}
-
-	private void handle(ProtocolEvent evt) {
-		if (evt instanceof CurrentNegoState && ((CurrentNegoState) evt)
-				.getState().isFinal(System.currentTimeMillis())) {
-			stop();
-		}
-	}
-
-	protected void stop() {
-		logFinal(Level.INFO, protocol.getState());
-		properlyStopped = true;
-	}
-
-	/**
-	 * Separate so that we can intercept this when mocking, as this will crash
-	 * on mocks because {@link #jackson} can not handle mocks.
-	 * 
-	 * @param level the log {@link Level}
-	 * @param state the {@link NegoState} to log
-	 */
-	protected void logFinal(Level level, NegoState state) {
-		try {
-			log.log(level, "protocol ended normally: "
-					+ jackson.writeValueAsString(protocol.getState()));
-		} catch (JsonProcessingException e) {
-			e.printStackTrace();
-		}
-	}
-
-	/**
-	 * @return protocol that runs/ran the session.
-	 */
-	public NegoProtocol getProtocol() {
-		return protocol;
-	}
-}
