diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/org/connectbot/ConsoleActivity.java | 10 | ||||
| -rw-r--r-- | src/org/connectbot/HostEditorActivity.java | 8 | ||||
| -rw-r--r-- | src/org/connectbot/HostListActivity.java | 4 | ||||
| -rw-r--r-- | src/org/connectbot/PortForwardListActivity.java | 12 | ||||
| -rw-r--r-- | src/org/connectbot/service/TerminalBridge.java | 13 | ||||
| -rw-r--r-- | src/org/connectbot/service/TerminalManager.java | 202 | ||||
| -rw-r--r-- | src/org/connectbot/transport/AbsTransport.java | 5 | ||||
| -rw-r--r-- | src/org/connectbot/transport/Local.java | 8 | ||||
| -rw-r--r-- | src/org/connectbot/transport/SSH.java | 8 | ||||
| -rw-r--r-- | src/org/connectbot/transport/Telnet.java | 8 | 
10 files changed, 195 insertions, 83 deletions
| diff --git a/src/org/connectbot/ConsoleActivity.java b/src/org/connectbot/ConsoleActivity.java index b0c9e83..234ef43 100644 --- a/src/org/connectbot/ConsoleActivity.java +++ b/src/org/connectbot/ConsoleActivity.java @@ -149,7 +149,7 @@ public class ConsoleActivity extends Activity {  			final String requestedNickname = (requested != null) ? requested.getFragment() : null;  			int requestedIndex = 0; -			TerminalBridge requestedBridge = bound.getBridgeByName(requestedNickname); +			TerminalBridge requestedBridge = bound.getConnectedBridge(requestedNickname);  			// If we didn't find the requested connection, try opening it  			if (requestedNickname != null && requestedBridge == null) { @@ -176,8 +176,10 @@ public class ConsoleActivity extends Activity {  		public void onServiceDisconnected(ComponentName className) {  			// tell each bridge to forget about our prompt handler -			for(TerminalBridge bridge : bound.bridges) -				bridge.promptHelper.setHandler(null); +			synchronized (bound.bridges) { +				for(TerminalBridge bridge : bound.bridges) +					bridge.promptHelper.setHandler(null); +			}  			flip.removeAllViews();  			updateEmptyVisible(); @@ -852,7 +854,7 @@ public class ConsoleActivity extends Activity {  			return;  		} -		TerminalBridge requestedBridge = bound.getBridgeByName(requested.getFragment()); +		TerminalBridge requestedBridge = bound.getConnectedBridge(requested.getFragment());  		int requestedIndex = 0;  		synchronized (flip) { diff --git a/src/org/connectbot/HostEditorActivity.java b/src/org/connectbot/HostEditorActivity.java index e8202e2..95d04cc 100644 --- a/src/org/connectbot/HostEditorActivity.java +++ b/src/org/connectbot/HostEditorActivity.java @@ -240,13 +240,7 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr  			public void onServiceConnected(ComponentName className, IBinder service) {  				TerminalManager bound = ((TerminalManager.TerminalBinder) service).getService(); -				for (TerminalBridge bridge: bound.bridges) { -					if (bridge.host.equals(host)) { -						hostBridge = bridge; -						Log.d(TAG, "Found host bridge; charset updates will be made live"); -						break; -					} -				} +				hostBridge = bound.getConnectedBridge(host);  			}  			public void onServiceDisconnected(ComponentName name) { diff --git a/src/org/connectbot/HostListActivity.java b/src/org/connectbot/HostListActivity.java index c477a58..94cc1ad 100644 --- a/src/org/connectbot/HostListActivity.java +++ b/src/org/connectbot/HostListActivity.java @@ -330,7 +330,7 @@ public class HostListActivity extends ListActivity {  		// edit, disconnect, delete  		MenuItem connect = menu.add(R.string.list_host_disconnect); -		final TerminalBridge bridge = bound.findBridge(host); +		final TerminalBridge bridge = bound.getConnectedBridge(host);  		connect.setEnabled((bridge != null));  		connect.setOnMenuItemClickListener(new OnMenuItemClickListener() {  			public boolean onMenuItemClick(MenuItem item) { @@ -473,7 +473,7 @@ public class HostListActivity extends ListActivity {  			if (this.manager == null)  				return STATE_UNKNOWN; -			if (manager.findBridge(host) != null) +			if (manager.getConnectedBridge(host) != null)  				return STATE_CONNECTED;  			if (manager.disconnected.contains(host)) diff --git a/src/org/connectbot/PortForwardListActivity.java b/src/org/connectbot/PortForwardListActivity.java index 2cb5dbc..137030a 100644 --- a/src/org/connectbot/PortForwardListActivity.java +++ b/src/org/connectbot/PortForwardListActivity.java @@ -132,16 +132,8 @@ public class PortForwardListActivity extends ListActivity {  			public void onServiceConnected(ComponentName className, IBinder service) {  				TerminalManager bound = ((TerminalManager.TerminalBinder) service).getService(); -				for (TerminalBridge bridge: bound.bridges) { -					if (bridge.host.equals(host)) { -						hostBridge = bridge; -						updateHandler.sendEmptyMessage(-1); -						Log.d(TAG, "Found host bridge; using that instead of database"); -						break; -					} -				} - - +				hostBridge = bound.getConnectedBridge(host); +				updateHandler.sendEmptyMessage(-1);  			}  			public void onServiceDisconnected(ComponentName name) { diff --git a/src/org/connectbot/service/TerminalBridge.java b/src/org/connectbot/service/TerminalBridge.java index c748046..9a2a946 100644 --- a/src/org/connectbot/service/TerminalBridge.java +++ b/src/org/connectbot/service/TerminalBridge.java @@ -455,8 +455,12 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener {  			if (disconnectListener != null)  				disconnectListener.onDisconnected(TerminalBridge.this);  		} else { +			{ +				final String line = manager.res.getString(R.string.alert_disconnect_msg); +				((vt320) buffer).putString("\r\n" + line + "\r\n"); +			}  			if (host.getStayConnected()) { -				startConnection(); +				manager.requestReconnect(this);  				return;  			}  			Thread disconnectPromptThread = new Thread(new Runnable() { @@ -1348,4 +1352,11 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener {  		return urls;  	} + +	/** +	 * @return +	 */ +	public boolean isUsingNetwork() { +		return transport.usesNetwork(); +	}  } diff --git a/src/org/connectbot/service/TerminalManager.java b/src/org/connectbot/service/TerminalManager.java index 083969d..1b7b91d 100644 --- a/src/org/connectbot/service/TerminalManager.java +++ b/src/org/connectbot/service/TerminalManager.java @@ -18,6 +18,7 @@  package org.connectbot.service;  import java.io.IOException; +import java.lang.ref.WeakReference;  import java.security.PrivateKey;  import java.security.PublicKey;  import java.util.Arrays; @@ -48,10 +49,7 @@ import android.content.res.Resources;  import android.media.AudioManager;  import android.media.MediaPlayer;  import android.media.MediaPlayer.OnCompletionListener; -import android.net.ConnectivityManager; -import android.net.NetworkInfo;  import android.net.Uri; -import android.net.wifi.WifiManager;  import android.os.Binder;  import android.os.Handler;  import android.os.IBinder; @@ -73,6 +71,11 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen  	public final static String TAG = "ConnectBot.TerminalManager";  	public List<TerminalBridge> bridges = new LinkedList<TerminalBridge>(); +	public Map<HostBean, WeakReference<TerminalBridge>> mHostBridgeMap = +		new HashMap<HostBean, WeakReference<TerminalBridge>>(); +	public Map<String, WeakReference<TerminalBridge>> mNicknameBridgeMap = +		new HashMap<String, WeakReference<TerminalBridge>>(); +  	public TerminalBridge defaultBridge = null;  	public List<HostBean> disconnected = new LinkedList<HostBean>(); @@ -88,10 +91,9 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen  	protected SharedPreferences prefs; -	private final IBinder binder = new TerminalBinder(); +	final private IBinder binder = new TerminalBinder(); -	private ConnectivityManager connectivityManager; -	private WifiManager.WifiLock wifilock; +	private ConnectivityReceiver connectivityManager;  	private MediaPlayer mediaPlayer; @@ -108,6 +110,9 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen  	private boolean resizeAllowed = true; +	protected List<WeakReference<TerminalBridge>> mPendingReconnect +			= new LinkedList<WeakReference<TerminalBridge>>(); +  	@Override  	public void onCreate() {  		Log.i(TAG, "Starting background service"); @@ -139,29 +144,22 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen  			}  		} -		connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); - -		WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE); -		wifilock = manager.createWifiLock(TAG); -  		vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);  		wantKeyVibration = prefs.getBoolean(PreferenceConstants.BUMPY_ARROWS, true);  		wantBellVibration = prefs.getBoolean(PreferenceConstants.BELL_VIBRATE, true);  		enableMediaPlayer(); + +		final boolean lockingWifi = prefs.getBoolean(PreferenceConstants.WIFI_LOCK, true); + +		connectivityManager = new ConnectivityReceiver(this, lockingWifi);  	}  	@Override  	public void onDestroy() {  		Log.i(TAG, "Destroying background service"); -		if (bridges.size() > 0) { -			TerminalBridge[] tmpBridges = bridges.toArray(new TerminalBridge[bridges.size()]); - -			// disconnect and dispose of any existing bridges -			for (int i = 0; i < tmpBridges.length; i++) -				tmpBridges[i].dispatchDisconnect(true); -		} +		disconnectAll(true);  		if(hostdb != null) {  			hostdb.close(); @@ -180,8 +178,7 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen  				pubkeyTimer.cancel();  		} -		if (wifilock != null && wifilock.isHeld()) -			wifilock.release(); +		connectivityManager.cleanup();  		ConnectionNotifier.getInstance().hideRunningNotification(this); @@ -189,26 +186,50 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen  	}  	/** +	 * Disconnect all currently connected bridges. +	 */ +	private void disconnectAll(final boolean immediate) { +		TerminalBridge[] tmpBridges = null; + +		synchronized (bridges) { +			if (bridges.size() > 0) { +				tmpBridges = bridges.toArray(new TerminalBridge[bridges.size()]); +			} +		} + +		if (tmpBridges != null) { +			// disconnect and dispose of any existing bridges +			for (int i = 0; i < tmpBridges.length; i++) +				tmpBridges[i].dispatchDisconnect(immediate); +		} +	} + +	/**  	 * Open a new SSH session using the given parameters.  	 */  	private TerminalBridge openConnection(HostBean host) throws IllegalArgumentException, IOException {  		// throw exception if terminal already open -		if (findBridge(host) != null) { +		if (getConnectedBridge(host) != null) {  			throw new IllegalArgumentException("Connection already open for that nickname");  		}  		TerminalBridge bridge = new TerminalBridge(this, host);  		bridge.setOnDisconnectedListener(this);  		bridge.startConnection(); -		bridges.add(bridge); -		// Add a reference to the WifiLock -		NetworkInfo info = connectivityManager.getActiveNetworkInfo(); -		if (isLockingWifi() && -				info != null && -				info.getType() == ConnectivityManager.TYPE_WIFI) { -			Log.d(TAG, "Acquiring WifiLock"); -			wifilock.acquire(); +		synchronized (bridges) { +			bridges.add(bridge); +			WeakReference<TerminalBridge> wr = new WeakReference<TerminalBridge>(bridge); +			mHostBridgeMap.put(bridge.host, wr); +			mNicknameBridgeMap.put(bridge.host.getNickname(), wr); +		} + +		synchronized (disconnected) { +			disconnected.remove(bridge.host); +		} + +		if (bridge.isUsingNetwork()) { +			connectivityManager.incRef();  		}  		// also update database with new connected time @@ -238,10 +259,6 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen  		return prefs.getString(PreferenceConstants.KEYMODE, PreferenceConstants.KEYMODE_RIGHT); // "Use right-side keys"  	} -	public boolean isLockingWifi() { -		return prefs.getBoolean(PreferenceConstants.WIFI_LOCK, true); -	} -  	/**  	 * Open a new connection by reading parameters from the given URI. Follows  	 * format specified by an individual transport. @@ -264,30 +281,57 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen  	}  	/** -	 * Find the {@link TerminalBridge} with the given nickname. +	 * Find a connected {@link TerminalBridge} with the given HostBean. +	 * +	 * @param host the HostBean to search for +	 * @return TerminalBridge that uses the HostBean  	 */ -	public TerminalBridge findBridge(HostBean host) { -		// find the first active bridge with given nickname -		for(TerminalBridge bridge : bridges) { -			if (bridge.host.equals(host)) -				return bridge; +	public TerminalBridge getConnectedBridge(HostBean host) { +		WeakReference<TerminalBridge> wr = mHostBridgeMap.get(host); +		if (wr != null) { +			return wr.get(); +		} else { +			return null; +		} +	} + +	/** +	 * Find a connected {@link TerminalBridge} using its nickname. +	 * +	 * @param nickname +	 * @return TerminalBridge that matches nickname +	 */ +	public TerminalBridge getConnectedBridge(final String nickname) { +		if (nickname == null) { +			return null; +		} +		WeakReference<TerminalBridge> wr = mNicknameBridgeMap.get(nickname); +		if (wr != null) { +			return wr.get(); +		} else { +			return null;  		} -		return null;  	}  	/**  	 * Called by child bridge when somehow it's been disconnected.  	 */  	public void onDisconnected(TerminalBridge bridge) { -		// remove this bridge from our list -		bridges.remove(bridge); +		synchronized (bridges) { +			// remove this bridge from our list +			bridges.remove(bridge); -		if (bridges.size() == 0 && wifilock.isHeld()) { -			Log.d(TAG, "WifiLock was held, releasing"); -			wifilock.release(); +			mHostBridgeMap.remove(bridge.host); +			mNicknameBridgeMap.remove(bridge.host.getNickname()); + +			if (bridge.isUsingNetwork()) { +				connectivityManager.decRef(); +			}  		} -		disconnected.add(bridge.host); +		synchronized (disconnected) { +			disconnected.add(bridge.host); +		}  		// pass notification back up to gui  		if (disconnectHandler != null) @@ -557,6 +601,9 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen  		} else if (PreferenceConstants.BUMPY_ARROWS.equals(key)) {  			wantKeyVibration = sharedPreferences.getBoolean(  					PreferenceConstants.BUMPY_ARROWS, true); +		} else if (PreferenceConstants.WIFI_LOCK.equals(key)) { +			final boolean lockingWifi = prefs.getBoolean(PreferenceConstants.WIFI_LOCK, true); +			connectivityManager.setWantWifiLock(lockingWifi);  		}  	} @@ -579,25 +626,62 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen  	}  	/** -	 * @param requestedNickname -	 * @return TerminalBridge that matches nickname. +	 * Called when connectivity to the network is lost and it doesn't appear +	 * we'll be getting a different connection any time soon.  	 */ -	public TerminalBridge getBridgeByName(final String requestedNickname) { -		if (requestedNickname == null) { -			return null; -		} +	public void onConnectivityLost() { +		final Thread t = new Thread() { +			@Override +			public void run() { +				disconnectAll(false); +			} +		}; +		t.start(); +	} -		for (final TerminalBridge bridge : bridges) { -			final String nick = bridge.host.getNickname(); -			if (nick == null) { -				continue; +	/** +	 * Called when connectivity to the network is restored. +	 */ +	public void onConnectivityRestored() { +		final Thread t = new Thread() { +			@Override +			public void run() { +				reconnectPending();  			} +		}; +		t.start(); +	} -			if (nick.equals(requestedNickname)) { -				return bridge; +	/** +	 * Insert request into reconnect queue to be executed either immediately +	 * or later when connectivity is restored depending on whether we're +	 * currently connected. +	 * +	 * @param bridge the TerminalBridge to reconnect when possible +	 */ +	public void requestReconnect(TerminalBridge bridge) { +		synchronized (mPendingReconnect) { +			mPendingReconnect.add(new WeakReference<TerminalBridge>(bridge)); +			if (connectivityManager.isConnected()) { +				reconnectPending();  			}  		} +	} -		return null; +	/** +	 * Reconnect all bridges that were pending a reconnect when connectivity +	 * was lost. +	 */ +	private void reconnectPending() { +		synchronized (mPendingReconnect) { +			for (WeakReference<TerminalBridge> ref : mPendingReconnect) { +				TerminalBridge bridge = ref.get(); +				if (bridge == null) { +					continue; +				} +				bridge.startConnection(); +			} +			mPendingReconnect.clear(); +		}  	}  } diff --git a/src/org/connectbot/transport/AbsTransport.java b/src/org/connectbot/transport/AbsTransport.java index fbd4655..18397ea 100644 --- a/src/org/connectbot/transport/AbsTransport.java +++ b/src/org/connectbot/transport/AbsTransport.java @@ -246,4 +246,9 @@ public abstract class AbsTransport {  	public static String getFormatHint(Context context) {  		return "???";  	} + +	/** +	 * @return +	 */ +	public abstract boolean usesNetwork();  } diff --git a/src/org/connectbot/transport/Local.java b/src/org/connectbot/transport/Local.java index 46903b2..5ace1b0 100644 --- a/src/org/connectbot/transport/Local.java +++ b/src/org/connectbot/transport/Local.java @@ -208,4 +208,12 @@ public class Local extends AbsTransport {  	public static String getFormatHint(Context context) {  		return context.getString(R.string.hostpref_nickname_title);  	} + +	/* (non-Javadoc) +	 * @see org.connectbot.transport.AbsTransport#usesNetwork() +	 */ +	@Override +	public boolean usesNetwork() { +		return false; +	}  } diff --git a/src/org/connectbot/transport/SSH.java b/src/org/connectbot/transport/SSH.java index 11e0659..7dfaf0c 100644 --- a/src/org/connectbot/transport/SSH.java +++ b/src/org/connectbot/transport/SSH.java @@ -944,4 +944,12 @@ public class SSH extends AbsTransport implements ConnectionMonitor, InteractiveC  		agentLockPassphrase = lockPassphrase;  		return true;  	} + +	/* (non-Javadoc) +	 * @see org.connectbot.transport.AbsTransport#usesNetwork() +	 */ +	@Override +	public boolean usesNetwork() { +		return true; +	}  } diff --git a/src/org/connectbot/transport/Telnet.java b/src/org/connectbot/transport/Telnet.java index b7388ad..5fde2f6 100644 --- a/src/org/connectbot/transport/Telnet.java +++ b/src/org/connectbot/transport/Telnet.java @@ -319,4 +319,12 @@ public class Telnet extends AbsTransport {  				context.getString(R.string.format_hostname),  				context.getString(R.string.format_port));  	} + +	/* (non-Javadoc) +	 * @see org.connectbot.transport.AbsTransport#usesNetwork() +	 */ +	@Override +	public boolean usesNetwork() { +		return true; +	}  } | 
