/** * @param remote Indicates who "generated" <code>code</code>.<br> * <code>true</code> means that this endpoint received the <code>code</code> from the other * endpoint.<br> * false means this endpoint decided to send the given code,<br> * <code>remote</code> may also be true if this endpoint started the closing handshake since * the other endpoint may not simply echo the <code>code</code> but close the connection the * same time this endpoint does do but with an other <code>code</code>. <br> */ protected synchronized void closeConnection(int code, String message, boolean remote) { if (readystate == READYSTATE.CLOSED) { return; } if (key != null) { // key.attach( null ); //see issue #114 key.cancel(); } if (channel != null) { try { channel.close(); } catch (IOException e) { wsl.onWebsocketError(this, e); } } try { this.wsl.onWebsocketClose(this, code, message, remote); } catch (RuntimeException e) { wsl.onWebsocketError(this, e); } if (draft != null) draft.reset(); handshakerequest = null; readystate = READYSTATE.CLOSED; this.outQueue.clear(); }
private void open(Handshakedata d) { if (DEBUG) System.out.println("open using draft: " + draft.getClass().getSimpleName()); readystate = READYSTATE.OPEN; try { wsl.onWebsocketOpen(this, d); } catch (RuntimeException e) { wsl.onWebsocketError(this, e); } }
/** {@inheritDoc} */ @Override public final void onFailure(Throwable t) { for (WebSocketListener listener : listeners) { if (!ok.get() && webSocket != null) { webSocket.addWebSocketListener(listener); } listener.onError(t); } }
/** {@inheritDoc} */ @Override public final void onSuccess(WebSocket webSocket) { this.webSocket = webSocket; for (WebSocketListener listener : listeners) { webSocket.addWebSocketListener(listener); listener.onOpen(webSocket); } ok.set(true); }
/** {@inheritDoc} */ @Override public final WebSocket onCompleted() throws Exception { if (status != SWITCHING_PROTOCOLS) { IllegalStateException e = new IllegalStateException("Invalid Status Code " + status); for (WebSocketListener listener : listeners) { listener.onError(e); } throw e; } return webSocket; }
/** {@inheritDoc} */ @Override public final void onSuccess(WebSocket webSocket) { this.webSocket = webSocket; for (WebSocketListener listener : listeners) { webSocket.addWebSocketListener(listener); listener.onOpen(webSocket); } if (isNonEmpty(bufferedFrames)) { for (Runnable bufferedFrame : bufferedFrames) { bufferedFrame.run(); } bufferedFrames = null; } ok.set(true); }
public final void onClose(WebSocket webSocket, int status, String reasonPhrase) { // Connect failure if (this.webSocket == null) this.webSocket = webSocket; for (WebSocketListener listener : listeners) { if (webSocket != null) { webSocket.addWebSocketListener(listener); } listener.onClose(webSocket); if (listener instanceof WebSocketCloseCodeReasonListener) { WebSocketCloseCodeReasonListener.class .cast(listener) .onClose(webSocket, status, reasonPhrase); } } }
/** {@inheritDoc} */ @Override public final WebSocket onCompleted() throws Exception { if (status != 101) { IllegalStateException e = new IllegalStateException("Invalid Status Code " + status); for (WebSocketListener listener : listeners) { listener.onError(e); } throw e; } if (webSocket == null) { throw new NullPointerException("webSocket"); } return webSocket; }
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Request progress bar requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.activity_main); mAppView = (WebView) findViewById(R.id.webView1); mButton1 = (Button) findViewById(R.id.button1); mEditText = (EditText) findViewById(R.id.editText1); mTimePicker = (TimePicker) findViewById(R.id.timePicker1); mSocketSpinner = (Spinner) findViewById(R.id.spinner1); mSendTools = (LinearLayout) findViewById(R.id.sendTools); mProgresBar = (ProgressBar) findViewById(R.id.progressBar); setProgressBarIndeterminateVisibility(true); // Add listener for spinner addListenerOnSpinnerItemSelection(); // Choose selected web socket address mSelectedSocketPos = mSocketSpinner.getSelectedItemPosition(); mWebSocketAddress = getResources().getStringArray(R.array.sockets)[mSelectedSocketPos]; // webSocketAddress = WEB_SOCKET_ADDRESS; // Set web socket address and add listener setWebSocket(mWebSocketAddress); // connect Toast.makeText(getApplicationContext(), "Connecting", Toast.LENGTH_SHORT).show(); mWebSocketListener.connectTh(); }
/** * Close Web Socket connection, and reconnect if needed * * @param reconnect - if true reconnect will be performed */ private void closeWebSocket(boolean reconnect) { this.mReconnect = reconnect; // Disable send button setButtonSendEnabledT(false); // Close current connection mWebSocketListener.close(); }
protected synchronized void flushAndClose(int code, String message, boolean remote) { if (flushandclosestate) { return; } closecode = code; closemessage = message; closedremotely = remote; flushandclosestate = true; wsl.onWriteDemand( this); // ensures that all outgoing frames are flushed before closing the connection try { wsl.onWebsocketClosing(this, code, message, remote); } catch (RuntimeException e) { wsl.onWebsocketError(this, e); } if (draft != null) draft.reset(); handshakerequest = null; }
public void startHandshake(ClientHandshakeBuilder handshakedata) throws InvalidHandshakeException { assert (readystate != READYSTATE.CONNECTING) : "shall only be called once"; // Store the Handshake Request we are about to send this.handshakerequest = draft.postProcessHandshakeRequestAsClient(handshakedata); // Notify Listener try { wsl.onWebsocketHandshakeSentAsClient(this, this.handshakerequest); } catch (InvalidDataException e) { // Stop if the client code throws an exception throw new InvalidHandshakeException("Handshake data rejected by client."); } catch (RuntimeException e) { wsl.onWebsocketError(this, e); throw new InvalidHandshakeException("rejected because of" + e); } // Send write(draft.createHandshake(this.handshakerequest, role)); }
private void close(int code, String message, boolean remote) { if (readystate != READYSTATE.CLOSING && readystate != READYSTATE.CLOSED) { if (readystate == READYSTATE.OPEN) { if (code == CloseFrame.ABNORMAL_CLOSE) { assert (remote == false); readystate = READYSTATE.CLOSING; flushAndClose(code, message, false); return; } if (draft.getCloseHandshakeType() != CloseHandshakeType.NONE) { try { if (!remote) { try { wsl.onWebsocketCloseInitiated(this, code, message); } catch (RuntimeException e) { wsl.onWebsocketError(this, e); } } sendFrame(new CloseFrameBuilder(code, message)); } catch (InvalidDataException e) { wsl.onWebsocketError(this, e); flushAndClose(CloseFrame.ABNORMAL_CLOSE, "generated frame is invalid", false); } } flushAndClose(code, message, remote); } else if (code == CloseFrame.FLASHPOLICY) { assert (remote); flushAndClose(CloseFrame.FLASHPOLICY, message, true); } else { flushAndClose(CloseFrame.NEVER_CONNECTED, message, false); } if (code == CloseFrame.PROTOCOL_ERROR) // this endpoint found a PROTOCOL_ERROR flushAndClose(code, message, remote); readystate = READYSTATE.CLOSING; tmpHandshakeBytes = null; return; } }
private void write(ByteBuffer buf) { if (DEBUG) System.out.println( "write(" + buf.remaining() + "): {" + (buf.remaining() > 1000 ? "too big to display" : new String(buf.array())) + "}"); outQueue.add(buf); /*try { outQueue.put( buf ); } catch ( InterruptedException e ) { write( buf ); Thread.currentThread().interrupt(); // keep the interrupted status e.printStackTrace(); }*/ wsl.onWriteDemand(this); }
/** * Button callback function * * @param v - related Button view */ public void onClickButton1(View v) { if (mEditText.getText().length() > 0) { mButton1.setEnabled(false); mWebSocketListener.send(mEditText.getText().toString()); } }
@Override public InetSocketAddress getLocalSocketAddress() { return wsl.getLocalSocketAddress(this); }
@Override public InetSocketAddress getRemoteSocketAddress() { return wsl.getRemoteSocketAddress(this); }
private void addWebSocketEventListener() { mWebSocketListener.addWebSocketEventListener( new WebSocketEventListener() { public void handleOpenEvent() { Log.v("handleOpenEvent", "OPENED"); String customHtml = "<html><body>Conected</body></html>"; mAppView.loadData(customHtml, "text/html", "UTF-8"); // only for appView if (mSelectedSocketPos == DEFAULT_POS) { // editText.setEnabled(false); setTonePickerVisibilityT(true); } else { setSendToolsVisibilityT(true); setButtonSendEnabledT(true); mEditText.setEnabled(true); } setProgressBarVisibilityT(false); } public void handleSendEvent(String newMsg) { Log.v("handleOpenEvent", "RECEIVED"); String customHtml; if (mSelectedSocketPos == DEFAULT_POS) { // default socket handle TimePicker customHtml = "<html><body>" + newMsg + "<br/>" + mOldMessage + "</body></html>"; updateTimePickerT(getHourFromString(newMsg), getMinuteFromString(newMsg)); } else { customHtml = "<html><body><font color=\"red\">RESPONSE: </font>" + newMsg + "<br/>" + mOldMessage + "</body></html>"; setEditTextT(""); setButtonSendEnabledT(true); } mAppView.loadData(customHtml, "text/html", "UTF-8"); if (mSelectedSocketPos != DEFAULT_POS) { mOldMessage = newMsg + "<br/>" + mOldMessage; // to store history } } public void handleCloseEvent() { Log.v("handleOpenEvent", "CLOSED"); // Toast.makeText(getApplicationContext(), "Closed", Toast.LENGTH_SHORT).show(); if (mReconnect) { Toast.makeText(getApplicationContext(), "Reconnecting", Toast.LENGTH_SHORT).show(); mReconnect = RECONNECT_DEFAULT; // Set web socket address and add listener setWebSocket(mWebSocketAddress); // connect mWebSocketListener.connectTh(); } else { // setButtonSendEnabledT(true); // enable button } } }); }
private void decodeFrames(ByteBuffer socketBuffer) { List<Framedata> frames; try { frames = draft.translateFrame(socketBuffer); for (Framedata f : frames) { if (DEBUG) System.out.println("matched frame: " + f); Opcode curop = f.getOpcode(); boolean fin = f.isFin(); if (curop == Opcode.CLOSING) { int code = CloseFrame.NOCODE; String reason = ""; if (f instanceof CloseFrame) { CloseFrame cf = (CloseFrame) f; code = cf.getCloseCode(); reason = cf.getMessage(); } if (readystate == READYSTATE.CLOSING) { // complete the close handshake by disconnecting closeConnection(code, reason, true); } else { // echo close handshake if (draft.getCloseHandshakeType() == CloseHandshakeType.TWOWAY) close(code, reason, true); else flushAndClose(code, reason, false); } continue; } else if (curop == Opcode.PING) { wsl.onWebsocketPing(this, f); continue; } else if (curop == Opcode.PONG) { wsl.onWebsocketPong(this, f); continue; } else if (!fin || curop == Opcode.CONTINUOUS) { if (curop != Opcode.CONTINUOUS) { if (current_continuous_frame_opcode != null) throw new InvalidDataException( CloseFrame.PROTOCOL_ERROR, "Previous continuous frame sequence not completed."); current_continuous_frame_opcode = curop; } else if (fin) { if (current_continuous_frame_opcode == null) throw new InvalidDataException( CloseFrame.PROTOCOL_ERROR, "Continuous frame sequence was not started."); current_continuous_frame_opcode = null; } else if (current_continuous_frame_opcode == null) { throw new InvalidDataException( CloseFrame.PROTOCOL_ERROR, "Continuous frame sequence was not started."); } try { wsl.onWebsocketMessageFragment(this, f); } catch (RuntimeException e) { wsl.onWebsocketError(this, e); } } else if (current_continuous_frame_opcode != null) { throw new InvalidDataException( CloseFrame.PROTOCOL_ERROR, "Continuous frame sequence not completed."); } else if (curop == Opcode.TEXT) { try { wsl.onWebsocketMessage(this, Charsetfunctions.stringUtf8(f.getPayloadData())); } catch (RuntimeException e) { wsl.onWebsocketError(this, e); } } else if (curop == Opcode.BINARY) { try { wsl.onWebsocketMessage(this, f.getPayloadData()); } catch (RuntimeException e) { wsl.onWebsocketError(this, e); } } else { throw new InvalidDataException( CloseFrame.PROTOCOL_ERROR, "non control or continious frame expected"); } } } catch (InvalidDataException e1) { wsl.onWebsocketError(this, e1); close(e1); return; } }
/** * Returns whether the handshake phase has is completed. In case of a broken handshake this will * be never the case. */ private boolean decodeHandshake(ByteBuffer socketBufferNew) { ByteBuffer socketBuffer; if (tmpHandshakeBytes.capacity() == 0) { socketBuffer = socketBufferNew; } else { if (tmpHandshakeBytes.remaining() < socketBufferNew.remaining()) { ByteBuffer buf = ByteBuffer.allocate(tmpHandshakeBytes.capacity() + socketBufferNew.remaining()); tmpHandshakeBytes.flip(); buf.put(tmpHandshakeBytes); tmpHandshakeBytes = buf; } tmpHandshakeBytes.put(socketBufferNew); tmpHandshakeBytes.flip(); socketBuffer = tmpHandshakeBytes; } socketBuffer.mark(); try { if (draft == null) { HandshakeState isflashedgecase = isFlashEdgeCase(socketBuffer); if (isflashedgecase == HandshakeState.MATCHED) { try { write(ByteBuffer.wrap(Charsetfunctions.utf8Bytes(wsl.getFlashPolicy(this)))); close(CloseFrame.FLASHPOLICY, ""); } catch (InvalidDataException e) { close( CloseFrame.ABNORMAL_CLOSE, "remote peer closed connection before flashpolicy could be transmitted", true); } return false; } } HandshakeState handshakestate = null; try { if (role == Role.SERVER) { if (draft == null) { for (Draft d : knownDrafts) { d = d.copyInstance(); try { d.setParseMode(role); socketBuffer.reset(); Handshakedata tmphandshake = d.translateHandshake(socketBuffer); if (tmphandshake instanceof ClientHandshake == false) { flushAndClose(CloseFrame.PROTOCOL_ERROR, "wrong http function", false); return false; } ClientHandshake handshake = (ClientHandshake) tmphandshake; handshakestate = d.acceptHandshakeAsServer(handshake); if (handshakestate == HandshakeState.MATCHED) { resourceDescriptor = handshake.getResourceDescriptor(); ServerHandshakeBuilder response; try { response = wsl.onWebsocketHandshakeReceivedAsServer(this, d, handshake); } catch (InvalidDataException e) { flushAndClose(e.getCloseCode(), e.getMessage(), false); return false; } catch (RuntimeException e) { wsl.onWebsocketError(this, e); flushAndClose(CloseFrame.NEVER_CONNECTED, e.getMessage(), false); return false; } write( d.createHandshake( d.postProcessHandshakeResponseAsServer(handshake, response), role)); draft = d; open(handshake); return true; } } catch (InvalidHandshakeException e) { // go on with an other draft } } if (draft == null) { close(CloseFrame.PROTOCOL_ERROR, "no draft matches"); } return false; } else { // special case for multiple step handshakes Handshakedata tmphandshake = draft.translateHandshake(socketBuffer); if (tmphandshake instanceof ClientHandshake == false) { flushAndClose(CloseFrame.PROTOCOL_ERROR, "wrong http function", false); return false; } ClientHandshake handshake = (ClientHandshake) tmphandshake; handshakestate = draft.acceptHandshakeAsServer(handshake); if (handshakestate == HandshakeState.MATCHED) { open(handshake); return true; } else { close(CloseFrame.PROTOCOL_ERROR, "the handshake did finaly not match"); } return false; } } else if (role == Role.CLIENT) { draft.setParseMode(role); Handshakedata tmphandshake = draft.translateHandshake(socketBuffer); if (tmphandshake instanceof ServerHandshake == false) { flushAndClose(CloseFrame.PROTOCOL_ERROR, "wrong http function", false); return false; } ServerHandshake handshake = (ServerHandshake) tmphandshake; handshakestate = draft.acceptHandshakeAsClient(handshakerequest, handshake); if (handshakestate == HandshakeState.MATCHED) { try { wsl.onWebsocketHandshakeReceivedAsClient(this, handshakerequest, handshake); } catch (InvalidDataException e) { flushAndClose(e.getCloseCode(), e.getMessage(), false); return false; } catch (RuntimeException e) { wsl.onWebsocketError(this, e); flushAndClose(CloseFrame.NEVER_CONNECTED, e.getMessage(), false); return false; } open(handshake); return true; } else { close(CloseFrame.PROTOCOL_ERROR, "draft " + draft + " refuses handshake"); } } } catch (InvalidHandshakeException e) { close(e); } } catch (IncompleteHandshakeException e) { if (tmpHandshakeBytes.capacity() == 0) { socketBuffer.reset(); int newsize = e.getPreferedSize(); if (newsize == 0) { newsize = socketBuffer.capacity() + 16; } else { assert (e.getPreferedSize() >= socketBuffer.remaining()); } tmpHandshakeBytes = ByteBuffer.allocate(newsize); tmpHandshakeBytes.put(socketBufferNew); // tmpHandshakeBytes.flip(); } else { tmpHandshakeBytes.position(tmpHandshakeBytes.limit()); tmpHandshakeBytes.limit(tmpHandshakeBytes.capacity()); } } return false; }