< prev index next >
test/jdk/com/sun/jndi/dns/lib/DNSServer.java
Print this page
@@ -24,10 +24,12 @@
import sun.security.util.HexDumpEncoder;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -47,11 +49,11 @@
* xxxx: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff ................
*
* Typically, DNS protocol exchange is generated by DNSTracer who captures
* communication messages between DNS application program and real DNS server
*/
-public class DNSServer implements Runnable {
+public class DNSServer extends Thread implements Server {
public class Pair<F, S> {
private F first;
private S second;
@@ -85,23 +87,25 @@
private DatagramSocket socket;
private String filename;
private boolean loop;
private final List<Pair<byte[], byte[]>> cache = new ArrayList<>();
private ByteBuffer reqBuffer = ByteBuffer.allocate(DNS_PACKET_SIZE);
+ private volatile boolean isRunning;
- public DNSServer(DatagramSocket socket, String filename) {
- this(socket, filename, false);
+ public DNSServer(String filename) throws SocketException {
+ this(filename, false);
}
- public DNSServer(DatagramSocket socket, String filename, boolean loop) {
- this.socket = socket;
+ public DNSServer(String filename, boolean loop) throws SocketException {
+ this.socket = new DatagramSocket(0, InetAddress.getLoopbackAddress());
this.filename = filename;
this.loop = loop;
}
public void run() {
try {
+ isRunning = true;
System.out.println(
"DNSServer: Loading DNS cache data from : " + filename);
loadCaptureFile(filename);
System.out.println(
@@ -110,47 +114,85 @@
System.out.println("DNSServer: loop playback: " + loop);
int playbackIndex = 0;
while (playbackIndex < cache.size()) {
- DatagramPacket reqPacket = new DatagramPacket(reqBuffer.array(),
- reqBuffer.array().length);
- socket.receive(reqPacket);
-
- System.out.println(
- "DNSServer: received query message from " + reqPacket
- .getSocketAddress());
+ DatagramPacket reqPacket = receiveQuery();
if (!verifyRequestMsg(reqPacket, playbackIndex)) {
+ if (playbackIndex > 0 && verifyRequestMsg(reqPacket,
+ playbackIndex - 1)) {
+ System.out.println(
+ "DNSServer: received retry query, resend");
+ playbackIndex--;
+ } else {
throw new RuntimeException(
"DNSServer: Error: Failed to verify DNS request. "
+ "Not identical request message : \n"
+ encoder.encodeBuffer(
Arrays.copyOf(reqPacket.getData(),
reqPacket.getLength())));
}
+ }
- byte[] payload = generateResponsePayload(reqPacket,
- playbackIndex);
- socket.send(new DatagramPacket(payload, payload.length,
- reqPacket.getSocketAddress()));
- System.out.println(
- "DNSServer: send response message to " + reqPacket
- .getSocketAddress());
+ sendResponse(reqPacket, playbackIndex);
playbackIndex++;
if (loop && playbackIndex >= cache.size()) {
playbackIndex = 0;
}
}
System.out.println(
"DNSServer: Done for all cached messages playback");
+
+ System.out.println(
+ "DNSServer: Still listening for possible retry query");
+ while (true) {
+ DatagramPacket reqPacket = receiveQuery();
+
+ // here we only handle the retry query for last one
+ if (!verifyRequestMsg(reqPacket, playbackIndex - 1)) {
+ throw new RuntimeException(
+ "DNSServer: Error: Failed to verify DNS request. "
+ + "Not identical request message : \n"
+ + encoder.encodeBuffer(
+ Arrays.copyOf(reqPacket.getData(),
+ reqPacket.getLength())));
+ }
+
+ sendResponse(reqPacket, playbackIndex - 1);
+ }
} catch (Exception e) {
+ if (isRunning) {
System.err.println("DNSServer: Error: " + e);
+ e.printStackTrace();
+ } else {
+ System.out.println("DNSServer: Exit");
}
}
+ }
+
+ private DatagramPacket receiveQuery() throws IOException {
+ DatagramPacket reqPacket = new DatagramPacket(reqBuffer.array(),
+ reqBuffer.array().length);
+ socket.receive(reqPacket);
+
+ System.out.println("DNSServer: received query message from " + reqPacket
+ .getSocketAddress());
+
+ return reqPacket;
+ }
+
+ private void sendResponse(DatagramPacket reqPacket, int playbackIndex)
+ throws IOException {
+ byte[] payload = generateResponsePayload(reqPacket, playbackIndex);
+ socket.send(new DatagramPacket(payload, payload.length,
+ reqPacket.getSocketAddress()));
+ System.out.println("DNSServer: send response message to " + reqPacket
+ .getSocketAddress());
+ }
/*
* Load a capture file containing an DNS protocol exchange in the
* hexadecimal dump format emitted by sun.misc.HexDumpEncoder:
*
@@ -297,6 +339,25 @@
if ('a' <= ch && ch <= 'f') {
return ch - 'a' + 10;
}
return -1;
}
+
+ @Override public void stopServer() {
+ isRunning = false;
+ if (socket != null) {
+ try {
+ socket.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+
+ @Override public int getPort() {
+ if (socket != null) {
+ return socket.getLocalPort();
+ } else {
+ return -1;
+ }
+ }
}
< prev index next >