|
|
@@ -22,61 +22,61 @@ package ca.psiphon.psibot;
|
|
|
import android.content.Context;
|
|
|
import android.os.Build;
|
|
|
|
|
|
+import java.io.BufferedReader;
|
|
|
import java.io.File;
|
|
|
import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.io.InputStreamReader;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
-import java.util.Scanner;
|
|
|
import java.util.concurrent.CountDownLatch;
|
|
|
|
|
|
public class Client {
|
|
|
|
|
|
private final Context mContext;
|
|
|
+ private final CountDownLatch mTunnelStartedSignal;
|
|
|
private File mRootDirectory;
|
|
|
private File mExecutableFile;
|
|
|
private File mConfigFile;
|
|
|
private Process mProcess;
|
|
|
- private Thread mThread;
|
|
|
+ private Thread mStdoutThread;
|
|
|
private int mLocalSocksProxyPort;
|
|
|
private int mLocalHttpProxyPort;
|
|
|
private List<String> mHomePages;
|
|
|
|
|
|
- public Client(Context context) {
|
|
|
+ public Client(Context context, CountDownLatch tunnelStartedSignal) {
|
|
|
mContext = context;
|
|
|
+ mTunnelStartedSignal = tunnelStartedSignal;
|
|
|
}
|
|
|
|
|
|
- public void start(final CountDownLatch tunnelStartedSignal) throws Utils.PsibotError {
|
|
|
+ public void start() throws Utils.PsibotError {
|
|
|
stop();
|
|
|
prepareFiles();
|
|
|
|
|
|
- ProcessBuilder processBuilder =
|
|
|
- new ProcessBuilder(
|
|
|
- mExecutableFile.getAbsolutePath(),
|
|
|
- "--config", mConfigFile.getAbsolutePath());
|
|
|
- processBuilder.directory(mRootDirectory);
|
|
|
-
|
|
|
try {
|
|
|
- mProcess = processBuilder.start();
|
|
|
+ mProcess = new ProcessBuilder(
|
|
|
+ mExecutableFile.getAbsolutePath(),
|
|
|
+ "--config", mConfigFile.getAbsolutePath())
|
|
|
+ .directory(mRootDirectory)
|
|
|
+ .redirectErrorStream(true)
|
|
|
+ .start();
|
|
|
} catch (IOException e) {
|
|
|
throw new Utils.PsibotError("failed to start client process", e);
|
|
|
}
|
|
|
|
|
|
- mThread = new Thread(new Runnable() {
|
|
|
+ mStdoutThread = new Thread(new Runnable() {
|
|
|
@Override
|
|
|
public void run() {
|
|
|
- Scanner stdout = new Scanner(mProcess.getInputStream());
|
|
|
- while(stdout.hasNextLine()) {
|
|
|
- String line = stdout.nextLine();
|
|
|
- boolean isTunnelStarted = parseLine(line);
|
|
|
- if (isTunnelStarted) {
|
|
|
- tunnelStartedSignal.countDown();
|
|
|
- }
|
|
|
- Log.addEntry(line);
|
|
|
- }
|
|
|
- stdout.close();
|
|
|
+ consumeStream(mProcess.getInputStream());
|
|
|
+ Log.addEntry("Psiphon client stopping");
|
|
|
}
|
|
|
});
|
|
|
- mThread.start();
|
|
|
+ mStdoutThread.start();
|
|
|
+
|
|
|
+ mLocalSocksProxyPort = 0;
|
|
|
+ mLocalHttpProxyPort = 0;
|
|
|
+ mHomePages = new ArrayList<String>();
|
|
|
+
|
|
|
Log.addEntry("Psiphon client started");
|
|
|
}
|
|
|
|
|
|
@@ -88,36 +88,17 @@ public class Client {
|
|
|
} catch (InterruptedException e) {
|
|
|
Thread.currentThread().interrupt();
|
|
|
}
|
|
|
+ Log.addEntry("Psiphon client stopped");
|
|
|
}
|
|
|
- if (mThread != null) {
|
|
|
+ if (mStdoutThread != null) {
|
|
|
try {
|
|
|
- mThread.join();
|
|
|
+ mStdoutThread.join();
|
|
|
} catch (InterruptedException e) {
|
|
|
Thread.currentThread().interrupt();
|
|
|
}
|
|
|
}
|
|
|
mProcess = null;
|
|
|
- mThread = null;
|
|
|
- Log.addEntry("Psiphon client stopped");
|
|
|
- }
|
|
|
-
|
|
|
- public synchronized boolean parseLine(String line) {
|
|
|
- // TODO: this is based on temporary log line formats
|
|
|
- final String socksProxy = "SOCKS-PROXY local SOCKS proxy running at address 127.0.0.1:";
|
|
|
- final String httpProxy = "HTTP-PROXY local HTTP proxy running at address 127.0.0.1:";
|
|
|
- final String homePage = "HOMEPAGE ";
|
|
|
- final String tunnelStarted = "TUNNEL tunnel started";
|
|
|
- int index;
|
|
|
- if (-1 != (index = line.indexOf(socksProxy))) {
|
|
|
- mLocalSocksProxyPort = Integer.parseInt(line.substring(index + homePage.length()));
|
|
|
- } else if (-1 != (index = line.indexOf(httpProxy))) {
|
|
|
- mLocalHttpProxyPort = Integer.parseInt(line.substring(index + homePage.length()));
|
|
|
- } else if (-1 != (index = line.indexOf(homePage))) {
|
|
|
- mHomePages.add(line.substring(index + homePage.length()));
|
|
|
- } else if (line.contains(tunnelStarted)) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
+ mStdoutThread = null;
|
|
|
}
|
|
|
|
|
|
public synchronized int getLocalSocksProxyPort() {
|
|
|
@@ -146,4 +127,40 @@ public class Client {
|
|
|
throw new Utils.PsibotError("failed to prepare client files", e);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ private void consumeStream(InputStream inputStream) {
|
|
|
+ try {
|
|
|
+ BufferedReader reader =
|
|
|
+ new BufferedReader(new InputStreamReader(inputStream));
|
|
|
+ String line;
|
|
|
+ while ((line = reader.readLine()) != null) {
|
|
|
+ parseLine(line);
|
|
|
+ // TODO: parse and use the Go client timestamp
|
|
|
+ // Don't display the first 20 characters: the Go client log timestamp
|
|
|
+ Log.addEntry(line.substring(20));
|
|
|
+ }
|
|
|
+ reader.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ // TODO: stop service if exiting due to error?
|
|
|
+ Log.addEntry("Psiphon client consume error: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private synchronized void parseLine(String line) {
|
|
|
+ // TODO: this is based on temporary log line formats
|
|
|
+ final String socksProxy = "SOCKS-PROXY local SOCKS proxy running at address 127.0.0.1:";
|
|
|
+ final String httpProxy = "HTTP-PROXY local HTTP proxy running at address 127.0.0.1:";
|
|
|
+ final String homePage = "HOMEPAGE ";
|
|
|
+ final String tunnelStarted = "TUNNEL tunnel started";
|
|
|
+ int index;
|
|
|
+ if (-1 != (index = line.indexOf(socksProxy))) {
|
|
|
+ mLocalSocksProxyPort = Integer.parseInt(line.substring(index + socksProxy.length()));
|
|
|
+ } else if (-1 != (index = line.indexOf(httpProxy))) {
|
|
|
+ mLocalHttpProxyPort = Integer.parseInt(line.substring(index + httpProxy.length()));
|
|
|
+ } else if (-1 != (index = line.indexOf(homePage))) {
|
|
|
+ mHomePages.add(line.substring(index + homePage.length()));
|
|
|
+ } else if (line.contains(tunnelStarted)) {
|
|
|
+ mTunnelStartedSignal.countDown();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|