summaryrefslogtreecommitdiffstats
blob: a94fbc567d7b79a4eb79f00ffdf06c582026483c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 * Copyright (c) 2012-2015 Isode Limited.
 * All rights reserved.
 * See the COPYING file for more information.
 */
/*
 * Copyright (c) 2015 Tarun Gupta.
 * Licensed under the simplified BSD license.
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 */

package com.isode.stroke.network;

import com.isode.stroke.signals.SignalConnection;
import com.isode.stroke.signals.Slot2;
import com.isode.stroke.signals.Slot1;
import com.isode.stroke.base.SafeByteArray;

public abstract class ProxiedConnection extends Connection {

	private boolean connected_;
	private DomainNameResolver resolver_;
	private ConnectionFactory connectionFactory_;	
	private TimerFactory timerFactory_;
	private String proxyHost_ = "";
	private int proxyPort_;
	private HostAddressPort server_;
	private Connector connector_;
	private Connection connection_;
	private SignalConnection onDataReadConnection;
	private SignalConnection onDisconnectedConnection;
	private SignalConnection onConnectFinishedConnection;

	public ProxiedConnection(DomainNameResolver resolver, ConnectionFactory connectionFactory, TimerFactory timerFactory, final String proxyHost, int proxyPort) {
		this.resolver_ = resolver;
		this.connectionFactory_ = connectionFactory;
		this.timerFactory_ = timerFactory;
		this.proxyHost_ = proxyHost;
		this.proxyPort_ = proxyPort;
		this.server_ = new HostAddressPort(new HostAddress("0.0.0.0"), 0);
		this.connected_ = false;
	}

	protected void finalize() throws Throwable {
		try {
			cancelConnector();
			if (connection_ != null) {
				onDataReadConnection.disconnect();
				onDisconnectedConnection.disconnect();
			}
			if (connected_) {
				System.err.println("Warning: Connection was still established.");
			}
		}
		finally {
			super.finalize();
		}
	}

	public void listen() {
		assert(false);
		connection_.listen();		
	}

	public void connect(final HostAddressPort server) {
		server_ = server;

		connector_ = Connector.create(proxyHost_, proxyPort_, null, resolver_, connectionFactory_, timerFactory_);
		onConnectFinishedConnection = connector_.onConnectFinished.connect(new Slot2<Connection, com.isode.stroke.base.Error>() {
			@Override
			public void call(Connection c, com.isode.stroke.base.Error e) {
				handleConnectFinished(c);
			}
		});
		connector_.start();
	}

	public void disconnect() {
		connected_ = false;
		connection_.disconnect();
	}

	public void write(final SafeByteArray data) {
		connection_.write(data);
	}

	public HostAddressPort getLocalAddress() {
		return connection_.getLocalAddress();
	}

	private void handleConnectFinished(Connection connection) {
		cancelConnector();
		if (connection != null) {
			connection_ = connection;
			connection_.onDataRead.connect(new Slot1<SafeByteArray>() {
				@Override
				public void call(SafeByteArray s) {
					handleDataRead(s);
				}
			});
			connection_.onDisconnected.connect(new Slot1<Error>() {
				@Override
				public void call(Error e) {
					handleDisconnected(e);
				}
			});

			initializeProxy();
		}
		else {
			onConnectFinished.emit(true);
		}
	}

	private void handleDataRead(SafeByteArray data) {
		if (!connected_) {
			handleProxyInitializeData(data);
		}
		else {
			onDataRead.emit(data);
		}
	}

	private void handleDisconnected(final Error error) {
		onDisconnected.emit(error);
	}

	private void cancelConnector() {
		if (connector_ != null) {
			onConnectFinishedConnection.disconnect();
			connector_.stop();
			connector_ = null;
		}
	}

	protected void setProxyInitializeFinished(boolean success) {
		connected_ = success;
		if (!success) {
			disconnect();
		}
		onConnectFinished.emit(!success);		
	}

	protected abstract void initializeProxy();
	protected abstract void handleProxyInitializeData(SafeByteArray data);

	protected HostAddressPort getServer() {
		return server_;
	}
}