use of io.crossbar.autobahn.websocket.exceptions.WebSocketException in project autobahn-java by crossbario.
the class EchoClientActivity method start.
private void start() {
String hostname = mHostname.getText().toString();
if (!hostname.startsWith("ws://") && !hostname.startsWith("wss://")) {
hostname = "ws://" + hostname;
}
String port = mPort.getText().toString();
String wsuri;
if (!port.isEmpty()) {
wsuri = hostname + ":" + port;
} else {
wsuri = hostname;
}
mStatusline.setText("Status: Connecting to " + wsuri + " ..");
setButtonDisconnect();
WebSocketOptions connectOptions = new WebSocketOptions();
connectOptions.setReconnectInterval(5000);
try {
mConnection.connect(wsuri, new WebSocketConnectionHandler() {
@Override
public void onOpen() {
mStatusline.setText("Status: Connected to " + wsuri);
savePrefs();
mSendMessage.setEnabled(true);
mMessage.setEnabled(true);
}
@Override
public void onMessage(String payload) {
alert("Got echo: " + payload);
}
@Override
public void onClose(int code, String reason) {
alert("Connection lost.");
mStatusline.setText("Status: Ready.");
setButtonConnect();
mSendMessage.setEnabled(false);
mMessage.setEnabled(false);
}
}, connectOptions);
} catch (WebSocketException e) {
Log.d(TAG, e.toString());
}
}
use of io.crossbar.autobahn.websocket.exceptions.WebSocketException in project autobahn-java by crossbario.
the class WebSocketReader method processData.
/**
* Process incoming WebSockets data (after handshake).
*/
private boolean processData() throws Exception {
// outside frame?
if (mFrameHeader == null) {
// need at least 2 bytes from WS frame header to start processing
if (mPosition >= 2) {
byte b0 = mMessageData[0];
boolean fin = (b0 & 0x80) != 0;
int rsv = (b0 & 0x70) >> 4;
int opcode = b0 & 0x0f;
byte b1 = mMessageData[1];
boolean masked = (b1 & 0x80) != 0;
int payload_len1 = b1 & 0x7f;
if (rsv != 0) {
throw new WebSocketException("RSV != 0 and no extension negotiated");
}
if (masked) {
// currently, we don't allow this. need to see whats the final spec.
throw new WebSocketException("masked server frame");
}
if (opcode > 7) {
// control frame
if (!fin) {
throw new WebSocketException("fragmented control frame");
}
if (payload_len1 > 125) {
throw new WebSocketException("control frame with payload length > 125 octets");
}
if (opcode != 8 && opcode != 9 && opcode != 10) {
throw new WebSocketException("control frame using reserved opcode " + opcode);
}
if (opcode == 8 && payload_len1 == 1) {
throw new WebSocketException("received close control frame with payload len 1");
}
} else {
// message frame
if (opcode != 0 && opcode != 1 && opcode != 2) {
throw new WebSocketException("data frame using reserved opcode " + opcode);
}
if (!mInsideMessage && opcode == 0) {
throw new WebSocketException("received continuation data frame outside fragmented message");
}
if (mInsideMessage && opcode != 0) {
throw new WebSocketException("received non-continuation data frame while inside fragmented message");
}
}
int mask_len = masked ? 4 : 0;
int header_len;
if (payload_len1 < 126) {
header_len = 2 + mask_len;
} else if (payload_len1 == 126) {
header_len = 2 + 2 + mask_len;
} else if (payload_len1 == 127) {
header_len = 2 + 8 + mask_len;
} else {
// should not arrive here
throw new Exception("logic error");
}
// continue when complete frame header is available
if (mPosition >= header_len) {
// determine frame payload length
int i = 2;
long payload_len;
if (payload_len1 == 126) {
payload_len = ((0xff & mMessageData[i]) << 8) | (0xff & mMessageData[i + 1]);
if (payload_len < 126) {
throw new WebSocketException("invalid data frame length (not using minimal length encoding)");
}
i += 2;
} else if (payload_len1 == 127) {
if ((0x80 & mMessageData[i]) != 0) {
throw new WebSocketException("invalid data frame length (> 2^63)");
}
payload_len = ((long) (0xff & mMessageData[i]) << 56) | ((long) (0xff & mMessageData[i + 1]) << 48) | ((long) (0xff & mMessageData[i + 2]) << 40) | ((long) (0xff & mMessageData[i + 3]) << 32) | ((long) (0xff & mMessageData[i + 4]) << 24) | ((long) (0xff & mMessageData[i + 5]) << 16) | ((long) (0xff & mMessageData[i + 6]) << 8) | ((long) (0xff & mMessageData[i + 7]));
if (payload_len < 65536) {
throw new WebSocketException("invalid data frame length (not using minimal length encoding)");
}
i += 8;
} else {
payload_len = payload_len1;
}
// immediately bail out on frame too large
if (payload_len > mOptions.getMaxFramePayloadSize()) {
throw new WebSocketException("frame payload too large");
}
// save frame header metadata
mFrameHeader = new FrameHeader();
mFrameHeader.mOpcode = opcode;
mFrameHeader.mFin = fin;
mFrameHeader.mReserved = rsv;
mFrameHeader.mPayloadLen = (int) payload_len;
mFrameHeader.mHeaderLen = header_len;
mFrameHeader.mTotalLen = mFrameHeader.mHeaderLen + mFrameHeader.mPayloadLen;
if (masked) {
mFrameHeader.mMask = new byte[4];
for (int j = 0; j < 4; ++j) {
mFrameHeader.mMask[i] = (byte) (0xff & mMessageData[i + j]);
}
i += 4;
} else {
mFrameHeader.mMask = null;
}
// continue processing when payload empty or completely buffered
return mFrameHeader.mPayloadLen == 0 || mPosition >= mFrameHeader.mTotalLen;
} else {
// need more data
return false;
}
} else {
// need more data
return false;
}
} else {
// see if we buffered complete frame
if (mPosition >= mFrameHeader.mTotalLen) {
// cut out frame payload
byte[] framePayload = null;
if (mFrameHeader.mPayloadLen > 0) {
framePayload = new byte[mFrameHeader.mPayloadLen];
System.arraycopy(mMessageData, mFrameHeader.mHeaderLen, framePayload, 0, mFrameHeader.mPayloadLen);
}
mMessageData = Arrays.copyOfRange(mMessageData, mFrameHeader.mTotalLen, mMessageData.length + mFrameHeader.mTotalLen);
mPosition -= mFrameHeader.mTotalLen;
if (mFrameHeader.mOpcode > 7) {
// control frame
if (mFrameHeader.mOpcode == 8) {
// CLOSE_STATUS_CODE_NULL : no status code received
int code = 1005;
String reason = null;
if (mFrameHeader.mPayloadLen >= 2) {
// parse and check close code - see http://tools.ietf.org/html/rfc6455#section-7.4
code = (framePayload[0] & 0xff) * 256 + (framePayload[1] & 0xff);
if (code < 1000 || (code >= 1000 && code <= 2999 && code != 1000 && code != 1001 && code != 1002 && code != 1003 && code != 1007 && code != 1008 && code != 1009 && code != 1010 && code != 1011) || code >= 5000) {
throw new WebSocketException("invalid close code " + code);
}
// parse and check close reason
if (mFrameHeader.mPayloadLen > 2) {
byte[] ra = new byte[mFrameHeader.mPayloadLen - 2];
System.arraycopy(framePayload, 2, ra, 0, mFrameHeader.mPayloadLen - 2);
Utf8Validator val = new Utf8Validator();
val.validate(ra);
if (!val.isValid()) {
throw new WebSocketException("invalid close reasons (not UTF-8)");
} else {
reason = new String(ra, "UTF-8");
}
}
}
onClose(code, reason);
// We have received a close, so lets set the state as early as possible.
// It seems that Handler() has a lag to deliver a message, so if the onClose
// is sent to master and just after that the other peer closes the socket,
// BufferedInputReader.read() will throw an exception which results in
// our code sending a ConnectionLost() message to master.
mState = STATE_CLOSED;
} else if (mFrameHeader.mOpcode == 9) {
// dispatch WS ping
onPing(framePayload);
} else if (mFrameHeader.mOpcode == 10) {
// dispatch WS pong
onPong(framePayload);
} else {
// should not arrive here (handled before)
throw new Exception("logic error");
}
} else {
if (!mInsideMessage) {
// new message started
mInsideMessage = true;
mMessageOpcode = mFrameHeader.mOpcode;
if (mMessageOpcode == 1 && mOptions.getValidateIncomingUtf8()) {
mUtf8Validator.reset();
}
}
if (framePayload != null) {
// immediately bail out on message too large
if (mMessagePayload.size() + framePayload.length > mOptions.getMaxMessagePayloadSize()) {
throw new WebSocketException("message payload too large");
}
// validate incoming UTF-8
if (mMessageOpcode == 1 && mOptions.getValidateIncomingUtf8() && !mUtf8Validator.validate(framePayload)) {
throw new WebSocketException("invalid UTF-8 in text message payload");
}
// buffer frame payload for message
mMessagePayload.write(framePayload);
}
// on final frame ..
if (mFrameHeader.mFin) {
if (mMessageOpcode == 1) {
// verify that UTF-8 ends on codepoint
if (mOptions.getValidateIncomingUtf8() && !mUtf8Validator.isValid()) {
throw new WebSocketException("UTF-8 text message payload ended within Unicode code point");
}
// deliver text message
if (mOptions.getReceiveTextMessagesRaw()) {
// dispatch WS text message as raw (but validated) UTF-8
onRawTextMessage(mMessagePayload.toByteArray());
} else {
// dispatch WS text message as Java String (previously already validated)
String s = new String(mMessagePayload.toByteArray(), "UTF-8");
onTextMessage(s);
}
} else if (mMessageOpcode == 2) {
// dispatch WS binary message
onBinaryMessage(mMessagePayload.toByteArray());
} else {
// should not arrive here (handled before)
throw new Exception("logic error");
}
// ok, message completed - reset all
mInsideMessage = false;
mMessagePayload.reset();
}
}
// reset frame
mFrameHeader = null;
// reprocess if more data left
return mPosition > 0;
} else {
// need more data
return false;
}
}
}
use of io.crossbar.autobahn.websocket.exceptions.WebSocketException in project autobahn-java by crossbario.
the class WebSocketReader method run.
/**
* Run the background reader thread loop.
*/
@Override
public void run() {
LOGGER.d("Running");
try {
do {
// blocking read on socket
int len = mBufferedStream.read(mMessageData, mPosition, mMessageData.length - mPosition);
mPosition += len;
if (len > 0) {
mLastReadTime = System.currentTimeMillis();
// process buffered data
while (consumeData()) {
}
} else if (mState == STATE_CLOSED) {
mStopped = true;
} else if (len < 0) {
LOGGER.d("run() : ConnectionLost");
notify(new ConnectionLost(null));
mStopped = true;
}
} while (!mStopped);
} catch (WebSocketException e) {
LOGGER.d("run() : WebSocketException (" + e.toString() + ")");
// wrap the exception and notify master
notify(new ProtocolViolation(e));
} catch (SocketException e) {
// eat the exception if we are already in STATE_CLOSED.
if (mState != STATE_CLOSED && !mSocket.isClosed()) {
LOGGER.d("run() : SocketException (" + e.toString() + ")");
// wrap the exception and notify master
notify(new ConnectionLost(null));
}
} catch (Exception e) {
LOGGER.d("run() : Exception (" + e.toString() + ")");
// wrap the exception and notify master
notify(new Error(e));
} finally {
mStopped = true;
}
LOGGER.d("Ended");
}
use of io.crossbar.autobahn.websocket.exceptions.WebSocketException in project autobahn-java by crossbario.
the class WebSocketConnection method connect.
@Override
public void connect(String wsUri, String[] wsSubprotocols, IWebSocketConnectionHandler wsHandler, WebSocketOptions options, Map<String, String> headers) throws WebSocketException {
//
if (isConnected()) {
throw new WebSocketException("already connected");
}
//
try {
mWsUri = new URI(wsUri);
if (!mWsUri.getScheme().equals("ws") && !mWsUri.getScheme().equals("wss")) {
throw new WebSocketException("unsupported scheme for WebSockets URI");
}
mWsScheme = mWsUri.getScheme();
if (mWsUri.getPort() == -1) {
if (mWsScheme.equals("ws")) {
mWsPort = 80;
} else {
mWsPort = 443;
}
} else {
mWsPort = mWsUri.getPort();
}
if (mWsUri.getHost() == null) {
throw new WebSocketException("no host specified in WebSockets URI");
} else {
mWsHost = mWsUri.getHost();
}
if (mWsUri.getRawPath() == null || mWsUri.getRawPath().equals("")) {
mWsPath = "/";
} else {
mWsPath = mWsUri.getRawPath();
}
if (mWsUri.getRawQuery() == null || mWsUri.getRawQuery().equals("")) {
mWsQuery = null;
} else {
mWsQuery = mWsUri.getRawQuery();
}
} catch (URISyntaxException e) {
throw new WebSocketException("invalid WebSockets URI");
}
mWsSubprotocols = wsSubprotocols;
mWsHeaders = headers;
mWsHandler = wsHandler;
// make copy of options!
mOptions = new WebSocketOptions(options);
// set connection active
mActive = true;
// reset value
onCloseCalled = false;
// use async connector on short-lived background thread
new WebSocketConnector().start();
}
Aggregations