// TryMany by Rowland http://home.comcast.net/~rowland3/ // Base class to attempt connections on many possible servers at a given port. // Useful for finding a usable server on an IRC net, for example. // This is the crude version, no threading or NBIO. import java.io.*; import java.net.*; import java.util.*; /** FileEntriesIterator reads a file of tokens as an Iterator **/ class FileEntriesIterator implements Iterator { protected final FileReader fr; protected final StreamTokenizer in; protected int token; protected boolean gotToken; public FileEntriesIterator(String fileSpec) throws Exception { fr= new FileReader(fileSpec); in= new StreamTokenizer(fr); in.resetSyntax(); in.wordChars(33, 127); token= 0; gotToken= false; } protected void getnext() { if (!gotToken) try { do { token= in.nextToken(); } while (token!=in.TT_EOF && token!=in.TT_WORD); // skip over all else } catch (Exception E) { System.err.println("ERR FileEntriesIterator: "+ E.toString()); token= in.TT_EOF; // encourage caller to can halt gracefully } gotToken= true; } public boolean hasNext() { if (in== null) return false; getnext(); if (token== in.TT_EOF) return false; return true; } public Object next() { Object result= null; if (in== null) return null; getnext(); if (token== in.TT_EOF) result= null; else result= in.sval; gotToken= false; return result; } public void remove() { } // not implemented } /** TryMany tries to connect to many possible servers on a given port. Override callbackGotOne() to get useful behavior. **/ public class TryMany implements Runnable { protected final Iterator candidates; final int port; int timeout= 15000; protected boolean debug= false; /** set scanning to false if you want to stop trying for more connections **/ protected boolean scanning= false; /** constructor to read in candidates from a file **/ public TryMany(String fileSpec, int _port) throws Exception { candidates= new FileEntriesIterator(fileSpec); port= _port; } /** A more general constructor that will use any Iterator **/ public TryMany(Iterator _candidates, int _port) { candidates= _candidates; port= _port; } public void setDebug(boolean _debug) { debug= _debug; } public void setTimeout(int _timeout) { timeout= _timeout; } public void run() { // crude, single-threaded blocking version... scanning= true; if (candidates== null) { println("ERR: TryMany: no candidates"); return; } while (candidates.hasNext()) { String candidate= (String)candidates.next(); tryCandidate(candidate); if (!scanning) return; } } /** println is for debug output, controlled by setDebug() **/ protected final void println(String line) { if (debug) System.out.println(line); } protected boolean tryCandidate(String candidate) { println("\n\nTRYING: "+ candidate); Socket socket= null; try { InetAddress addr = InetAddress.getByName(candidate); SocketAddress sockaddr = new InetSocketAddress(addr, port); socket = new Socket(); socket.connect(sockaddr, timeout); println(" ...connected"); socket.setSoTimeout(timeout); } catch (Exception E) { callbackFailed(candidate, E); socket= null; return false; } if (socket!= null) try { callbackGotOne(candidate, socket); } catch (Exception E) { println("ERR from callback: "+ E.toString()); return false; } return true; } /** callbackGotOne called when a connection succeeeds. override in derived class. */ protected synchronized void callbackGotOne(String host, Socket socket) throws Exception { System.out.println("CONNECT: "+ host); } /** callbackFailed called when a connection fails. override in derived class. */ protected synchronized void callbackFailed(String host, Exception E) { println("ERR TryMany connect: "+ E.toString()); } /** main routine for testing. Pass file with list of IRC servers as command line argument. **/ public static void main(String args[]) { try { String fileSpec= args[0]; TryMany tm= new TryMany(fileSpec, 6667); tm.run(); } catch (Exception E) { System.err.println("ERR: "+ E.toString()); } } }