Search in sources :

Example 1 with WebSocketException

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());
    }
}
Also used : WebSocketOptions(io.crossbar.autobahn.websocket.types.WebSocketOptions) WebSocketException(io.crossbar.autobahn.websocket.exceptions.WebSocketException) WebSocketConnectionHandler(io.crossbar.autobahn.websocket.WebSocketConnectionHandler)

Example 2 with WebSocketException

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;
        }
    }
}
Also used : WebSocketException(io.crossbar.autobahn.websocket.exceptions.WebSocketException) Utf8Validator(io.crossbar.autobahn.websocket.utils.Utf8Validator) SocketException(java.net.SocketException) WebSocketException(io.crossbar.autobahn.websocket.exceptions.WebSocketException) IOException(java.io.IOException) UnsupportedEncodingException(java.io.UnsupportedEncodingException)

Example 3 with WebSocketException

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");
}
Also used : SocketException(java.net.SocketException) WebSocketException(io.crossbar.autobahn.websocket.exceptions.WebSocketException) WebSocketException(io.crossbar.autobahn.websocket.exceptions.WebSocketException) ProtocolViolation(io.crossbar.autobahn.websocket.messages.ProtocolViolation) ServerError(io.crossbar.autobahn.websocket.messages.ServerError) Error(io.crossbar.autobahn.websocket.messages.Error) ConnectionLost(io.crossbar.autobahn.websocket.messages.ConnectionLost) SocketException(java.net.SocketException) WebSocketException(io.crossbar.autobahn.websocket.exceptions.WebSocketException) IOException(java.io.IOException) UnsupportedEncodingException(java.io.UnsupportedEncodingException)

Example 4 with WebSocketException

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();
}
Also used : WebSocketOptions(io.crossbar.autobahn.websocket.types.WebSocketOptions) WebSocketException(io.crossbar.autobahn.websocket.exceptions.WebSocketException) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI)

Aggregations

WebSocketException (io.crossbar.autobahn.websocket.exceptions.WebSocketException)4 WebSocketOptions (io.crossbar.autobahn.websocket.types.WebSocketOptions)2 IOException (java.io.IOException)2 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 SocketException (java.net.SocketException)2 WebSocketConnectionHandler (io.crossbar.autobahn.websocket.WebSocketConnectionHandler)1 ConnectionLost (io.crossbar.autobahn.websocket.messages.ConnectionLost)1 Error (io.crossbar.autobahn.websocket.messages.Error)1 ProtocolViolation (io.crossbar.autobahn.websocket.messages.ProtocolViolation)1 ServerError (io.crossbar.autobahn.websocket.messages.ServerError)1 Utf8Validator (io.crossbar.autobahn.websocket.utils.Utf8Validator)1 URI (java.net.URI)1 URISyntaxException (java.net.URISyntaxException)1