All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.websocket.common.io.ConnectionState Maven / Gradle / Ivy

There is a newer version: 9.4.56.v20240826
Show newest version
//
//  ========================================================================
//  Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.websocket.common.io;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * WebSocket Connection State.
 * 

* {@code State} can only go in one direction from {@code HANDSHAKING} to {@code DISCONNECTED}. *

*/ public class ConnectionState { private final AtomicReference state = new AtomicReference<>(State.HANDSHAKING); private final AtomicBoolean wasOpened = new AtomicBoolean(false); /** * Test to see if state allows writing of WebSocket frames * * @return true if state allows for writing of websocket frames */ public boolean canWriteWebSocketFrames() { State current = state.get(); return current == State.OPENING || current == State.OPENED; } /** * Tests to see if state allows for reading of WebSocket frames * * @return true if state allows for reading of websocket frames */ public boolean canReadWebSocketFrames() { State current = state.get(); return current == State.OPENED || current == State.CLOSING; } /** * Tests to see if state got past the initial HANDSHAKING state * * @return true if the connection state was opened */ public boolean wasOpened() { return wasOpened.get(); } /** * Requests that the connection migrate to OPENING state * * @return true if OPENING state attained */ public boolean opening() { while (true) { State current = state.get(); switch (current) { case HANDSHAKING: if (state.compareAndSet(current, State.OPENING)) { wasOpened.set(true); return true; } break; case CLOSING: // Connection closed from WebSocketSession doStop before connection was opened) return false; case DISCONNECTED: return false; default: throw new IllegalStateException(toString(current)); } } } /** * Requests that the connection migrate to OPENED state * * @return true if OPENED state attained */ public boolean opened() { while (true) { State current = state.get(); switch (current) { case OPENING: if (state.compareAndSet(current, State.OPENED)) { return true; } break; case CLOSING: // connection went from OPENING to CLOSING (likely to to failure to onOpen) return false; case DISCONNECTED: return false; default: throw new IllegalStateException(toString(current)); } } } /** * The Local Endpoint wants to close. * * @return true if this is the first local close */ public boolean closing() { while (true) { State current = state.get(); switch (current) { case HANDSHAKING: case OPENING: case OPENED: if (state.compareAndSet(current, State.CLOSING)) { return true; } break; case CLOSING: // already closing return false; case DISCONNECTED: return false; default: throw new IllegalStateException(toString(current)); } } } /** * Final Terminal state indicating the connection is disconnected * * @return true if disconnected reached for the first time */ public boolean disconnected() { while (true) { State current = state.get(); switch (current) { case DISCONNECTED: return false; default: if (state.compareAndSet(current, State.DISCONNECTED)) { return true; } break; } } } private String toString(State state) { return String.format("%s@%x[%s]", getClass().getSimpleName(), hashCode(), state); } @Override public String toString() { return toString(state.get()); } private enum State { /** * Initial state of a connection, the upgrade request / response handshake is in progress */ HANDSHAKING, /** * Intermediate state between HANDSHAKING and OPENED, used to indicate that a upgrade * request/response handshake is successful, but the Application provided socket's * onOpen code has yet completed. *

* This state is to allow the local socket endpoint to initiate the sending of messages and * frames, but to NOT start reading yet. */ OPENING, /** * The websocket connection is established and open. *

* This indicates that the Upgrade has succeed, and the Application provided * socket's onOpen code has returned. *

* It is now time to start reading from the remote endpoint. */ OPENED, /** * The WebSocket is closing *

* There are several conditions that would start this state. *

* - A CLOSE Frame has been received (and parsed) from the remote endpoint * - A CLOSE Frame has been enqueued by the local endpoint */ CLOSING, /** * The WebSocket connection is disconnected. *

* Connection is complete and no longer valid. */ DISCONNECTED } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy