protected void tunnel(final Socket internal, final Socket external) {

		this.logger.info("Established tunnel between "
				+ StringUtils.formatSocket(internal) + " and "
				+ StringUtils.formatSocket(external));

		this.executor.execute(new TunnelThread(external, internal));

		try {
			SocketUtils.copy(internal, external);

			// Wait for the other thread to die
			if (this.logger.isLoggable(Level.FINE)) {
				this.logger.fine("Waiting to disconnect");
			}

		} catch (final IOException ioe) {
			if (this.logger.isLoggable(Level.FINE)) {
				this.logger.log(Level.FINE, "IOException occurred between "
						+ StringUtils.formatSocket(internal) + " and "
						+ StringUtils.formatSocket(external), ioe);
			}
		} finally {

			try {
				this.countDownLatch.await();
			} catch (final InterruptedException e) {
			}

			try {
				external.close();
			} catch (final IOException e) {
			}

			try {
				internal.close();
			} catch (final IOException e) {
			}

			this.logger.info("Shutdown connection between "
					+ StringUtils.formatSocket(internal) + " and "
					+ StringUtils.formatSocket(external));
		}
	}