
org.threadly.litesockets.protocols.websocket.WSFrame Maven / Gradle / Ivy
package org.threadly.litesockets.protocols.websocket;
import java.nio.ByteBuffer;
import java.text.ParseException;
import java.util.concurrent.ThreadLocalRandom;
import org.threadly.litesockets.buffers.MergedByteBuffers;
import org.threadly.litesockets.buffers.SimpleMergedByteBuffers;
/**
* WSFrame object. This is allows you to easily get information about a WebSocket Frame data.
* This object is immutable.
*
*/
public class WSFrame {
private final ByteBuffer bb;
private final int frameLength;
protected WSFrame(final ByteBuffer bb) {
ByteBuffer sbb = bb.slice();
frameLength = WSUtils.getFrameLength(sbb);
if(frameLength < 0 || bb.remaining() < frameLength) {
throw new IllegalStateException("Not enough data to make a WebSocketFrame");
}
this.bb = sbb;
}
/**
* ByteBuffer for the raw frame. This is just the frame, not the payload thats associated with it.
*
* @return ByteBuffer of this frame.
*/
public ByteBuffer getRawFrame() {
return bb.duplicate();
}
/**
* Is the finished bit set in the frame.
*
* @return true if the frame is marked as finished, false if not.
*/
public boolean isFinished() {
return ((bb.get(0)&WSConstants.UNSIGN_BYTE_MASK) >> WSConstants.STATIC_SEVEN) == 1;
}
/**
* Is the RSV1 bit set.
*
* @return true if its set false if its not.
*/
public boolean hasRSV1() {
return ((bb.get(0) >> WSConstants.STATIC_SIX) &0x1) == 1;
}
/**
* Is the RSV2 bit set.
*
* @return true if its set false if its not.
*/
public boolean hasRSV2() {
return ((bb.get(0) >> WSConstants.STATIC_FIVE) &0x1) == 1;
}
/**
* Is the RSV3 bit set.
*
* @return true if its set false if its not.
*/
public boolean hasRSV3() {
return ((bb.get(0) >> WSConstants.STATIC_FOUR) &0x1) == 1;
}
/**
* The opCode for this websocket frame.
*
* @return The opCode for this websocket frame.
*/
public int getOpCode() {
return bb.get(0) & WSConstants.OPCODE_MASK;
}
/**
* Is the mask bit set for this WSFrames payload.
*
* @return true if the payload is masked, false if it is not.
*/
public boolean hasMask() {
return (bb.get(1) & WSConstants.UNSIGN_BYTE_MASK) >> WSConstants.STATIC_SEVEN == 1;
}
/**
* Returns the size of the websocket frames payload.
*
* @return size of the payload.
*/
public long getPayloadDataLength() {
byte sl = WSUtils.getSmallLen(bb);
if(sl < WSConstants.WS_SHORT_SIZE) {
return sl;
} else if(sl == WSConstants.WS_SHORT_SIZE) {
return bb.getShort(2) & WSConstants.UNSIGNED_SHORT_MASK;
} else {
return bb.getLong(2);
}
}
/**
* Gets the int used to mask this payload.
*
* @return the int used to mask the payload.
*/
public int getMaskValue() {
if(hasMask()) {
return bb.getInt(WSUtils.getFrameLength(bb)-WSConstants.MASK_SIZE);
}
return 0;
}
/**
* Gets the mask as a byte array.
*
* @return the make bytes as an array.
*/
public byte[] getMaskArray() {
byte[] ba = new byte[WSConstants.MASK_SIZE];
if(hasMask()) {
final int start = WSUtils.getFrameLength(bb)-WSConstants.MASK_SIZE;
for(int i=0; i 0 && mbb.remaining() >= size) {
ByteBuffer nbb = mbb.pullBuffer(size);
return new WSFrame(nbb);
} else {
throw new ParseException("Not enough data to make a WebSocketFrame", 0);
}
}
/**
* Creates a {@link WSFrame} object with the provided parameters.
*
* @param size the size of the payload in the WebSocket Frame.
* @param opCode The opCode to put in this WebSocket.
* @param mask true if a mask should be added to this frame, false if not.
* @return a {@link WSFrame} object created with the provided params.
*/
public static WSFrame makeWSFrame(final int size, byte opCode, final boolean mask) {
return makeWSFrame(size, true, opCode, mask);
}
/**
* Creates a {@link WSFrame} object with the provided parameters.
*
* @param size the size of the payload in the WSFrame.
* @param opCode The {@link WSOPCode} to use in this WSFrame.
* @param mask true if a mask should be added to this frame, false if not.
* @return a {@link WSFrame} object created with the provided params.
*/
public static WSFrame makeWSFrame(final int size, WSOPCode opCode, final boolean mask) {
return makeWSFrame(size, true, opCode.getValue(), mask);
}
/**
* Creates a {@link WSFrame} object with the provided parameters.
*
* @param size the size of the payload in the WSFrame.
* @param isFinished true if we should mark this WSFrame as finished false if not.
* @param opCode The opCode to put in this WebSocket.
* @param mask true if a mask should be added to this frame, false if not.
* @return a {@link WSFrame} object created with the provided params.
*/
public static WSFrame makeWSFrame(final int size, boolean isFinished, byte opCode, final boolean mask) {
ByteBuffer nbb;
int maskExtra = mask ? WSConstants.MASK_SIZE : 0;
byte bmask = mask ? (byte)1 : (byte)0;
byte firstByte = opCode;
if(isFinished) {
firstByte = (byte)(firstByte | (1<
© 2015 - 2025 Weber Informatics LLC | Privacy Policy