Author: markt Date: Mon Dec 24 20:53:25 2012 New Revision: 1425679 URL: http://svn.apache.org/viewvc?rev=1425679&view=rev Log: Fix failures in Autobahn fragmentation tests - control messages must be sent as a single frame - control messages may appear between the frames of non-control messages
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java Modified: tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties?rev=1425679&r1=1425678&r2=1425679&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties Mon Dec 24 20:53:25 2012 @@ -20,8 +20,10 @@ serverContainer.servletContextMismatch=A serverContainer.servletContextMissing=No ServletContext was specified uriTemplate.noMatch=The input template [{0}] generated the pattern [{1}] which did not match the supplied pathInfo [{2}] wsFrame.byteToLongFail=Too many bytes ([{0}]) were provided to be converted into a long +wsFrame.controlFragmented=A fragmented control frame was received but control frames may not be fragmented wsFrame.controlPayloadTooBig=A control frame was sent with a payload of length [{0}] which is larger than the maximum length permitted of 125 bytes wsFrame.controlNoFin=A control frame was sent that did not have the fin bit set. Control frames are not permitted to use continuation frames. wsFrame.invalidOpCode= A WebSocket frame was sent with an unrecognised opCode of [{0}] +wsFrame.noContinuation=A new message was started when a continuation frame was expected wsFrame.notMasked=The client frame was not masked but all client frames must be masked wsFrame.wrongRsv=The client frame set the reserved bits to [{0}] which was not supported by this endpoint \ No newline at end of file Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java?rev=1425679&r1=1425678&r2=1425679&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java Mon Dec 24 20:53:25 2012 @@ -42,6 +42,11 @@ public class WsFrame { private final WsSession wsSession; private final byte[] inputBuffer; + // Attributes for control messages + // Control messages can appear in the middle of other messages so need + // separate attributes + private final ByteBuffer controlBuffer = ByteBuffer.allocate(125); + // Attributes of the current message private final ByteBuffer messageBuffer; private boolean continuationExpected = false; @@ -130,11 +135,18 @@ public class WsFrame { sm.getString("wsFrame.wrongRsv", Integer.valueOf(rsv)))); } opCode = (byte) (b & 0x0F); - if (!isControl()) { + if (isControl()) { + if (!fin) { + throw new WsIOException(new CloseReason( + CloseCodes.PROTOCOL_ERROR, + sm.getString("wsFrame.controlFragmented"))); + } + } else { if (continuationExpected) { if (opCode != Constants.OPCODE_CONTINUATION) { - // TODO i18n - throw new IllegalStateException(); + throw new WsIOException(new CloseReason( + CloseCodes.PROTOCOL_ERROR, + sm.getString("wsFrame.noContinuation"))); } } else { if (opCode == Constants.OPCODE_BINARY) { @@ -204,33 +216,31 @@ public class WsFrame { private boolean processData() throws IOException { checkRoomPayload(); - appendPayloadToMessage(); if (isControl()) { + appendPayloadToMessage(controlBuffer); if (writePos < frameStart + headerLength + payloadLength) { return false; } + controlBuffer.flip(); if (opCode == Constants.OPCODE_CLOSE) { - messageBuffer.flip(); String reason = null; int code = CloseCodes.NORMAL_CLOSURE.getCode(); - if (messageBuffer.remaining() > 1) { - code = messageBuffer.getShort(); - if (messageBuffer.remaining() > 0) { - reason = new String(messageBuffer.array(), - messageBuffer.arrayOffset() + messageBuffer.position(), - messageBuffer.remaining(), "UTF8"); + if (controlBuffer.remaining() > 1) { + code = controlBuffer.getShort(); + if (controlBuffer.remaining() > 0) { + reason = new String(controlBuffer.array(), + controlBuffer.arrayOffset() + controlBuffer.position(), + controlBuffer.remaining(), "UTF8"); } } wsSession.onClose( new CloseReason(Util.getCloseCode(code), reason)); } else if (opCode == Constants.OPCODE_PING) { - messageBuffer.flip(); - wsSession.getRemote().sendPong(messageBuffer); + wsSession.getRemote().sendPong(controlBuffer); } else if (opCode == Constants.OPCODE_PONG) { MessageHandler.Basic<PongMessage> mhPong = wsSession.getPongMessageHandler(); if (mhPong != null) { - messageBuffer.flip(); - mhPong.onMessage(new WsPongMessage(messageBuffer)); + mhPong.onMessage(new WsPongMessage(controlBuffer)); } } else { throw new WsIOException(new CloseReason( @@ -238,9 +248,11 @@ public class WsFrame { sm.getString("wsFrame.invalidOpCode", Integer.valueOf(opCode)))); } - newMessage(); + controlBuffer.clear(); + newFrame(); return true; } + appendPayloadToMessage(messageBuffer); if (payloadWritten == payloadLength) { if (continuationExpected) { if (usePartial()) { @@ -385,7 +397,7 @@ public class WsFrame { } - private void appendPayloadToMessage() { + private void appendPayloadToMessage(ByteBuffer dest) { while (payloadWritten < payloadLength && payloadRead < writePos) { byte b = (byte) ((inputBuffer[payloadRead] ^ mask[maskIndex]) & 0xFF); maskIndex++; @@ -394,7 +406,7 @@ public class WsFrame { } payloadRead++; payloadWritten++; - messageBuffer.put(b); + dest.put(b); } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org