1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43:
44: import ;
45: import ;
46:
47:
58: public final class Extension implements Builder, Constructed
59: {
60:
61:
62:
63:
64: private ByteBuffer buffer;
65:
66:
67:
68:
69: public Extension(final ByteBuffer buffer)
70: {
71: this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
72: }
73:
74: public Extension(final Type type, final Value value)
75: {
76: ByteBuffer valueBuffer = value.buffer();
77: int length = 2 + 2 + valueBuffer.remaining();
78: buffer = ByteBuffer.allocate(length);
79: buffer.putShort((short) type.getValue());
80: buffer.putShort((short) valueBuffer.remaining());
81: buffer.put(valueBuffer);
82: buffer.rewind();
83: }
84:
85:
86:
87:
88: public int length ()
89: {
90: return (buffer.getShort (2) & 0xFFFF) + 4;
91: }
92:
93: public ByteBuffer buffer()
94: {
95: return (ByteBuffer) buffer.duplicate().limit(length());
96: }
97:
98: public Type type()
99: {
100: return Type.forValue (buffer.getShort (0) & 0xFFFF);
101: }
102:
103: public byte[] valueBytes()
104: {
105: int len = buffer.getShort (2) & 0xFFFF;
106: byte[] value = new byte[len];
107: ((ByteBuffer) buffer.duplicate ().position (4)).get (value);
108: return value;
109: }
110:
111: public ByteBuffer valueBuffer()
112: {
113: int len = buffer.getShort(2) & 0xFFFF;
114: return ((ByteBuffer) buffer.duplicate().position(4).limit(len+4)).slice();
115: }
116:
117: public Value value()
118: {
119: switch (type ())
120: {
121: case SERVER_NAME:
122: return new ServerNameList(valueBuffer());
123:
124: case MAX_FRAGMENT_LENGTH:
125: switch (valueBuffer().get() & 0xFF)
126: {
127: case 1: return MaxFragmentLength.LEN_2_9;
128: case 2: return MaxFragmentLength.LEN_2_10;
129: case 3: return MaxFragmentLength.LEN_2_11;
130: case 4: return MaxFragmentLength.LEN_2_12;
131: default:
132: throw new IllegalArgumentException("invalid max_fragment_len");
133: }
134:
135: case TRUNCATED_HMAC:
136: return new TruncatedHMAC();
137:
138: case CLIENT_CERTIFICATE_URL:
139: return new CertificateURL(valueBuffer());
140:
141: case TRUSTED_CA_KEYS:
142: return new TrustedAuthorities(valueBuffer());
143:
144: case STATUS_REQUEST:
145: return new CertificateStatusRequest(valueBuffer());
146:
147: case SRP:
148: case CERT_TYPE:
149: }
150: return new UnresolvedExtensionValue(valueBuffer());
151: }
152:
153: public void setLength (final int newLength)
154: {
155: if (newLength < 0 || newLength > 65535)
156: throw new IllegalArgumentException ("length is out of bounds");
157: buffer.putShort (2, (short) newLength);
158: }
159:
160: public void setType (final Type type)
161: {
162: buffer.putShort(0, (short) type.getValue());
163: }
164:
165: public void setValue (byte[] value)
166: {
167: setValue (value, 0, value.length);
168: }
169:
170: public void setValue (final byte[] value, final int offset, final int length)
171: {
172: if (length != length ())
173: throw new IllegalArgumentException ("length is different than claimed length");
174: ((ByteBuffer) buffer.duplicate().position(4)).put(value, offset, length);
175: }
176:
177: public String toString()
178: {
179: return toString(null);
180: }
181:
182: public String toString(String prefix)
183: {
184: StringWriter str = new StringWriter();
185: PrintWriter out = new PrintWriter(str);
186: if (prefix != null) out.print (prefix);
187: out.println("struct {");
188: if (prefix != null) out.print (prefix);
189: out.println(" type = " + type () + ";");
190: if (prefix != null) out.print (prefix);
191: String subprefix = " ";
192: if (prefix != null) subprefix = prefix + subprefix;
193: out.println(" value =");
194: out.println(value().toString(subprefix));
195: if (prefix != null) out.print (prefix);
196: out.print("} Extension;");
197: return str.toString();
198: }
199:
200:
201:
202:
203: public static enum Type
204: {
205: SERVER_NAME (0),
206: MAX_FRAGMENT_LENGTH (1),
207: CLIENT_CERTIFICATE_URL (2),
208: TRUSTED_CA_KEYS (3),
209: TRUNCATED_HMAC (4),
210: STATUS_REQUEST (5),
211: SRP (6),
212: CERT_TYPE (7);
213:
214: private final int value;
215:
216: private Type(int value)
217: {
218: this.value = value;
219: }
220:
221: public static Type forValue (final int value)
222: {
223: switch (value & 0xFFFF)
224: {
225: case 0: return SERVER_NAME;
226: case 1: return MAX_FRAGMENT_LENGTH;
227: case 2: return CLIENT_CERTIFICATE_URL;
228: case 3: return TRUSTED_CA_KEYS;
229: case 4: return TRUNCATED_HMAC;
230: case 5: return STATUS_REQUEST;
231: case 6: return SRP;
232: case 7: return CERT_TYPE;
233: default: return null;
234: }
235: }
236:
237: public int getValue()
238: {
239: return value;
240: }
241: }
242:
243: public static abstract class Value implements Builder, Constructed
244: {
245: }
246: }