1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org) 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.xbill.DNS; 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.*; 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.text.*; 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.*; 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.utils.*; 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A generic DNS resource record. The specific record types extend this class. 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A record contains a name, type, class, ttl, and rdata. 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Brian Wellington 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic abstract class Record implements Cloneable, Comparable, Serializable { 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final long serialVersionUID = 2694906050116005466L; 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected Name name; 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected int type, dclass; 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected long ttl; 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final DecimalFormat byteFormat = new DecimalFormat(); 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic { 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byteFormat.setMinimumIntegerDigits(3); 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenRecord() {} 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenRecord(Name name, int type, int dclass, long ttl) { 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!name.isAbsolute()) 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new RelativeNameException(name); 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Type.check(type); 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DClass.check(dclass); 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen TTL.check(ttl); 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.name = name; 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.type = type; 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.dclass = dclass; 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.ttl = ttl; 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates an empty record of the correct type; must be overriden 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenabstract Record 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetObject(); 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final Record 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetEmptyRecord(Name name, int type, int dclass, long ttl, boolean hasData) { 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record proto, rec; 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (hasData) { 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen proto = Type.getProto(type); 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (proto != null) 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec = proto.getObject(); 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec = new UNKRecord(); 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec = new EmptyRecord(); 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec.name = name; 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec.type = type; 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec.dclass = dclass; 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec.ttl = ttl; 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return rec; 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the type-specific RR to wire format - must be overriden 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenabstract void 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrrFromWire(DNSInput in) throws IOException; 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static Record 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennewRecord(Name name, int type, int dclass, long ttl, int length, DNSInput in) 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenthrows IOException 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen{ 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record rec; 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec = getEmptyRecord(name, type, dclass, ttl, in != null); 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (in != null) { 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (in.remaining() < length) 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new WireParseException("truncated record"); 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen in.setActive(length); 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec.rrFromWire(in); 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (in.remaining() > 0) 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new WireParseException("invalid record length"); 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen in.clearActive(); 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return rec; 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new record, with the given parameters. 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The owner name of the record. 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The record's type. 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The record's class. 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ttl The record's time to live. 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param length The length of the record's data. 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param data The rdata of the record, in uncompressed DNS wire format. Only 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the first length bytes are used. 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennewRecord(Name name, int type, int dclass, long ttl, int length, byte [] data) { 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!name.isAbsolute()) 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new RelativeNameException(name); 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Type.check(type); 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DClass.check(dclass); 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen TTL.check(ttl); 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DNSInput in; 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (data != null) 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen in = new DNSInput(data); 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen in = null; 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return newRecord(name, type, dclass, ttl, length, in); 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (IOException e) { 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new record, with the given parameters. 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The owner name of the record. 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The record's type. 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The record's class. 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ttl The record's time to live. 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param data The complete rdata of the record, in uncompressed DNS wire 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * format. 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennewRecord(Name name, int type, int dclass, long ttl, byte [] data) { 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return newRecord(name, type, dclass, ttl, data.length, data); 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new empty record, with the given parameters. 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The owner name of the record. 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The record's type. 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The record's class. 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ttl The record's time to live. 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return An object of a subclass of Record 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennewRecord(Name name, int type, int dclass, long ttl) { 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!name.isAbsolute()) 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new RelativeNameException(name); 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Type.check(type); 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DClass.check(dclass); 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen TTL.check(ttl); 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return getEmptyRecord(name, type, dclass, ttl, false); 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new empty record, with the given parameters. This method is 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * designed to create records that will be added to the QUERY section 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * of a message. 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The owner name of the record. 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The record's type. 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The record's class. 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return An object of a subclass of Record 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennewRecord(Name name, int type, int dclass) { 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return newRecord(name, type, dclass, 0); 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic Record 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfromWire(DNSInput in, int section, boolean isUpdate) throws IOException { 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int type, dclass; 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen long ttl; 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int length; 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Name name; 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record rec; 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen name = new Name(in); 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen type = in.readU16(); 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen dclass = in.readU16(); 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (section == Section.QUESTION) 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return newRecord(name, type, dclass); 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ttl = in.readU32(); 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen length = in.readU16(); 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (length == 0 && isUpdate && 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen (section == Section.PREREQ || section == Section.UPDATE)) 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return newRecord(name, type, dclass, ttl); 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec = newRecord(name, type, dclass, ttl, length, in); 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return rec; 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic Record 200d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfromWire(DNSInput in, int section) throws IOException { 201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return fromWire(in, section, false); 202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Builds a Record from DNS uncompressed wire format. 206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record 208d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfromWire(byte [] b, int section) throws IOException { 209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return fromWire(new DNSInput(b), section, false); 210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenvoid 213d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWire(DNSOutput out, int section, Compression c) { 214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen name.toWire(out, c); 215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeU16(type); 216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeU16(dclass); 217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (section == Section.QUESTION) 218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeU32(ttl); 220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int lengthPosition = out.current(); 221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeU16(0); /* until we know better */ 222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rrToWire(out, c, false); 223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int rrlength = out.current() - lengthPosition - 2; 224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeU16At(rrlength, lengthPosition); 225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a Record into DNS uncompressed wire format. 229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte [] 231d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWire(int section) { 232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DNSOutput out = new DNSOutput(); 233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen toWire(out, section, null); 234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return out.toByteArray(); 235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void 238d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWireCanonical(DNSOutput out, boolean noTTL) { 239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen name.toWireCanonical(out); 240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeU16(type); 241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeU16(dclass); 242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (noTTL) { 243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeU32(0); 244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeU32(ttl); 246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int lengthPosition = out.current(); 248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeU16(0); /* until we know better */ 249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rrToWire(out, null, true); 250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int rrlength = out.current() - lengthPosition - 2; 251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.writeU16At(rrlength, lengthPosition); 252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* 255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a Record into canonical DNS uncompressed wire format (all names are 256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * converted to lowercase), optionally ignoring the TTL. 257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate byte [] 259d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWireCanonical(boolean noTTL) { 260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DNSOutput out = new DNSOutput(); 261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen toWireCanonical(out, noTTL); 262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return out.toByteArray(); 263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a Record into canonical DNS uncompressed wire format (all names are 267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * converted to lowercase). 268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte [] 270d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWireCanonical() { 271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return toWireCanonical(false); 272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the rdata in a Record into canonical DNS uncompressed wire format 276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (all names are converted to lowercase). 277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte [] 279d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrdataToWireCanonical() { 280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DNSOutput out = new DNSOutput(); 281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rrToWire(out, null, true); 282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return out.toByteArray(); 283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the type-specific RR to text format - must be overriden 287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenabstract String rrToString(); 289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the rdata portion of a Record into a String representation 292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic String 294d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrdataToString() { 295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return rrToString(); 296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a Record into a String representation 300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic String 302d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoString() { 303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringBuffer sb = new StringBuffer(); 304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(name); 305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sb.length() < 8) 306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append("\t"); 307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sb.length() < 16) 308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append("\t"); 309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append("\t"); 310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (Options.check("BINDTTL")) 311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(TTL.format(ttl)); 312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(ttl); 314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append("\t"); 315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (dclass != DClass.IN || !Options.check("noPrintIN")) { 316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(DClass.string(dclass)); 317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append("\t"); 318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(Type.string(type)); 320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String rdata = rrToString(); 321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!rdata.equals("")) { 322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append("\t"); 323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(rdata); 324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return sb.toString(); 326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the text format of an RR to the internal format - must be overriden 330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenabstract void 332d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrdataFromString(Tokenizer st, Name origin) throws IOException; 333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a String into a byte array. 336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected static byte [] 338d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenbyteArrayFromString(String s) throws TextParseException { 339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] array = s.getBytes(); 340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean escaped = false; 341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean hasEscapes = false; 342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < array.length; i++) { 344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (array[i] == '\\') { 345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen hasEscapes = true; 346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen break; 347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!hasEscapes) { 350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (array.length > 255) { 351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new TextParseException("text string too long"); 352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return array; 354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ByteArrayOutputStream os = new ByteArrayOutputStream(); 357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int digits = 0; 359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int intval = 0; 360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < array.length; i++) { 361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte b = array[i]; 362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (escaped) { 363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (b >= '0' && b <= '9' && digits < 3) { 364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen digits++; 365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen intval *= 10; 366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen intval += (b - '0'); 367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (intval > 255) 368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new TextParseException 369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ("bad escape"); 370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (digits < 3) 371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen continue; 372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen b = (byte) intval; 373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (digits > 0 && digits < 3) 375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new TextParseException("bad escape"); 376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen os.write(b); 377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen escaped = false; 378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (array[i] == '\\') { 380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen escaped = true; 381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen digits = 0; 382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen intval = 0; 383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen os.write(array[i]); 386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (digits > 0 && digits < 3) 388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new TextParseException("bad escape"); 389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen array = os.toByteArray(); 390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (array.length > 255) { 391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new TextParseException("text string too long"); 392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return os.toByteArray(); 395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a byte array into a String. 399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected static String 401d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenbyteArrayToString(byte [] array, boolean quote) { 402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringBuffer sb = new StringBuffer(); 403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (quote) 404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append('"'); 405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < array.length; i++) { 406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int b = array[i] & 0xFF; 407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (b < 0x20 || b >= 0x7f) { 408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append('\\'); 409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(byteFormat.format(b)); 410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (b == '"' || b == '\\') { 411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append('\\'); 412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append((char)b); 413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else 414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append((char)b); 415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (quote) 417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append('"'); 418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return sb.toString(); 419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a byte array into the unknown RR format. 423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected static String 425d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenunknownToString(byte [] data) { 426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringBuffer sb = new StringBuffer(); 427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append("\\# "); 428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(data.length); 429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(" "); 430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(base16.toString(data)); 431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return sb.toString(); 432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Builds a new Record from its textual representation 436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The owner name of the record. 437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The record's type. 438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The record's class. 439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ttl The record's time to live. 440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param st A tokenizer containing the textual representation of the rdata. 441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param origin The default origin to be appended to relative domain names. 442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The new record 443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException The text format was invalid. 444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record 446d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfromString(Name name, int type, int dclass, long ttl, Tokenizer st, Name origin) 447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenthrows IOException 448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen{ 449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record rec; 450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!name.isAbsolute()) 452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new RelativeNameException(name); 453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Type.check(type); 454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DClass.check(dclass); 455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen TTL.check(ttl); 456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Tokenizer.Token t = st.get(); 458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (t.type == Tokenizer.IDENTIFIER && t.value.equals("\\#")) { 459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int length = st.getUInt16(); 460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] data = st.getHex(); 461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (data == null) { 462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen data = new byte[0]; 463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (length != data.length) 465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw st.exception("invalid unknown RR encoding: " + 466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "length mismatch"); 467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DNSInput in = new DNSInput(data); 468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return newRecord(name, type, dclass, ttl, length, in); 469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen st.unget(); 471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec = getEmptyRecord(name, type, dclass, ttl, true); 472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec.rdataFromString(st, origin); 473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen t = st.get(); 474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (t.type != Tokenizer.EOL && t.type != Tokenizer.EOF) { 475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw st.exception("unexpected tokens at end of record"); 476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return rec; 478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Builds a new Record from its textual representation 482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The owner name of the record. 483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The record's type. 484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The record's class. 485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ttl The record's time to live. 486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param s The textual representation of the rdata. 487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param origin The default origin to be appended to relative domain names. 488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The new record 489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException The text format was invalid. 490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record 492d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfromString(Name name, int type, int dclass, long ttl, String s, Name origin) 493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenthrows IOException 494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen{ 495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return fromString(name, type, dclass, ttl, new Tokenizer(s), origin); 496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the record's name 500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Name 501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Name 503d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetName() { 504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return name; 505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the record's type 509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Type 510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int 512d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetType() { 513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return type; 514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 517d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the type of RRset that this record would belong to. For all types 518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * except RRSIG, this is equivalent to getType(). 519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The type of record, if not RRSIG. If the type is RRSIG, 520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the type covered is returned. 521d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Type 522d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see RRset 523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see SIGRecord 524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int 526d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetRRsetType() { 527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (type == Type.RRSIG) { 528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen RRSIGRecord sig = (RRSIGRecord) this; 529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return sig.getTypeCovered(); 530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return type; 532d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 534d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the record's class 536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int 538d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetDClass() { 539d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return dclass; 540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 541d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the record's TTL 544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic long 546d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetTTL() { 547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return ttl; 548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 550d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the type-specific RR to wire format - must be overriden 552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenabstract void 554d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrrToWire(DNSOutput out, Compression c, boolean canonical); 555d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Determines if two Records could be part of the same RRset. 558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This compares the name, type, and class of the Records; the ttl and 559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * rdata are not compared. 560d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 561d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic boolean 562d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensameRRset(Record rec) { 563d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (getRRsetType() == rec.getRRsetType() && 564d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen dclass == rec.dclass && 565d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen name.equals(rec.name)); 566d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 567d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 568d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 569d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Determines if two Records are identical. This compares the name, type, 570d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * class, and rdata (with names canonicalized). The TTLs are not compared. 571d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param arg The record to compare to 572d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return true if the records are equal, false otherwise. 573d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 574d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic boolean 575d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenequals(Object arg) { 576d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (arg == null || !(arg instanceof Record)) 577d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 578d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record r = (Record) arg; 579d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (type != r.type || dclass != r.dclass || !name.equals(r.name)) 580d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 581d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] array1 = rdataToWireCanonical(); 582d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] array2 = r.rdataToWireCanonical(); 583d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return Arrays.equals(array1, array2); 584d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 585d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 586d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 587d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Generates a hash code based on the Record's data. 588d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 589d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int 590d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenhashCode() { 591d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] array = toWireCanonical(true); 592d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int code = 0; 593d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < array.length; i++) 594d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen code += ((code << 3) + (array[i] & 0xFF)); 595d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return code; 596d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 597d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 598d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenRecord 599d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencloneRecord() { 600d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 601d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (Record) clone(); 602d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 603d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (CloneNotSupportedException e) { 604d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException(); 605d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 606d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 607d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 608d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 609d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new record identical to the current record, but with a different 610d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * name. This is most useful for replacing the name of a wildcard record. 611d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 612d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Record 613d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenwithName(Name name) { 614d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!name.isAbsolute()) 615d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new RelativeNameException(name); 616d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record rec = cloneRecord(); 617d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec.name = name; 618d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return rec; 619d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 620d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 621d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 622d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new record identical to the current record, but with a different 623d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * class and ttl. This is most useful for dynamic update. 624d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 625d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenRecord 626d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenwithDClass(int dclass, long ttl) { 627d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record rec = cloneRecord(); 628d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec.dclass = dclass; 629d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec.ttl = ttl; 630d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return rec; 631d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 632d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 633d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* Sets the TTL to the specified value. This is intentionally not public. */ 634d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenvoid 635d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetTTL(long ttl) { 636d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.ttl = ttl; 637d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 638d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 639d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 640d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Compares this Record to another Object. 641d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param o The Object to be compared. 642d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The value 0 if the argument is a record equivalent to this record; 643d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * a value less than 0 if the argument is less than this record in the 644d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * canonical ordering, and a value greater than 0 if the argument is greater 645d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * than this record in the canonical ordering. The canonical ordering 646d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is defined to compare by name, class, type, and rdata. 647d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws ClassCastException if the argument is not a Record. 648d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 649d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int 650d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencompareTo(Object o) { 651d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record arg = (Record) o; 652d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 653d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (this == arg) 654d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (0); 655d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 656d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int n = name.compareTo(arg.name); 657d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (n != 0) 658d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (n); 659d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen n = dclass - arg.dclass; 660d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (n != 0) 661d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (n); 662d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen n = type - arg.type; 663d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (n != 0) 664d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (n); 665d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] rdata1 = rdataToWireCanonical(); 666d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] rdata2 = arg.rdataToWireCanonical(); 667d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < rdata1.length && i < rdata2.length; i++) { 668d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen n = (rdata1[i] & 0xFF) - (rdata2[i] & 0xFF); 669d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (n != 0) 670d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (n); 671d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 672d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (rdata1.length - rdata2.length); 673d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 674d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 675d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 676d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the name for which additional data processing should be done 677d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * for this record. This can be used both for building responses and 678d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * parsing responses. 679d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The name to used for additional data processing, or null if this 680d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * record type does not require additional data processing. 681d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 682d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Name 683d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetAdditionalName() { 684d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 685d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 686d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 687d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* Checks that an int contains an unsigned 8 bit value */ 688d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic int 689d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencheckU8(String field, int val) { 690d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (val < 0 || val > 0xFF) 691d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("\"" + field + "\" " + val + 692d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen " must be an unsigned 8 " + 693d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "bit value"); 694d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return val; 695d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 696d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 697d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* Checks that an int contains an unsigned 16 bit value */ 698d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic int 699d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencheckU16(String field, int val) { 700d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (val < 0 || val > 0xFFFF) 701d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("\"" + field + "\" " + val + 702d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen " must be an unsigned 16 " + 703d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "bit value"); 704d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return val; 705d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 706d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 707d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* Checks that a long contains an unsigned 32 bit value */ 708d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic long 709d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencheckU32(String field, long val) { 710d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (val < 0 || val > 0xFFFFFFFFL) 711d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("\"" + field + "\" " + val + 712d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen " must be an unsigned 32 " + 713d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "bit value"); 714d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return val; 715d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 716d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 717d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* Checks that a name is absolute */ 718d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic Name 719d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencheckName(String field, Name name) { 720d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!name.isAbsolute()) 721d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new RelativeNameException(name); 722d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return name; 723d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 724d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 725d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic byte [] 726d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencheckByteArrayLength(String field, byte [] array, int maxLength) { 727d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (array.length > 0xFFFF) 728d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("\"" + field + "\" array " + 729d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "must have no more than " + 730d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen maxLength + " elements"); 731d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] out = new byte[array.length]; 732d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.arraycopy(array, 0, out, 0, array.length); 733d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return out; 734d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 735d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 736d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 737