Skip to content

Commit ccc3ae5

Browse files
committed
[UNDERTOW-2532] prevents intrinsic lock from being affected when transmitting partial messages through the websocket channel
1 parent 77fd1aa commit ccc3ae5

File tree

1 file changed

+64
-50
lines changed

1 file changed

+64
-50
lines changed

websockets-jsr/src/main/java/io/undertow/websockets/jsr/WebSocketSessionRemoteEndpoint.java

+64-50
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,24 @@
1717
*/
1818
package io.undertow.websockets.jsr;
1919

20+
import java.io.IOException;
21+
import java.io.OutputStream;
22+
import java.io.OutputStreamWriter;
23+
import java.io.Writer;
24+
import java.nio.ByteBuffer;
25+
import java.nio.charset.StandardCharsets;
26+
import java.util.concurrent.Future;
27+
2028
import io.undertow.websockets.core.BinaryOutputStream;
2129
import io.undertow.websockets.core.StreamSinkFrameChannel;
2230
import io.undertow.websockets.core.WebSocketCallback;
2331
import io.undertow.websockets.core.WebSocketFrameType;
2432
import io.undertow.websockets.core.WebSocketUtils;
2533
import io.undertow.websockets.core.WebSockets;
26-
import org.xnio.channels.Channels;
27-
2834
import jakarta.websocket.EncodeException;
2935
import jakarta.websocket.RemoteEndpoint;
3036
import jakarta.websocket.SendHandler;
31-
import java.io.IOException;
32-
import java.io.OutputStream;
33-
import java.io.OutputStreamWriter;
34-
import java.io.Writer;
35-
import java.nio.ByteBuffer;
36-
import java.nio.charset.StandardCharsets;
37-
import java.util.concurrent.Future;
37+
import org.xnio.channels.Channels;
3838

3939
/**
4040
* {@link RemoteEndpoint} implementation which uses a WebSocketSession for all its operation.
@@ -243,11 +243,9 @@ class BasicWebSocketSessionRemoteEndpoint implements Basic {
243243
private StreamSinkFrameChannel binaryFrameSender;
244244
private StreamSinkFrameChannel textFrameSender;
245245

246-
public void assertNotInFragment() {
247-
synchronized (this) {
248-
if (textFrameSender != null || binaryFrameSender != null) {
249-
throw JsrWebSocketMessages.MESSAGES.cannotSendInMiddleOfFragmentedMessage();
250-
}
246+
public synchronized void assertNotInFragment() {
247+
if (textFrameSender != null || binaryFrameSender != null) {
248+
throw JsrWebSocketMessages.MESSAGES.cannotSendInMiddleOfFragmentedMessage();
251249
}
252250
}
253251

@@ -270,29 +268,23 @@ public void sendBinary(final ByteBuffer data) throws IOException {
270268
data.clear(); //for some reason the TCK expects this, might as well just match the RI behaviour
271269
}
272270

273-
@Override
271+
@Override
274272
public void sendText(final String partialMessage, final boolean isLast) throws IOException {
275-
if(partialMessage == null) {
273+
if (partialMessage == null) {
276274
throw JsrWebSocketMessages.MESSAGES.messageInNull();
277275
}
278276

279-
synchronized (this) {
280-
if (binaryFrameSender != null) {
281-
throw JsrWebSocketMessages.MESSAGES.cannotSendInMiddleOfFragmentedMessage();
282-
}
283-
if(textFrameSender == null) {
284-
textFrameSender = undertowSession.getWebSocketChannel().send(WebSocketFrameType.TEXT);
277+
StreamSinkFrameChannel sender = getTextFrameSender();
278+
279+
try {
280+
Channels.writeBlocking(sender, WebSocketUtils.fromUtf8String(partialMessage));
281+
if (isLast) {
282+
sender.shutdownWrites();
285283
}
286-
try {
287-
Channels.writeBlocking(textFrameSender, WebSocketUtils.fromUtf8String(partialMessage));
288-
if(isLast) {
289-
textFrameSender.shutdownWrites();
290-
}
291-
Channels.flushBlocking(textFrameSender);
292-
} finally {
293-
if(isLast) {
294-
textFrameSender = null;
295-
}
284+
Channels.flushBlocking(sender);
285+
} finally {
286+
if (isLast) {
287+
clearTextFrameSender();
296288
}
297289
}
298290
}
@@ -303,27 +295,49 @@ public void sendBinary(final ByteBuffer partialByte, final boolean isLast) throw
303295
throw JsrWebSocketMessages.MESSAGES.messageInNull();
304296
}
305297

306-
synchronized (this) {
307-
if (textFrameSender != null) {
308-
throw JsrWebSocketMessages.MESSAGES.cannotSendInMiddleOfFragmentedMessage();
309-
}
310-
if (binaryFrameSender == null) {
311-
binaryFrameSender = undertowSession.getWebSocketChannel().send(WebSocketFrameType.BINARY);
312-
}
313-
try {
314-
Channels.writeBlocking(binaryFrameSender, partialByte);
315-
if (isLast) {
316-
binaryFrameSender.shutdownWrites();
317-
}
318-
Channels.flushBlocking(binaryFrameSender);
298+
StreamSinkFrameChannel sender = getBinaryFrameSender();
299+
300+
try {
301+
Channels.writeBlocking(sender, partialByte);
302+
if (isLast) {
303+
sender.shutdownWrites();
319304
}
320-
finally {
321-
if (isLast) {
322-
binaryFrameSender = null;
323-
}
305+
Channels.flushBlocking(sender);
306+
}
307+
finally {
308+
if (isLast) {
309+
clearBinaryFrameSender();
324310
}
325-
partialByte.clear();
326311
}
312+
partialByte.clear();
313+
}
314+
315+
private synchronized StreamSinkFrameChannel getTextFrameSender() throws IOException {
316+
if (binaryFrameSender != null) {
317+
throw JsrWebSocketMessages.MESSAGES.cannotSendInMiddleOfFragmentedMessage();
318+
}
319+
if (textFrameSender == null) {
320+
textFrameSender = undertowSession.getWebSocketChannel().send(WebSocketFrameType.TEXT);
321+
}
322+
return textFrameSender;
323+
}
324+
325+
private synchronized void clearTextFrameSender() {
326+
textFrameSender = null;
327+
}
328+
329+
private synchronized StreamSinkFrameChannel getBinaryFrameSender() throws IOException {
330+
if (textFrameSender != null) {
331+
throw JsrWebSocketMessages.MESSAGES.cannotSendInMiddleOfFragmentedMessage();
332+
}
333+
if (binaryFrameSender == null) {
334+
binaryFrameSender = undertowSession.getWebSocketChannel().send(WebSocketFrameType.BINARY);
335+
}
336+
return binaryFrameSender;
337+
}
338+
339+
private synchronized void clearBinaryFrameSender() {
340+
binaryFrameSender = null;
327341
}
328342

329343
@Override

0 commit comments

Comments
 (0)