1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * Copyright (c) 2003-2012 by AG-Software * 3 * All Rights Reserved. * 4 * Contact information for AG-Software is available at http://www.ag-software.de * 5 * * 6 * Licence: * 7 * The agsXMPP SDK is released under a dual licence * 8 * agsXMPP can be used under either of two licences * 9 * * 10 * A commercial licence which is probably the most appropriate for commercial * 11 * corporate use and closed source projects. * 12 * * 13 * The GNU Public License (GPL) is probably most appropriate for inclusion in * 14 * other open source projects. * 15 * * 16 * See README.html for details. * 17 * * 18 * For general enquiries visit our website at: * 19 * http://www.ag-software.de * 20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 21 22 // 23 // Bdev.Net.Dns by Rob Philpott, Big Developments Ltd. Please send all bugs/enhancements to 24 // rob@bigdevelopments.co.uk This file and the code contained within is freeware and may be 25 // distributed and edited without restriction. 26 // 27 28 using System; 29 using System.Net; 30 31 namespace agsXMPP.Net.Dns 32 { 33 /// <summary> 34 /// A Response is a logical representation of the byte data returned from a DNS query 35 /// </summary> 36 public class Response 37 { 38 // these are fields we're interested in from the message 39 private readonly ReturnCode _returnCode; 40 private readonly bool _authoritativeAnswer; 41 private readonly bool _recursionAvailable; 42 private readonly bool _truncated; 43 private readonly Question[] _questions; 44 private readonly Answer[] _answers; 45 private readonly NameServer[] _nameServers; 46 private readonly AdditionalRecord[] _additionalRecords; 47 48 // these fields are readonly outside the assembly - use r/o properties 49 public ReturnCode ReturnCode { get { return _returnCode; }} 50 public bool AuthoritativeAnswer { get { return _authoritativeAnswer; }} 51 public bool RecursionAvailable { get { return _recursionAvailable; }} 52 public bool MessageTruncated { get { return _truncated; }} 53 public Question[] Questions { get { return _questions; }} 54 public Answer[] Answers { get { return _answers; }} 55 public NameServer[] NameServers { get { return _nameServers; }} 56 public AdditionalRecord[] AdditionalRecords { get { return _additionalRecords; }} 57 58 /// <summary> 59 /// Construct a Response object from the supplied byte array 60 /// </summary> 61 /// <param name="message">a byte array returned from a DNS server query</param> Response(byte[] message)62 internal Response(byte[] message) 63 { 64 // the bit flags are in bytes 2 and 3 65 byte flags1 = message[2]; 66 byte flags2 = message[3]; 67 68 // get return code from lowest 4 bits of byte 3 69 int returnCode = flags2 & 15; 70 71 // if its in the reserved section, set to other 72 if (returnCode > 6) returnCode = 6; 73 _returnCode = (ReturnCode)returnCode; 74 75 // other bit flags 76 _authoritativeAnswer = ((flags1 & 4) != 0); 77 _recursionAvailable = ((flags2 & 128) != 0); 78 _truncated = ((flags1 & 2) != 0); 79 80 // create the arrays of response objects 81 _questions = new Question[GetShort(message, 4)]; 82 _answers = new Answer[GetShort(message, 6)]; 83 _nameServers = new NameServer[GetShort(message, 8)]; 84 _additionalRecords = new AdditionalRecord[GetShort(message, 10)]; 85 86 // need a pointer to do this, position just after the header 87 Pointer pointer = new Pointer(message, 12); 88 89 // and now populate them, they always follow this order 90 for (int index = 0; index < _questions.Length; index++) 91 { 92 try 93 { 94 // try to build a quesion from the response 95 _questions[index] = new Question(pointer); 96 } 97 catch (Exception ex) 98 { 99 // something grim has happened, we can't continue 100 throw new InvalidResponseException(ex); 101 } 102 } 103 for (int index = 0; index < _answers.Length; index++) 104 { 105 _answers[index] = new Answer(pointer); 106 } 107 for (int index = 0; index < _nameServers.Length; index++) 108 { 109 _nameServers[index] = new NameServer(pointer); 110 } 111 for (int index = 0; index < _additionalRecords.Length; index++) 112 { 113 _additionalRecords[index] = new AdditionalRecord(pointer); 114 } 115 } 116 117 /// <summary> 118 /// Convert 2 bytes to a short. It would have been nice to use BitConverter for this, 119 /// it however reads the bytes in the wrong order (at least on Windows) 120 /// </summary> 121 /// <param name="message">byte array to look in</param> 122 /// <param name="position">position to look at</param> 123 /// <returns>short representation of the two bytes</returns> GetShort(byte[] message, int position)124 private static short GetShort(byte[] message, int position) 125 { 126 return (short)(message[position]<<8 | message[position+1]); 127 } 128 } 129 } 130