private void sendCloseMessage(CloseReason closeReason) { // 125 is maximum size for the payload of a control message ByteBuffer msg = ByteBuffer.allocate(125); CloseCode closeCode = closeReason.getCloseCode(); // CLOSED_ABNORMALLY should not be put on the wire if (closeCode == CloseCodes.CLOSED_ABNORMALLY) { // PROTOCOL_ERROR is probably better than GOING_AWAY here msg.putShort((short) CloseCodes.PROTOCOL_ERROR.getCode()); } else { msg.putShort((short) closeCode.getCode()); } String reason = closeReason.getReasonPhrase(); if (reason != null && reason.length() > 0) { appendCloseReasonWithTruncation(msg, reason); } msg.flip(); try { wsRemoteEndpoint.startMessageBlock(Constants.OPCODE_CLOSE, msg, true); } catch (IOException ioe) { // Failed to send close message. Close the socket and let the caller // deal with the Exception WebsocketsLogger.ROOT_LOGGER.closeMessageFail(ioe); wsRemoteEndpoint.close(); // Failure to send a close message is not unexpected in the case of // an abnormal closure (usually triggered by a failure to read/write // from/to the client. In this case do not trigger the endpoint's // error handling if (closeCode != CloseCodes.CLOSED_ABNORMALLY) { localEndpoint.onError(this, ioe); } } finally { webSocketContainer.unregisterSession(localEndpoint, this); } }
/** * Called when a close message is received. Should only ever happen once. Also called after a * protocol error when the ProtocolHandler needs to force the closing of the connection. */ public void onClose(CloseReason closeReason) { synchronized (stateLock) { if (state == State.OPEN) { sendCloseMessage(closeReason); fireEndpointOnClose(closeReason); state = State.CLOSED; } // Close the socket wsRemoteEndpoint.close(); } }
/** * Creates a new WebSocket session for communication between the two provided end points. The * result of {@link Thread#getContextClassLoader()} at the time this constructor is called will be * used when calling {@link Endpoint#onClose(Session, CloseReason)}. * * @param localEndpoint * @param wsRemoteEndpoint * @throws DeploymentException */ public WsSession( Endpoint localEndpoint, WsRemoteEndpointImplBase wsRemoteEndpoint, WsWebSocketContainer wsWebSocketContainer, URI requestUri, Map<String, List<String>> requestParameterMap, String queryString, Principal userPrincipal, String httpSessionId, String subProtocol, Map<String, String> pathParameters, boolean secure, EndpointConfig endpointConfig) throws DeploymentException { this.localEndpoint = localEndpoint; this.wsRemoteEndpoint = wsRemoteEndpoint; this.wsRemoteEndpoint.setSession(this); this.remoteEndpointAsync = new WsRemoteEndpointAsync(wsRemoteEndpoint); this.remoteEndpointBasic = new WsRemoteEndpointBasic(wsRemoteEndpoint); this.webSocketContainer = wsWebSocketContainer; applicationClassLoader = Thread.currentThread().getContextClassLoader(); wsRemoteEndpoint.setSendTimeout(wsWebSocketContainer.getDefaultAsyncSendTimeout()); this.maxBinaryMessageBufferSize = webSocketContainer.getDefaultMaxBinaryMessageBufferSize(); this.maxTextMessageBufferSize = webSocketContainer.getDefaultMaxTextMessageBufferSize(); this.maxIdleTimeout = webSocketContainer.getDefaultMaxSessionIdleTimeout(); this.requestUri = requestUri; if (requestParameterMap == null) { this.requestParameterMap = Collections.emptyMap(); } else { this.requestParameterMap = requestParameterMap; } this.queryString = queryString; this.userPrincipal = userPrincipal; this.httpSessionId = httpSessionId; if (subProtocol == null) { this.subProtocol = ""; } else { this.subProtocol = subProtocol; } this.pathParameters = pathParameters; this.secure = secure; this.wsRemoteEndpoint.setEncoders(endpointConfig); this.endpointConfig = endpointConfig; this.userProperties.putAll(endpointConfig.getUserProperties()); this.id = Long.toHexString(ids.getAndIncrement()); }
/** Force an autoblocking flush. */ public void writeBlock() { wsRemoteEndpoint.writeBlock(); }