diff --git a/briar-api/src/org/briarproject/api/plugins/ConnectionRegistry.java b/briar-api/src/org/briarproject/api/plugins/ConnectionRegistry.java
index 6de3d00c5b55e34b4ca4a364a6056f4a510fa6cd..dc9376195387a5da851a9aab37a67707bc470e1c 100644
--- a/briar-api/src/org/briarproject/api/plugins/ConnectionRegistry.java
+++ b/briar-api/src/org/briarproject/api/plugins/ConnectionRegistry.java
@@ -16,5 +16,7 @@ public interface ConnectionRegistry {
 
 	Collection<ContactId> getConnectedContacts(TransportId t);
 
+	boolean isConnected(ContactId c, TransportId t);
+
 	boolean isConnected(ContactId c);
 }
diff --git a/briar-core/src/org/briarproject/plugins/ConnectionRegistryImpl.java b/briar-core/src/org/briarproject/plugins/ConnectionRegistryImpl.java
index 6f01f02d7a597e49a94bb2932d47515eedc9d13d..0fe9c3b4b4cae11e0f407d61498acd62a89b9ff9 100644
--- a/briar-core/src/org/briarproject/plugins/ConnectionRegistryImpl.java
+++ b/briar-core/src/org/briarproject/plugins/ConnectionRegistryImpl.java
@@ -114,6 +114,16 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
 		}
 	}
 
+	public boolean isConnected(ContactId c, TransportId t) {
+		lock.lock();
+		try {
+			Map<ContactId, Integer> m = connections.get(t);
+			return m != null && m.containsKey(c);
+		} finally {
+			lock.unlock();
+		}
+	}
+
 	public boolean isConnected(ContactId c) {
 		lock.lock();
 		try {
diff --git a/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java b/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java
index 9f2f85b978f47a876d0b6701f0cca2d017b756a5..4eb8da75b93907cb3e5ef1a03fbea07f9e74d21c 100644
--- a/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java
+++ b/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java
@@ -3,13 +3,17 @@ package org.briarproject.plugins;
 import org.briarproject.api.TransportId;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.event.ContactStatusChangedEvent;
+import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
+import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.TransportDisabledEvent;
 import org.briarproject.api.event.TransportEnabledEvent;
 import org.briarproject.api.lifecycle.IoExecutor;
 import org.briarproject.api.lifecycle.Service;
 import org.briarproject.api.lifecycle.ServiceException;
 import org.briarproject.api.plugins.ConnectionManager;
+import org.briarproject.api.plugins.ConnectionRegistry;
 import org.briarproject.api.plugins.Plugin;
 import org.briarproject.api.plugins.PluginCallback;
 import org.briarproject.api.plugins.PluginConfig;
@@ -46,7 +50,7 @@ import javax.inject.Inject;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 
-class PluginManagerImpl implements PluginManager, Service {
+class PluginManagerImpl implements PluginManager, Service, EventListener {
 
 	private static final Logger LOG =
 			Logger.getLogger(PluginManagerImpl.class.getName());
@@ -56,6 +60,7 @@ class PluginManagerImpl implements PluginManager, Service {
 	private final PluginConfig pluginConfig;
 	private final Poller poller;
 	private final ConnectionManager connectionManager;
+	private final ConnectionRegistry connectionRegistry;
 	private final SettingsManager settingsManager;
 	private final TransportPropertyManager transportPropertyManager;
 	private final UiCallback uiCallback;
@@ -67,6 +72,7 @@ class PluginManagerImpl implements PluginManager, Service {
 	PluginManagerImpl(@IoExecutor Executor ioExecutor, EventBus eventBus,
 			PluginConfig pluginConfig, Poller poller,
 			ConnectionManager connectionManager,
+			ConnectionRegistry connectionRegistry,
 			SettingsManager settingsManager,
 			TransportPropertyManager transportPropertyManager,
 			UiCallback uiCallback) {
@@ -75,6 +81,7 @@ class PluginManagerImpl implements PluginManager, Service {
 		this.pluginConfig = pluginConfig;
 		this.poller = poller;
 		this.connectionManager = connectionManager;
+		this.connectionRegistry = connectionRegistry;
 		this.settingsManager = settingsManager;
 		this.transportPropertyManager = transportPropertyManager;
 		this.uiCallback = uiCallback;
@@ -106,10 +113,14 @@ class PluginManagerImpl implements PluginManager, Service {
 		} catch (InterruptedException e) {
 			throw new ServiceException(e);
 		}
+		// Listen for events
+		eventBus.addListener(this);
 	}
 
 	@Override
 	public void stopService() throws ServiceException {
+		// Stop listening for events
+		eventBus.removeListener(this);
 		// Stop the poller
 		LOG.info("Stopping poller");
 		poller.stop();
@@ -122,9 +133,6 @@ class PluginManagerImpl implements PluginManager, Service {
 		LOG.info("Stopping duplex plugins");
 		for (DuplexPlugin plugin : duplexPlugins)
 			ioExecutor.execute(new PluginStopper(plugin, latch));
-		plugins.clear();
-		simplexPlugins.clear();
-		duplexPlugins.clear();
 		// Wait for all the plugins to stop
 		try {
 			latch.await();
@@ -151,6 +159,47 @@ class PluginManagerImpl implements PluginManager, Service {
 		return Collections.unmodifiableList(supported);
 	}
 
+	@Override
+	public void eventOccurred(Event e) {
+		if (e instanceof ContactStatusChangedEvent) {
+			ContactStatusChangedEvent c = (ContactStatusChangedEvent) e;
+			if (c.isActive()) connectToContact(c.getContactId());
+		}
+	}
+
+	private void connectToContact(ContactId c) {
+		for (SimplexPlugin s : simplexPlugins)
+			if (s.shouldPoll()) connectToContact(c, s);
+		for (DuplexPlugin d : duplexPlugins)
+			if (d.shouldPoll()) connectToContact(c, d);
+	}
+
+	private void connectToContact(final ContactId c, final SimplexPlugin p) {
+		ioExecutor.execute(new Runnable() {
+			public void run() {
+				TransportId t = p.getId();
+				if (!connectionRegistry.isConnected(c, t)) {
+					TransportConnectionWriter w = p.createWriter(c);
+					if (w != null)
+						connectionManager.manageOutgoingConnection(c, t, w);
+				}
+			}
+		});
+	}
+
+	private void connectToContact(final ContactId c, final DuplexPlugin p) {
+		ioExecutor.execute(new Runnable() {
+			public void run() {
+				TransportId t = p.getId();
+				if (!connectionRegistry.isConnected(c, t)) {
+					DuplexTransportConnection d = p.createConnection(c);
+					if (d != null)
+						connectionManager.manageOutgoingConnection(c, t, d);
+				}
+			}
+		});
+	}
+
 	private class SimplexPluginStarter implements Runnable {
 
 		private final SimplexPluginFactory factory;
diff --git a/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java b/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java
index 872985ff15f92e9759349064cbe26c40dd4014f1..6627225c3ddf3417e92b3a2316d4d52baab1e6f9 100644
--- a/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java
@@ -1,13 +1,20 @@
 package org.briarproject.plugins;
 
 import org.briarproject.BriarTestCase;
+import org.briarproject.ImmediateExecutor;
 import org.briarproject.api.TransportId;
+import org.briarproject.api.contact.ContactId;
+import org.briarproject.api.event.ContactStatusChangedEvent;
 import org.briarproject.api.event.EventBus;
+import org.briarproject.api.event.EventListener;
 import org.briarproject.api.plugins.ConnectionManager;
+import org.briarproject.api.plugins.ConnectionRegistry;
 import org.briarproject.api.plugins.PluginConfig;
+import org.briarproject.api.plugins.TransportConnectionWriter;
 import org.briarproject.api.plugins.duplex.DuplexPlugin;
 import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
 import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
+import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
 import org.briarproject.api.plugins.simplex.SimplexPlugin;
 import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
 import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
@@ -36,6 +43,8 @@ public class PluginManagerImplTest extends BriarTestCase {
 		final Poller poller = context.mock(Poller.class);
 		final ConnectionManager connectionManager =
 				context.mock(ConnectionManager.class);
+		final ConnectionRegistry connectionRegistry =
+				context.mock(ConnectionRegistry.class);
 		final SettingsManager settingsManager =
 				context.mock(SettingsManager.class);
 		final TransportPropertyManager transportPropertyManager =
@@ -63,6 +72,7 @@ public class PluginManagerImplTest extends BriarTestCase {
 		final TransportId duplexFailId = new TransportId("duplex1");
 
 		context.checking(new Expectations() {{
+			// start()
 			// First simplex plugin
 			oneOf(pluginConfig).getSimplexFactories();
 			will(returnValue(Arrays.asList(simplexFactory,
@@ -103,6 +113,11 @@ public class PluginManagerImplTest extends BriarTestCase {
 			oneOf(duplexFailFactory).createPlugin(with(any(
 					DuplexPluginCallback.class)));
 			will(returnValue(null)); // Failed to create a plugin
+			// Start listening for events
+			oneOf(eventBus).addListener(with(any(EventListener.class)));
+			// stop()
+			// Stop listening for events
+			oneOf(eventBus).removeListener(with(any(EventListener.class)));
 			// Stop the poller
 			oneOf(poller).stop();
 			// Stop the plugins
@@ -111,8 +126,8 @@ public class PluginManagerImplTest extends BriarTestCase {
 		}});
 
 		PluginManagerImpl p = new PluginManagerImpl(ioExecutor, eventBus,
-				pluginConfig, poller, connectionManager, settingsManager,
-				transportPropertyManager, uiCallback);
+				pluginConfig, poller, connectionManager, connectionRegistry,
+				settingsManager, transportPropertyManager, uiCallback);
 
 		// Two plugins should be started and stopped
 		p.startService();
@@ -120,4 +135,151 @@ public class PluginManagerImplTest extends BriarTestCase {
 
 		context.assertIsSatisfied();
 	}
+
+	@Test
+	public void testConnectToNewContact() throws Exception {
+		Mockery context = new Mockery();
+		final Executor ioExecutor = new ImmediateExecutor();
+		final EventBus eventBus = context.mock(EventBus.class);
+		final PluginConfig pluginConfig = context.mock(PluginConfig.class);
+		final Poller poller = context.mock(Poller.class);
+		final ConnectionManager connectionManager =
+				context.mock(ConnectionManager.class);
+		final ConnectionRegistry connectionRegistry =
+				context.mock(ConnectionRegistry.class);
+		final SettingsManager settingsManager =
+				context.mock(SettingsManager.class);
+		final TransportPropertyManager transportPropertyManager =
+				context.mock(TransportPropertyManager.class);
+		final UiCallback uiCallback = context.mock(UiCallback.class);
+		final TransportConnectionWriter transportConnectionWriter =
+				context.mock(TransportConnectionWriter.class);
+		final DuplexTransportConnection duplexTransportConnection =
+				context.mock(DuplexTransportConnection.class);
+
+		final ContactId contactId = new ContactId(234);
+
+		// Two simplex plugins: one supports polling, the other doesn't
+		final SimplexPluginFactory simplexFactory =
+				context.mock(SimplexPluginFactory.class);
+		final SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class);
+		final TransportId simplexId = new TransportId("simplex");
+		final SimplexPluginFactory simplexFactory1 =
+				context.mock(SimplexPluginFactory.class, "simplexFactory1");
+		final SimplexPlugin simplexPlugin1 =
+				context.mock(SimplexPlugin.class, "simplexPlugin1");
+		final TransportId simplexId1 = new TransportId("simplex1");
+
+		// Two duplex plugins: one supports polling, the other doesn't
+		final DuplexPluginFactory duplexFactory =
+				context.mock(DuplexPluginFactory.class);
+		final DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class);
+		final TransportId duplexId = new TransportId("duplex");
+		final DuplexPluginFactory duplexFactory1 =
+				context.mock(DuplexPluginFactory.class, "duplexFactory1");
+		final DuplexPlugin duplexPlugin1 =
+				context.mock(DuplexPlugin.class, "duplexPlugin1");
+		final TransportId duplexId1 = new TransportId("duplex1");
+
+		context.checking(new Expectations() {{
+			// start()
+			// First simplex plugin
+			oneOf(pluginConfig).getSimplexFactories();
+			will(returnValue(Arrays.asList(simplexFactory, simplexFactory1)));
+			oneOf(simplexFactory).getId();
+			will(returnValue(simplexId));
+			oneOf(simplexFactory).createPlugin(with(any(
+					SimplexPluginCallback.class)));
+			will(returnValue(simplexPlugin)); // Created
+			oneOf(simplexPlugin).start();
+			will(returnValue(true)); // Started
+			oneOf(simplexPlugin).shouldPoll();
+			will(returnValue(true)); // Should poll
+			oneOf(poller).addPlugin(simplexPlugin);
+			// Second simplex plugin
+			oneOf(simplexFactory1).getId();
+			will(returnValue(simplexId1));
+			oneOf(simplexFactory1).createPlugin(with(any(
+					SimplexPluginCallback.class)));
+			will(returnValue(simplexPlugin1)); // Created
+			oneOf(simplexPlugin1).start();
+			will(returnValue(true)); // Started
+			oneOf(simplexPlugin1).shouldPoll();
+			will(returnValue(false)); // Should not poll
+			// First duplex plugin
+			oneOf(pluginConfig).getDuplexFactories();
+			will(returnValue(Arrays.asList(duplexFactory, duplexFactory1)));
+			oneOf(duplexFactory).getId();
+			will(returnValue(duplexId));
+			oneOf(duplexFactory).createPlugin(with(any(
+					DuplexPluginCallback.class)));
+			will(returnValue(duplexPlugin)); // Created
+			oneOf(duplexPlugin).start();
+			will(returnValue(true)); // Started
+			oneOf(duplexPlugin).shouldPoll();
+			will(returnValue(true)); // Should poll
+			oneOf(poller).addPlugin(duplexPlugin);
+			// Second duplex plugin
+			oneOf(duplexFactory1).getId();
+			will(returnValue(duplexId1));
+			oneOf(duplexFactory1).createPlugin(with(any(
+					DuplexPluginCallback.class)));
+			will(returnValue(duplexPlugin1)); // Created
+			oneOf(duplexPlugin1).start();
+			will(returnValue(true)); // Started
+			oneOf(duplexPlugin1).shouldPoll();
+			will(returnValue(false)); // Should not poll
+			// Start listening for events
+			oneOf(eventBus).addListener(with(any(EventListener.class)));
+			// eventOccurred()
+			// First simplex plugin
+			oneOf(simplexPlugin).shouldPoll();
+			will(returnValue(true));
+			oneOf(simplexPlugin).getId();
+			will(returnValue(simplexId));
+			oneOf(connectionRegistry).isConnected(contactId, simplexId);
+			will(returnValue(false));
+			oneOf(simplexPlugin).createWriter(contactId);
+			will(returnValue(transportConnectionWriter));
+			oneOf(connectionManager).manageOutgoingConnection(contactId,
+					simplexId, transportConnectionWriter);
+			// Second simplex plugin
+			oneOf(simplexPlugin1).shouldPoll();
+			will(returnValue(false));
+			// First duplex plugin
+			oneOf(duplexPlugin).shouldPoll();
+			will(returnValue(true));
+			oneOf(duplexPlugin).getId();
+			will(returnValue(duplexId));
+			oneOf(connectionRegistry).isConnected(contactId, duplexId);
+			will(returnValue(false));
+			oneOf(duplexPlugin).createConnection(contactId);
+			will(returnValue(duplexTransportConnection));
+			oneOf(connectionManager).manageOutgoingConnection(contactId,
+					duplexId, duplexTransportConnection);
+			// Second duplex plugin
+			oneOf(duplexPlugin1).shouldPoll();
+			will(returnValue(false));
+			// stop()
+			// Stop listening for events
+			oneOf(eventBus).removeListener(with(any(EventListener.class)));
+			// Stop the poller
+			oneOf(poller).stop();
+			// Stop the plugins
+			oneOf(simplexPlugin).stop();
+			oneOf(simplexPlugin1).stop();
+			oneOf(duplexPlugin).stop();
+			oneOf(duplexPlugin1).stop();
+		}});
+
+		PluginManagerImpl p = new PluginManagerImpl(ioExecutor, eventBus,
+				pluginConfig, poller, connectionManager, connectionRegistry,
+				settingsManager, transportPropertyManager, uiCallback);
+
+		p.startService();
+		p.eventOccurred(new ContactStatusChangedEvent(contactId, true));
+		p.stopService();
+
+		context.assertIsSatisfied();
+	}
 }