/** * Make the session aware of a {@link FutureToSendHandler} that will need to * be forcibly closed if the session closes before the * {@link FutureToSendHandler} completes. */ protected void registerFuture(FutureToSendHandler f2sh) { boolean fail = false; synchronized (stateLock) { // If the session has already been closed the any registered futures // will have been processed so the failure result for this future // needs to be set here. if (state == State.OPEN || f2sh.isCloseMessage()) { // WebSocket session is open or this is the close message futures.put(f2sh, f2sh); } else if (f2sh.isDone()) { // NO-OP. The future completed before the session closed so no // need to register in case the session closes before it // completes. } else { // Construct the exception outside of the sync block fail = true; } } if (fail) { IOException ioe = new IOException(sm.getString("wsSession.messageFailed")); SendResult sr = new SendResult(ioe); f2sh.onResult(sr); } }
public void broadcast(@Observes @LeaderDataQualifier String leaderboard) { for (final Session s : CLIENTS) { if (s != null && s.isOpen()) { /** * Asynchronous push */ s.getAsyncRemote().sendText(leaderboard, new SendHandler() { @Override public void onResult(SendResult result) { if (result.isOK()) { //Logger.getLogger(MeetupGroupsLiveLeaderboardEndpoint.class.getName()).log(Level.INFO, " sent to client {0}", s.getId()); } else { Logger.getLogger(MeetupGroupsLiveLeaderboardEndpoint.class.getName()).log(Level.SEVERE, "Could not send to client " + s.getId(), result.getException()); } } }); } } }
@Override public void onResult(SendResult result) { if (!result.isOK()) { // Message could not be sent. In this case, we don't // set isSendingMessage to false because we must assume the connection // broke (and onClose will be called), so we don't try to send // other messages. // As a precaution, we close the session (e.g. if a send timeout occured). // TODO: session.close() blocks, while this handler shouldn't block. // Ideally, there should be some abort() method that cancels the // connection immediately... try { session.close(); } catch (IOException ex) { // Ignore } } }
public void onOpen(final Session session, EndpointConfig endpointConfig) { session.getAsyncRemote().sendText( "Client Success!Your id is: " + session.getId()); session.addMessageHandler(new MessageHandler.Whole<String>() { @Override public void onMessage(String message) { session.getAsyncRemote().sendObject(message, new SendHandler() { @Override public void onResult(SendResult result) { System.out.println(session.getId() + ":" + result.isOK()); } }); } }); }
/** * sendMessage is executed snychronously to avoid tomcat nativelib crashes. * @param session * @param message * @param handler */ public synchronized static void sendMessage(final Session session, final String message, final SendHandler handler) { // synchronized (session) { try { session.getBasicRemote().sendText(message); handler.onResult(new SendResult()); } catch (IOException ex) { Logger.getLogger(WebSocket.class.getName()).log(Level.SEVERE, null, ex); handler.onResult(new SendResult(ex)); try { //close broken session session.close(); } catch (IOException ex1) { Logger.getLogger(WebSocket.class.getName()).log(Level.SEVERE, null, ex1); } } // } // } }
@OnMessage public void onWebSocketText(String message) { System.out.println("Received TEXT message: " + message); try { if ((session != null) && (session.isOpen())) { System.out.println("Echoing back text message "+message); session.getAsyncRemote().sendText("Received: "+message,new SendHandler(){ @Override public void onResult(SendResult arg0) { if (!arg0.isOK()){ System.out.println("Error Sending Response: "+arg0.getException().getMessage()); } } }); } } catch (Exception e){ System.out.println("Error: "+e.getMessage()); e.printStackTrace(); } }
@Override public void writeData(ByteBuffer data) { if (!this.isConnected()) { System.err.println("attempted to write before connection is open."); return; } new Thread(() -> this.dataSession.getAsyncRemote().sendBinary(data, new SendHandler() { @Override public void onResult(SendResult arg0) { RemoteP2PConnection.this.executor.execute(new Runnable() { @Override public void run() { if (RemoteP2PConnection.this.handler != null) RemoteP2PConnection.this.handler.onDataSent(RemoteP2PConnection.this); } }); } })).start(); }
@Override public void onOpen(final Session session, EndpointConfig ec) { session.addMessageHandler(new MessageHandler.Whole<String>() { @Override public void onMessage(String data) { System.out.println("Received (MyEndpointHandler) : " + data); session.getAsyncRemote().sendText(data, new SendHandler() { @Override public void onResult(SendResult sr) { if (sr.isOK()) { System.out.println("Message written to the socket (handler)"); } else { System.out.println("Message NOT written to the socket (handler)"); sr.getException().printStackTrace(); } } }); } }); }
/** * WebSocket 1.0. Section 2.1.5. * Need internal close method as spec requires that the local endpoint * receives a 1006 on timeout. */ public void doClose(CloseReason closeReasonMessage, CloseReason closeReasonLocal) { // Double-checked locking. OK because state is volatile if (state != State.OPEN) { return; } synchronized (stateLock) { if (state != State.OPEN) { return; } if (log.isDebugEnabled()) { log.debug(sm.getString("wsSession.doClose", id)); } try { wsRemoteEndpoint.setBatchingAllowed(false); } catch (IOException e) { log.warn(sm.getString("wsSession.flushFailOnClose"), e); fireEndpointOnError(e); } state = State.OUTPUT_CLOSED; sendCloseMessage(closeReasonMessage); fireEndpointOnClose(closeReasonLocal); } IOException ioe = new IOException(sm.getString("wsSession.messageFailed")); SendResult sr = new SendResult(ioe); for (FutureToSendHandler f2sh : futures.keySet()) { f2sh.onResult(sr); } }
void endMessage(SendHandler handler, SendResult result) { boolean doWrite = false; MessagePart mpNext = null; synchronized (messagePartLock) { fragmented = nextFragmented; text = nextText; mpNext = messagePartQueue.poll(); if (mpNext == null) { messagePartInProgress = false; } else if (!closed){ // Session may have been closed unexpectedly in the middle of // sending a fragmented message closing the endpoint. If this // happens, clearly there is no point trying to send the rest of // the message. doWrite = true; } } if (doWrite) { // Actual write has to be outside sync block to avoid possible // deadlock between messagePartLock and writeLock in // o.a.coyote.http11.upgrade.AbstractServletOutputStream writeMessagePart(mpNext); } wsSession.updateLastActive(); // Some handlers, such as the IntermediateMessageHandler, do not have a // nested handler so handler may be null. if (handler != null) { handler.onResult(result); } }
@Override public void onResult(SendResult result) { if (isDone) { endpoint.stateMachine.complete(isLast); handler.onResult(result); } else if(!result.isOK()) { handler.onResult(result); } else if (closed){ SendResult sr = new SendResult(new IOException( sm.getString("wsRemoteEndpoint.closedDuringMessage"))); handler.onResult(sr); } else { write(); } }
@Override public void onResult(SendResult result) { if (result.isOK()) { if (outputBuffer.hasRemaining()) { endpoint.doWrite(this, outputBuffer); } else { outputBuffer.clear(); write(); } } else { handler.onResult(result); } }
@Override public void onResult(SendResult result) { if (result.isOK()) { outputBuffer.clear(); } handler.onResult(result); }
@Override public void onResult(SendResult result) { if (result.isOK()) { stateMachine.complete(true); } handler.onResult(result); }
/** * * @param t The throwable associated with any error that * occurred * @param useDispatch Should {@link SendHandler#onResult(SendResult)} be * called from a new thread, keeping in mind the * requirements of * {@link javax.websocket.RemoteEndpoint.Async} */ private void clearHandler(Throwable t, boolean useDispatch) { // Setting the result marks this (partial) message as // complete which means the next one may be sent which // could update the value of the handler. Therefore, keep a // local copy before signalling the end of the (partial) // message. SendHandler sh = handler; handler = null; buffers = null; if (sh != null) { if (useDispatch) { OnResultRunnable r = onResultRunnables.poll(); if (r == null) { r = new OnResultRunnable(onResultRunnables); } r.init(sh, t); if (executorService == null || executorService.isShutdown()) { // Can't use the executor so call the runnable directly. // This may not be strictly specification compliant in all // cases but during shutdown only close messages are going // to be sent so there should not be the issue of nested // calls leading to stack overflow as described in bug // 55715. The issues with nested calls was the reason for // the separate thread requirement in the specification. r.run(); } else { executorService.execute(r); } } else { if (t == null) { sh.onResult(new SendResult()); } else { sh.onResult(new SendResult(t)); } } } }
@Override public void run() { if (t == null) { sh.onResult(new SendResult()); } else { sh.onResult(new SendResult(t)); } t = null; sh = null; // Return the Runnable to the queue when it has been finished with // Note if this method takes an age to finish there shouldn't be any // thread safety issues as the fields are cleared above. queue.add(this); }
@Override public void onResult(SendResult result) { if (!result.isOK()) { // Message could not be sent. In this case, we don't // set isSendingMessage to false because we must assume the connection // broke (and onClose will be called), so we don't try to send // other messages. // As a precaution, we close the session (e.g. if a send timeout occured). // TODO: session.close() blocks, while this handler shouldn't block. // Ideally, there should be some abort() method that cancels the // connection immediately... try { session.close(); } catch (IOException ex) { // Ignore } } synchronized (messagesToSend) { if (!messagesToSend.isEmpty()) { AbstractWebsocketMessage msg = messagesToSend.remove(); messagesToSendLength -= calculateMessageLength(msg); internalSendMessageAsync(msg); } else { isSendingMessage = false; } } }
/** * WebSocket 1.0. Section 2.1.5. Need internal close method as spec requires * that the local endpoint receives a 1006 on timeout. */ public void doClose(CloseReason closeReasonMessage, CloseReason closeReasonLocal) { // Double-checked locking. OK because state is volatile if (state != State.OPEN) { return; } synchronized (stateLock) { if (state != State.OPEN) { return; } if (log.isDebugEnabled()) { log.debug(sm.getString("wsSession.doClose", id)); } try { wsRemoteEndpoint.setBatchingAllowed(false); } catch (IOException e) { log.warn(sm.getString("wsSession.flushFailOnClose"), e); fireEndpointOnError(e); } state = State.OUTPUT_CLOSED; sendCloseMessage(closeReasonMessage); fireEndpointOnClose(closeReasonLocal); } IOException ioe = new IOException(sm.getString("wsSession.messageFailed")); SendResult sr = new SendResult(ioe); for (FutureToSendHandler f2sh : futures.keySet()) { f2sh.onResult(sr); } }
void endMessage(SendHandler handler, SendResult result) { boolean doWrite = false; MessagePart mpNext = null; synchronized (messagePartLock) { fragmented = nextFragmented; text = nextText; mpNext = messagePartQueue.poll(); if (mpNext == null) { messagePartInProgress = false; } else if (!closed) { // Session may have been closed unexpectedly in the middle of // sending a fragmented message closing the endpoint. If this // happens, clearly there is no point trying to send the rest of // the message. doWrite = true; } } if (doWrite) { // Actual write has to be outside sync block to avoid possible // deadlock between messagePartLock and writeLock in // o.a.coyote.http11.upgrade.AbstractServletOutputStream writeMessagePart(mpNext); } wsSession.updateLastActive(); // Some handlers, such as the IntermediateMessageHandler, do not have a // nested handler so handler may be null. if (handler != null) { handler.onResult(result); } }
@Override public void onResult(SendResult result) { if (isDone) { endpoint.stateMachine.complete(isLast); handler.onResult(result); } else if (!result.isOK()) { handler.onResult(result); } else if (closed) { SendResult sr = new SendResult(new IOException(sm.getString("wsRemoteEndpoint.closedDuringMessage"))); handler.onResult(sr); } else { write(); } }
/** * * @param t * The throwable associated with any error that occurred * @param useDispatch * Should {@link SendHandler#onResult(SendResult)} be called from * a new thread, keeping in mind the requirements of * {@link javax.websocket.RemoteEndpoint.Async} */ private void clearHandler(Throwable t, boolean useDispatch) { // Setting the result marks this (partial) message as // complete which means the next one may be sent which // could update the value of the handler. Therefore, keep a // local copy before signalling the end of the (partial) // message. SendHandler sh = handler; handler = null; buffers = null; if (sh != null) { if (useDispatch) { OnResultRunnable r = onResultRunnables.poll(); if (r == null) { r = new OnResultRunnable(onResultRunnables); } r.init(sh, t); if (executorService == null || executorService.isShutdown()) { // Can't use the executor so call the runnable directly. // This may not be strictly specification compliant in all // cases but during shutdown only close messages are going // to be sent so there should not be the issue of nested // calls leading to stack overflow as described in bug // 55715. The issues with nested calls was the reason for // the separate thread requirement in the specification. r.run(); } else { executorService.execute(r); } } else { if (t == null) { sh.onResult(new SendResult()); } else { sh.onResult(new SendResult(t)); } } } }
@Override public void onResult(SendResult arg0) { // TODO Auto-generated method stub if (mToken.isUsing()) { mToken.setCanSend(true); if (arg0.isOK()) { mToken.completeSend(mLength); } } }
/** * WebSocket 1.0. Section 2.1.5. * Need internal close method as spec requires that the local endpoint * receives a 1006 on timeout. */ private void doClose(CloseReason closeReasonMessage, CloseReason closeReasonLocal) { // Double-checked locking. OK because state is volatile if (state != State.OPEN) { return; } synchronized (stateLock) { if (state != State.OPEN) { return; } state = State.CLOSING; sendCloseMessage(closeReasonMessage); fireEndpointOnClose(closeReasonLocal); state = State.CLOSED; } IOException ioe = new IOException(sm.getString("wsSession.messageFailed")); SendResult sr = new SendResult(ioe); for (FutureToSendHandler f2sh : futures.keySet()) { f2sh.onResult(sr); } }
void endMessage(SendHandler handler, SendResult result) { boolean doWrite = false; MessagePart mpNext = null; synchronized (messagePartLock) { fragmented = nextFragmented; text = nextText; mpNext = messagePartQueue.poll(); if (mpNext == null) { messagePartInProgress = false; } else if (!closed){ // Session may have been closed unexpectedly in the middle of // sending a fragmented message closing the endpoint. If this // happens, clearly there is no point trying to send the rest of // the message. doWrite = true; } } if (doWrite) { // Actual write has to be outside sync block to avoid possible // deadlock between messagePartLock and writeLock in // o.a.coyote.http11.upgrade.AbstractServletOutputStream writeMessagePart(mpNext); } wsSession.updateLastActive(); handler.onResult(result); }