You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
4.0 KiB
182 lines
4.0 KiB
4 years ago
|
package org.purplei2p.i2pd;
|
||
|
|
||
|
import java.util.HashSet;
|
||
|
import java.util.Set;
|
||
|
import android.os.Environment;
|
||
|
import android.util.Log;
|
||
|
|
||
|
import org.purplei2p.i2pd.R;
|
||
|
|
||
|
public class DaemonSingleton {
|
||
|
private static final String TAG = "i2pd";
|
||
|
private static final DaemonSingleton instance = new DaemonSingleton();
|
||
|
|
||
|
public interface StateUpdateListener {
|
||
|
void daemonStateUpdate();
|
||
|
}
|
||
|
|
||
|
private final Set<StateUpdateListener> stateUpdateListeners = new HashSet<>();
|
||
|
|
||
|
public static DaemonSingleton getInstance() {
|
||
|
return instance;
|
||
|
}
|
||
|
|
||
|
public synchronized void addStateChangeListener(StateUpdateListener listener) {
|
||
|
stateUpdateListeners.add(listener);
|
||
|
}
|
||
|
|
||
|
public synchronized void removeStateChangeListener(StateUpdateListener listener) {
|
||
|
stateUpdateListeners.remove(listener);
|
||
|
}
|
||
|
|
||
|
private synchronized void setState(State newState) {
|
||
|
if (newState == null)
|
||
|
throw new NullPointerException();
|
||
|
|
||
|
State oldState = state;
|
||
|
|
||
|
if (oldState == null)
|
||
|
throw new NullPointerException();
|
||
|
|
||
|
if (oldState.equals(newState))
|
||
|
return;
|
||
|
|
||
|
state = newState;
|
||
|
fireStateUpdate1();
|
||
|
}
|
||
|
|
||
|
public synchronized void stopAcceptingTunnels() {
|
||
|
if (isStartedOkay()) {
|
||
|
setState(State.gracefulShutdownInProgress);
|
||
|
I2PD_JNI.stopAcceptingTunnels();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public synchronized void startAcceptingTunnels() {
|
||
|
if (isStartedOkay()) {
|
||
|
setState(State.startedOkay);
|
||
|
I2PD_JNI.startAcceptingTunnels();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public synchronized void reloadTunnelsConfigs() {
|
||
|
if (isStartedOkay()) {
|
||
|
I2PD_JNI.reloadTunnelsConfigs();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public synchronized int GetTransitTunnelsCount() {
|
||
|
return I2PD_JNI.GetTransitTunnelsCount();
|
||
|
}
|
||
|
|
||
|
private volatile boolean startedOkay;
|
||
|
|
||
|
public enum State {
|
||
|
uninitialized(R.string.uninitialized),
|
||
|
starting(R.string.starting),
|
||
|
jniLibraryLoaded(R.string.jniLibraryLoaded),
|
||
|
startedOkay(R.string.startedOkay),
|
||
|
startFailed(R.string.startFailed),
|
||
|
gracefulShutdownInProgress(R.string.gracefulShutdownInProgress),
|
||
|
stopped(R.string.stopped);
|
||
|
|
||
|
State(int statusStringResourceId) {
|
||
|
this.statusStringResourceId = statusStringResourceId;
|
||
|
}
|
||
|
|
||
|
private final int statusStringResourceId;
|
||
|
|
||
|
public int getStatusStringResourceId() {
|
||
|
return statusStringResourceId;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
private volatile State state = State.uninitialized;
|
||
|
|
||
|
public State getState() {
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
setState(State.starting);
|
||
|
new Thread(new Runnable() {
|
||
|
|
||
|
@Override
|
||
|
public void run() {
|
||
|
try {
|
||
|
I2PD_JNI.loadLibraries();
|
||
|
setState(State.jniLibraryLoaded);
|
||
|
} catch (Throwable tr) {
|
||
|
lastThrowable = tr;
|
||
|
setState(State.startFailed);
|
||
|
return;
|
||
|
}
|
||
|
try {
|
||
|
synchronized (DaemonSingleton.this) {
|
||
|
I2PD_JNI.setDataDir(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd");
|
||
|
daemonStartResult = I2PD_JNI.startDaemon();
|
||
|
if ("ok".equals(daemonStartResult)) {
|
||
|
setState(State.startedOkay);
|
||
|
setStartedOkay(true);
|
||
|
} else
|
||
|
setState(State.startFailed);
|
||
|
}
|
||
|
} catch (Throwable tr) {
|
||
|
lastThrowable = tr;
|
||
|
setState(State.startFailed);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}, "i2pdDaemonStart").start();
|
||
|
}
|
||
|
|
||
|
private Throwable lastThrowable;
|
||
|
private String daemonStartResult = "N/A";
|
||
|
|
||
|
private void fireStateUpdate1() {
|
||
|
Log.i(TAG, "daemon state change: " + state);
|
||
|
for (StateUpdateListener listener : stateUpdateListeners) {
|
||
|
try {
|
||
|
listener.daemonStateUpdate();
|
||
|
} catch (Throwable tr) {
|
||
|
Log.e(TAG, "exception in listener ignored", tr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public Throwable getLastThrowable() {
|
||
|
return lastThrowable;
|
||
|
}
|
||
|
|
||
|
public String getDaemonStartResult() {
|
||
|
return daemonStartResult;
|
||
|
}
|
||
|
|
||
|
private final Object startedOkayLock = new Object();
|
||
|
|
||
|
public boolean isStartedOkay() {
|
||
|
synchronized (startedOkayLock) {
|
||
|
return startedOkay;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void setStartedOkay(boolean startedOkay) {
|
||
|
synchronized (startedOkayLock) {
|
||
|
this.startedOkay = startedOkay;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public synchronized void stopDaemon() {
|
||
|
if (isStartedOkay()) {
|
||
|
try {
|
||
|
I2PD_JNI.stopDaemon();
|
||
|
} catch(Throwable tr) {
|
||
|
Log.e(TAG, "", tr);
|
||
|
}
|
||
|
|
||
|
setStartedOkay(false);
|
||
|
setState(State.stopped);
|
||
|
}
|
||
|
}
|
||
|
}
|