Author: bago
Date: Mon Apr 30 09:53:10 2007
New Revision: 533800
URL: http://svn.apache.org/viewvc?view=rev&rev=533800
Log:
Dummy implementation of an authoritative only DNSServer whose behaviour is
configurable via Yaml zone definition (it also simulates timeouts and per
lookup delays).
WARNING: some of the code is inspired (and something copy/pasted) by
jnamed.java file from dnsjava-2.0.3 demo sources. There's a pending issue about
the correct way to "publish" this (I currently added a warning in the source
headers and a sentence in the NOTICE.txt file).
Added:
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/DNSTestingServer.java
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/DNSTestingServerTest.java
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/ResponseGenerator.java
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/TCPListener.java
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/UDPListener.java
Modified:
james/jspf/branches/asynch-jspf/NOTICE.txt
Modified: james/jspf/branches/asynch-jspf/NOTICE.txt
URL:
http://svn.apache.org/viewvc/james/jspf/branches/asynch-jspf/NOTICE.txt?view=diff&rev=533800&r1=533799&r2=533800
==============================================================================
--- james/jspf/branches/asynch-jspf/NOTICE.txt (original)
+++ james/jspf/branches/asynch-jspf/NOTICE.txt Mon Apr 30 09:53:10 2007
@@ -16,6 +16,9 @@
written and copyright by Brian Wellington. The original software
is available from http://www.dnsjava.org/
+ Some of the DNS-aware tests have been inspired by DNSJava test code
+ written and copyrighted by Brian Wellington, too.
+
SPF Test (test*.txt) contains resources derived from the
libspf2 library (http://www.libspf2.org/) and distributed under
the BSD license and copyright by Wayne Schlitt, Shevek.
Added:
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/DNSTestingServer.java
URL:
http://svn.apache.org/viewvc/james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/DNSTestingServer.java?view=auto&rev=533800
==============================================================================
---
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/DNSTestingServer.java
(added)
+++
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/DNSTestingServer.java
Mon Apr 30 09:53:10 2007
@@ -0,0 +1,467 @@
+// ATTENTION PLEASE ATTENTION PLEASE ATTENTION PLEASE ATTENTION PLEASE
+// ATTENTION PLEASE ATTENTION PLEASE ATTENTION PLEASE ATTENTION PLEASE
+//
+// Part of this class have been inspired and copy&pasted from the jnamed.java
+// file found in the root of the dnsjava-2.0.3 distribution file.
+//
+// The Copyright for the original work is:
+// Copyright (c) 1999-2004 Brian Wellington ([EMAIL PROTECTED])
+//
+// The License for the dnsjava-2.0.3 package is BSD
+
+package org.apache.james.jspf.dnsserver;
+
+import org.xbill.DNS.AAAARecord;
+import org.xbill.DNS.ARecord;
+import org.xbill.DNS.Address;
+import org.xbill.DNS.CNAMERecord;
+import org.xbill.DNS.DClass;
+import org.xbill.DNS.DNAMERecord;
+import org.xbill.DNS.ExtendedFlags;
+import org.xbill.DNS.Flags;
+import org.xbill.DNS.Header;
+import org.xbill.DNS.MXRecord;
+import org.xbill.DNS.Message;
+import org.xbill.DNS.NSRecord;
+import org.xbill.DNS.Name;
+import org.xbill.DNS.NameTooLongException;
+import org.xbill.DNS.OPTRecord;
+import org.xbill.DNS.Opcode;
+import org.xbill.DNS.PTRRecord;
+import org.xbill.DNS.RRset;
+import org.xbill.DNS.Rcode;
+import org.xbill.DNS.Record;
+import org.xbill.DNS.SOARecord;
+import org.xbill.DNS.SPFRecord;
+import org.xbill.DNS.Section;
+import org.xbill.DNS.SetResponse;
+import org.xbill.DNS.TXTRecord;
+import org.xbill.DNS.TextParseException;
+import org.xbill.DNS.Type;
+import org.xbill.DNS.Zone;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+
+public class DNSTestingServer implements ResponseGenerator {
+
+ static final int FLAG_DNSSECOK = 1;
+
+ static final int FLAG_SIGONLY = 2;
+
+ protected Zone zone;
+
+ private HashSet timeoutServers;
+
+ Random random = new Random();
+
+ public DNSTestingServer(String address, String porta)
+ throws TextParseException, IOException {
+
+ Integer port = new Integer(porta != null ? porta : "53");
+ InetAddress addr = Address.getByAddress(address != null ? address
+ : "0.0.0.0");
+
+ Thread t;
+ t = new Thread(new TCPListener(addr, port.intValue(), this));
+ t.setDaemon(true);
+ t.start();
+
+ t = new Thread(new UDPListener(addr, port.intValue(), this));
+ t.setDaemon(true);
+ t.start();
+
+ zone = null;
+ }
+
+ public void setData(HashMap zonedata) {
+ try {
+ this.timeoutServers = new HashSet();
+ List records = new LinkedList();
+
+ records.add(new SOARecord(Name.root, DClass.IN, 3600, Name.root,
+ Name.root, 857623948, 0, 0, 0, 0));
+ records.add(new NSRecord(Name.root, DClass.IN, 3600, Name.root));
+
+ Iterator hosts = zonedata.keySet().iterator();
+ while (hosts.hasNext()) {
+ String host = (String) hosts.next();
+ Name hostname;
+ if (!host.endsWith(".")) {
+ hostname = Name.fromString(host + ".");
+ } else {
+ hostname = Name.fromString(host);
+ }
+
+ List l = (List) zonedata.get(host);
+ if (l != null)
+ for (Iterator i = l.iterator(); i.hasNext();) {
+ Object o = i.next();
+ if (o instanceof HashMap) {
+ HashMap hm = (HashMap) o;
+
+ Iterator types = hm.keySet().iterator();
+
+ while (types.hasNext()) {
+ String type = (String) types.next();
+ if ("MX".equals(type)) {
+ List mxList = (List) hm.get(type);
+ Iterator mxs = mxList.iterator();
+ while (mxs.hasNext()) {
+ Long prio = (Long) mxs.next();
+ String cname = (String) mxs.next();
+ if (cname != null) {
+ if (cname.length() > 0 &&
!cname.endsWith(".")) cname += ".";
+
+ records.add(new MXRecord(hostname,
+ DClass.IN, 3600, prio
+ .intValue(), Name
+
.fromString(cname)));
+ }
+ }
+ } else {
+ Object value = hm.get(type);
+ if ("A".equals(type)) {
+ records.add(new ARecord(hostname,
+ DClass.IN, 3600, Address
+ .getByAddress((String)
value)));
+ } else if ("AAAA".equals(type)) {
+ records.add(new AAAARecord(hostname,
+ DClass.IN, 3600, Address
+ .getByAddress((String)
value)));
+ } else if ("SPF".equals(type)) {
+ if (value instanceof List) {
+ records.add(new SPFRecord(hostname,
+ DClass.IN, 3600, (List)
value));
+ } else {
+ records.add(new SPFRecord(hostname,
+ DClass.IN, 3600, (String)
value));
+ }
+ } else if ("TXT".equals(type)) {
+ if (value instanceof List) {
+ records.add(new TXTRecord(hostname,
+ DClass.IN, 3600, (List)
value));
+ } else {
+ records.add(new TXTRecord(hostname,
+ DClass.IN, 3600, (String)
value));
+ }
+ } else {
+ if (!((String) value).endsWith(".")) {
+ value = ((String) value)+".";
+ }
+ if ("PTR".equals(type)) {
+ records
+ .add(new PTRRecord(
+ hostname,
+ DClass.IN,
+ 3600,
+ Name
+
.fromString((String) value)));
+ } else if ("CNAME".equals(type)) {
+ records.add(new CNAMERecord(
+ hostname, DClass.IN, 3600,
+ Name.fromString((String)
value)));
+ } else {
+ throw new IllegalStateException(
+ "Unsupported type: " +
type);
+ }
+ }
+ }
+ }
+ } else if ("TIMEOUT".equals(o)) {
+ timeoutServers.add(hostname);
+ } else {
+ throw new IllegalStateException(
+ "getRecord found an unexpected data");
+ }
+ }
+ }
+
+ zone = new Zone(Name.root, (Record[]) records
+ .toArray(new Record[] {}));
+
+ } catch (TextParseException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (UnknownHostException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private SOARecord findSOARecord() {
+ return zone.getSOA();
+ }
+
+ private RRset findNSRecords() {
+ return zone.getNS();
+ }
+
+ // TODO verify why enabling this lookup will make some test to fail!
+ private RRset findARecord(Name name) {
+ return null;
+ //return zone.findExactMatch(name, Type.A);
+ }
+
+ private SetResponse findRecords(Name name, int type) {
+ SetResponse sr = zone.findRecords(name, type);
+
+ if (sr == null || sr.answers() == null || sr.answers().length == 0) {
+ boolean timeout = timeoutServers.contains(name);
+ if (timeout) {
+ try {
+ Thread.sleep(2100);
+ }
+ catch (InterruptedException e) {
+ }
+ return null;
+ }
+ }
+
+ try {
+ Thread.sleep(random.nextInt(500));
+ }
+ catch (Exception e) {}
+
+ return sr;
+ }
+
+ void addRRset(Name name, Message response, RRset rrset, int section,
+ int flags) {
+ for (int s = 1; s <= section; s++)
+ if (response.findRRset(name, rrset.getType(), s))
+ return;
+ if ((flags & FLAG_SIGONLY) == 0) {
+ Iterator it = rrset.rrs();
+ while (it.hasNext()) {
+ Record r = (Record) it.next();
+ if (r.getName().isWild() && !name.isWild())
+ r = r.withName(name);
+ response.addRecord(r, section);
+ }
+ }
+ if ((flags & (FLAG_SIGONLY | FLAG_DNSSECOK)) != 0) {
+ Iterator it = rrset.sigs();
+ while (it.hasNext()) {
+ Record r = (Record) it.next();
+ if (r.getName().isWild() && !name.isWild())
+ r = r.withName(name);
+ response.addRecord(r, section);
+ }
+ }
+ }
+
+ private void addGlue(Message response, Name name, int flags) {
+ RRset a = findARecord(name);
+ if (a == null)
+ return;
+ addRRset(name, response, a, Section.ADDITIONAL, flags);
+ }
+
+ private void addAdditional2(Message response, int section, int flags) {
+ Record[] records = response.getSectionArray(section);
+ for (int i = 0; i < records.length; i++) {
+ Record r = records[i];
+ Name glueName = r.getAdditionalName();
+ if (glueName != null)
+ addGlue(response, glueName, flags);
+ }
+ }
+
+ private final void addAdditional(Message response, int flags) {
+ addAdditional2(response, Section.ANSWER, flags);
+ addAdditional2(response, Section.AUTHORITY, flags);
+ }
+
+ byte addAnswer(Message response, Name name, int type, int dclass,
+ int iterations, int flags) {
+ SetResponse sr;
+ byte rcode = Rcode.NOERROR;
+
+ if (iterations > 6)
+ return Rcode.NOERROR;
+
+ if (type == Type.SIG || type == Type.RRSIG) {
+ type = Type.ANY;
+ flags |= FLAG_SIGONLY;
+ }
+
+ sr = findRecords(name, type);
+
+ // TIMEOUT
+ if (sr == null) {
+ return -1;
+ }
+
+ if (sr.isNXDOMAIN() || sr.isNXRRSET()) {
+ if (sr.isNXDOMAIN())
+ response.getHeader().setRcode(Rcode.NXDOMAIN);
+
+ response.addRecord(findSOARecord(), Section.AUTHORITY);
+
+ if (iterations == 0)
+ response.getHeader().setFlag(Flags.AA);
+
+ rcode = Rcode.NXDOMAIN;
+
+ } else if (sr.isDelegation()) {
+ RRset nsRecords = sr.getNS();
+ addRRset(nsRecords.getName(), response, nsRecords,
+ Section.AUTHORITY, flags);
+ } else if (sr.isCNAME()) {
+ CNAMERecord cname = sr.getCNAME();
+ RRset rrset = new RRset(cname);
+ addRRset(name, response, rrset, Section.ANSWER, flags);
+ if (iterations == 0)
+ response.getHeader().setFlag(Flags.AA);
+ rcode = addAnswer(response, cname.getTarget(), type, dclass,
+ iterations + 1, flags);
+ } else if (sr.isDNAME()) {
+ DNAMERecord dname = sr.getDNAME();
+ RRset rrset = new RRset(dname);
+ addRRset(name, response, rrset, Section.ANSWER, flags);
+ Name newname;
+ try {
+ newname = name.fromDNAME(dname);
+ } catch (NameTooLongException e) {
+ return Rcode.YXDOMAIN;
+ }
+ rrset = new RRset(new CNAMERecord(name, dclass, 0, newname));
+ addRRset(name, response, rrset, Section.ANSWER, flags);
+ if (iterations == 0)
+ response.getHeader().setFlag(Flags.AA);
+ rcode = addAnswer(response, newname, type, dclass, iterations + 1,
+ flags);
+ } else if (sr.isSuccessful()) {
+ RRset[] rrsets = sr.answers();
+ for (int i = 0; i < rrsets.length; i++)
+ addRRset(name, response, rrsets[i], Section.ANSWER, flags);
+
+ RRset findNSRecords = findNSRecords();
+ addRRset(findNSRecords.getName(), response, findNSRecords,
+ Section.AUTHORITY, flags);
+
+ if (iterations == 0)
+ response.getHeader().setFlag(Flags.AA);
+ }
+ return rcode;
+ }
+
+ public byte[] generateReply(Message query, int length, Socket s)
+ throws IOException {
+ Header header;
+ int maxLength;
+ int flags = 0;
+
+ header = query.getHeader();
+ if (header.getFlag(Flags.QR))
+ return null;
+ if (header.getRcode() != Rcode.NOERROR)
+ return errorMessage(query, Rcode.FORMERR);
+ if (header.getOpcode() != Opcode.QUERY)
+ return errorMessage(query, Rcode.NOTIMP);
+
+ Record queryRecord = query.getQuestion();
+
+ OPTRecord queryOPT = query.getOPT();
+ if (queryOPT != null && queryOPT.getVersion() > 0) {
+ }
+
+ if (s != null)
+ maxLength = 65535;
+ else if (queryOPT != null)
+ maxLength = Math.max(queryOPT.getPayloadSize(), 512);
+ else
+ maxLength = 512;
+
+ if (queryOPT != null && (queryOPT.getFlags() & ExtendedFlags.DO) != 0)
+ flags = FLAG_DNSSECOK;
+
+ Message response = new Message(query.getHeader().getID());
+ response.getHeader().setFlag(Flags.QR);
+ if (query.getHeader().getFlag(Flags.RD))
+ response.getHeader().setFlag(Flags.RD);
+ response.addRecord(queryRecord, Section.QUESTION);
+
+ Name name = queryRecord.getName();
+ int type = queryRecord.getType();
+ int dclass = queryRecord.getDClass();
+ if (!Type.isRR(type) && type != Type.ANY)
+ return errorMessage(query, Rcode.NOTIMP);
+
+ byte rcode = addAnswer(response, name, type, dclass, 0, flags);
+
+ // TIMEOUT
+ if (rcode == -1) {
+ return null;
+ }
+
+ if (rcode != Rcode.NOERROR && rcode != Rcode.NXDOMAIN)
+ return errorMessage(query, rcode);
+
+ addAdditional(response, flags);
+
+ if (queryOPT != null) {
+ int optflags = (flags == FLAG_DNSSECOK) ? ExtendedFlags.DO : 0;
+ OPTRecord opt = new OPTRecord((short) 4096, rcode, (byte) 0,
+ optflags);
+ response.addRecord(opt, Section.ADDITIONAL);
+ }
+
+ return response.toWire(maxLength);
+ }
+
+ byte[] buildErrorMessage(Header header, int rcode, Record question) {
+ Message response = new Message();
+ response.setHeader(header);
+ for (int i = 0; i < 4; i++)
+ response.removeAllRecords(i);
+ if (rcode == Rcode.SERVFAIL)
+ response.addRecord(question, Section.QUESTION);
+ header.setRcode(rcode);
+ return response.toWire();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.james.jspf.MessageGenerator#formerrMessage(byte[])
+ */
+ public byte[] formerrMessage(byte[] in) {
+ Header header;
+ try {
+ header = new Header(in);
+ } catch (IOException e) {
+ return null;
+ }
+ return buildErrorMessage(header, Rcode.FORMERR, null);
+ }
+
+ public byte[] errorMessage(Message query, int rcode) {
+ return buildErrorMessage(query.getHeader(), rcode,
query.getQuestion());
+ }
+
+ public byte[] generateReply(byte[] in, int length) {
+ Message query;
+ byte[] response = null;
+ try {
+ query = new Message(in);
+ response = generateReply(query, length, null);
+ } catch (IOException e) {
+ response = formerrMessage(in);
+ }
+ return response;
+ }
+
+}
Added:
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/DNSTestingServerTest.java
URL:
http://svn.apache.org/viewvc/james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/DNSTestingServerTest.java?view=auto&rev=533800
==============================================================================
---
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/DNSTestingServerTest.java
(added)
+++
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/DNSTestingServerTest.java
Mon Apr 30 09:53:10 2007
@@ -0,0 +1,73 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jspf.dnsserver;
+
+import org.apache.james.jspf.ConsoleLogger;
+import org.apache.james.jspf.core.DNSService;
+import org.apache.james.jspf.impl.DNSServiceXBillImpl;
+import org.xbill.DNS.Cache;
+import org.xbill.DNS.DClass;
+import org.xbill.DNS.Lookup;
+import org.xbill.DNS.Name;
+import org.xbill.DNS.Resolver;
+import org.xbill.DNS.SimpleResolver;
+
+import junit.framework.TestCase;
+
+public class DNSTestingServerTest extends TestCase {
+
+ private DNSTestingServer server;
+ private Cache origCache;
+ private Resolver origResolver;
+ private Name[] origSearchPaths;
+ private DNSService dnsService;
+
+ protected void setUp() throws Exception {
+ server = new DNSTestingServer("0.0.0.0", "34876");
+ origCache = Lookup.getDefaultCache(DClass.IN);
+ origResolver = Lookup.getDefaultResolver();
+ origSearchPaths = Lookup.getDefaultSearchPath();
+
+ Lookup.setDefaultSearchPath(new Name[] {});
+ Lookup.setDefaultCache(null, DClass.IN);
+ SimpleResolver simpleResolver = new SimpleResolver("127.0.0.1");
+ simpleResolver.setPort(34876);
+ Lookup.setDefaultResolver(simpleResolver);
+
+ dnsService = new DNSServiceXBillImpl(new ConsoleLogger());
+ }
+
+ public void testNothing() {
+
+ }
+// public void testSimple() throws TimeoutException {
+// List res = dnsService.getRecords(new DNSRequest("test.foo.bar.",
DNSRequest.MX));
+// System.out.println(res);
+//
+// }
+
+ protected void tearDown() throws Exception {
+ Lookup.setDefaultCache(origCache, DClass.IN);
+ Lookup.setDefaultResolver(origResolver);
+ Lookup.setDefaultSearchPath(origSearchPaths);
+ }
+
+
+}
Added:
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/ResponseGenerator.java
URL:
http://svn.apache.org/viewvc/james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/ResponseGenerator.java?view=auto&rev=533800
==============================================================================
---
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/ResponseGenerator.java
(added)
+++
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/ResponseGenerator.java
Mon Apr 30 09:53:10 2007
@@ -0,0 +1,27 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jspf.dnsserver;
+
+
+public interface ResponseGenerator {
+
+ public byte[] generateReply(byte[] in, int length);
+
+}
Added:
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/TCPListener.java
URL:
http://svn.apache.org/viewvc/james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/TCPListener.java?view=auto&rev=533800
==============================================================================
---
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/TCPListener.java
(added)
+++
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/TCPListener.java
Mon Apr 30 09:53:10 2007
@@ -0,0 +1,90 @@
+// ATTENTION PLEASE ATTENTION PLEASE ATTENTION PLEASE ATTENTION PLEASE
+// ATTENTION PLEASE ATTENTION PLEASE ATTENTION PLEASE ATTENTION PLEASE
+//
+// Part of this class have been inspired and copy&pasted from the jnamed.java
+// file found in the root of the dnsjava-2.0.3 distribution file.
+//
+// The Copyright for the original work is:
+// Copyright (c) 1999-2004 Brian Wellington ([EMAIL PROTECTED])
+//
+// The License for the dnsjava-2.0.3 package is BSD
+
+package org.apache.james.jspf.dnsserver;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+public final class TCPListener implements Runnable {
+
+ private final static class TCPServer implements Runnable {
+ private final Socket serverSocket;
+
+ private ResponseGenerator responseGenerator;
+
+ private TCPServer(Socket s, ResponseGenerator rg) {
+ this.serverSocket = s;
+ this.responseGenerator = rg;
+ }
+
+ public void run() {
+ try {
+ int inLength;
+ DataInputStream dataIn;
+ DataOutputStream dataOut;
+ byte[] in;
+
+ InputStream is = serverSocket.getInputStream();
+ dataIn = new DataInputStream(is);
+ inLength = dataIn.readUnsignedShort();
+ in = new byte[inLength];
+ dataIn.readFully(in);
+
+ int length = in.length;
+ byte[] response = responseGenerator.generateReply(in, length);
+ if (response == null) return;
+ dataOut = new DataOutputStream(serverSocket.getOutputStream());
+ dataOut.writeShort(response.length);
+ dataOut.write(response);
+ } catch (IOException e) {
+ System.out.println("TCPclient("
+ + serverSocket.getLocalAddress().getHostAddress() +
"#" + serverSocket.getLocalPort()
+ + "): " + e);
+ } finally {
+ try {
+ serverSocket.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ }
+
+ private final int port;
+
+ private final InetAddress addr;
+
+ private ResponseGenerator responseGenerator;
+
+ public TCPListener(InetAddress addr, int port, ResponseGenerator rg) {
+ this.port = port;
+ this.addr = addr;
+ this.responseGenerator = rg;
+ }
+
+ public void run() {
+ try {
+ ServerSocket sock = new ServerSocket(port, 128, addr);
+ while (true) {
+ new Thread(new TCPServer(sock.accept(),
responseGenerator)).start();
+ }
+ } catch (IOException e) {
+ System.out.println("serveTCP(" + addr.getHostAddress() + "#" +
port + "): "
+ + e);
+ }
+ }
+}
\ No newline at end of file
Added:
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/UDPListener.java
URL:
http://svn.apache.org/viewvc/james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/UDPListener.java?view=auto&rev=533800
==============================================================================
---
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/UDPListener.java
(added)
+++
james/jspf/branches/asynch-jspf/src/test/java/org/apache/james/jspf/dnsserver/UDPListener.java
Mon Apr 30 09:53:10 2007
@@ -0,0 +1,102 @@
+// ATTENTION PLEASE ATTENTION PLEASE ATTENTION PLEASE ATTENTION PLEASE
+// ATTENTION PLEASE ATTENTION PLEASE ATTENTION PLEASE ATTENTION PLEASE
+//
+// Part of this class have been inspired and copy&pasted from the jnamed.java
+// file found in the root of the dnsjava-2.0.3 distribution file.
+//
+// The Copyright for the original work is:
+// Copyright (c) 1999-2004 Brian Wellington ([EMAIL PROTECTED])
+//
+// The License for the dnsjava-2.0.3 package is BSD
+
+package org.apache.james.jspf.dnsserver;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+
+public final class UDPListener implements Runnable {
+
+ private final static class UDPResponder implements Runnable {
+ private ResponseGenerator responseGenerator;
+
+ private DatagramSocket sock;
+ private InetAddress addr;
+ private int port;
+ private byte[] in;
+
+ private UDPResponder(DatagramSocket sock, InetAddress addr, int port,
byte[] in, ResponseGenerator rg) {
+ this.sock = sock;
+ this.addr = addr;
+ this.port = port;
+ this.in = in;
+ this.responseGenerator = rg;
+ }
+
+ public void run() {
+ try {
+ DatagramPacket outdp = null;
+ byte[] response = responseGenerator.generateReply(in,
in.length);
+ if (response == null)
+ return;
+ if (outdp == null) {
+ outdp = new DatagramPacket(response, response.length,
+ addr, port);
+ } else {
+ outdp.setData(response);
+ outdp.setLength(response.length);
+ outdp.setAddress(addr);
+ outdp.setPort(port);
+ }
+ sock.send(outdp);
+ } catch (IOException e) {
+ System.out.println("UDPResponder(" + addr.getHostAddress() +
"#" + port + "): "
+ + e);
+ }
+ }
+
+ }
+
+
+
+ private final InetAddress addr;
+
+ private final int port;
+
+ private ResponseGenerator responseGenerator;
+
+ UDPListener(InetAddress addr, int port, ResponseGenerator rg) {
+ this.addr = addr;
+ this.port = port;
+ this.responseGenerator = rg;
+ }
+
+ public void run() {
+ try {
+ DatagramSocket sock = new DatagramSocket(port, addr);
+ final short udpLength = 512;
+ byte[] in = new byte[udpLength];
+ DatagramPacket indp = new DatagramPacket(in, in.length);
+ while (true) {
+ indp.setLength(in.length);
+ try {
+ sock.receive(indp);
+ } catch (InterruptedIOException e) {
+ continue;
+ }
+
+ byte[] local = new byte[indp.getLength()];
+ System.arraycopy(in, 0, local, 0, indp.getLength());
+ Runnable runnable = new UDPResponder(sock, indp.getAddress(),
indp.getPort(), local, responseGenerator);
+
+ new Thread(runnable).start();
+ }
+ } catch (IOException e) {
+ System.out.println("UDPListener(" + addr.getHostAddress() + "#" +
port + "): "
+ + e);
+ }
+ }
+
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]