Bug 63019

Summary: Websocket frame header encoding + fix
Product: Tomcat 8 Reporter: benoit.courtilly
Component: WebSocketAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: 8.5.32   
Target Milestone: ----   
Hardware: PC   
OS: Linux   

Description benoit.courtilly 2018-12-19 11:10:18 UTC
Hi,

i found that sending non 0 offseted bytebuffer through websocket does not work.
I guessed bug is at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.java, 
- function writeHeader 
- lines 747 to 770
- all occurences of payload.limit() should be replaced by payload.remaining()

Let's see it in details :
>> private static void writeHeader(ByteBuffer headerBuffer, boolean fin,
>> 		int rsv, byte opCode, boolean masked, ByteBuffer payload,
>> 		byte[] mask, boolean first) {
>> [...]
>> 	// Next write the mask && length length
>> 	if (payload.limit() < 126) {
>> 		headerBuffer.put((byte) (payload.limit() | b));
>> 	} else if (payload.limit() < 65536) {
>> 		headerBuffer.put((byte) (126 | b));
>> 		headerBuffer.put((byte) (payload.limit() >>> 8));
>> 		headerBuffer.put((byte) (payload.limit() & 0xFF));
>> 	} else {
>> 		// Will never be more than 2^31-1
>> 		headerBuffer.put((byte) (127 | b));
>> 		headerBuffer.put((byte) 0);
>> 		headerBuffer.put((byte) 0);
>> 		headerBuffer.put((byte) 0);
>> 		headerBuffer.put((byte) 0);
>> 		headerBuffer.put((byte) (payload.limit() >>> 24));
>> 		headerBuffer.put((byte) (payload.limit() >>> 16));
>> 		headerBuffer.put((byte) (payload.limit() >>> 8));
>> 		headerBuffer.put((byte) (payload.limit() & 0xFF));
>> 	}
>> 	if (masked) {
>> 		headerBuffer.put(mask[0]);
>> 		headerBuffer.put(mask[1]);
>> 		headerBuffer.put(mask[2]);
>> 		headerBuffer.put(mask[3]);
>> 	}
>> }

payload.limit() is ***NOT*** the length, it will be equal to payload.remaining() ***ONLY*** if offset = 0 and position = 0...
Even if it is the case most of the time, sometimes it is not.
For now, as a workaround I copy my buffer to a fresh one 0 offseted before sending thus leading to a slight performance hit.

Best regards,

Benoit
Comment 1 Remy Maucherat 2019-01-04 16:32:09 UTC
That sounds reasonable, the fix will be in 9.0.15, 8.5.38 and 7.0.93.