Source Code Cross Referenced for Message.java in  » Net » dnsjava » org » xbill » DNS » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » dnsjava » org.xbill.DNS 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
002:
003:        package org.xbill.DNS;
004:
005:        import java.util.*;
006:        import java.io.*;
007:
008:        /**
009:         * A DNS Message.  A message is the basic unit of communication between
010:         * the client and server of a DNS operation.  A message consists of a Header
011:         * and 4 message sections.
012:         * @see Resolver
013:         * @see Header
014:         * @see Section
015:         *
016:         * @author Brian Wellington
017:         */
018:
019:        public class Message implements  Cloneable {
020:
021:            /** The maximum length of a message in wire format. */
022:            public static final int MAXLENGTH = 65535;
023:
024:            private Header header;
025:            private List[] sections;
026:            private int size;
027:            private TSIG tsigkey;
028:            private TSIGRecord querytsig;
029:            private int tsigerror;
030:
031:            int tsigstart;
032:            int tsigState;
033:
034:            /* The message was not signed */
035:            static final int TSIG_UNSIGNED = 0;
036:
037:            /* The message was signed and verification succeeded */
038:            static final int TSIG_VERIFIED = 1;
039:
040:            /* The message was an unsigned message in multiple-message response */
041:            static final int TSIG_INTERMEDIATE = 2;
042:
043:            /* The message was signed and no verification was attempted.  */
044:            static final int TSIG_SIGNED = 3;
045:
046:            /*
047:             * The message was signed and verification failed, or was not signed
048:             * when it should have been.
049:             */
050:            static final int TSIG_FAILED = 4;
051:
052:            private static Record[] emptyRecordArray = new Record[0];
053:            private static RRset[] emptyRRsetArray = new RRset[0];
054:
055:            private Message(Header header) {
056:                sections = new List[4];
057:                this .header = header;
058:            }
059:
060:            /** Creates a new Message with the specified Message ID */
061:            public Message(int id) {
062:                this (new Header(id));
063:            }
064:
065:            /** Creates a new Message with a random Message ID */
066:            public Message() {
067:                this (new Header());
068:            }
069:
070:            /**
071:             * Creates a new Message with a random Message ID suitable for sending as a
072:             * query.
073:             * @param r A record containing the question
074:             */
075:            public static Message newQuery(Record r) {
076:                Message m = new Message();
077:                m.header.setOpcode(Opcode.QUERY);
078:                m.header.setFlag(Flags.RD);
079:                m.addRecord(r, Section.QUESTION);
080:                return m;
081:            }
082:
083:            /**
084:             * Creates a new Message to contain a dynamic update.  A random Message ID
085:             * and the zone are filled in.
086:             * @param zone The zone to be updated
087:             */
088:            public static Message newUpdate(Name zone) {
089:                return new Update(zone);
090:            }
091:
092:            Message(DNSInput in) throws IOException {
093:                this (new Header(in));
094:                boolean isUpdate = (header.getOpcode() == Opcode.UPDATE);
095:                boolean truncated = header.getFlag(Flags.TC);
096:                try {
097:                    for (int i = 0; i < 4; i++) {
098:                        int count = header.getCount(i);
099:                        if (count > 0)
100:                            sections[i] = new ArrayList(count);
101:                        for (int j = 0; j < count; j++) {
102:                            int pos = in.current();
103:                            Record rec = Record.fromWire(in, i, isUpdate);
104:                            sections[i].add(rec);
105:                            if (rec.getType() == Type.TSIG)
106:                                tsigstart = pos;
107:                        }
108:                    }
109:                } catch (WireParseException e) {
110:                    if (!truncated)
111:                        throw e;
112:                }
113:                size = in.current();
114:            }
115:
116:            /**
117:             * Creates a new Message from its DNS wire format representation
118:             * @param b A byte array containing the DNS Message.
119:             */
120:            public Message(byte[] b) throws IOException {
121:                this (new DNSInput(b));
122:            }
123:
124:            /**
125:             * Replaces the Header with a new one.
126:             * @see Header
127:             */
128:            public void setHeader(Header h) {
129:                header = h;
130:            }
131:
132:            /**
133:             * Retrieves the Header.
134:             * @see Header
135:             */
136:            public Header getHeader() {
137:                return header;
138:            }
139:
140:            /**
141:             * Adds a record to a section of the Message, and adjusts the header.
142:             * @see Record
143:             * @see Section
144:             */
145:            public void addRecord(Record r, int section) {
146:                if (sections[section] == null)
147:                    sections[section] = new LinkedList();
148:                header.incCount(section);
149:                sections[section].add(r);
150:            }
151:
152:            /**
153:             * Removes a record from a section of the Message, and adjusts the header.
154:             * @see Record
155:             * @see Section
156:             */
157:            public boolean removeRecord(Record r, int section) {
158:                if (sections[section] != null && sections[section].remove(r)) {
159:                    header.decCount(section);
160:                    return true;
161:                } else
162:                    return false;
163:            }
164:
165:            /**
166:             * Removes all records from a section of the Message, and adjusts the header.
167:             * @see Record
168:             * @see Section
169:             */
170:            public void removeAllRecords(int section) {
171:                sections[section] = null;
172:                header.setCount(section, 0);
173:            }
174:
175:            /**
176:             * Determines if the given record is already present in the given section.
177:             * @see Record
178:             * @see Section
179:             */
180:            public boolean findRecord(Record r, int section) {
181:                return (sections[section] != null && sections[section]
182:                        .contains(r));
183:            }
184:
185:            /**
186:             * Determines if the given record is already present in any section.
187:             * @see Record
188:             * @see Section
189:             */
190:            public boolean findRecord(Record r) {
191:                for (int i = Section.ANSWER; i <= Section.ADDITIONAL; i++)
192:                    if (sections[i] != null && sections[i].contains(r))
193:                        return true;
194:                return false;
195:            }
196:
197:            /**
198:             * Determines if an RRset with the given name and type is already
199:             * present in the given section.
200:             * @see RRset
201:             * @see Section
202:             */
203:            public boolean findRRset(Name name, int type, int section) {
204:                if (sections[section] == null)
205:                    return false;
206:                for (int i = 0; i < sections[section].size(); i++) {
207:                    Record r = (Record) sections[section].get(i);
208:                    if (r.getType() == type && name.equals(r.getName()))
209:                        return true;
210:                }
211:                return false;
212:            }
213:
214:            /**
215:             * Determines if an RRset with the given name and type is already
216:             * present in any section.
217:             * @see RRset
218:             * @see Section
219:             */
220:            public boolean findRRset(Name name, int type) {
221:                return (findRRset(name, type, Section.ANSWER)
222:                        || findRRset(name, type, Section.AUTHORITY) || findRRset(
223:                        name, type, Section.ADDITIONAL));
224:            }
225:
226:            /**
227:             * Returns the first record in the QUESTION section.
228:             * @see Record
229:             * @see Section
230:             */
231:            public Record getQuestion() {
232:                List l = sections[Section.QUESTION];
233:                if (l == null || l.size() == 0)
234:                    return null;
235:                return (Record) l.get(0);
236:            }
237:
238:            /**
239:             * Returns the TSIG record from the ADDITIONAL section, if one is present.
240:             * @see TSIGRecord
241:             * @see TSIG
242:             * @see Section
243:             */
244:            public TSIGRecord getTSIG() {
245:                int count = header.getCount(Section.ADDITIONAL);
246:                if (count == 0)
247:                    return null;
248:                List l = sections[Section.ADDITIONAL];
249:                Record rec = (Record) l.get(count - 1);
250:                if (rec.type != Type.TSIG)
251:                    return null;
252:                return (TSIGRecord) rec;
253:            }
254:
255:            /**
256:             * Was this message signed by a TSIG?
257:             * @see TSIG
258:             */
259:            public boolean isSigned() {
260:                return (tsigState == TSIG_SIGNED || tsigState == TSIG_VERIFIED || tsigState == TSIG_FAILED);
261:            }
262:
263:            /**
264:             * If this message was signed by a TSIG, was the TSIG verified?
265:             * @see TSIG
266:             */
267:            public boolean isVerified() {
268:                return (tsigState == TSIG_VERIFIED);
269:            }
270:
271:            /**
272:             * Returns the OPT record from the ADDITIONAL section, if one is present.
273:             * @see OPTRecord
274:             * @see Section
275:             */
276:            public OPTRecord getOPT() {
277:                Record[] additional = getSectionArray(Section.ADDITIONAL);
278:                for (int i = 0; i < additional.length; i++)
279:                    if (additional[i] instanceof  OPTRecord)
280:                        return (OPTRecord) additional[i];
281:                return null;
282:            }
283:
284:            /**
285:             * Returns the message's rcode (error code).  This incorporates the EDNS
286:             * extended rcode.
287:             */
288:            public int getRcode() {
289:                int rcode = header.getRcode();
290:                OPTRecord opt = getOPT();
291:                if (opt != null)
292:                    rcode += (opt.getExtendedRcode() << 4);
293:                return rcode;
294:            }
295:
296:            /**
297:             * Returns an array containing all records in the given section, or an
298:             * empty array if the section is empty.
299:             * @see Record
300:             * @see Section
301:             */
302:            public Record[] getSectionArray(int section) {
303:                if (sections[section] == null)
304:                    return emptyRecordArray;
305:                List l = sections[section];
306:                return (Record[]) l.toArray(new Record[l.size()]);
307:            }
308:
309:            private static boolean sameSet(Record r1, Record r2) {
310:                return (r1.getRRsetType() == r2.getRRsetType()
311:                        && r1.getDClass() == r2.getDClass() && r1.getName()
312:                        .equals(r2.getName()));
313:            }
314:
315:            /**
316:             * Returns an array containing all records in the given section grouped into
317:             * RRsets.
318:             * @see RRset
319:             * @see Section
320:             */
321:            public RRset[] getSectionRRsets(int section) {
322:                if (sections[section] == null)
323:                    return emptyRRsetArray;
324:                List sets = new LinkedList();
325:                Record[] recs = getSectionArray(section);
326:                Set hash = new HashSet();
327:                for (int i = 0; i < recs.length; i++) {
328:                    Name name = recs[i].getName();
329:                    boolean newset = true;
330:                    if (hash.contains(name)) {
331:                        for (int j = sets.size() - 1; j >= 0; j--) {
332:                            RRset set = (RRset) sets.get(j);
333:                            if (set.getType() == recs[i].getRRsetType()
334:                                    && set.getDClass() == recs[i].getDClass()
335:                                    && set.getName().equals(name)) {
336:                                set.addRR(recs[i]);
337:                                newset = false;
338:                                break;
339:                            }
340:                        }
341:                    }
342:                    if (newset) {
343:                        RRset set = new RRset(recs[i]);
344:                        sets.add(set);
345:                        hash.add(name);
346:                    }
347:                }
348:                return (RRset[]) sets.toArray(new RRset[sets.size()]);
349:            }
350:
351:            void toWire(DNSOutput out) {
352:                header.toWire(out);
353:                Compression c = new Compression();
354:                for (int i = 0; i < 4; i++) {
355:                    if (sections[i] == null)
356:                        continue;
357:                    for (int j = 0; j < sections[i].size(); j++) {
358:                        Record rec = (Record) sections[i].get(j);
359:                        rec.toWire(out, i, c);
360:                    }
361:                }
362:            }
363:
364:            /* Returns the number of records not successfully rendered. */
365:            private int sectionToWire(DNSOutput out, int section,
366:                    Compression c, int maxLength) {
367:                int n = sections[section].size();
368:                int pos = out.current();
369:                int rendered = 0;
370:                Record lastrec = null;
371:
372:                for (int i = 0; i < n; i++) {
373:                    Record rec = (Record) sections[section].get(i);
374:                    if (lastrec != null && !sameSet(rec, lastrec)) {
375:                        pos = out.current();
376:                        rendered = i;
377:                    }
378:                    lastrec = rec;
379:                    rec.toWire(out, section, c);
380:                    if (out.current() > maxLength) {
381:                        out.jump(pos);
382:                        return n - rendered;
383:                    }
384:                }
385:                return 0;
386:            }
387:
388:            /* Returns true if the message could be rendered. */
389:            private boolean toWire(DNSOutput out, int maxLength) {
390:                if (maxLength < Header.LENGTH)
391:                    return false;
392:
393:                Header newheader = null;
394:
395:                int tempMaxLength = maxLength;
396:                if (tsigkey != null)
397:                    tempMaxLength -= tsigkey.recordLength();
398:
399:                int startpos = out.current();
400:                header.toWire(out);
401:                Compression c = new Compression();
402:                for (int i = 0; i < 4; i++) {
403:                    int skipped;
404:                    if (sections[i] == null)
405:                        continue;
406:                    skipped = sectionToWire(out, i, c, tempMaxLength);
407:                    if (skipped != 0) {
408:                        if (i != Section.ADDITIONAL) {
409:                            if (newheader == null)
410:                                newheader = (Header) header.clone();
411:                            newheader.setFlag(Flags.TC);
412:                            int count = newheader.getCount(i);
413:                            newheader.setCount(i, count - skipped);
414:                            for (int j = i + 1; j < 4; j++)
415:                                newheader.setCount(j, 0);
416:
417:                            out.save();
418:                            out.jump(startpos);
419:                            newheader.toWire(out);
420:                            out.restore();
421:                        }
422:                        break;
423:                    }
424:                }
425:
426:                if (tsigkey != null) {
427:                    TSIGRecord tsigrec = tsigkey.generate(this , out
428:                            .toByteArray(), tsigerror, querytsig);
429:
430:                    if (newheader == null)
431:                        newheader = (Header) header.clone();
432:                    tsigrec.toWire(out, Section.ADDITIONAL, c);
433:                    newheader.incCount(Section.ADDITIONAL);
434:
435:                    out.save();
436:                    out.jump(startpos);
437:                    newheader.toWire(out);
438:                    out.restore();
439:                }
440:
441:                return true;
442:            }
443:
444:            /**
445:             * Returns an array containing the wire format representation of the Message.
446:             */
447:            public byte[] toWire() {
448:                DNSOutput out = new DNSOutput();
449:                toWire(out);
450:                size = out.current();
451:                return out.toByteArray();
452:            }
453:
454:            /**
455:             * Returns an array containing the wire format representation of the Message
456:             * with the specified maximum length.  This will generate a truncated
457:             * message (with the TC bit) if the message doesn't fit, and will also
458:             * sign the message with the TSIG key set by a call to setTSIG().  This
459:             * method may return null if the message could not be rendered at all; this
460:             * could happen if maxLength is smaller than a DNS header, for example.
461:             * @param maxLength The maximum length of the message.
462:             * @return The wire format of the message, or null if the message could not be
463:             * rendered into the specified length.
464:             * @see Flags
465:             * @see TSIG
466:             */
467:            public byte[] toWire(int maxLength) {
468:                DNSOutput out = new DNSOutput();
469:                toWire(out, maxLength);
470:                size = out.current();
471:                return out.toByteArray();
472:            }
473:
474:            /**
475:             * Sets the TSIG key and other necessary information to sign a message.
476:             * @param key The TSIG key.
477:             * @param error The value of the TSIG error field.
478:             * @param querytsig If this is a response, the TSIG from the request.
479:             */
480:            public void setTSIG(TSIG key, int error, TSIGRecord querytsig) {
481:                this .tsigkey = key;
482:                this .tsigerror = error;
483:                this .querytsig = querytsig;
484:            }
485:
486:            /**
487:             * Returns the size of the message.  Only valid if the message has been
488:             * converted to or from wire format.
489:             */
490:            public int numBytes() {
491:                return size;
492:            }
493:
494:            /**
495:             * Converts the given section of the Message to a String.
496:             * @see Section
497:             */
498:            public String sectionToString(int i) {
499:                if (i > 3)
500:                    return null;
501:
502:                StringBuffer sb = new StringBuffer();
503:
504:                Record[] records = getSectionArray(i);
505:                for (int j = 0; j < records.length; j++) {
506:                    Record rec = records[j];
507:                    if (i == Section.QUESTION) {
508:                        sb.append(";;\t" + rec.name);
509:                        sb.append(", type = " + Type.string(rec.type));
510:                        sb.append(", class = " + DClass.string(rec.dclass));
511:                    } else
512:                        sb.append(rec);
513:                    sb.append("\n");
514:                }
515:                return sb.toString();
516:            }
517:
518:            /**
519:             * Converts the Message to a String.
520:             */
521:            public String toString() {
522:                StringBuffer sb = new StringBuffer();
523:                OPTRecord opt = getOPT();
524:                if (opt != null)
525:                    sb.append(header.toStringWithRcode(getRcode()) + "\n");
526:                else
527:                    sb.append(header + "\n");
528:                if (isSigned()) {
529:                    sb.append(";; TSIG ");
530:                    if (isVerified())
531:                        sb.append("ok");
532:                    else
533:                        sb.append("invalid");
534:                    sb.append('\n');
535:                }
536:                for (int i = 0; i < 4; i++) {
537:                    if (header.getOpcode() != Opcode.UPDATE)
538:                        sb.append(";; " + Section.longString(i) + ":\n");
539:                    else
540:                        sb.append(";; " + Section.updString(i) + ":\n");
541:                    sb.append(sectionToString(i) + "\n");
542:                }
543:                sb.append(";; Message size: " + numBytes() + " bytes");
544:                return sb.toString();
545:            }
546:
547:            /**
548:             * Creates a copy of this Message.  This is done by the Resolver before adding
549:             * TSIG and OPT records, for example.
550:             * @see Resolver
551:             * @see TSIGRecord
552:             * @see OPTRecord
553:             */
554:            public Object clone() {
555:                Message m = new Message();
556:                for (int i = 0; i < sections.length; i++) {
557:                    if (sections[i] != null)
558:                        m.sections[i] = new LinkedList(sections[i]);
559:                }
560:                m.header = (Header) header.clone();
561:                m.size = size;
562:                return m;
563:            }
564:
565:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.