Home | History | Annotate | Download | only in DNS
      1 // Copyright (c) 2004-2009 Brian Wellington (bwelling (at) xbill.org)
      2 
      3 package org.xbill.DNS;
      4 
      5 /**
      6  * Routines for deal with the lists of types found in NSEC/NSEC3 records.
      7  *
      8  * @author Brian Wellington
      9  */
     10 
     11 import java.io.*;
     12 import java.util.*;
     13 
     14 final class TypeBitmap implements Serializable {
     15 
     16 private static final long serialVersionUID = -125354057735389003L;
     17 
     18 private TreeSet types;
     19 
     20 private
     21 TypeBitmap() {
     22 	types = new TreeSet();
     23 }
     24 
     25 public
     26 TypeBitmap(int [] array) {
     27 	this();
     28 	for (int i = 0; i < array.length; i++) {
     29 		Type.check(array[i]);
     30 		types.add(new Integer(array[i]));
     31 	}
     32 }
     33 
     34 public
     35 TypeBitmap(DNSInput in) throws WireParseException {
     36 	this();
     37 	int lastbase = -1;
     38 	while (in.remaining() > 0) {
     39 		if (in.remaining() < 2)
     40 			throw new WireParseException
     41 				("invalid bitmap descriptor");
     42 		int mapbase = in.readU8();
     43 		if (mapbase < lastbase)
     44 			throw new WireParseException("invalid ordering");
     45 		int maplength = in.readU8();
     46 		if (maplength > in.remaining())
     47 			throw new WireParseException("invalid bitmap");
     48 		for (int i = 0; i < maplength; i++) {
     49 			int current = in.readU8();
     50 			if (current == 0)
     51 				continue;
     52 			for (int j = 0; j < 8; j++) {
     53 				if ((current & (1 << (7 - j))) == 0)
     54 					continue;
     55 				int typecode = mapbase * 256 + + i * 8 + j;
     56 				types.add(Mnemonic.toInteger(typecode));
     57 			}
     58 		}
     59 	}
     60 }
     61 
     62 public
     63 TypeBitmap(Tokenizer st) throws IOException {
     64 	this();
     65 	while (true) {
     66 		Tokenizer.Token t = st.get();
     67 		if (!t.isString())
     68 			break;
     69 		int typecode = Type.value(t.value);
     70 		if (typecode < 0) {
     71 			throw st.exception("Invalid type: " + t.value);
     72 		}
     73 		types.add(Mnemonic.toInteger(typecode));
     74 	}
     75 	st.unget();
     76 }
     77 
     78 public int []
     79 toArray() {
     80 	int [] array = new int[types.size()];
     81 	int n = 0;
     82 	for (Iterator it = types.iterator(); it.hasNext(); )
     83 		array[n++] = ((Integer)it.next()).intValue();
     84 	return array;
     85 }
     86 
     87 public String
     88 toString() {
     89 	StringBuffer sb = new StringBuffer();
     90 	for (Iterator it = types.iterator(); it.hasNext(); ) {
     91 		int t = ((Integer)it.next()).intValue();
     92 		sb.append(Type.string(t));
     93 		if (it.hasNext())
     94 			sb.append(' ');
     95 	}
     96 	return sb.toString();
     97 }
     98 
     99 private static void
    100 mapToWire(DNSOutput out, TreeSet map, int mapbase) {
    101 	int arraymax = (((Integer)map.last()).intValue()) & 0xFF;
    102 	int arraylength = (arraymax / 8) + 1;
    103 	int [] array = new int[arraylength];
    104 	out.writeU8(mapbase);
    105 	out.writeU8(arraylength);
    106 	for (Iterator it = map.iterator(); it.hasNext(); ) {
    107 		int typecode = ((Integer)it.next()).intValue();
    108 		array[(typecode & 0xFF) / 8] |= (1 << ( 7 - typecode % 8));
    109 	}
    110 	for (int j = 0; j < arraylength; j++)
    111 		out.writeU8(array[j]);
    112 }
    113 
    114 public void
    115 toWire(DNSOutput out) {
    116 	if (types.size() == 0)
    117 		return;
    118 
    119 	int mapbase = -1;
    120 	TreeSet map = new TreeSet();
    121 
    122 	for (Iterator it = types.iterator(); it.hasNext(); ) {
    123 		int t = ((Integer)it.next()).intValue();
    124 		int base = t >> 8;
    125 		if (base != mapbase) {
    126 			if (map.size() > 0) {
    127 				mapToWire(out, map, mapbase);
    128 				map.clear();
    129 			}
    130 			mapbase = base;
    131 		}
    132 			map.add(new Integer(t));
    133 	}
    134 	mapToWire(out, map, mapbase);
    135 }
    136 
    137 public boolean
    138 empty() {
    139 	return types.isEmpty();
    140 }
    141 
    142 public boolean
    143 contains(int typecode) {
    144 	return types.contains(Mnemonic.toInteger(typecode));
    145 }
    146 
    147 }
    148