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.
184 lines
5.0 KiB
184 lines
5.0 KiB
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); |
|
} |
|
} |
|
}
|
|
|