OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / javax / net / ssl / provider / Extension.java
1 /* Extension.java -- A TLS hello extension.
2    Copyright (C) 2006  Free Software Foundation, Inc.
3
4 This file is a part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at
9 your option) any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 USA
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version.  */
37
38
39 package gnu.javax.net.ssl.provider;
40
41 import java.io.PrintWriter;
42 import java.io.StringWriter;
43
44 import java.nio.ByteBuffer;
45 import java.nio.ByteOrder;
46
47 /**
48  * An SSL hello extension.
49  * 
50  * <pre>
51  * struct {
52  *   ExtensionType extension_type;
53  *   opaque extension_data<0..2^16-1>;
54  * } Extension;</pre>
55  * 
56  * @author csm@gnu.org
57  */
58 public final class Extension implements Builder, Constructed
59 {
60
61   // Fields.
62   // -------------------------------------------------------------------------
63
64   private ByteBuffer buffer;
65
66   // Constructor.
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   // Instance methods.
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   // Inner classes.
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 }