1 4 package com.tc.net.protocol; 5 6 import com.tc.bytes.TCByteBuffer; 7 import com.tc.bytes.TCByteBufferFactory; 8 import com.tc.util.Assert; 9 10 import java.util.zip.Adler32 ; 11 12 17 public abstract class AbstractTCNetworkHeader implements TCNetworkHeader { 18 protected static final int LENGTH_NOT_AVAIL = -1; 19 20 private static final byte[] EMTPY_BYTE_ARRAY = new byte[] {}; 21 private static final byte[] FOUR_ZERO_BYTES = new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0 }; 22 23 protected final int minLength; 24 protected final int maxLength; 25 protected TCByteBuffer data; 26 private final boolean localAllocation; 27 28 abstract protected void setHeaderLength(short headerLength); 29 30 36 protected boolean isHeaderLengthAvail() { 37 return true; 38 } 39 40 protected AbstractTCNetworkHeader(TCByteBuffer buffer, int min, int max) { 41 this.minLength = min; 42 this.maxLength = max; 43 44 if (buffer == null) { 45 this.data = TCByteBufferFactory.getInstance(false, max); 46 this.data.limit(min); 47 localAllocation = true; 48 } else { 49 this.data = buffer; 50 localAllocation = false; 51 } 52 53 Assert.eval(!this.data.isDirect()); 54 Assert.eval(this.data.capacity() >= this.maxLength); 55 if (this.data.limit() % 4 != 0) { throw new AssertionError ("buffer limit not a multiple of 4: " + this.data.limit()); } 56 } 57 58 protected AbstractTCNetworkHeader(int min, int max) { 59 this(null, min, max); 60 } 61 62 public TCByteBuffer getDataBuffer() { 63 return data; 64 } 65 66 abstract public void validate() throws TCProtocolException; 67 68 public void recycle() { 69 Assert.assertTrue(localAllocation); 70 if(data != null) { 71 data.recycle(); 72 data = null; 73 } 74 else { 75 Thread.dumpStack(); 77 } 78 } 79 80 private void setBytes(int pos, byte[] value) { 81 setBytes(pos, value, 0, value.length); 82 } 83 84 private void setBytes(int pos, byte[] value, int offset, int length) { 85 data.put(pos, value, offset, length); 86 } 87 88 protected byte getByte(int index) { 89 return data.get(index); 90 } 91 92 protected byte[] getBytes(int offset, int len) { 93 Assert.eval(len >= 0); 94 95 if (0 == len) { return EMTPY_BYTE_ARRAY; } 96 97 byte rv[] = new byte[len]; 98 data.get(offset, rv, 0, len); 99 100 return rv; 101 } 102 103 protected void set4BitValue(int pos, boolean high, byte value) { 104 byte other4 = (byte) (data.get(pos) & (high ? 0x0F : 0xF0)); 105 byte val = (byte) ((value << (high ? 4 : 0)) & (high ? 0xF0 : 0x0F)); 106 107 data.put(pos, (byte) (val | other4)); 108 } 109 110 protected byte get4BitValue(int pos, boolean high) { 111 byte bite = getByte(pos); 112 113 if (high) { 114 return (byte) ((bite >> 4) & 0x0F); 115 } else { 116 return (byte) (bite & 0x0F); 117 } 118 } 119 120 protected long computeAdler32Checksum(int pos, boolean set) { 121 Adler32 adler = new Adler32 (); 122 123 byte cksum[] = getBytes(pos, 4); 125 126 setBytes(pos, FOUR_ZERO_BYTES); 128 adler.update(data.array(), 0, getHeaderByteLength()); 129 130 long rv = adler.getValue(); 131 132 if (set) { 133 data.putUint(pos, rv); 134 } else { 135 setBytes(pos, cksum); 137 } 138 139 return rv; 140 } 141 142 protected void setLimit(int newLimit) { 143 data.limit(newLimit); 144 } 145 146 150 public void setOptions(byte[] options) { 151 if (options == null) { 152 options = new byte[] {}; 153 } 154 155 int optionsLen = options.length; 156 157 Assert.eval((optionsLen % 4) == 0); 158 Assert.eval(optionsLen <= (maxLength - minLength)); 159 160 if (optionsLen > 0) { 161 setLimit(minLength + optionsLen); 162 setBytes(minLength, options); 163 } else { 164 setLimit(minLength); 165 } 166 167 setHeaderLength((byte) ((minLength + optionsLen) / 4)); 168 } 169 170 public byte[] getOptions() { 171 return getBytes(minLength, getHeaderByteLength() - minLength); 172 } 173 174 } | Popular Tags |