OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / javax / net / ssl / provider / ServerHello.java
1 /* ServerHello.java -- SSL ServerHello message.
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
46 /**
47  * The server hello message.
48  *
49  * <pre>
50 struct
51 {
52   ProtocolVersion server_version;
53   Random random;
54   SessionID session_id;
55   CipherSuite cipher_suite;
56   CompressionMethod compression_method;
57   Extensions server_hello_extension_list&lt;0..2^16-1&gt;
58 } ServerHello;
59 </pre>
60  *
61  * <p>Server hello messages may contain extra data after the
62  * <tt>compression_method</tt> field, which are interpreted as
63  * extensions to the basic handshake.
64  */
65 public class ServerHello implements Handshake.Body
66 {
67
68   // Fields.
69   // -------------------------------------------------------------------------
70
71   protected static final int RANDOM_OFFSET = 2;
72   protected static final int SESSID_OFFSET = 32 + RANDOM_OFFSET;
73   protected static final int SESSID_OFFSET2 = SESSID_OFFSET + 1;
74
75   protected ByteBuffer buffer;
76   protected boolean disableExtensions;
77   
78   // Constructor.
79   // -------------------------------------------------------------------------
80
81   public ServerHello (final ByteBuffer buffer)
82   {
83     this.buffer = buffer;
84     disableExtensions = false;
85   }
86
87   public int length ()
88   {
89     int sessionLen = buffer.get(SESSID_OFFSET) & 0xFF;
90     int len = SESSID_OFFSET2 + sessionLen + 3;
91     int elen = 0;
92     if (!disableExtensions && len + 1 < buffer.limit()
93         && (elen = buffer.getShort(len)) != 0)
94       len += 2 + elen;
95     return len;
96   }
97
98   /**
99    * Returns the server's protocol version. This will read two bytes
100    * from the beginning of the underlying buffer, and return an
101    * instance of the appropriate {@link ProtocolVersion}; if the
102    * version read is a supported version, this method returns a static
103    * constant instance.
104    *
105    * @return The server's protocol version.
106    */
107   public ProtocolVersion version()
108   {
109     return ProtocolVersion.getInstance (buffer.getShort (0));
110   }
111
112   /**
113    * Returns the server's random value. This method returns a
114    * lightwieght wrapper around the existing bytes; modifications to
115    * the underlying buffer will modify the returned object, and
116    * vice-versa.
117    *
118    * @return The server's random value.
119    */
120   public Random random()
121   {
122     ByteBuffer randomBuf =
123       ((ByteBuffer) buffer.duplicate ().position (RANDOM_OFFSET)
124        .limit (SESSID_OFFSET)).slice ();
125     return new Random (randomBuf);
126   }
127
128   /**
129    * Returns the session ID. This method returns a new byte array with
130    * the session ID bytes.
131    *
132    * @return The session ID.
133    */
134   public byte[] sessionId()
135   {
136     int idlen = buffer.get (SESSID_OFFSET) & 0xFF;
137     byte[] sessionId = new byte[idlen];
138     buffer.position (SESSID_OFFSET2);
139     buffer.get (sessionId);
140     return sessionId;
141   }
142
143   /**
144    * Returns the server's chosen cipher suite. The returned cipher
145    * suite will be "resolved" to this structure's version.
146    *
147    * @return The server's chosen cipher suite.
148    */
149   public CipherSuite cipherSuite()
150   {
151     int offset = SESSID_OFFSET2 + (buffer.get(SESSID_OFFSET) & 0xFF);
152     return CipherSuite.forValue(buffer.getShort(offset)).resolve();
153   }
154
155   /**
156    * Returns the server's chosen compression method.
157    *
158    * @return The chosen compression method.
159    */
160   public CompressionMethod compressionMethod()
161   {
162     int offset = SESSID_OFFSET2 + (buffer.get(SESSID_OFFSET) & 0xFF) + 2;
163     return CompressionMethod.getInstance(buffer.get(offset) & 0xFF);
164   }
165
166   public int extensionsLength()
167   {
168     int offset = SESSID_OFFSET2 + (buffer.get (SESSID_OFFSET) & 0xFF) + 3;
169     if (offset + 1 >= buffer.limit())
170       return 0;
171     return buffer.getShort(offset) & 0xFFFF;
172   }
173   
174   public ExtensionList extensions ()
175   {
176     int offset = SESSID_OFFSET2 + (buffer.get (SESSID_OFFSET) & 0xFF) + 3;
177     if (offset + 1 >= buffer.limit())
178       return null;
179     int len = buffer.getShort(offset) & 0xFFFF;
180     if (len == 0)
181       len = buffer.limit() - offset - 2;
182     ByteBuffer ebuf = ((ByteBuffer) buffer.duplicate().position(offset)
183                        .limit(offset + len + 2)).slice();
184     return new ExtensionList(ebuf);
185   }
186
187   public String toString()
188   {
189     return toString(null);
190   }
191
192   public String toString (final String prefix)
193   {
194     StringWriter str = new StringWriter();
195     PrintWriter out = new PrintWriter(str);
196     if (prefix != null)
197       out.print (prefix);
198     out.println ("struct {");
199     String subprefix = "  ";
200     if (prefix != null)
201       subprefix += prefix;
202     out.print (subprefix);
203     out.print ("version: ");
204     out.print (version ());
205     out.println (";");
206     out.print (subprefix);
207     out.println ("random:");
208     out.println (random ().toString (subprefix));
209     out.print (subprefix);
210     out.print ("sessionId:         ");
211     out.print (Util.toHexString(sessionId (), ':'));
212     out.println (";");
213     out.print (subprefix);
214     out.print ("cipherSuite:       ");
215     out.print (cipherSuite ());
216     out.println (";");
217     out.print (subprefix);
218     out.print ("compressionMethod: ");
219     out.print (compressionMethod ());
220     out.println (";");
221     ExtensionList exts = extensions ();
222     out.print (subprefix);
223     out.println ("extensions:");
224     out.println (exts != null ? exts.toString (subprefix+"  ")
225                                 : subprefix + "  (nil)");
226     if (prefix != null)
227       out.print (prefix);
228     out.print ("} ServerHello;");
229     return str.toString();
230   }
231 }