2004-04-08 04:41:54 +00:00
|
|
|
package net.i2p.httptunnel;
|
|
|
|
|
2004-04-10 11:39:00 +00:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Properties;
|
|
|
|
|
|
|
|
import net.i2p.client.streaming.I2PSocketManager;
|
|
|
|
import net.i2p.client.streaming.I2PSocketManagerFactory;
|
2004-04-08 04:41:54 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Produces SocketManagers in a thread and gives them to those who
|
|
|
|
* need them.
|
|
|
|
*/
|
|
|
|
public class SocketManagerProducer extends Thread {
|
|
|
|
|
|
|
|
private ArrayList myManagers = new ArrayList();
|
|
|
|
private HashMap usedManagers = new HashMap();
|
|
|
|
private int port;
|
|
|
|
private String host;
|
|
|
|
private int maxManagers;
|
2004-04-10 06:47:15 +00:00
|
|
|
private boolean shouldThrowAwayManagers;
|
2004-04-08 04:41:54 +00:00
|
|
|
|
2004-04-10 06:27:18 +00:00
|
|
|
/**
|
|
|
|
* Public constructor creating a SocketManagerProducer
|
|
|
|
* @param initialManagers a list of socket managers to use
|
|
|
|
* @param maxManagers how many managers to have in the cache
|
2004-04-10 06:47:15 +00:00
|
|
|
* @param shouldThrowAwayManagers whether to throw away a manager after use
|
2004-04-10 06:27:18 +00:00
|
|
|
* @param host which host to listen on
|
|
|
|
* @param port which port to listen on
|
|
|
|
*/
|
2004-04-10 11:45:02 +00:00
|
|
|
public SocketManagerProducer(I2PSocketManager[] initialManagers, int maxManagers, boolean shouldThrowAwayManagers,
|
|
|
|
String host, int port) {
|
|
|
|
if (maxManagers < 1) { throw new IllegalArgumentException("maxManagers < 1"); }
|
|
|
|
this.host = host;
|
|
|
|
this.port = port;
|
|
|
|
this.shouldThrowAwayManagers = shouldThrowAwayManagers;
|
|
|
|
if (initialManagers != null) {
|
|
|
|
myManagers.addAll(Arrays.asList(initialManagers));
|
|
|
|
}
|
|
|
|
this.maxManagers = maxManagers;
|
|
|
|
this.shouldThrowAwayManagers = shouldThrowAwayManagers;
|
|
|
|
setDaemon(true);
|
|
|
|
start();
|
2004-04-08 04:41:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Thread producing new SocketManagers.
|
|
|
|
*/
|
|
|
|
public void run() {
|
2004-04-10 11:45:02 +00:00
|
|
|
while (true) {
|
|
|
|
synchronized (this) {
|
|
|
|
// without mcDonalds mode, we most probably need no
|
|
|
|
// new managers.
|
|
|
|
while (!shouldThrowAwayManagers && myManagers.size() == maxManagers) {
|
|
|
|
myWait();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// produce a new manager, regardless whether it is needed
|
|
|
|
// or not. Do not synchronized this part, since it can be
|
|
|
|
// quite time-consuming.
|
|
|
|
I2PSocketManager newManager = I2PSocketManagerFactory.createManager(host, port, new Properties());
|
|
|
|
// when done, check if it is needed.
|
|
|
|
synchronized (this) {
|
|
|
|
while (myManagers.size() == maxManagers) {
|
|
|
|
myWait();
|
|
|
|
}
|
|
|
|
myManagers.add(newManager);
|
|
|
|
notifyAll();
|
|
|
|
}
|
|
|
|
}
|
2004-04-08 04:41:54 +00:00
|
|
|
}
|
2004-04-10 11:45:02 +00:00
|
|
|
|
2004-04-08 04:41:54 +00:00
|
|
|
/**
|
|
|
|
* Get a manager for connecting to a given destination. Each
|
|
|
|
* destination will always get the same manager.
|
|
|
|
*
|
|
|
|
* @param dest the destination to connect to
|
|
|
|
* @return the SocketManager to use
|
|
|
|
*/
|
|
|
|
public synchronized I2PSocketManager getManager(String dest) {
|
2004-04-10 11:45:02 +00:00
|
|
|
I2PSocketManager result = (I2PSocketManager) usedManagers.get(dest);
|
|
|
|
if (result == null) {
|
|
|
|
result = getManager();
|
|
|
|
usedManagers.put(dest, result);
|
|
|
|
}
|
|
|
|
return result;
|
2004-04-08 04:41:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a "new" SocketManager. Depending on the anonymity settings,
|
|
|
|
* this can be a completely new one or one randomly selected from
|
|
|
|
* a pool.
|
|
|
|
*
|
|
|
|
* @return the SocketManager to use
|
|
|
|
*/
|
|
|
|
public synchronized I2PSocketManager getManager() {
|
2004-04-10 11:45:02 +00:00
|
|
|
while (myManagers.size() == 0) {
|
|
|
|
myWait(); // no manager here, so wait until one is produced
|
|
|
|
}
|
|
|
|
int which = (int) (Math.random() * myManagers.size());
|
|
|
|
I2PSocketManager result = (I2PSocketManager) myManagers.get(which);
|
|
|
|
if (shouldThrowAwayManagers) {
|
|
|
|
myManagers.remove(which);
|
|
|
|
notifyAll();
|
|
|
|
}
|
|
|
|
return result;
|
2004-04-08 04:41:54 +00:00
|
|
|
}
|
|
|
|
|
2004-04-10 06:27:18 +00:00
|
|
|
/**
|
|
|
|
* Wait until InterruptedException
|
|
|
|
*/
|
2004-04-08 04:41:54 +00:00
|
|
|
public void myWait() {
|
2004-04-10 11:45:02 +00:00
|
|
|
try {
|
|
|
|
wait();
|
|
|
|
} catch (InterruptedException ex) {
|
|
|
|
ex.printStackTrace();
|
|
|
|
}
|
2004-04-08 04:41:54 +00:00
|
|
|
}
|
2004-04-10 11:45:02 +00:00
|
|
|
}
|