001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: *
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: /**
020: * @author Alexei Y. Zakharov
021: * @version $Revision: 1.1.2.4 $
022: */package org.apache.harmony.jndi.provider.dns;
023:
024: import java.util.Vector;
025: import java.util.Enumeration;
026:
027: import org.apache.harmony.jndi.internal.nls.Messages;
028:
029: /**
030: * This class represents a domain protocol message.
031: *
032: * @see RFC 1035
033: */
034: public class Message {
035:
036: // header section fields
037:
038: /** an ID */
039: private int id = 0;
040:
041: /** QR; false stands for QUERY request, true for RESPONSE */
042: private boolean qr = ProviderConstants.QR_QUERY;
043:
044: /** OPCODE; QUERY or IQUERY or STATUS */
045: private int opCode = 0;
046:
047: /** AA, Authoritative Answer */
048: private boolean aa = false;
049:
050: /** TC, TrunCation */
051: private boolean tc = false;
052:
053: /** RD, Recursion Desired */
054: private boolean rd = false;
055:
056: /** RA, Recursion Available */
057: private boolean ra = false;
058:
059: /** Z, always should be zero */
060: // private int z;
061: /** RCODE, Response CODE */
062: private int rCode = 0;
063:
064: /** QDCOUNT, number of records in question section */
065: private int qdCount = 0;
066:
067: /** ANCOUNT, number of records in answer section */
068: private int anCount = 0;
069:
070: /** NSCOUNT, number of records in authority records section */
071: private int nsCount = 0;
072:
073: /** ARCOUNT, number of records in additional section */
074: private int arCount = 0;
075:
076: private Vector<QuestionRecord> questionRecords = null;
077:
078: private Vector<ResourceRecord> answerRRs = null;
079:
080: private Vector<ResourceRecord> authorityRRs = null;
081:
082: private Vector<ResourceRecord> additionalRRs = null;
083:
084: /** */
085: public Message() {
086: questionRecords = new Vector<QuestionRecord>();
087: answerRRs = new Vector<ResourceRecord>();
088: authorityRRs = new Vector<ResourceRecord>();
089: additionalRRs = new Vector<ResourceRecord>();
090: }
091:
092: /**
093: * Constructs Message object from given parameters
094: *
095: * @param id
096: * ID
097: * @param qr
098: * QR
099: * @param opCode
100: * OPCODE
101: * @param aa
102: * AA
103: * @param tc
104: * TC
105: * @param rd
106: * RA
107: * @param ra
108: * RA
109: * @param rCode
110: * RCODE
111: * @param qdCount
112: * QDCOUNT
113: * @param anCount
114: * ANCOUNT
115: * @param nsCount
116: * NSCOUNT
117: * @param arCount
118: * ARCOUNT
119: */
120: public Message(int id, boolean qr, int opCode, boolean aa,
121: boolean tc, boolean rd, boolean ra, int rCode, int qdCount,
122: int anCount, int nsCount, int arCount) {
123: this .id = id;
124: this .qr = qr;
125: this .opCode = opCode;
126: this .aa = aa;
127: this .tc = tc;
128: this .rd = rd;
129: this .ra = ra;
130: this .rCode = rCode;
131: this .qdCount = qdCount;
132: this .anCount = anCount;
133: this .nsCount = nsCount;
134: this .arCount = arCount;
135: questionRecords = new Vector<QuestionRecord>();
136: answerRRs = new Vector<ResourceRecord>();
137: authorityRRs = new Vector<ResourceRecord>();
138: additionalRRs = new Vector<ResourceRecord>();
139: }
140:
141: /**
142: * Generates sequence of bytes that represents the message.
143: *
144: * @param buffer
145: * the buffer to write bytes into
146: * @param startIdx
147: * the index of <code>buffer</code> to start writing at
148: * @return updated index of the <code>buffer</code>
149: * @throws DomainProtocolException
150: * if something went wrong
151: */
152: public int writeBytes(byte[] buffer, int startIdx)
153: throws DomainProtocolException {
154: int idx = startIdx;
155: int tmp = 0;
156:
157: // basic check
158: if (buffer == null) {
159: // jndi.32=buffer is null
160: throw new DomainProtocolException(Messages
161: .getString("jndi.32")); //$NON-NLS-1$
162: }
163: // ID
164: idx = ProviderMgr.write16Int(id, buffer, idx);
165: // QR
166: tmp = ProviderMgr.setBit(tmp, ProviderConstants.QR_MASK, qr);
167: // OPCODE
168: tmp &= ~ProviderConstants.OPCODE_MASK;
169: tmp |= (opCode & 0xf) << ProviderConstants.OPCODE_SHIFT;
170: // AA
171: tmp = ProviderMgr.setBit(tmp, ProviderConstants.AA_MASK, aa);
172: // TC
173: tmp = ProviderMgr.setBit(tmp, ProviderConstants.TC_MASK, tc);
174: // RD
175: tmp = ProviderMgr.setBit(tmp, ProviderConstants.RD_MASK, rd);
176: // RA
177: tmp = ProviderMgr.setBit(tmp, ProviderConstants.RA_MASK, ra);
178: // Z, drop all those bits
179: tmp &= ~ProviderConstants.Z_MASK;
180: // RCODE
181: tmp &= ~ProviderConstants.RCODE_MASK;
182: tmp |= (rCode & 0xf) << ProviderConstants.RCODE_SHIFT;
183: // write to buffer
184: idx = ProviderMgr.write16Int(tmp, buffer, idx);
185: // QDCOUNT
186: idx = ProviderMgr.write16Int(qdCount, buffer, idx);
187: // ANCOUNT
188: idx = ProviderMgr.write16Int(anCount, buffer, idx);
189: // NSCOUNT
190: idx = ProviderMgr.write16Int(nsCount, buffer, idx);
191: // ARCOUNT
192: idx = ProviderMgr.write16Int(arCount, buffer, idx);
193: // question section
194: for (int i = 0; i < questionRecords.size(); i++) {
195: QuestionRecord qr = questionRecords.elementAt(i);
196:
197: idx = qr.writeBytes(buffer, idx);
198: }
199: // answer section
200: for (int i = 0; i < answerRRs.size(); i++) {
201: ResourceRecord rr = answerRRs.elementAt(i);
202:
203: idx = rr.writeBytes(buffer, idx);
204: }
205: // authority section
206: for (int i = 0; i < authorityRRs.size(); i++) {
207: ResourceRecord rr = answerRRs.elementAt(i);
208:
209: idx = rr.writeBytes(buffer, idx);
210: }
211: // additional section
212: for (int i = 0; i < additionalRRs.size(); i++) {
213: ResourceRecord rr = answerRRs.elementAt(i);
214:
215: idx = rr.writeBytes(buffer, idx);
216: }
217: return idx;
218: }
219:
220: /**
221: * Parses given sequence of bytes and constructs a message object from it.
222: *
223: * @param mesBytes
224: * the byte array that should be parsed
225: * @param startIdx
226: * an index of <code>mesBytes</code> array to start the parsing
227: * at
228: * @param mes
229: * an object to write a result to, should already be created
230: * @return updated index of <code>mesBytes</code> array
231: * @throws DomainProtocolException
232: * if some error has occurred
233: */
234: public static int parseMessage(byte[] mesBytes, int startIdx,
235: Message mesObj) throws DomainProtocolException {
236: int idx = startIdx;
237: int tmp, tmp2;
238: int qdCnt;
239: int anCnt;
240: int nsCnt;
241: int arCnt;
242:
243: if (mesObj == null) {
244: // jndi.58=The value of parameter mesObj is null
245: throw new DomainProtocolException(Messages
246: .getString("jndi.58")); //$NON-NLS-1$
247: }
248: // header section
249: // ID
250: mesObj.setId(ProviderMgr.parse16Int(mesBytes, idx));
251: idx += 2;
252: // QR & opCode & AA & TC & RD & RA & Z & rCode
253: tmp = ProviderMgr.parse16Int(mesBytes, idx);
254: idx += 2;
255: // QR
256: mesObj.setQR(ProviderMgr.checkBit(tmp,
257: ProviderConstants.QR_MASK));
258: // OPCODE
259: tmp2 = (tmp & ProviderConstants.OPCODE_MASK) >> ProviderConstants.OPCODE_SHIFT;
260: mesObj.setOpCode(tmp2);
261: // AA
262: mesObj.setAA(ProviderMgr.checkBit(tmp,
263: ProviderConstants.AA_MASK));
264: // TC
265: mesObj.setTc(ProviderMgr.checkBit(tmp,
266: ProviderConstants.TC_MASK));
267: // RD
268: mesObj.setRD(ProviderMgr.checkBit(tmp,
269: ProviderConstants.RD_MASK));
270: // RA
271: mesObj.setRA(ProviderMgr.checkBit(tmp,
272: ProviderConstants.RA_MASK));
273: // RCODE
274: tmp2 = (tmp & ProviderConstants.RCODE_MASK) >> ProviderConstants.RCODE_SHIFT;
275: mesObj.setRCode(tmp2);
276: // QDCOUNT
277: qdCnt = ProviderMgr.parse16Int(mesBytes, idx);
278: mesObj.setQDCount(qdCnt);
279: idx += 2;
280: // ANCOUNT
281: anCnt = ProviderMgr.parse16Int(mesBytes, idx);
282: mesObj.setANCount(anCnt);
283: idx += 2;
284: // NSCOUNT
285: nsCnt = ProviderMgr.parse16Int(mesBytes, idx);
286: mesObj.setNSCount(nsCnt);
287: idx += 2;
288: // ARCOUNT
289: arCnt = ProviderMgr.parse16Int(mesBytes, idx);
290: mesObj.setARCount(arCnt);
291: idx += 2;
292: // question section
293: for (int i = 0; i < qdCnt; i++) {
294: QuestionRecord qr = new QuestionRecord();
295: idx = QuestionRecord.parseRecord(mesBytes, idx, qr);
296: mesObj.addQuestionRecord(qr);
297: }
298: // answer section
299: for (int i = 0; i < anCnt; i++) {
300: ResourceRecord rr = new ResourceRecord();
301: idx = ResourceRecord.parseRecord(mesBytes, idx, rr);
302: mesObj.addAnswerRR(rr);
303: }
304: // authority section
305: for (int i = 0; i < nsCnt; i++) {
306: ResourceRecord rr = new ResourceRecord();
307: idx = ResourceRecord.parseRecord(mesBytes, idx, rr);
308: mesObj.addAuthorityRR(rr);
309: }
310: // additional section
311: for (int i = 0; i < arCnt; i++) {
312: ResourceRecord rr = new ResourceRecord();
313: idx = ResourceRecord.parseRecord(mesBytes, idx, rr);
314: mesObj.addAdditionalRR(rr);
315: }
316: return idx;
317: }
318:
319: /**
320: * @return string representation of this message
321: */
322: @Override
323: @SuppressWarnings("nls")
324: public String toString() {
325: StringBuffer sb = new StringBuffer();
326:
327: sb.append("ID=" + id + "\n");
328: if (qr) {
329: sb.append(" QR");
330: }
331: sb.append(" OPCODE=" + opCode);
332: if (aa) {
333: sb.append(" AA");
334: }
335: if (tc) {
336: sb.append(" TC");
337: }
338: if (rd) {
339: sb.append(" RD");
340: }
341: if (ra) {
342: sb.append(" RA");
343: }
344: sb.append(" RCODE=" + rCode);
345: sb.append("\n");
346: sb.append("QDCOUNT=" + qdCount);
347: for (int i = 0; i < questionRecords.size(); i++) {
348: sb.append("\n");
349: sb.append(questionRecords.elementAt(i).toString());
350: }
351: sb.append("\n");
352: sb.append(" ANCOUNT=" + anCount);
353: for (int i = 0; i < answerRRs.size(); i++) {
354: sb.append("\n");
355: sb.append(answerRRs.elementAt(i).toString());
356: }
357: sb.append("\n");
358: sb.append(" NSCOUNT=" + nsCount);
359: for (int i = 0; i < authorityRRs.size(); i++) {
360: sb.append("\n");
361: sb.append(authorityRRs.elementAt(i).toString());
362: }
363: sb.append("\n");
364: sb.append(" ARCOUNT=" + arCount);
365: for (int i = 0; i < additionalRRs.size(); i++) {
366: sb.append("\n");
367: sb.append(additionalRRs.elementAt(i).toString());
368: }
369: return sb.toString();
370: }
371:
372: /**
373: * @return Returns the AA.
374: */
375: public boolean isAA() {
376: return aa;
377: }
378:
379: /**
380: * @param aa
381: * The AA to set.
382: */
383: public void setAA(boolean aa) {
384: this .aa = aa;
385: }
386:
387: /**
388: * @return Returns the anCount.
389: */
390: public int getANCount() {
391: return anCount;
392: }
393:
394: /**
395: * @param anCount
396: * The anCount to set.
397: */
398: public void setANCount(int anCount) {
399: this .anCount = anCount;
400: }
401:
402: /**
403: * @return Returns the arCount.
404: */
405: public int getARCount() {
406: return arCount;
407: }
408:
409: /**
410: * @param arCount
411: * The arCount to set.
412: */
413: public void setARCount(int arCount) {
414: this .arCount = arCount;
415: }
416:
417: /**
418: * @return Returns the id.
419: */
420: public int getId() {
421: return id;
422: }
423:
424: /**
425: * @param id
426: * The id to set.
427: */
428: public void setId(int id) {
429: this .id = id;
430: }
431:
432: /**
433: * @return Returns the nsCount.
434: */
435: public int getNSCount() {
436: return nsCount;
437: }
438:
439: /**
440: * @param nsCount
441: * The nsCount to set.
442: */
443: public void setNSCount(int nsCount) {
444: this .nsCount = nsCount;
445: }
446:
447: /**
448: * @return Returns the opCode.
449: */
450: public int getOpCode() {
451: return opCode;
452: }
453:
454: /**
455: * @param opCode
456: * The opCode to set.
457: */
458: public void setOpCode(int opCode) {
459: this .opCode = opCode;
460: }
461:
462: /**
463: * @return Returns the qdCount.
464: */
465: public int getQDCount() {
466: return qdCount;
467: }
468:
469: /**
470: * @param qdCount
471: * The qdCount to set.
472: */
473: public void setQDCount(int qdCount) {
474: this .qdCount = qdCount;
475: }
476:
477: /**
478: * @return Returns the QR.
479: */
480: public boolean getQR() {
481: return qr;
482: }
483:
484: /**
485: * @param qr
486: * The QR to set.
487: */
488: public void setQR(boolean qr) {
489: this .qr = qr;
490: }
491:
492: /**
493: * @return Returns the RA.
494: */
495: public boolean isRA() {
496: return ra;
497: }
498:
499: /**
500: * @param ra
501: * The RA to set.
502: */
503: public void setRA(boolean ra) {
504: this .ra = ra;
505: }
506:
507: /**
508: * @return Returns the rCode.
509: */
510: public int getRCode() {
511: return rCode;
512: }
513:
514: /**
515: * @param code
516: * The rCode to set.
517: */
518: public void setRCode(int code) {
519: rCode = code;
520: }
521:
522: /**
523: * @return Returns the RD.
524: */
525: public boolean isRD() {
526: return rd;
527: }
528:
529: /**
530: * @param rd
531: * The RD to set.
532: */
533: public void setRD(boolean rd) {
534: this .rd = rd;
535: }
536:
537: /**
538: * @return Returns the TC.
539: */
540: public boolean isTc() {
541: return tc;
542: }
543:
544: /**
545: * @param tc
546: * The TC to set.
547: */
548: public void setTc(boolean tc) {
549: this .tc = tc;
550: }
551:
552: /**
553: * @return question records that are contained by the current message.
554: */
555: public Enumeration<QuestionRecord> getQuestionRecords() {
556: return questionRecords.elements();
557: }
558:
559: /**
560: * Adds a new question record to the message.
561: *
562: * @param qr
563: * a record to add
564: */
565: public void addQuestionRecord(QuestionRecord qr) {
566: questionRecords.addElement(qr);
567: }
568:
569: /**
570: * @return available answer resource records
571: */
572: public Enumeration<ResourceRecord> getAnswerRRs() {
573: return answerRRs.elements();
574: }
575:
576: /**
577: * Adds a new question record to the message.
578: *
579: * @param rr
580: * a record to add
581: */
582: public void addAnswerRR(ResourceRecord rr) {
583: answerRRs.addElement(rr);
584: }
585:
586: /**
587: * @return available authority resource records
588: */
589: public Enumeration<ResourceRecord> getAuthorityRRs() {
590: return authorityRRs.elements();
591: }
592:
593: /**
594: * Adds a new question record to the message.
595: *
596: * @param rr
597: * a record to add
598: */
599: public void addAuthorityRR(ResourceRecord rr) {
600: authorityRRs.addElement(rr);
601: }
602:
603: /**
604: * @return available additional resource records
605: */
606: public Enumeration<ResourceRecord> getAdditionalRRs() {
607: return additionalRRs.elements();
608: }
609:
610: /**
611: * Adds a new question record to the message.
612: *
613: * @param rr
614: * a record to add
615: */
616: public void addAdditionalRR(ResourceRecord rr) {
617: additionalRRs.addElement(rr);
618: }
619:
620: }
|