use of org.eclipse.jetty.websocket.common.frames.CloseFrame in project jetty.project by eclipse.
the class AbstractEventDriver method incomingFrame.
@Override
public void incomingFrame(Frame frame) {
if (LOG.isDebugEnabled()) {
LOG.debug("incomingFrame({})", frame);
}
try {
onFrame(frame);
byte opcode = frame.getOpCode();
switch(opcode) {
case OpCode.CLOSE:
{
boolean validate = true;
CloseFrame closeframe = (CloseFrame) frame;
CloseInfo close = new CloseInfo(closeframe, validate);
// process handshake
session.getConnection().getIOState().onCloseRemote(close);
return;
}
case OpCode.PING:
{
if (LOG.isDebugEnabled()) {
LOG.debug("PING: {}", BufferUtil.toDetailString(frame.getPayload()));
}
ByteBuffer pongBuf;
if (frame.hasPayload()) {
pongBuf = ByteBuffer.allocate(frame.getPayload().remaining());
BufferUtil.put(frame.getPayload().slice(), pongBuf);
BufferUtil.flipToFlush(pongBuf, 0);
} else {
pongBuf = ByteBuffer.allocate(0);
}
onPing(frame.getPayload());
session.getRemote().sendPong(pongBuf);
break;
}
case OpCode.PONG:
{
if (LOG.isDebugEnabled()) {
LOG.debug("PONG: {}", BufferUtil.toDetailString(frame.getPayload()));
}
onPong(frame.getPayload());
break;
}
case OpCode.BINARY:
{
onBinaryFrame(frame.getPayload(), frame.isFin());
return;
}
case OpCode.TEXT:
{
onTextFrame(frame.getPayload(), frame.isFin());
return;
}
case OpCode.CONTINUATION:
{
onContinuationFrame(frame.getPayload(), frame.isFin());
return;
}
default:
{
if (LOG.isDebugEnabled())
LOG.debug("Unhandled OpCode: {}", opcode);
}
}
} catch (NotUtf8Exception e) {
terminateConnection(StatusCode.BAD_PAYLOAD, e.getMessage());
} catch (CloseException e) {
terminateConnection(e.getStatusCode(), e.getMessage());
} catch (Throwable t) {
unhandled(t);
}
}
use of org.eclipse.jetty.websocket.common.frames.CloseFrame in project jetty.project by eclipse.
the class Parser method parseFrame.
/**
* Parse the base framing protocol buffer.
* <p>
* Note the first byte (fin,rsv1,rsv2,rsv3,opcode) are parsed by the {@link Parser#parse(ByteBuffer)} method
* <p>
* Not overridable
*
* @param buffer
* the buffer to parse from.
* @return true if done parsing base framing protocol and ready for parsing of the payload. false if incomplete parsing of base framing protocol.
*/
private boolean parseFrame(ByteBuffer buffer) {
if (LOG.isDebugEnabled()) {
LOG.debug("{} Parsing {} bytes", policy.getBehavior(), buffer.remaining());
}
while (buffer.hasRemaining()) {
switch(state) {
case START:
{
// peek at byte
byte b = buffer.get();
boolean fin = ((b & 0x80) != 0);
byte opcode = (byte) (b & 0x0F);
if (!OpCode.isKnown(opcode)) {
throw new ProtocolException("Unknown opcode: " + opcode);
}
if (LOG.isDebugEnabled())
LOG.debug("{} OpCode {}, fin={} rsv={}{}{}", policy.getBehavior(), OpCode.name(opcode), fin, (((b & 0x40) != 0) ? '1' : '.'), (((b & 0x20) != 0) ? '1' : '.'), (((b & 0x10) != 0) ? '1' : '.'));
// base framing flags
switch(opcode) {
case OpCode.TEXT:
frame = new TextFrame();
// data validation
if (priorDataFrame) {
throw new ProtocolException("Unexpected " + OpCode.name(opcode) + " frame, was expecting CONTINUATION");
}
break;
case OpCode.BINARY:
frame = new BinaryFrame();
// data validation
if (priorDataFrame) {
throw new ProtocolException("Unexpected " + OpCode.name(opcode) + " frame, was expecting CONTINUATION");
}
break;
case OpCode.CONTINUATION:
frame = new ContinuationFrame();
// continuation validation
if (!priorDataFrame) {
throw new ProtocolException("CONTINUATION frame without prior !FIN");
}
// Be careful to use the original opcode
break;
case OpCode.CLOSE:
frame = new CloseFrame();
// control frame validation
if (!fin) {
throw new ProtocolException("Fragmented Close Frame [" + OpCode.name(opcode) + "]");
}
break;
case OpCode.PING:
frame = new PingFrame();
// control frame validation
if (!fin) {
throw new ProtocolException("Fragmented Ping Frame [" + OpCode.name(opcode) + "]");
}
break;
case OpCode.PONG:
frame = new PongFrame();
// control frame validation
if (!fin) {
throw new ProtocolException("Fragmented Pong Frame [" + OpCode.name(opcode) + "]");
}
break;
}
frame.setFin(fin);
// Are any flags set?
if ((b & 0x70) != 0) {
/*
* RFC 6455 Section 5.2
*
* MUST be 0 unless an extension is negotiated that defines meanings for non-zero values. If a nonzero value is received and none of the
* negotiated extensions defines the meaning of such a nonzero value, the receiving endpoint MUST _Fail the WebSocket Connection_.
*/
if ((b & 0x40) != 0) {
if (isRsv1InUse())
frame.setRsv1(true);
else {
String err = "RSV1 not allowed to be set";
if (LOG.isDebugEnabled()) {
LOG.debug(err + ": Remaining buffer: {}", BufferUtil.toDetailString(buffer));
}
throw new ProtocolException(err);
}
}
if ((b & 0x20) != 0) {
if (isRsv2InUse())
frame.setRsv2(true);
else {
String err = "RSV2 not allowed to be set";
if (LOG.isDebugEnabled()) {
LOG.debug(err + ": Remaining buffer: {}", BufferUtil.toDetailString(buffer));
}
throw new ProtocolException(err);
}
}
if ((b & 0x10) != 0) {
if (isRsv3InUse())
frame.setRsv3(true);
else {
String err = "RSV3 not allowed to be set";
if (LOG.isDebugEnabled()) {
LOG.debug(err + ": Remaining buffer: {}", BufferUtil.toDetailString(buffer));
}
throw new ProtocolException(err);
}
}
}
state = State.PAYLOAD_LEN;
break;
}
case PAYLOAD_LEN:
{
byte b = buffer.get();
frame.setMasked((b & 0x80) != 0);
payloadLength = (byte) (0x7F & b);
if (// 0x7F
payloadLength == 127) {
// length 8 bytes (extended payload length)
payloadLength = 0;
state = State.PAYLOAD_LEN_BYTES;
cursor = 8;
// continue onto next state
break;
} else if (// 0x7E
payloadLength == 126) {
// length 2 bytes (extended payload length)
payloadLength = 0;
state = State.PAYLOAD_LEN_BYTES;
cursor = 2;
// continue onto next state
break;
}
assertSanePayloadLength(payloadLength);
if (frame.isMasked()) {
state = State.MASK;
} else {
// special case for empty payloads (no more bytes left in buffer)
if (payloadLength == 0) {
state = State.START;
return true;
}
maskProcessor.reset(frame);
state = State.PAYLOAD;
}
break;
}
case PAYLOAD_LEN_BYTES:
{
byte b = buffer.get();
--cursor;
payloadLength |= (b & 0xFF) << (8 * cursor);
if (cursor == 0) {
assertSanePayloadLength(payloadLength);
if (frame.isMasked()) {
state = State.MASK;
} else {
// special case for empty payloads (no more bytes left in buffer)
if (payloadLength == 0) {
state = State.START;
return true;
}
maskProcessor.reset(frame);
state = State.PAYLOAD;
}
}
break;
}
case MASK:
{
byte[] m = new byte[4];
frame.setMask(m);
if (buffer.remaining() >= 4) {
buffer.get(m, 0, 4);
// special case for empty payloads (no more bytes left in buffer)
if (payloadLength == 0) {
state = State.START;
return true;
}
maskProcessor.reset(frame);
state = State.PAYLOAD;
} else {
state = State.MASK_BYTES;
cursor = 4;
}
break;
}
case MASK_BYTES:
{
byte b = buffer.get();
frame.getMask()[4 - cursor] = b;
--cursor;
if (cursor == 0) {
// special case for empty payloads (no more bytes left in buffer)
if (payloadLength == 0) {
state = State.START;
return true;
}
maskProcessor.reset(frame);
state = State.PAYLOAD;
}
break;
}
case PAYLOAD:
{
frame.assertValid();
if (parsePayload(buffer)) {
// special check for close
if (frame.getOpCode() == OpCode.CLOSE) {
// TODO: yuck. Don't create an object to do validation checks!
new CloseInfo(frame);
}
state = State.START;
// we have a frame!
return true;
}
break;
}
}
}
return false;
}
use of org.eclipse.jetty.websocket.common.frames.CloseFrame in project jetty.project by eclipse.
the class CloseInfo method asFrame.
public CloseFrame asFrame() {
CloseFrame frame = new CloseFrame();
frame.setFin(true);
if ((statusCode >= 1000) && (statusCode != StatusCode.NO_CLOSE) && (statusCode != StatusCode.NO_CODE)) {
if (statusCode == StatusCode.FAILED_TLS_HANDSHAKE) {
throw new ProtocolException("Close Frame with status code " + statusCode + " not allowed (per RFC6455)");
}
frame.setPayload(asByteBuffer());
}
return frame;
}
use of org.eclipse.jetty.websocket.common.frames.CloseFrame in project jetty.project by eclipse.
the class CloseInfoTest method testAnonymousClose.
/**
* A test where no close is provided
*/
@Test
public void testAnonymousClose() {
CloseInfo close = new CloseInfo();
assertThat("close.code", close.getStatusCode(), is(NO_CODE));
assertThat("close.reason", close.getReason(), nullValue());
CloseFrame frame = close.asFrame();
assertThat("close frame op code", frame.getOpCode(), is(OpCode.CLOSE));
// should result in no payload
assertThat("close frame has payload", frame.hasPayload(), is(false));
assertThat("close frame payload length", frame.getPayloadLength(), is(0));
}
use of org.eclipse.jetty.websocket.common.frames.CloseFrame in project jetty.project by eclipse.
the class WebSocketFrameTest method testLaxInvalidClose.
@Test
public void testLaxInvalidClose() {
WebSocketFrame frame = new CloseFrame().setFin(false);
ByteBuffer actual = generateWholeFrame(laxGenerator, frame);
String expected = "0800";
assertFrameHex("Lax Invalid Close Frame", expected, actual);
}
Aggregations