Skip to content

Commit 4648afa

Browse files
author
alberto lalama
authored
Invoke start callback accurately (#10)
1 parent a8e9d37 commit 4648afa

File tree

3 files changed

+67
-19
lines changed

3 files changed

+67
-19
lines changed

src/android/org/uproxy/tun2socks/Tun2Socks.java

+40-14
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class Tun2Socks extends CordovaPlugin {
3030
public static final int RESULT_OK = -1;
3131

3232
private String m_socksServerAddress;
33+
private CallbackContext m_onStartCallback = null;
3334
private CallbackContext m_onDisconnectCallback = null;
3435

3536
@Override
@@ -48,7 +49,8 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
4849
// from onActivityResult.
4950
m_socksServerAddress = args.getString(0);
5051
Log.i(LOG_TAG, "Got socks server address: " + m_socksServerAddress);
51-
prepareAndStartTunnelService(callbackContext);
52+
m_onStartCallback = callbackContext;
53+
prepareAndStartTunnelService();
5254
}
5355
return true;
5456
} else if (action.equals(STOP_ACTION)) {
@@ -76,10 +78,12 @@ protected void pluginInitialize() {
7678
return;
7779
}
7880

81+
IntentFilter broadcastFilter =
82+
new IntentFilter(TunnelVpnService.TUNNEL_VPN_DISCONNECT_BROADCAST);
83+
broadcastFilter.addAction(TunnelVpnService.TUNNEL_VPN_START_BROADCAST);
84+
7985
LocalBroadcastManager.getInstance(getBaseContext())
80-
.registerReceiver(
81-
m_disconnectBroadcastReceiver,
82-
new IntentFilter(TunnelVpnService.TUNNEL_VPN_DISCONNECT_BROADCAST));
86+
.registerReceiver(m_vpnTunnelBroadcastReceiver, broadcastFilter);
8387
}
8488

8589
@Override
@@ -89,16 +93,15 @@ public void onDestroy() {
8993
stopTunnelService();
9094
}
9195

92-
protected void prepareAndStartTunnelService(CallbackContext callbackContext) {
96+
protected void prepareAndStartTunnelService() {
9397
Log.d(LOG_TAG, "Starting tun2socks...");
9498
if (hasVpnService()) {
9599
if (prepareVpnService()) {
96100
startTunnelService(getBaseContext());
97101
}
98-
callbackContext.success("Started tun2socks");
99102
} else {
100103
Log.e(LOG_TAG, "Device does not support whole device VPN mode.");
101-
callbackContext.error("Failed to start tun2socks");
104+
m_onStartCallback.error("Failed to start tun2socks");
102105
}
103106
}
104107

@@ -127,13 +130,16 @@ protected boolean prepareVpnService() throws ActivityNotFoundException {
127130
public void onActivityResult(int request, int result, Intent data) {
128131
if (request == REQUEST_CODE_PREPARE_VPN && result == RESULT_OK) {
129132
startTunnelService(getBaseContext());
133+
} else {
134+
Log.e(LOG_TAG, "failed to prepare VPN");
135+
m_onStartCallback.error("Failed to start tun2socks");
130136
}
131137
}
132138

133139
protected void startTunnelService(Context context) {
134140
Log.i(LOG_TAG, "starting tunnel service");
135141
if (isServiceRunning()) {
136-
Log.w(LOG_TAG, "already running service");
142+
Log.d(LOG_TAG, "already running service");
137143
TunnelManager tunnelManager = TunnelState.getTunnelState().getTunnelManager();
138144
if (tunnelManager != null) {
139145
tunnelManager.restartTunnel(m_socksServerAddress);
@@ -172,6 +178,19 @@ private Context getBaseContext() {
172178
return this.cordova.getActivity().getApplicationContext();
173179
}
174180

181+
public void onStartVpn(boolean success) {
182+
if (m_onStartCallback == null || m_onStartCallback.isFinished()) {
183+
Log.e(LOG_TAG, "failed to call on start callback");
184+
return;
185+
}
186+
187+
if (success) {
188+
m_onStartCallback.success("Started tun2socks");
189+
} else {
190+
m_onStartCallback.error("Failed to start tun2socks");
191+
}
192+
}
193+
175194
public void onDisconnect() {
176195
if (m_onDisconnectCallback != null) {
177196
PluginResult result = new PluginResult(PluginResult.Status.OK);
@@ -180,20 +199,27 @@ public void onDisconnect() {
180199
}
181200
}
182201

183-
private DisconnectBroadcastReceiver m_disconnectBroadcastReceiver =
184-
new DisconnectBroadcastReceiver(Tun2Socks.this);
202+
private VpnTunnelBroadcastReceiver m_vpnTunnelBroadcastReceiver =
203+
new VpnTunnelBroadcastReceiver(Tun2Socks.this);
185204

186-
private class DisconnectBroadcastReceiver extends BroadcastReceiver {
205+
private class VpnTunnelBroadcastReceiver extends BroadcastReceiver {
187206
private Tun2Socks m_handler;
188207

189-
public DisconnectBroadcastReceiver(Tun2Socks handler) {
208+
public VpnTunnelBroadcastReceiver(Tun2Socks handler) {
190209
m_handler = handler;
191210
}
192211

193212
@Override
194213
public void onReceive(Context context, Intent intent) {
195-
// Callback into handler so we can communicate the disconnect event to js.
196-
m_handler.onDisconnect();
214+
final String action = intent.getAction();
215+
if (TunnelVpnService.TUNNEL_VPN_START_BROADCAST.equals(action)) {
216+
boolean startSuccess = intent.getBooleanExtra(
217+
TunnelVpnService.TUNNEL_VPN_START_SUCCESS_EXTRA, true);
218+
m_handler.onStartVpn(startSuccess);
219+
220+
} else if (TunnelVpnService.TUNNEL_VPN_DISCONNECT_BROADCAST.equals(action)) {
221+
m_handler.onDisconnect();
222+
}
197223
}
198224
};
199225
}

src/android/org/uproxy/tun2socks/TunnelManager.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,15 @@ public class TunnelManager implements Tunnel.HostService {
4040
private static final String LOG_TAG = "TunnelManager";
4141
public static final String SOCKS_SERVER_ADDRESS_EXTRA = "socksServerAddress";
4242

43-
private Service m_parentService = null;
43+
private TunnelVpnService m_parentService = null;
4444
private CountDownLatch m_tunnelThreadStopSignal;
4545
private Thread m_tunnelThread;
4646
private AtomicBoolean m_isStopping;
4747
private Tunnel m_tunnel = null;
4848
private String m_socksServerAddress;
4949
private AtomicBoolean m_isReconnecting;
5050

51-
public TunnelManager(Service parentService) {
51+
public TunnelManager(TunnelVpnService parentService) {
5252
m_parentService = parentService;
5353
m_isStopping = new AtomicBoolean(false);
5454
m_isReconnecting = new AtomicBoolean(false);
@@ -65,15 +65,18 @@ public int onStartCommand(Intent intent, int flags, int startId) {
6565
m_socksServerAddress = intent.getStringExtra(SOCKS_SERVER_ADDRESS_EXTRA);
6666
if (m_socksServerAddress == null) {
6767
Log.e(LOG_TAG, "Failed to receive the socks server address.");
68+
m_parentService.broadcastVpnStart(false /* success */);
6869
return 0;
6970
}
7071

7172
try {
7273
if (!m_tunnel.startRouting()) {
7374
Log.e(LOG_TAG, "Failed to establish VPN");
75+
m_parentService.broadcastVpnStart(false /* success */);
7476
}
7577
} catch (Tunnel.Exception e) {
7678
Log.e(LOG_TAG, String.format("Failed to establish VPN: %s", e.getMessage()));
79+
m_parentService.broadcastVpnStart(false /* success */);
7780
}
7881
return android.app.Service.START_NOT_STICKY;
7982
}
@@ -119,6 +122,7 @@ public void restartTunnel(final String socksServerAddress) {
119122
if (socksServerAddress == null ||
120123
socksServerAddress.equals(m_socksServerAddress)) {
121124
// Don't reconnect if the socks server address hasn't changed.
125+
m_parentService.broadcastVpnStart(true /* success */);
122126
return;
123127
}
124128
m_socksServerAddress = socksServerAddress;
@@ -152,6 +156,7 @@ private void runTunnel(String socksServerAddress, String dnsResolverAddress) {
152156
throw new Tunnel.Exception("application is not prepared or revoked");
153157
}
154158
Log.i(LOG_TAG, "VPN service running");
159+
m_parentService.broadcastVpnStart(true /* success */);
155160

156161
try {
157162
m_tunnelThreadStopSignal.await();
@@ -163,6 +168,7 @@ private void runTunnel(String socksServerAddress, String dnsResolverAddress) {
163168

164169
} catch (Tunnel.Exception e) {
165170
Log.e(LOG_TAG, String.format("Start tunnel failed: %s", e.getMessage()));
171+
m_parentService.broadcastVpnStart(false /* success */);
166172
} finally {
167173
if (m_isReconnecting.get()) {
168174
// Stop tunneling only, not VPN, if reconnecting.

src/android/org/uproxy/tun2socks/TunnelVpnService.java

+19-3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ public class TunnelVpnService extends VpnService {
3434
private static final String LOG_TAG = "TunnelVpnService";
3535
public static final String TUNNEL_VPN_DISCONNECT_BROADCAST =
3636
"tunnelVpnDisconnectBroadcast";
37+
public static final String TUNNEL_VPN_START_BROADCAST =
38+
"tunnelVpnStartBroadcast";
39+
public static final String TUNNEL_VPN_START_SUCCESS_EXTRA =
40+
"tunnelVpnStartSuccessExtra";
3741

3842
private TunnelManager m_tunnelManager = new TunnelManager(this);
3943

@@ -85,9 +89,21 @@ public VpnService.Builder newBuilder() {
8589
return new VpnService.Builder();
8690
}
8791

88-
private void broadcastVpnDisconnect() {
89-
Intent disconnectBroadcast = new Intent(TUNNEL_VPN_DISCONNECT_BROADCAST);
92+
// Broadcast non-user-initiated VPN disconnect.
93+
public void broadcastVpnDisconnect() {
94+
dispatchBroadcast(new Intent(TUNNEL_VPN_DISCONNECT_BROADCAST));
95+
}
96+
97+
// Broadcast VPN start. |success| is true if the VPN and tunnel were started
98+
// successfully, and false otherwise.
99+
public void broadcastVpnStart(boolean success) {
100+
Intent vpnStart = new Intent(TUNNEL_VPN_START_BROADCAST);
101+
vpnStart.putExtra(TUNNEL_VPN_START_SUCCESS_EXTRA, success);
102+
dispatchBroadcast(vpnStart);
103+
}
104+
105+
private void dispatchBroadcast(final Intent broadcast) {
90106
LocalBroadcastManager.getInstance(TunnelVpnService.this)
91-
.sendBroadcast(disconnectBroadcast);
107+
.sendBroadcast(broadcast);
92108
}
93109
}

0 commit comments

Comments
 (0)