diff options
author | Casey Marshall <csm@gnu.org> | 2006-06-06 01:01:19 +0000 |
---|---|---|
committer | Casey Marshall <csm@gnu.org> | 2006-06-06 01:01:19 +0000 |
commit | 61dcae3967de896a92e7e61754738b1c80ed5482 (patch) | |
tree | 7463efff3f3fe4d2265219abc6275c3ebbd68f86 | |
parent | 6ed1dcd5f536296e20cf30c98e96067f6bf0148b (diff) | |
download | classpath-61dcae3967de896a92e7e61754738b1c80ed5482.tar.gz |
2006-06-05 Casey Marshall <csm@gnu.org>
* gnu/javax/net/ssl/provider/Extension.java: add Javadoc.
(length): return the length of the extension value.
(setLength, setType, setValue, setValue): new methods.
* gnu/javax/net/ssl/provider/ExtensionList.java: new file.
* jessie-tests/run-tests.sh: add testExtensionList.
* jessie-tests/testExtensionList.java: new file.
-rw-r--r-- | ChangeLog-ssl-nio | 12 | ||||
-rw-r--r-- | gnu/javax/net/ssl/provider/Extension.java | 37 | ||||
-rw-r--r-- | gnu/javax/net/ssl/provider/ExtensionList.java | 270 | ||||
-rw-r--r-- | jessie-tests/run-tests.sh | 2 |
4 files changed, 317 insertions, 4 deletions
diff --git a/ChangeLog-ssl-nio b/ChangeLog-ssl-nio index b1fa00f70..ffca8bdac 100644 --- a/ChangeLog-ssl-nio +++ b/ChangeLog-ssl-nio @@ -1,4 +1,13 @@ -2006-06-05 Casey Marshall <csm@gnu.org> +2006-06-05 Casey Marshall <csm@gnu.org> + + * gnu/javax/net/ssl/provider/Extension.java: add Javadoc. + (length): return the length of the extension value. + (setLength, setType, setValue, setValue): new methods. + * gnu/javax/net/ssl/provider/ExtensionList.java: new file. + * jessie-tests/run-tests.sh: add testExtensionList. + * jessie-tests/testExtensionList.java: new file. + +2006-06-05 Casey Marshall <csm@gnu.org> * gnu/javax/net/ssl/provider/CipherSuiteList.java: implement Iterable<CipherSuite>. @@ -20,4 +29,3 @@ * gnu/javax/net/ssl/provider/ServerHelloDone.java: made public. * jessie-tests/run-tests.sh: add `testServerHelloDone.' * jessie-tests/testServerHelloDone.java: new test. - diff --git a/gnu/javax/net/ssl/provider/Extension.java b/gnu/javax/net/ssl/provider/Extension.java index fda5e11bd..9e2b69e3b 100644 --- a/gnu/javax/net/ssl/provider/Extension.java +++ b/gnu/javax/net/ssl/provider/Extension.java @@ -43,6 +43,17 @@ import java.io.StringWriter; import java.nio.ByteBuffer; +/** + * An SSL hello extension. + * + * <pre> + * struct { + * ExtensionType extension_type; + * opaque extension_data<0..2^16-1>; + * } Extension;</pre> + * + * @author csm@gnu.org + */ public final class Extension implements Constructed { @@ -64,7 +75,7 @@ public final class Extension implements Constructed public int length () { - return (buffer.getShort (2) & 0xFFFF) + 4; + return (buffer.getShort (2) & 0xFFFF); } public Type type() @@ -79,7 +90,31 @@ public final class Extension implements Constructed ((ByteBuffer) buffer.duplicate ().position (4)).get (value); return value; } + + public void setLength (final int newLength) + { + if (newLength < 0 || newLength > 65535) + throw new IllegalArgumentException ("length is out of bounds"); + buffer.putShort (2, (short) newLength); + } + + public void setType (final Type type) + { + buffer.putShort(0, (short) type.getValue()); + } + public void setValue (byte[] value) + { + setValue (value, 0, value.length); + } + + public void setValue (final byte[] value, final int offset, final int length) + { + if (length != length ()) + throw new IllegalArgumentException ("length is different than claimed length"); + ((ByteBuffer) buffer.duplicate().position(4)).put(value, offset, length); + } + public String toString() { return toString(null); diff --git a/gnu/javax/net/ssl/provider/ExtensionList.java b/gnu/javax/net/ssl/provider/ExtensionList.java new file mode 100644 index 000000000..ddb104491 --- /dev/null +++ b/gnu/javax/net/ssl/provider/ExtensionList.java @@ -0,0 +1,270 @@ +package gnu.javax.net.ssl.provider; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.ByteBuffer; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.ListIterator; +import java.util.NoSuchElementException; + +/** + * A list of extensions, that may appear in either the {@link ClientHello} or + * {@link ServerHello}. The form of the extensions list is: + * + * <tt> Extension extensions_list<1..2^16-1></tt> + * + * @author csm + */ +public class ExtensionList implements Iterable<Extension> +{ + private final ByteBuffer buffer; + private int modCount; + + public ExtensionList (ByteBuffer buffer) + { + this.buffer = buffer; + modCount = 0; + } + + public Extension get (final int index) + { + int length = length (); + int i; + int n = 0; + for (i = 2; i < length && n < index; ) + { + int l = buffer.getShort (i+2) & 0xFFFF; + i += l + 4; + n++; + } + if (n < index) + throw new IndexOutOfBoundsException ("no elemenet at " + index); + int el = buffer.getShort (i+2) & 0xFFFF; + return new Extension (((ByteBuffer) buffer.duplicate().position(i).limit(i+el+4)).slice()); + } + + /** + * Returns the number of extensions this list contains. + * + * @return The number of extensions. + */ + public int size () + { + int length = length (); + if (length == 0) + return 0; + int n = 0; + for (int i = 2; i < length; ) + { + int len = buffer.getShort (i+2) & 0xFFFF; + i += len + 4; + n++; + } + return n; + } + + /** + * Returns the length of this extension list, in bytes. + * + * @return The length of this extension list, in bytes. + */ + public int length () + { + return buffer.getShort (0) & 0xFFFF; + } + + /** + * Sets the extension at index <i>i</i> to <i>e</i>. Note that setting an + * element at an index <b>may</b> invalidate any other elements that come + * after element at index <i>i</i>. In other words, no attempt is made to + * move existing elements in this list, and since extensions are variable + * length, you can <em>not</em> guarantee that extensions later in the list + * will still be valid. + * + * <p>Thus, elements of this list <b>must</b> be set in order of increasing + * index. + * + * @param index The index to set the extension at. + * @param e The extension. + * @throws java.nio.BufferOverflowException If setting the extension overflows + * the buffer. + * @throws IllegalArgumentException If it isn't possible to find the given index + * in the current list (say, if no element index - 1 is set), or if setting + * the extension will overflow the current list length (given by {@link + * #length()}). + */ + public void set (final int index, Extension e) + { + int length = length(); + int n = 0; + int i; + for (i = 2; i < length && n < index; ) + { + int len = buffer.getShort(i+2) & 0xFFFF; + i += len + 4; + n++; + } + if (n < index) + throw new IllegalArgumentException("nothing set at index " + (index-1) + + " or insufficient space"); + if (i + e.length() + 2 > length) + throw new IllegalArgumentException("adding this element will exceed the " + + "list length"); + buffer.putShort(i, (short) e.type().getValue()); + buffer.putShort(i+2, (short) e.length()); + ((ByteBuffer) buffer.duplicate().position(i+4)).put (e.value()); + modCount++; + } + + /** + * Reserve space for an extension at index <i>i</i> in the list. In other + * words, this does the job of {@link #set(int, Extension)}, but does not + * copy the extension value to the underlying buffer. + * + * @param index The index of the extension to reserve space for. + * @param t The type of the extension. + * @param eLength The number of bytes to reserve for this extension. The total + * number of bytes used by this method is this length, plus four. + */ + public void set (final int index, Extension.Type t, final int eLength) + { + int length = length (); + int n = 0; + int i; + for (i = 2; i < length && n < index; ) + { + int len = buffer.getShort (i+2) & 0xFFFF; + i += len + 4; + n++; + } + if (n < index) + throw new IllegalArgumentException ("nothing set at index " + (index-1) + + " or insufficient space"); + if (i + eLength + 2 > length) + throw new IllegalArgumentException ("adding this element will exceed the " + + "list length"); + buffer.putShort(i, (short) t.getValue()); + buffer.putShort(i+2, (short) eLength); + modCount++; + } + + /** + * Set the total length of this list, in bytes. + * + * @param newLength The new list length. + */ + public void setLength (final int newLength) + { + if (newLength < 0 || newLength > 65535) + throw new IllegalArgumentException ("invalid length"); + buffer.putShort (0, (short) newLength); + modCount++; + } + + public Iterator<Extension> iterator() + { + return new ExtensionsIterator (); + } + + public String toString () + { + return toString (null); + } + + public String toString (final String prefix) + { + StringWriter str = new StringWriter (); + PrintWriter out = new PrintWriter (str); + if (prefix != null) out.print (prefix); + out.println ("ExtensionList {"); + if (prefix != null) out.print (prefix); + out.print (" length = "); + out.print (length ()); + out.println (";"); + String subprefix = " "; + if (prefix != null) + subprefix = prefix + subprefix; + for (Extension e : this) + out.println (e.toString(subprefix)); + if (prefix != null) out.print (prefix); + out.println ("};"); + return str.toString(); + } + + /** + * List iterator interface to an extensions list. + * + * @author csm@gnu.org + */ + public final class ExtensionsIterator implements ListIterator<Extension> + { + private final int modCount; + private int index; + private final int size; + + public ExtensionsIterator () + { + this.modCount = ExtensionList.this.modCount; + index = 0; + size = size (); + } + + public boolean hasNext() + { + return index < size; + } + + public boolean hasPrevious() + { + return index > 0; + } + + public Extension next() throws NoSuchElementException + { + if (modCount != ExtensionList.this.modCount) + throw new ConcurrentModificationException (); + if (!hasNext ()) + throw new NoSuchElementException (); + return get (index++); + } + + public Extension previous() throws NoSuchElementException + { + if (modCount != ExtensionList.this.modCount) + throw new ConcurrentModificationException (); + if (!hasPrevious ()) + throw new NoSuchElementException (); + return get (--index); + } + + public int nextIndex() + { + if (hasNext ()) + return index + 1; + return index; + } + + public int previousIndex() + { + if (hasPrevious ()) + return index - 1; + return -1; + } + + public void add(Extension e) + { + throw new UnsupportedOperationException ("cannot add items to this iterator"); + } + + public void remove() + { + throw new UnsupportedOperationException ("cannot remove items from this iterator"); + } + + public void set(Extension e) + { + ExtensionList.this.set (index, e); + } + } +} diff --git a/jessie-tests/run-tests.sh b/jessie-tests/run-tests.sh index c61e06fa9..d4a3dd499 100644 --- a/jessie-tests/run-tests.sh +++ b/jessie-tests/run-tests.sh @@ -7,7 +7,7 @@ test -z "$CLASSPATH" && export CLASSPATH=. tests="testAlert testCertificate testCertificateRequest \ testCipherSuiteList testClientHello testCompressionMethodList \ - testHelloRequest testRecord testServerDHParams \ + testExtensionList testHelloRequest testRecord testServerDHParams \ testServerHello testServerHelloDone testServerKeyExchange \ testServerRSAParams testSignature" |