Skip to content

Commit 32c1ce0

Browse files
committed
Deprecating onFragment and combining fragmented frames
This should fix #564 as well as other issues like that
1 parent 2d8f5fe commit 32c1ce0

File tree

5 files changed

+72
-44
lines changed

5 files changed

+72
-44
lines changed

src/main/java/org/java_websocket/WebSocketImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ private void send( Collection<Framedata> frames ) {
605605
if( !isOpen() ) {
606606
throw new WebsocketNotConnectedException();
607607
}
608-
if( frames == null || frames.isEmpty() ) {
608+
if( frames == null) {
609609
throw new IllegalArgumentException();
610610
}
611611
ArrayList<ByteBuffer> outgoingFrames = new ArrayList<ByteBuffer>();

src/main/java/org/java_websocket/WebSocketListener.java

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public interface WebSocketListener {
5959
* @throws InvalidDataException
6060
* Throwing this exception will cause this handshake to be rejected
6161
*/
62-
public ServerHandshakeBuilder onWebsocketHandshakeReceivedAsServer( WebSocket conn, Draft draft, ClientHandshake request ) throws InvalidDataException;
62+
ServerHandshakeBuilder onWebsocketHandshakeReceivedAsServer( WebSocket conn, Draft draft, ClientHandshake request ) throws InvalidDataException;
6363

6464
/**
6565
* Called on the client side when the socket connection is first established, and the WebSocketImpl
@@ -74,7 +74,7 @@ public interface WebSocketListener {
7474
* @throws InvalidDataException
7575
* Allows the client to reject the connection with the server in respect of its handshake response.
7676
*/
77-
public void onWebsocketHandshakeReceivedAsClient( WebSocket conn, ClientHandshake request, ServerHandshake response ) throws InvalidDataException;
77+
void onWebsocketHandshakeReceivedAsClient( WebSocket conn, ClientHandshake request, ServerHandshake response ) throws InvalidDataException;
7878

7979
/**
8080
* Called on the client side when the socket connection is first established, and the WebSocketImpl
@@ -87,7 +87,7 @@ public interface WebSocketListener {
8787
* @throws InvalidDataException
8888
* Allows the client to stop the connection from progressing
8989
*/
90-
public void onWebsocketHandshakeSentAsClient( WebSocket conn, ClientHandshake request ) throws InvalidDataException;
90+
void onWebsocketHandshakeSentAsClient( WebSocket conn, ClientHandshake request ) throws InvalidDataException;
9191

9292
/**
9393
* Called when an entire text frame has been received. Do whatever you want
@@ -98,7 +98,7 @@ public interface WebSocketListener {
9898
* @param message
9999
* The UTF-8 decoded message that was received.
100100
*/
101-
public void onWebsocketMessage( WebSocket conn, String message );
101+
void onWebsocketMessage( WebSocket conn, String message );
102102

103103
/**
104104
* Called when an entire binary frame has been received. Do whatever you want
@@ -109,16 +109,18 @@ public interface WebSocketListener {
109109
* @param blob
110110
* The binary message that was received.
111111
*/
112-
public void onWebsocketMessage( WebSocket conn, ByteBuffer blob );
112+
void onWebsocketMessage( WebSocket conn, ByteBuffer blob );
113113

114114
/**
115115
* Called when a frame fragment has been recieved
116116
*
117+
* This method will be removed in a future version since the lib will also call the respective onWebsocketMessage method
117118
* @param conn
118119
* The <tt>WebSocket</tt> instance this event is occurring on.
119120
* @param frame The fragmented frame
120121
*/
121-
public void onWebsocketMessageFragment( WebSocket conn, Framedata frame );
122+
@Deprecated
123+
void onWebsocketMessageFragment( WebSocket conn, Framedata frame );
122124

123125
/**
124126
* Called after <var>onHandshakeReceived</var> returns <var>true</var>.
@@ -128,7 +130,7 @@ public interface WebSocketListener {
128130
* @param conn The <tt>WebSocket</tt> instance this event is occuring on.
129131
* @param d The handshake of the websocket instance
130132
*/
131-
public void onWebsocketOpen( WebSocket conn, Handshakedata d );
133+
void onWebsocketOpen( WebSocket conn, Handshakedata d );
132134

133135
/**
134136
* Called after <tt>WebSocket#close</tt> is explicity called, or when the
@@ -139,7 +141,7 @@ public interface WebSocketListener {
139141
* @param reason Additional information string
140142
* @param remote Returns whether or not the closing of the connection was initiated by the remote host.
141143
*/
142-
public void onWebsocketClose( WebSocket ws, int code, String reason, boolean remote );
144+
void onWebsocketClose( WebSocket ws, int code, String reason, boolean remote );
143145

144146
/** Called as soon as no further frames are accepted
145147
*
@@ -148,15 +150,15 @@ public interface WebSocketListener {
148150
* @param reason Additional information string
149151
* @param remote Returns whether or not the closing of the connection was initiated by the remote host.
150152
*/
151-
public void onWebsocketClosing( WebSocket ws, int code, String reason, boolean remote );
153+
void onWebsocketClosing( WebSocket ws, int code, String reason, boolean remote );
152154

153155
/** send when this peer sends a close handshake
154156
*
155157
* @param ws The <tt>WebSocket</tt> instance this event is occuring on.
156158
* @param code The codes can be looked up here: {@link CloseFrame}
157159
* @param reason Additional information string
158160
*/
159-
public void onWebsocketCloseInitiated( WebSocket ws, int code, String reason );
161+
void onWebsocketCloseInitiated( WebSocket ws, int code, String reason );
160162

161163
/**
162164
* Called if an exception worth noting occurred.
@@ -167,7 +169,7 @@ public interface WebSocketListener {
167169
* The exception that occurred. <br>
168170
* Might be null if the exception is not related to any specific connection. For example if the server port could not be bound.
169171
*/
170-
public void onWebsocketError( WebSocket conn, Exception ex );
172+
void onWebsocketError( WebSocket conn, Exception ex );
171173

172174
/**
173175
* Called a ping frame has been received.
@@ -176,42 +178,43 @@ public interface WebSocketListener {
176178
* @param conn The <tt>WebSocket</tt> instance this event is occuring on.
177179
* @param f The ping frame. Control frames may contain payload.
178180
*/
179-
public void onWebsocketPing( WebSocket conn, Framedata f );
181+
void onWebsocketPing( WebSocket conn, Framedata f );
180182

181183
/**
182184
* Called when a pong frame is received.
183185
*
184186
* @param conn The <tt>WebSocket</tt> instance this event is occuring on.
185187
* @param f The pong frame. Control frames may contain payload.
186188
**/
187-
public void onWebsocketPong( WebSocket conn, Framedata f );
189+
void onWebsocketPong( WebSocket conn, Framedata f );
188190

189191
/**
190192
* @see WebSocketAdapter#getFlashPolicy(WebSocket)
191193
* @param conn The <tt>WebSocket</tt> instance this event is occuring on.
192194
* @throws InvalidDataException thrown when some data that is required to generate the flash-policy like the websocket local port could not be obtained.
193195
* @return An XML String that comforts to Flash's security policy. You MUST not include the null char at the end, it is appended automatically.
194196
*/
195-
public String getFlashPolicy( WebSocket conn ) throws InvalidDataException;
197+
@Deprecated
198+
String getFlashPolicy( WebSocket conn ) throws InvalidDataException;
196199

197200
/** This method is used to inform the selector thread that there is data queued to be written to the socket.
198201
* @param conn The <tt>WebSocket</tt> instance this event is occuring on.
199202
*/
200-
public void onWriteDemand( WebSocket conn );
203+
void onWriteDemand( WebSocket conn );
201204

202205
/**
203206
* @see WebSocket#getLocalSocketAddress()
204207
*
205208
* @param conn The <tt>WebSocket</tt> instance this event is occuring on.
206209
* @return Returns the address of the endpoint this socket is bound to.
207210
*/
208-
public InetSocketAddress getLocalSocketAddress( WebSocket conn );
211+
InetSocketAddress getLocalSocketAddress( WebSocket conn );
209212

210213
/**
211214
* @see WebSocket#getRemoteSocketAddress()
212215
*
213216
* @param conn The <tt>WebSocket</tt> instance this event is occuring on.
214217
* @return Returns the address of the endpoint this socket is connected to, or{@code null} if it is unconnected.
215218
*/
216-
public InetSocketAddress getRemoteSocketAddress( WebSocket conn );
219+
InetSocketAddress getRemoteSocketAddress( WebSocket conn );
217220
}

src/main/java/org/java_websocket/drafts/Draft_6455.java

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ public class Draft_6455 extends Draft {
6262
*/
6363
private Framedata current_continuous_frame;
6464

65+
/**
66+
* Attribute for the payload of the current continuous frame
67+
*/
68+
private List<ByteBuffer> byteBufferList;
69+
6570
/**
6671
* Attribute for the current incomplete frame
6772
*/
@@ -96,6 +101,7 @@ public Draft_6455( IExtension inputExtension ) {
96101
public Draft_6455( List<IExtension> inputExtensions ) {
97102
knownExtensions = new ArrayList<IExtension>();
98103
boolean hasDefault = false;
104+
byteBufferList = new ArrayList<ByteBuffer>();
99105
for( IExtension inputExtension : inputExtensions ) {
100106
if( inputExtension.getClass().equals( DefaultExtension.class ) ) {
101107
hasDefault = true;
@@ -548,19 +554,30 @@ public void processFrame( WebSocketImpl webSocketImpl, Framedata frame ) throws
548554
if( current_continuous_frame != null )
549555
throw new InvalidDataException( CloseFrame.PROTOCOL_ERROR, "Previous continuous frame sequence not completed." );
550556
current_continuous_frame = frame;
557+
byteBufferList.add( frame.getPayloadData() );
551558
} else if( frame.isFin() ) {
552559
if( current_continuous_frame == null )
553560
throw new InvalidDataException( CloseFrame.PROTOCOL_ERROR, "Continuous frame sequence was not started." );
554-
//Check if the whole payload is valid utf8, when the opcode indicates a text
561+
byteBufferList.add( frame.getPayloadData() );
555562
if( current_continuous_frame.getOpcode() == Framedata.Opcode.TEXT ) {
556-
//Checking a bit more from the frame before this one just to make sure all the code points are correct
557-
int off = Math.max( current_continuous_frame.getPayloadData().limit() - 64, 0 );
558-
current_continuous_frame.append( frame );
559-
if( !Charsetfunctions.isValidUTF8( current_continuous_frame.getPayloadData(), off ) ) {
560-
throw new InvalidDataException( CloseFrame.NO_UTF8 );
563+
((FramedataImpl1) current_continuous_frame).setPayload( getPayloadFromByteBufferList() );
564+
((FramedataImpl1) current_continuous_frame ).isValid();
565+
try {
566+
webSocketImpl.getWebSocketListener().onWebsocketMessage( webSocketImpl, Charsetfunctions.stringUtf8( current_continuous_frame.getPayloadData() ) );
567+
} catch ( RuntimeException e ) {
568+
webSocketImpl.getWebSocketListener().onWebsocketError( webSocketImpl, e );
569+
}
570+
} else if( current_continuous_frame.getOpcode() == Framedata.Opcode.BINARY ) {
571+
((FramedataImpl1) current_continuous_frame).setPayload( getPayloadFromByteBufferList() );
572+
((FramedataImpl1) current_continuous_frame ).isValid();
573+
try {
574+
webSocketImpl.getWebSocketListener().onWebsocketMessage( webSocketImpl, current_continuous_frame.getPayloadData() );
575+
} catch ( RuntimeException e ) {
576+
webSocketImpl.getWebSocketListener().onWebsocketError( webSocketImpl, e );
561577
}
562578
}
563579
current_continuous_frame = null;
580+
byteBufferList.clear();
564581
} else if( current_continuous_frame == null ) {
565582
throw new InvalidDataException( CloseFrame.PROTOCOL_ERROR, "Continuous frame sequence was not started." );
566583
}
@@ -571,18 +588,8 @@ public void processFrame( WebSocketImpl webSocketImpl, Framedata frame ) throws
571588
}
572589
}
573590
//Checking if the current continous frame contains a correct payload with the other frames combined
574-
if( curop == Framedata.Opcode.CONTINUOUS && current_continuous_frame != null && current_continuous_frame.getOpcode() == Framedata.Opcode.TEXT ) {
575-
//Checking a bit more from the frame before this one just to make sure all the code points are correct
576-
int off = Math.max( current_continuous_frame.getPayloadData().limit() - 64, 0 );
577-
current_continuous_frame.append( frame );
578-
if( !Charsetfunctions.isValidUTF8( current_continuous_frame.getPayloadData(), off ) ) {
579-
throw new InvalidDataException( CloseFrame.NO_UTF8 );
580-
}
581-
}
582-
try {
583-
webSocketImpl.getWebSocketListener().onWebsocketMessageFragment( webSocketImpl, frame );
584-
} catch ( RuntimeException e ) {
585-
webSocketImpl.getWebSocketListener().onWebsocketError( webSocketImpl, e );
591+
if( curop == Framedata.Opcode.CONTINUOUS && current_continuous_frame != null ) {
592+
byteBufferList.add( frame.getPayloadData() );
586593
}
587594
return;
588595
} else if( current_continuous_frame != null ) {
@@ -632,4 +639,25 @@ public boolean equals( Object o ) {
632639
public int hashCode() {
633640
return extension != null ? extension.hashCode() : 0;
634641
}
642+
643+
/**
644+
* Method to generate a full bytebuffer out of all the fragmented frame payload
645+
* @return a bytebuffer containing all the data
646+
* @throws LimitExedeedException will be thrown when the totalSize is bigger then Integer.MAX_VALUE due to not being able to allocate more
647+
*/
648+
private ByteBuffer getPayloadFromByteBufferList() throws LimitExedeedException {
649+
long totalSize = 0;
650+
for (ByteBuffer buffer : byteBufferList) {
651+
totalSize +=buffer.limit();
652+
}
653+
if (totalSize > Integer.MAX_VALUE) {
654+
throw new LimitExedeedException( "Payloadsize is to big..." );
655+
}
656+
ByteBuffer resultingByteBuffer = ByteBuffer.allocate( (int) totalSize );
657+
for (ByteBuffer buffer : byteBufferList) {
658+
resultingByteBuffer.put( buffer );
659+
}
660+
resultingByteBuffer.flip();
661+
return resultingByteBuffer;
662+
}
635663
}

src/main/java/org/java_websocket/server/WebSocketServer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,7 @@ public void onMessage( WebSocket conn, ByteBuffer message ) {
767767
* The <tt>WebSocket</tt> instance this event is occurring on.
768768
* @param fragment The fragmented frame
769769
*/
770+
@Deprecated
770771
public void onFragment( WebSocket conn, Framedata fragment ) {
771772
}
772773

src/test/java/org/java_websocket/example/AutobahnServerTest.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848

4949
public class AutobahnServerTest extends WebSocketServer {
5050
private static int counter = 0;
51-
5251
public AutobahnServerTest( int port, Draft d ) throws UnknownHostException {
5352
super( new InetSocketAddress( port ), Collections.singletonList( d ) );
5453
}
@@ -83,17 +82,14 @@ public void onStart() {
8382
public void onMessage( WebSocket conn, String message ) {
8483
conn.send( message );
8584
}
86-
8785
@Override
88-
public void onMessage( WebSocket conn, ByteBuffer blob ) {
89-
conn.send( blob );
86+
public void onFragment( WebSocket conn, Framedata fragment ) {
87+
System.out.println( "received fragment: " + fragment );
9088
}
9189

9290
@Override
93-
public void onWebsocketMessageFragment( WebSocket conn, Framedata frame ) {
94-
FramedataImpl1 builder = ( FramedataImpl1 ) frame;
95-
builder.setTransferemasked( false );
96-
conn.sendFrame( frame );
91+
public void onMessage( WebSocket conn, ByteBuffer blob ) {
92+
conn.send( blob );
9793
}
9894

9995
public static void main( String[] args ) throws UnknownHostException {

0 commit comments

Comments
 (0)