}
public void start() throws Exception {
Map.Entry entry;
Selector selector;
ServerSocketChannel sock_channel;
MyInetSocketAddress key, value;
if (remote !=null && local !=null)
mappings.put(new InetSocketAddress(local, local_port), new InetSocketAddress(remote, remote_port));
if (mapping_file !=null) {
try {
populateMappings(mapping_file);
}
catch (Exception ex) {
log("Failed reading " + mapping_file);
throw ex;
}
}
log("\nProxy started at " + new java.util.Date());
if (verbose) {
log("\nMappings:\n---------");
for (Iterator it=mappings.entrySet().iterator(); it.hasNext();) {
entry=(Map.Entry) it.next();
log(toString((InetSocketAddress) entry.getKey()) + " <--> "
+ toString((InetSocketAddress) entry.getValue()));
}
log("\n");
}
// 1. Create a Selector
selector=Selector.open();
// Create a thread pool (Executor)
executor=new ThreadPoolExecutor(MIN_THREAD_POOL_SIZE, MAX_THREAD_POOL_SIZE, 30000, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(1000));
for (Iterator it=mappings.keySet().iterator(); it.hasNext();) {
key=(MyInetSocketAddress) it.next();
value=(MyInetSocketAddress) mappings.get(key);
// if either source or destination are SSL, we cannot use JDK 1.4
// NIO selectors, but have to fall back on separate threads per connection
if (key.ssl() || value.ssl()) {
// if(2 == 2) {
SocketAcceptor acceptor=new SocketAcceptor(key, value);
executor.execute(acceptor);
continue;
}
// 2. Create a ServerSocketChannel
sock_channel=ServerSocketChannel.open();
sock_channel.configureBlocking(false);
sock_channel.socket().bind(key);
// 3. Register the selector with all server sockets. 'Key' is attachment, so we get it again on
// select(). That way we can associate it with the mappings hashmap to find the corresponding
// value
sock_channel.register(selector, SelectionKey.OP_ACCEPT, key);
}
// 4. Start main loop. won't return until CTRL-C'ed
loop(selector);
}