package com.subgraph.orchid.circuits;
import com.subgraph.orchid.Tor;
import com.subgraph.orchid.TorInitializationListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class TorInitializationTracker {
private final static Logger logger = Logger.getLogger(TorInitializationTracker.class.getName());
private final static Map<Integer, String> messageMap = new HashMap<Integer, String>();
static {
messageMap.put(Tor.BOOTSTRAP_STATUS_STARTING, "Starting");
messageMap.put(Tor.BOOTSTRAP_STATUS_CONN_DIR, "Connecting to directory server");
messageMap.put(Tor.BOOTSTRAP_STATUS_HANDSHAKE_DIR, "Finishing handshake with directory server");
messageMap.put(Tor.BOOTSTRAP_STATUS_ONEHOP_CREATE, "Establishing an encrypted directory connection");
messageMap.put(Tor.BOOTSTRAP_STATUS_REQUESTING_STATUS, "Asking for network status consensus");
messageMap.put(Tor.BOOTSTRAP_STATUS_LOADING_STATUS, "Loading network status consensus");
messageMap.put(Tor.BOOTSTRAP_STATUS_REQUESTING_KEYS, "Asking for authority key certs");
messageMap.put(Tor.BOOTSTRAP_STATUS_LOADING_KEYS, "Loading authority key certs");
messageMap.put(Tor.BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, "Asking for relay descriptors");
messageMap.put(Tor.BOOTSTRAP_STATUS_LOADING_DESCRIPTORS, "Loading relay descriptors");
messageMap.put(Tor.BOOTSTRAP_STATUS_CONN_OR, "Connecting to the Tor network");
messageMap.put(Tor.BOOTSTRAP_STATUS_HANDSHAKE_OR, "Finished Handshake with first hop");
messageMap.put(Tor.BOOTSTRAP_STATUS_CIRCUIT_CREATE, "Establishing a Tor circuit");
messageMap.put(Tor.BOOTSTRAP_STATUS_DONE, "Done");
}
private final List<TorInitializationListener> listeners = new ArrayList<TorInitializationListener>();
private final Object stateLock = new Object();
private int bootstrapState = Tor.BOOTSTRAP_STATUS_STARTING;
public void addListener(TorInitializationListener listener) {
synchronized(listeners) {
if(!listeners.contains(listener)) {
listeners.add(listener);
}
}
}
public void removeListener(TorInitializationListener listener) {
synchronized(listeners) {
listeners.remove(listener);
}
}
public int getBootstrapState() {
return bootstrapState;
}
public void start() {
synchronized (stateLock) {
bootstrapState = Tor.BOOTSTRAP_STATUS_STARTING;
notifyListeners(Tor.BOOTSTRAP_STATUS_STARTING);
}
}
public void notifyEvent(int eventCode) {
synchronized(stateLock) {
if(eventCode <= bootstrapState || eventCode > 100) {
return;
}
bootstrapState = eventCode;
notifyListeners(eventCode);
}
}
private void notifyListeners(int code) {
final String message = getMessageForCode(code);
for(TorInitializationListener listener: getListeners()) {
try {
listener.initializationProgress(message, code);
if(code >= 100) {
listener.initializationCompleted();
}
} catch(Exception e) {
logger.log(Level.SEVERE, "Exception occurred in TorInitializationListener callback: "+ e.getMessage(), e);
}
}
}
private String getMessageForCode(int code) {
if(messageMap.containsKey(code)) {
return messageMap.get(code);
} else {
return "Unknown state";
}
}
private List<TorInitializationListener> getListeners() {
synchronized (listeners) {
return new ArrayList<TorInitializationListener>(listeners);
}
}
}