Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

port mosh implementation (fixes #5) #48

Open
wants to merge 1 commit into
base: termbot
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ android {
versionCode androidGitVersion.code()

minSdkVersion 14
targetSdkVersion 29
targetSdkVersion 28
buildToolsVersion "29.0.3"
ndkVersion "21.3.6528147"

Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<action android:name="android.intent.action.PICK"/>
<category android:name="android.intent.category.DEFAULT"/>

<data android:scheme="mosh" />
<data android:scheme="ssh"/>
<data android:scheme="telnet"/>
<data android:scheme="local"/>
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/cpp/com_google_ase_Exec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <signal.h>

#include "android/log.h"

Expand Down Expand Up @@ -130,6 +131,19 @@ static int create_subprocess(
}
}

JNIEXPORT jint JNICALL Java_com_google_ase_Exec_setenv(
JNIEnv* env, jclass clazz, jstring name, jstring value) {
char *name_8 = JNU_GetStringNativeChars(env, name);
char *value_8 = JNU_GetStringNativeChars(env, value);

return setenv(name_8, value_8, 1);
}

JNIEXPORT jint JNICALL Java_com_google_ase_Exec_kill(
JNIEnv * env, jclass clazz, jint pid, jint signal) {
return kill(pid, signal);
}

JNIEXPORT jobject JNICALL Java_com_google_ase_Exec_createSubprocess(
JNIEnv* env, jclass clazz, jstring cmd, jstring arg0, jstring arg1,
jintArray processIdArray) {
Expand Down
16 changes: 16 additions & 0 deletions app/src/main/cpp/com_google_ase_Exec.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions app/src/main/java/com/google/ase/Exec.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public static native FileDescriptor createSubprocess(String cmd, String arg0, St
public static native void setPtyWindowSize(FileDescriptor fd, int row, int col, int xpixel,
int ypixel);

public static native int setenv(String name, String value);

public static native int kill(int pid, int signal);

/**
* Causes the calling thread to wait for the process associated with the receiver to finish
* executing.
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/org/connectbot/ConsoleActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.connectbot.service.TerminalBridge;
import org.connectbot.service.TerminalKeyListener;
import org.connectbot.service.TerminalManager;
import org.connectbot.util.InstallMosh;
import org.connectbot.util.PreferenceConstants;
import org.connectbot.util.TerminalViewPager;

Expand Down Expand Up @@ -483,6 +484,10 @@ public void onCreate(Bundle icicle) {
StrictModeSetup.run();
}

if (!InstallMosh.isInstallStarted()) {
new InstallMosh(this);
}

hardKeyboard = getResources().getConfiguration().keyboard ==
Configuration.KEYBOARD_QWERTY;

Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/org/connectbot/HostEditorFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

import org.connectbot.bean.HostBean;
import org.connectbot.transport.SSH;
import org.connectbot.transport.Mosh;
import org.connectbot.transport.Telnet;
import org.connectbot.transport.TransportFactory;
import org.connectbot.util.HostDatabase;
Expand Down Expand Up @@ -506,6 +507,12 @@ private void setTransportType(String protocol, boolean setDefaultPortInModel) {
mPortContainer.setVisibility(View.VISIBLE);
mExpandCollapseButton.setVisibility(View.VISIBLE);
mNicknameItem.setVisibility(View.VISIBLE);
} else if (Mosh.getProtocolName().equals(protocol)) {
mUsernameContainer.setVisibility(View.VISIBLE);
mHostnameContainer.setVisibility(View.VISIBLE);
mPortContainer.setVisibility(View.VISIBLE);
mExpandCollapseButton.setVisibility(View.VISIBLE);
mNicknameItem.setVisibility(View.VISIBLE);
} else if (Telnet.getProtocolName().equals(protocol)) {
mUsernameContainer.setVisibility(View.GONE);
mHostnameContainer.setVisibility(View.VISIBLE);
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/org/connectbot/HostListActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import org.connectbot.service.TerminalManager;
import org.connectbot.transport.TransportFactory;
import org.connectbot.util.HostDatabase;
import org.connectbot.util.InstallMosh;
import org.connectbot.util.PreferenceConstants;

import java.util.List;
Expand Down Expand Up @@ -182,6 +183,9 @@ public void onCreate(Bundle icicle) {

this.prefs = PreferenceManager.getDefaultSharedPreferences(this);

// install Mosh binaries
new InstallMosh(this);

// detect HTC Dream and apply special preferences
if (Build.MANUFACTURER.equals("HTC") && Build.DEVICE.equals("dream")) {
SharedPreferences.Editor editor = prefs.edit();
Expand Down
77 changes: 76 additions & 1 deletion app/src/main/java/org/connectbot/bean/HostBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import org.connectbot.transport.Local;
import org.connectbot.transport.SSH;
import org.connectbot.transport.Mosh;
import org.connectbot.transport.Telnet;
import org.connectbot.transport.TransportFactory;
import org.connectbot.util.HostDatabase;
Expand All @@ -43,6 +44,8 @@ public class HostBean extends AbstractBean {
private String hostname = null;
private int port = 22;
private String protocol = "ssh";
private String hostKeyAlgo = null;
private byte[] hostKey = null;
private long lastConnect = -1;
private String color;
private boolean useKeys = true;
Expand All @@ -56,6 +59,9 @@ public class HostBean extends AbstractBean {
private String encoding = HostDatabase.ENCODING_DEFAULT;
private boolean stayConnected = false;
private boolean quickDisconnect = false;
private int moshPort = -1;
private String moshServer = null;
private String locale = HostDatabase.LOCALE_DEFAULT;

public HostBean() {

Expand Down Expand Up @@ -113,6 +119,24 @@ public String getProtocol() {
return protocol;
}

public void setHostKeyAlgo(String hostKeyAlgo) {
this.hostKeyAlgo = hostKeyAlgo;
}
public String getHostKeyAlgo() {
return hostKeyAlgo;
}
public void setHostKey(byte[] hostKey) {
if (hostKey == null)
this.hostKey = null;
else
this.hostKey = hostKey.clone();
}
public byte[] getHostKey() {
if (hostKey == null)
return null;
else
return hostKey.clone();
}
public void setLastConnect(long lastConnect) {
this.lastConnect = lastConnect;
}
Expand Down Expand Up @@ -190,6 +214,30 @@ public boolean getStayConnected() {
return stayConnected;
}

public void setMoshPort(int moshPort) {
this.moshPort = moshPort;
}

public int getMoshPort() {
return moshPort;
}

public void setMoshServer(String moshServer) {
this.moshServer = moshServer;
}

public String getMoshServer() {
return moshServer;
}

public void setLocale(String locale) {
this.locale = locale;
}

public String getLocale() {
return locale;
}

public void setQuickDisconnect(boolean quickDisconnect) {
this.quickDisconnect = quickDisconnect;
}
Expand Down Expand Up @@ -230,6 +278,9 @@ public ContentValues getValues() {
values.put(HostDatabase.FIELD_HOST_ENCODING, encoding);
values.put(HostDatabase.FIELD_HOST_STAYCONNECTED, Boolean.toString(stayConnected));
values.put(HostDatabase.FIELD_HOST_QUICKDISCONNECT, Boolean.toString(quickDisconnect));
values.put(HostDatabase.FIELD_HOST_MOSHPORT, moshPort);
values.put(HostDatabase.FIELD_HOST_MOSH_SERVER, moshServer);
values.put(HostDatabase.FIELD_HOST_LOCALE, locale);

return values;
}
Expand All @@ -254,6 +305,9 @@ public static HostBean fromContentValues(ContentValues values) {
host.setEncoding(values.getAsString(HostDatabase.FIELD_HOST_ENCODING));
host.setStayConnected(values.getAsBoolean(HostDatabase.FIELD_HOST_STAYCONNECTED));
host.setQuickDisconnect(values.getAsBoolean(HostDatabase.FIELD_HOST_QUICKDISCONNECT));
host.setMoshPort(values.getAsInteger(HostDatabase.FIELD_HOST_MOSHPORT));
host.setMoshServer(values.getAsString(HostDatabase.FIELD_HOST_MOSH_SERVER));
host.setLocale(values.getAsString(HostDatabase.FIELD_HOST_LOCALE));
return host;
}

Expand Down Expand Up @@ -291,7 +345,19 @@ public boolean equals(Object o) {
} else if (!hostname.equals(host.getHostname()))
return false;

return port == host.getPort();
if (port != host.getPort())
return false;

if (moshPort != host.getMoshPort())
return false;

if (moshServer != host.getMoshServer())
return false;

if (locale != host.getLocale())
return false;

return true;
}

@Override
Expand Down Expand Up @@ -345,6 +411,15 @@ public String toString() {
username.equals("") || hostname.equals(""))
return "";

if (port == defaultPort)
return username + "@" + hostname;
else
return username + "@" + hostname + ":" + port;
} else if (Mosh.getProtocolName().equals(protocol)) {
if (username == null || hostname == null ||
username.equals("") || hostname.equals(""))
return "";

if (port == defaultPort)
return username + "@" + hostname;
else
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/java/org/connectbot/service/TerminalBridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,10 @@ public void run() {
* authentication. If called before authenticated, it will just fail.
*/
public void onConnected() {
onConnected(true);
}

public void onConnected(boolean doPostLogin) {
disconnected = false;

((vt320) buffer).reset();
Expand Down Expand Up @@ -429,6 +433,11 @@ public void onConnected() {
injectString(host.getPostLogin());
}

public void postLogin() {
// send any post-login string, if requested
injectString(host.getPostLogin());
}

/**
* @return whether a session is open or not
*/
Expand Down
33 changes: 23 additions & 10 deletions app/src/main/java/org/connectbot/service/TerminalManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,11 @@ public void onDestroy() {
/**
* Disconnect all currently connected bridges.
*/
public void disconnectAll(final boolean immediate, final boolean excludeLocal) {
private void disconnectAll(final boolean immediate) {
disconnectAll(immediate, false);
}

public void disconnectAll(final boolean immediate, final boolean onlyRemote) {
TerminalBridge[] tmpBridges = null;

synchronized (bridges) {
Expand All @@ -202,9 +206,9 @@ public void disconnectAll(final boolean immediate, final boolean excludeLocal) {
if (tmpBridges != null) {
// disconnect and dispose of any existing bridges
for (int i = 0; i < tmpBridges.length; i++) {
if (excludeLocal && !tmpBridges[i].isUsingNetwork())
continue;
tmpBridges[i].dispatchDisconnect(immediate);
if (tmpBridges[i].transport.resetOnConnectionChange() || !onlyRemote) {
tmpBridges[i].dispatchDisconnect(immediate);
}
}
}
}
Expand Down Expand Up @@ -519,6 +523,12 @@ public void onRebind(Intent intent) {
Log.i(TAG, "Someone rebound to TerminalManager with " + bridges.size() + " bridges active");
keepServiceAlive();
setResizeAllowed(true);

synchronized (bridges) {
for (TerminalBridge bridge : bridges) {
//bridge.onForeground();
}
}
}

@Override
Expand All @@ -527,12 +537,15 @@ public boolean onUnbind(Intent intent) {

setResizeAllowed(true);

if (bridges.size() == 0) {
stopWithDelay();
} else {
// tell each bridge to forget about their previous prompt handler
for (TerminalBridge bridge : bridges) {
bridge.promptHelper.setHandler(null);
synchronized (bridges) {
if (bridges.size() == 0) {
stopWithDelay();
} else {
// tell each bridge to forget about their previous prompt handler
for (TerminalBridge bridge : bridges) {
bridge.promptHelper.setHandler(null);
//bridge.onBackground();
}
}
}

Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/org/connectbot/transport/AbsTransport.java
Original file line number Diff line number Diff line change
Expand Up @@ -251,4 +251,18 @@ public static String getFormatHint(Context context) {
* @return
*/
public abstract boolean usesNetwork();

public abstract boolean resetOnConnectionChange();

public void onBackground() {
}

public void onForeground() {
}

public void onScreenOff() {
}

public void onScreenOn() {
}
}
5 changes: 5 additions & 0 deletions app/src/main/java/org/connectbot/transport/Local.java
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@ public boolean usesNetwork() {
return false;
}

@Override
public boolean resetOnConnectionChange() {
return false;
}

private interface Killer {
void killProcess(int pid);
}
Expand Down
Loading