1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org) 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.xbill.DNS; 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.*; 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.*; 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.net.*; 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * An implementation of Resolver that can send queries to multiple servers, 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * sending the queries multiple times if necessary. 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Resolver 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Brian Wellington 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class ExtendedResolver implements Resolver { 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static class Resolution implements ResolverListener { 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Resolver [] resolvers; 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int [] sent; 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Object [] inprogress; 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int retries; 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int outstanding; 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean done; 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message query; 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message response; 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Throwable thrown; 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ResolverListener listener; 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Resolution(ExtendedResolver eres, Message query) { 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List l = eres.resolvers; 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen resolvers = (Resolver []) l.toArray (new Resolver[l.size()]); 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (eres.loadBalance) { 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int nresolvers = resolvers.length; 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Note: this is not synchronized, since the 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * worst thing that can happen is a random 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * ordering, which is ok. 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int start = eres.lbStart++ % nresolvers; 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (eres.lbStart > nresolvers) 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen eres.lbStart %= nresolvers; 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (start > 0) { 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Resolver [] shuffle = new Resolver[nresolvers]; 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < nresolvers; i++) { 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int pos = (i + start) % nresolvers; 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen shuffle[i] = resolvers[pos]; 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen resolvers = shuffle; 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sent = new int[resolvers.length]; 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen inprogress = new Object[resolvers.length]; 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen retries = eres.retries; 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.query = query; 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* Asynchronously sends a message. */ 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen send(int n) { 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sent[n]++; 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen outstanding++; 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen inprogress[n] = resolvers[n].sendAsync(query, this); 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (Throwable t) { 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (this) { 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen thrown = t; 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen done = true; 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (listener == null) { 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen notifyAll(); 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* Start a synchronous resolution */ 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Message 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen start() throws IOException { 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * First, try sending synchronously. If this works, 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * we're done. Otherwise, we'll get an exception 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and continue. It would be easier to call send(0), 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * but this avoids a thread creation. If and when 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * SimpleResolver.sendAsync() can be made to not 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * create a thread, this could be changed. 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sent[0]++; 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen outstanding++; 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen inprogress[0] = new Object(); 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return resolvers[0].send(query); 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (Exception e) { 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This will either cause more queries to be sent 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * asynchronously or will set the 'done' flag. 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen handleException(inprogress[0], e); 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Wait for a successful response or for each 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * subresolver to fail. 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (this) { 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (!done) { 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen wait(); 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (InterruptedException e) { 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* Return the response or throw an exception */ 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (response != null) 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return response; 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (thrown instanceof IOException) 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw (IOException) thrown; 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (thrown instanceof RuntimeException) 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw (RuntimeException) thrown; 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (thrown instanceof Error) 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw (Error) thrown; 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ("ExtendedResolver failure"); 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* Start an asynchronous resolution */ 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen startAsync(ResolverListener listener) { 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.listener = listener; 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen send(0); 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Receive a response. If the resolution hasn't been completed, 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * either wake up the blocking thread or call the callback. 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen receiveMessage(Object id, Message m) { 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (Options.check("verbose")) 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.err.println("ExtendedResolver: " + 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "received message"); 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (this) { 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (done) 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response = m; 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen done = true; 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (listener == null) { 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen notifyAll(); 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listener.receiveMessage(this, response); 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Receive an exception. If the resolution has been completed, 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * do nothing. Otherwise make progress. 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen handleException(Object id, Exception e) { 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (Options.check("verbose")) 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.err.println("ExtendedResolver: got " + e); 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (this) { 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen outstanding--; 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (done) 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int n; 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (n = 0; n < inprogress.length; n++) 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (inprogress[n] == id) 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen break; 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* If we don't know what this is, do nothing. */ 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (n == inprogress.length) 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean startnext = false; 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If this is the first response from server n, 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * we should start sending queries to server n + 1. 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sent[n] == 1 && n < resolvers.length - 1) 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen startnext = true; 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (e instanceof InterruptedIOException) { 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* Got a timeout; resend */ 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sent[n] < retries) 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen send(n); 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (thrown == null) 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen thrown = e; 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (e instanceof SocketException) { 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Problem with the socket; don't resend 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * on it 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (thrown == null || 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen thrown instanceof InterruptedIOException) 199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen thrown = e; 200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* 202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Problem with the response; don't resend 203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * on the same socket. 204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen thrown = e; 206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (done) 208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (startnext) 210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen send(n + 1); 211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (done) 212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (outstanding == 0) { 214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* 215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If we're done and this is synchronous, 216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * wake up the blocking thread. 217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen done = true; 219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (listener == null) { 220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen notifyAll(); 221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!done) 225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* If we're done and this is asynchronous, call the callback. */ 228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!(thrown instanceof Exception)) 229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen thrown = new RuntimeException(thrown.getMessage()); 230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listener.handleException(this, (Exception) thrown); 231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final int quantum = 5; 235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate List resolvers; 237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean loadBalance = false; 238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int lbStart = 0; 239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int retries = 3; 240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void 242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Cheninit() { 243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen resolvers = new ArrayList(); 244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new Extended Resolver. The default ResolverConfig is used to 248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * determine the servers for which SimpleResolver contexts should be 249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * initialized. 250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see SimpleResolver 251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see ResolverConfig 252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @exception UnknownHostException Failure occured initializing SimpleResolvers 253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic 255d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenExtendedResolver() throws UnknownHostException { 256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen init(); 257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String [] servers = ResolverConfig.getCurrentConfig().servers(); 258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (servers != null) { 259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < servers.length; i++) { 260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Resolver r = new SimpleResolver(servers[i]); 261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen r.setTimeout(quantum); 262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen resolvers.add(r); 263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen resolvers.add(new SimpleResolver()); 267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new Extended Resolver 271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param servers An array of server names for which SimpleResolver 272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * contexts should be initialized. 273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see SimpleResolver 274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @exception UnknownHostException Failure occured initializing SimpleResolvers 275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic 277d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenExtendedResolver(String [] servers) throws UnknownHostException { 278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen init(); 279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < servers.length; i++) { 280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Resolver r = new SimpleResolver(servers[i]); 281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen r.setTimeout(quantum); 282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen resolvers.add(r); 283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new Extended Resolver 288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param res An array of pre-initialized Resolvers is provided. 289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see SimpleResolver 290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @exception UnknownHostException Failure occured initializing SimpleResolvers 291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic 293d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenExtendedResolver(Resolver [] res) throws UnknownHostException { 294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen init(); 295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < res.length; i++) 296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen resolvers.add(res[i]); 297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 300d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetPort(int port) { 301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < resolvers.size(); i++) 302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ((Resolver)resolvers.get(i)).setPort(port); 303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 306d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetTCP(boolean flag) { 307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < resolvers.size(); i++) 308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ((Resolver)resolvers.get(i)).setTCP(flag); 309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 312d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetIgnoreTruncation(boolean flag) { 313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < resolvers.size(); i++) 314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ((Resolver)resolvers.get(i)).setIgnoreTruncation(flag); 315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 318d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetEDNS(int level) { 319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < resolvers.size(); i++) 320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ((Resolver)resolvers.get(i)).setEDNS(level); 321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 324d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetEDNS(int level, int payloadSize, int flags, List options) { 325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < resolvers.size(); i++) 326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ((Resolver)resolvers.get(i)).setEDNS(level, payloadSize, 327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen flags, options); 328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 331d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetTSIGKey(TSIG key) { 332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < resolvers.size(); i++) 333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ((Resolver)resolvers.get(i)).setTSIGKey(key); 334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 337d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetTimeout(int secs, int msecs) { 338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < resolvers.size(); i++) 339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ((Resolver)resolvers.get(i)).setTimeout(secs, msecs); 340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 343d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetTimeout(int secs) { 344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setTimeout(secs, 0); 345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sends a message and waits for a response. Multiple servers are queried, 349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and queries are sent multiple times until either a successful response 350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is received, or it is clear that there is no successful response. 351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param query The query to send. 352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The response. 353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An error occurred while sending or receiving. 354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Message 356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chensend(Message query) throws IOException { 357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Resolution res = new Resolution(this, query); 358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return res.start(); 359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Asynchronously sends a message to multiple servers, potentially multiple 363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * times, registering a listener to receive a callback on success or exception. 364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Multiple asynchronous lookups can be performed in parallel. Since the 365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * callback may be invoked before the function returns, external 366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * synchronization is necessary. 367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param query The query to send 368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener The object containing the callbacks. 369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return An identifier, which is also a parameter in the callback 370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Object 372d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensendAsync(final Message query, final ResolverListener listener) { 373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Resolution res = new Resolution(this, query); 374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen res.startAsync(listener); 375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return res; 376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Returns the nth resolver used by this ExtendedResolver */ 379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Resolver 380d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetResolver(int n) { 381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (n < resolvers.size()) 382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (Resolver)resolvers.get(n); 383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Returns all resolvers used by this ExtendedResolver */ 387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Resolver [] 388d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetResolvers() { 389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (Resolver []) resolvers.toArray(new Resolver[resolvers.size()]); 390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Adds a new resolver to be used by this ExtendedResolver */ 393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 394d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenaddResolver(Resolver r) { 395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen resolvers.add(r); 396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Deletes a resolver used by this ExtendedResolver */ 399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 400d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChendeleteResolver(Resolver r) { 401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen resolvers.remove(r); 402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Sets whether the servers should be load balanced. 405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param flag If true, servers will be tried in round-robin order. If false, 406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * servers will always be queried in the same order. 407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 409d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetLoadBalance(boolean flag) { 410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen loadBalance = flag; 411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Sets the number of retries sent to each server per query */ 414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 415d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetRetries(int retries) { 416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.retries = retries; 417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 420