1 package com.ericsson.research.transport.ws.spi;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 import java.io.IOException;
37 import java.io.OutputStream;
38 import java.util.Arrays;
39 import java.util.Random;
40
41 import com.ericsson.research.transport.ws.WSException;
42 import com.ericsson.research.trap.utils.Base64;
43
44 public class WSRfc6455Handshake extends WSAbstractHandshake implements WSConstants
45 {
46
47 protected static final String SERVER_PREAMBLE = HTTP11 + " 101 Switching Protocols";
48 protected static final Random random = new Random();
49 protected String key;
50
51 public WSRfc6455Handshake(WSAbstractProtocol protocol)
52 {
53 super(protocol);
54 }
55
56 public void sendHandshake(OutputStream os) throws IOException
57 {
58 StringBuffer h = new StringBuffer();
59 if (this.protocol.client)
60 {
61 h.append(GET);
62 h.append(" ");
63 h.append(this.protocol.resource);
64 h.append(" ");
65 h.append(HTTP11);
66 h.append(WSHixie75Handshake.COMMON_PART);
67 h.append(HOST_HEADER);
68 h.append(COLON_SPACE);
69 h.append(this.protocol.host);
70 if ((this.protocol.securityContext == null && this.protocol.port != 80) || (this.protocol.securityContext != null && this.protocol.port != 443))
71 {
72 h.append(":");
73 h.append(this.protocol.port);
74 }
75 h.append(CRLF);
76 h.append(ORIGIN_HEADER);
77 h.append(COLON_SPACE);
78 h.append(this.protocol.origin);
79 h.append(CRLF);
80 h.append(SEC_WEBSOCKET_VERSION_HEADER);
81 h.append(COLON_SPACE);
82 h.append(13);
83 h.append(CRLF);
84 h.append(SEC_WEBSOCKET_KEY_HEADER);
85 h.append(COLON_SPACE);
86 byte[] randomBytes = new byte[16];
87 random.nextBytes(randomBytes);
88 this.key = new String(Base64.encode(randomBytes));
89 h.append(this.key);
90 h.append(CRLFCRLF);
91 }
92 else
93 {
94 h.append(SERVER_PREAMBLE);
95 h.append(WSHixie75Handshake.COMMON_PART);
96 h.append(SEC_WEBSOCKET_ACCEPT_HEADER);
97 h.append(COLON_SPACE);
98 String nounceAndGUID = this.key + GUID;
99 try
100 {
101 byte[] sha1 = this.computeSHA1(nounceAndGUID);
102 h.append(Base64.encode(sha1));
103 h.append(CRLFCRLF);
104 }
105 catch (WSException e)
106 {
107 throw new IOException(e);
108 }
109 }
110 synchronized (os)
111 {
112 os.write(h.toString().getBytes(ISO_8859_1));
113 os.flush();
114 }
115 }
116
117 public void headersRead() throws WSException
118 {
119 if (this.protocol.client)
120 {
121 byte[] expected = this.computeSHA1(this.key + GUID);
122 if (this.getHeader(SEC_WEBSOCKET_ACCEPT_HEADER) == null)
123 throw new WSException("Missing " + SEC_WEBSOCKET_ACCEPT_HEADER + " header");
124 byte[] actual = Base64.decode(this.getHeader(SEC_WEBSOCKET_ACCEPT_HEADER));
125 if (!Arrays.equals(expected, actual))
126 throw new WSException("Failed to validate " + SEC_WEBSOCKET_ACCEPT_HEADER + " header value");
127 this.protocol.protocol = this.getHeader(SEC_WEBSOCKET_PROTOCOL_HEADER);
128 }
129 else
130 {
131 if (this.getHeader(HOST_HEADER) == null)
132 throw new WSException("Missing " + HOST_HEADER + " header");
133 if (!"13".equals(this.getHeader(SEC_WEBSOCKET_VERSION_HEADER)))
134 throw new WSException("Unsupported version " + this.getHeader(SEC_WEBSOCKET_VERSION_HEADER));
135 this.key = this.getHeader(SEC_WEBSOCKET_KEY_HEADER);
136 if (this.key == null)
137 throw new WSException("Missing " + SEC_WEBSOCKET_KEY_HEADER + " header");
138 }
139 }
140
141 }