@@ -95,11 +95,18 @@ protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput
95
95
IoBuffer resultBuffer ;
96
96
WebSocketConnection conn = (WebSocketConnection ) session .getAttribute (Constants .CONNECTION );
97
97
if (conn == null ) {
98
+ log .debug ("Decode start pos: {}" , in .position ());
98
99
// first message on a new connection, check if its from a websocket or a native socket
99
100
if (doHandShake (session , in )) {
101
+ log .debug ("Decode end pos: {} limit: {}" , in .position (), in .limit ());
100
102
// websocket handshake was successful. Don't write anything to output as we want to abstract the handshake request message from the handler
101
- in .position (in .limit ());
103
+ if (in .position () != in .limit ()) {
104
+ in .position (in .limit ());
105
+ }
102
106
return true ;
107
+ } else if (session .containsAttribute (Constants .WS_HANDSHAKE )) {
108
+ // more still expected to come in before HS is completed
109
+ return false ;
103
110
} else {
104
111
// message is from a native socket. Simply wrap and pass through
105
112
resultBuffer = IoBuffer .wrap (in .array (), 0 , in .limit ());
@@ -145,14 +152,40 @@ protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput
145
152
*/
146
153
@ SuppressWarnings ("unchecked" )
147
154
private boolean doHandShake (IoSession session , IoBuffer in ) {
155
+ if (log .isDebugEnabled ()) {
156
+ log .debug ("Handshake: {}" , in );
157
+ }
158
+ // incoming data
159
+ byte [] data = null ;
160
+ // check for existing HS data
161
+ if (session .containsAttribute (Constants .WS_HANDSHAKE )) {
162
+ byte [] tmp = (byte []) session .getAttribute (Constants .WS_HANDSHAKE );
163
+ // size to hold existing and incoming
164
+ data = new byte [tmp .length + in .remaining ()];
165
+ System .arraycopy (tmp , 0 , data , 0 , tmp .length );
166
+ // get incoming bytes
167
+ in .get (data , tmp .length , in .remaining ());
168
+ } else {
169
+ // size for incoming bytes
170
+ data = new byte [in .remaining ()];
171
+ // get incoming bytes
172
+ in .get (data , 0 , data .length );
173
+ }
174
+ // ensure the incoming data is complete (ends with crlfcrlf)
175
+ byte [] tail = Arrays .copyOfRange (data , data .length - 4 , data .length );
176
+ if (!Arrays .equals (tail , Constants .END_OF_REQ )) {
177
+ // accumulate the HS data
178
+ session .setAttribute (Constants .WS_HANDSHAKE , data );
179
+ return false ;
180
+ }
148
181
// create the connection obj
149
182
WebSocketConnection conn = new WebSocketConnection (session );
150
183
// mark as secure if using ssl
151
184
if (session .getFilterChain ().contains ("sslFilter" )) {
152
185
conn .setSecure (true );
153
186
}
154
187
try {
155
- Map <String , Object > headers = parseClientRequest (conn , new String (in . array () ));
188
+ Map <String , Object > headers = parseClientRequest (conn , new String (data ));
156
189
if (log .isTraceEnabled ()) {
157
190
log .trace ("Header map: {}" , headers );
158
191
}
@@ -206,6 +239,8 @@ private boolean doHandShake(IoSession session, IoBuffer in) {
206
239
// prepare response and write it to the directly to the session
207
240
HandshakeResponse wsResponse = buildHandshakeResponse (conn , (String ) headers .get (Constants .WS_HEADER_KEY ));
208
241
session .write (wsResponse );
242
+ // remove handshake acculator
243
+ session .removeAttribute (Constants .WS_HANDSHAKE );
209
244
log .debug ("Handshake complete" );
210
245
return true ;
211
246
}
@@ -231,7 +266,7 @@ private Map<String, Object> parseClientRequest(WebSocketConnection conn, String
231
266
if (log .isTraceEnabled ()) {
232
267
log .trace ("Request: {}" , Arrays .toString (request ));
233
268
}
234
- Map <String , Object > map = new HashMap <String , Object >();
269
+ Map <String , Object > map = new HashMap <>();
235
270
for (int i = 0 ; i < request .length ; i ++) {
236
271
log .trace ("Request {}: {}" , i , request [i ]);
237
272
if (request [i ].startsWith ("GET " ) || request [i ].startsWith ("POST " ) || request [i ].startsWith ("PUT " )) {
@@ -291,7 +326,7 @@ public void operationComplete(IoFuture future) {
291
326
});
292
327
throw new WebSocketException ("Handshake failed, missing plugin" );
293
328
}
294
- }else if (request [i ].contains (Constants .WS_HEADER_KEY )) {
329
+ } else if (request [i ].contains (Constants .WS_HEADER_KEY )) {
295
330
map .put (Constants .WS_HEADER_KEY , extractHeaderValue (request [i ]));
296
331
} else if (request [i ].contains (Constants .WS_HEADER_VERSION )) {
297
332
map .put (Constants .WS_HEADER_VERSION , extractHeaderValue (request [i ]));
@@ -307,26 +342,22 @@ public void operationComplete(IoFuture future) {
307
342
conn .setOrigin (extractHeaderValue (request [i ]));
308
343
} else if (request [i ].contains (Constants .HTTP_HEADER_USERAGENT )) {
309
344
map .put (Constants .HTTP_HEADER_USERAGENT , extractHeaderValue (request [i ]));
310
- }else if (request [i ].startsWith (Constants .WS_HEADER_GENERIC_PREFIX )) {
311
- map .put (getHeaderName (request [i ]), extractHeaderValue (request [i ]));
345
+ } else if (request [i ].startsWith (Constants .WS_HEADER_GENERIC_PREFIX )) {
346
+ map .put (getHeaderName (request [i ]), extractHeaderValue (request [i ]));
312
347
}
313
348
}
314
349
return map ;
315
350
}
316
-
317
-
318
-
351
+
319
352
/**
320
353
* Returns the trimmed header name.
321
354
*
322
355
* @param requestHeader
323
356
* @return value
324
357
*/
325
- private String getHeaderName (String requestHeader ){
326
- return requestHeader .substring (0 , requestHeader .indexOf (':' )).trim ();
358
+ private String getHeaderName (String requestHeader ) {
359
+ return requestHeader .substring (0 , requestHeader .indexOf (':' )).trim ();
327
360
}
328
-
329
-
330
361
331
362
/**
332
363
* Returns the trimmed header value.
0 commit comments