Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/example/simplelogger.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
org.slf4j.simpleLogger.logFile=System.out
org.slf4j.simpleLogger.defaultLogLevel=error
org.slf4j.simpleLogger.defaultLogLevel=trace
org.slf4j.simpleLogger.showDateTime=true
org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss.SSS
org.slf4j.simpleLogger.showThreadName=false
Expand Down
14 changes: 11 additions & 3 deletions src/main/java/org/java_websocket/SSLSocketChannel.java
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,15 @@ private boolean doHandshake() throws IOException {
peerNetData.clear();

handshakeStatus = engine.getHandshakeStatus();
while( handshakeStatus != SSLEngineResult.HandshakeStatus.FINISHED && handshakeStatus != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING ) {
boolean handshakeComplete = false;
while( !handshakeComplete) {
switch(handshakeStatus) {
case FINISHED:
handshakeComplete = !this.peerNetData.hasRemaining();
if (handshakeComplete)
return true;
socketChannel.write(this.peerNetData);
break;
case NEED_UNWRAP:
if( socketChannel.read( peerNetData ) < 0 ) {
if( engine.isInboundDone() && engine.isOutboundDone() ) {
Expand Down Expand Up @@ -316,6 +323,8 @@ private boolean doHandshake() throws IOException {
}
break;
case NEED_WRAP:


myNetData.clear();
try {
result = engine.wrap( myAppData, myNetData );
Expand Down Expand Up @@ -363,8 +372,7 @@ private boolean doHandshake() throws IOException {
}
handshakeStatus = engine.getHandshakeStatus();
break;
case FINISHED:
break;

case NOT_HANDSHAKING:
break;
default:
Expand Down
11 changes: 7 additions & 4 deletions src/main/java/org/java_websocket/WebSocketImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.enums.*;
import org.java_websocket.exceptions.IncompleteHandshakeException;
import org.java_websocket.exceptions.InvalidDataException;
import org.java_websocket.exceptions.InvalidHandshakeException;
import org.java_websocket.exceptions.WebsocketNotConnectedException;
import org.java_websocket.exceptions.*;
import org.java_websocket.framing.CloseFrame;
import org.java_websocket.framing.Framedata;
import org.java_websocket.framing.PingFrame;
Expand Down Expand Up @@ -369,6 +366,12 @@ private void decodeFrames( ByteBuffer socketBuffer ) {
log.trace( "matched frame: {}" , f );
draft.processFrame( this, f );
}
} catch ( LimitExedeedException e ) {
if (e.getLimit() == Integer.MAX_VALUE) {
log.error("Closing due to invalid size of frame", e);
wsl.onWebsocketError(this, e);
}
close(e);
} catch ( InvalidDataException e ) {
log.error("Closing due to invalid data in frame", e);
wsl.onWebsocketError( this, e );
Expand Down
149 changes: 124 additions & 25 deletions src/main/java/org/java_websocket/drafts/Draft_6455.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public class Draft_6455 extends Draft {
/**
* Attribute for the payload of the current continuous frame
*/
private List<ByteBuffer> byteBufferList;
private final List<ByteBuffer> byteBufferList;

/**
* Attribute for the current incomplete frame
Expand All @@ -98,6 +98,13 @@ public class Draft_6455 extends Draft {
*/
private final Random reuseableRandom = new Random();

/**
* Attribute for the maximum allowed size of a frame
*
* @since 1.4.0
*/
private int maxFrameSize;

/**
* Constructor for the websocket protocol specified by RFC 6455 with default extensions
* @since 1.3.5
Expand Down Expand Up @@ -135,7 +142,32 @@ public Draft_6455( List<IExtension> inputExtensions ) {
* @since 1.3.7
*/
public Draft_6455( List<IExtension> inputExtensions , List<IProtocol> inputProtocols ) {
if (inputExtensions == null || inputProtocols == null) {
this(inputExtensions, inputProtocols, Integer.MAX_VALUE);
}

/**
* Constructor for the websocket protocol specified by RFC 6455 with custom extensions and protocols
*
* @param inputExtensions the extensions which should be used for this draft
* @param inputMaxFrameSize the maximum allowed size of a frame (the real payload size, decoded frames can be bigger)
*
* @since 1.4.0
*/
public Draft_6455( List<IExtension> inputExtensions , int inputMaxFrameSize) {
this(inputExtensions, Collections.<IProtocol>singletonList( new Protocol( "" )), inputMaxFrameSize);
}

/**
* Constructor for the websocket protocol specified by RFC 6455 with custom extensions and protocols
*
* @param inputExtensions the extensions which should be used for this draft
* @param inputProtocols the protocols which should be used for this draft
* @param inputMaxFrameSize the maximum allowed size of a frame (the real payload size, decoded frames can be bigger)
*
* @since 1.4.0
*/
public Draft_6455( List<IExtension> inputExtensions , List<IProtocol> inputProtocols, int inputMaxFrameSize ) {
if (inputExtensions == null || inputProtocols == null || inputMaxFrameSize < 1) {
throw new IllegalArgumentException();
}
knownExtensions = new ArrayList<IExtension>( inputExtensions.size());
Expand All @@ -153,6 +185,7 @@ public Draft_6455( List<IExtension> inputExtensions , List<IProtocol> inputProto
knownExtensions.add( this.knownExtensions.size(), extension );
}
knownProtocols.addAll( inputProtocols );
maxFrameSize = inputMaxFrameSize;
}

@Override
Expand Down Expand Up @@ -263,6 +296,17 @@ public IProtocol getProtocol() {
return protocol;
}


/**
* Getter for the maximum allowed payload size which is used by this draft
*
* @return the size, which is allowed for the payload
* @since 1.4.0
*/
public int getMaxFrameSize() {
return maxFrameSize;
}

/**
* Getter for all available protocols for this draft
* @return the protocols which are enabled for this draft
Expand Down Expand Up @@ -337,7 +381,7 @@ public Draft copyInstance() {
for( IProtocol protocol : getKnownProtocols() ) {
newProtocols.add( protocol.copyInstance() );
}
return new Draft_6455( newExtensions, newProtocols );
return new Draft_6455( newExtensions, newProtocols, maxFrameSize );
}

@Override
Expand Down Expand Up @@ -440,14 +484,18 @@ public Framedata translateSingleFrame( ByteBuffer buffer ) throws IncompleteExce
bytes[i] = buffer.get( /*1 + i*/ );
}
long length = new BigInteger( bytes ).longValue();
if( length > Integer.MAX_VALUE ) {
if( length > Integer.MAX_VALUE) {
log.trace( "Limit exedeed: Payloadsize is to big..." );
throw new LimitExedeedException( "Payloadsize is to big..." );
} else {
payloadlength = ( int ) length;
}
}
}
if( payloadlength > maxFrameSize) {
log.trace( "Payload limit reached. Allowed: {0} Current: {1}" , maxFrameSize, payloadlength);
throw new LimitExedeedException( "Payload limit reached.", maxFrameSize );
}

// int maskskeystart = foff + realpacketsize;
realpacketsize += ( MASK ? 4 : 0 );
Expand Down Expand Up @@ -682,13 +730,15 @@ public void processFrame( WebSocketImpl webSocketImpl, Framedata frame ) throws
throw new InvalidDataException( CloseFrame.PROTOCOL_ERROR, "Previous continuous frame sequence not completed." );
}
current_continuous_frame = frame;
byteBufferList.add( frame.getPayloadData() );
addToBufferList(frame.getPayloadData());
checkBufferLimit();
} else if( frame.isFin() ) {
if( current_continuous_frame == null ) {
log.trace( "Protocol error: Previous continuous frame sequence not completed." );
throw new InvalidDataException( CloseFrame.PROTOCOL_ERROR, "Continuous frame sequence was not started." );
}
byteBufferList.add( frame.getPayloadData() );
addToBufferList(frame.getPayloadData());
checkBufferLimit();
if( current_continuous_frame.getOpcode() == Opcode.TEXT ) {
((FramedataImpl1) current_continuous_frame).setPayload( getPayloadFromByteBufferList() );
((FramedataImpl1) current_continuous_frame ).isValid();
Expand All @@ -709,7 +759,7 @@ public void processFrame( WebSocketImpl webSocketImpl, Framedata frame ) throws
}
}
current_continuous_frame = null;
byteBufferList.clear();
clearBufferList();
} else if( current_continuous_frame == null ) {
log.error( "Protocol error: Continuous frame sequence was not started." );
throw new InvalidDataException( CloseFrame.PROTOCOL_ERROR, "Continuous frame sequence was not started." );
Expand All @@ -723,7 +773,7 @@ public void processFrame( WebSocketImpl webSocketImpl, Framedata frame ) throws
}
//Checking if the current continuous frame contains a correct payload with the other frames combined
if( curop == Opcode.CONTINUOUS && current_continuous_frame != null ) {
byteBufferList.add( frame.getPayloadData() );
addToBufferList(frame.getPayloadData());
}
} else if( current_continuous_frame != null ) {
log.error( "Protocol error: Continuous frame sequence not completed." );
Expand All @@ -748,6 +798,38 @@ public void processFrame( WebSocketImpl webSocketImpl, Framedata frame ) throws
}
}

/**
* Clear the current bytebuffer list
*/
private void clearBufferList() {
synchronized (byteBufferList) {
byteBufferList.clear();
}
}

/**
* Add a payload to the current bytebuffer list
* @param payloadData the new payload
*/
private void addToBufferList(ByteBuffer payloadData) {
synchronized (byteBufferList) {
byteBufferList.add(payloadData);
}
}

/**
* Check the current size of the buffer and throw an exception if the size is bigger than the max allowed frame size
* @throws LimitExedeedException if the current size is bigger than the allowed size
*/
private void checkBufferLimit() throws LimitExedeedException {
long totalSize = getByteBufferListSize();
if( totalSize > maxFrameSize ) {
clearBufferList();
log.trace("Payload limit reached. Allowed: {0} Current: {1}", maxFrameSize, totalSize);
throw new LimitExedeedException(maxFrameSize);
}
}

@Override
public CloseHandshakeType getCloseHandshakeType() {
return CloseHandshakeType.TWOWAY;
Expand All @@ -760,24 +842,27 @@ public String toString() {
result += " extension: " + getExtension().toString();
if ( getProtocol() != null )
result += " protocol: " + getProtocol().toString();
result += " max frame size: " + this.maxFrameSize;
return result;
}

@Override
public boolean equals( Object o ) {
if( this == o ) return true;
if( o == null || getClass() != o.getClass() ) return false;
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Draft_6455 that = ( Draft_6455 ) o;
Draft_6455 that = (Draft_6455) o;

if( extension != null ? !extension.equals( that.extension ) : that.extension != null ) return false;
return protocol != null ? protocol.equals( that.protocol ) : that.protocol == null;
if (maxFrameSize != that.getMaxFrameSize()) return false;
if (extension != null ? !extension.equals(that.getExtension()) : that.getExtension() != null) return false;
return protocol != null ? protocol.equals(that.getProtocol()) : that.getProtocol() == null;
}

@Override
public int hashCode() {
int result = extension != null ? extension.hashCode() : 0;
result = 31 * result + ( protocol != null ? protocol.hashCode() : 0 );
result = 31 * result + (protocol != null ? protocol.hashCode() : 0);
result = 31 * result + (int) (maxFrameSize ^ (maxFrameSize >>> 32));
return result;
}

Expand All @@ -788,18 +873,32 @@ public int hashCode() {
*/
private ByteBuffer getPayloadFromByteBufferList() throws LimitExedeedException {
long totalSize = 0;
for (ByteBuffer buffer : byteBufferList) {
totalSize +=buffer.limit();
}
if (totalSize > Integer.MAX_VALUE) {
log.trace( "Payloadsize is to big...");
throw new LimitExedeedException( "Payloadsize is to big..." );
}
ByteBuffer resultingByteBuffer = ByteBuffer.allocate( (int) totalSize );
for (ByteBuffer buffer : byteBufferList) {
resultingByteBuffer.put( buffer );
ByteBuffer resultingByteBuffer;
synchronized (byteBufferList) {
for (ByteBuffer buffer : byteBufferList) {
totalSize += buffer.limit();
}
checkBufferLimit();
resultingByteBuffer = ByteBuffer.allocate( (int) totalSize );
for (ByteBuffer buffer : byteBufferList) {
resultingByteBuffer.put( buffer );
}
}
resultingByteBuffer.flip();
return resultingByteBuffer;
}

/**
* Get the current size of the resulting bytebuffer in the bytebuffer list
* @return the size as long (to not get an integer overflow)
*/
private long getByteBufferListSize() {
long totalSize = 0;
synchronized (byteBufferList) {
for (ByteBuffer buffer : byteBufferList) {
totalSize += buffer.limit();
}
}
return totalSize;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,38 @@ public class LimitExedeedException extends InvalidDataException {
*/
private static final long serialVersionUID = 6908339749836826785L;

/**
* A closer indication about the limit
*/
private final int limit;

/**
* constructor for a LimitExedeedException
* <p>
* calling InvalidDataException with closecode TOOBIG
*/
public LimitExedeedException() {
this(Integer.MAX_VALUE);
}

/**
* constructor for a LimitExedeedException
* <p>
* calling InvalidDataException with closecode TOOBIG
*/
public LimitExedeedException(int limit) {
super( CloseFrame.TOOBIG);
this.limit = limit;
}

/**
* constructor for a LimitExedeedException
* <p>
* calling InvalidDataException with closecode TOOBIG
*/
public LimitExedeedException(String s, int limit) {
super( CloseFrame.TOOBIG, s);
this.limit = limit;
}

/**
Expand All @@ -54,7 +79,14 @@ public LimitExedeedException() {
* @param s the detail message.
*/
public LimitExedeedException(String s) {
super( CloseFrame.TOOBIG, s);
this(s, Integer.MAX_VALUE);
}

/**
* Get the limit which was hit so this exception was caused
* @return the limit as int
*/
public int getLimit() {
return limit;
}
}
Loading