예제 #1
0
  public static final class ResponseStatusCodes {
    public static final int CONTINUE_100 = HttpResponseStatus.CONTINUE.code();
    public static final int SWITCHING_PROTOCOLS_101 = HttpResponseStatus.SWITCHING_PROTOCOLS.code();
    public static final int OK_200 = HttpResponseStatus.OK.code();
    public static final int MOVED_PERMANENTLY_301 = HttpResponseStatus.MOVED_PERMANENTLY.code();
    public static final int FOUND_302 = HttpResponseStatus.FOUND.code();
    public static final int SEE_OTHER_303 = HttpResponseStatus.SEE_OTHER.code();
    public static final int NOT_MODIFIED_304 = HttpResponseStatus.NOT_MODIFIED.code();
    public static final int TEMPORARY_REDIRECT_307 = HttpResponseStatus.TEMPORARY_REDIRECT.code();
    public static final int UNAUTHORIZED_401 = HttpResponseStatus.UNAUTHORIZED.code();
    public static final int PROXY_AUTHENTICATION_REQUIRED_407 =
        HttpResponseStatus.PROXY_AUTHENTICATION_REQUIRED.code();

    private ResponseStatusCodes() {}
  }
/**
 * An {@link AsyncHandler} which is able to execute WebSocket upgrade. Use the Builder for
 * configuring WebSocket options.
 */
public class WebSocketUpgradeHandler implements UpgradeHandler<WebSocket>, AsyncHandler<WebSocket> {

  private static final int SWITCHING_PROTOCOLS =
      io.netty.handler.codec.http.HttpResponseStatus.SWITCHING_PROTOCOLS.code();

  private WebSocket webSocket;
  private final List<WebSocketListener> listeners;
  private final AtomicBoolean ok = new AtomicBoolean(false);
  private boolean onSuccessCalled;
  private int status;
  private List<Runnable> bufferedFrames;

  public WebSocketUpgradeHandler(List<WebSocketListener> listeners) {
    this.listeners = listeners;
  }

  public void bufferFrame(Runnable bufferedFrame) {
    if (bufferedFrames == null) {
      bufferedFrames = new ArrayList<>(1);
    }
    bufferedFrames.add(bufferedFrame);
  }

  /** {@inheritDoc} */
  @Override
  public final void onThrowable(Throwable t) {
    onFailure(t);
  }

  public boolean touchSuccess() {
    boolean prev = onSuccessCalled;
    onSuccessCalled = true;
    return prev;
  }

  /** {@inheritDoc} */
  @Override
  public final State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
    return State.CONTINUE;
  }

  /** {@inheritDoc} */
  @Override
  public final State onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
    status = responseStatus.getStatusCode();
    return status == SWITCHING_PROTOCOLS ? State.UPGRADE : State.ABORT;
  }

  /** {@inheritDoc} */
  @Override
  public final State onHeadersReceived(HttpResponseHeaders headers) throws Exception {
    return State.CONTINUE;
  }

  /** {@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);
  }

  /** {@inheritDoc} */
  @Override
  public final void onFailure(Throwable t) {
    for (WebSocketListener listener : listeners) {
      if (!ok.get() && webSocket != null) {
        webSocket.addWebSocketListener(listener);
      }
      listener.onError(t);
    }
  }

  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);
      }
    }
  }

  /** Build a {@link WebSocketUpgradeHandler} */
  public static final class Builder {

    private List<WebSocketListener> listeners = new ArrayList<>(1);

    /**
     * Add a {@link WebSocketListener} that will be added to the {@link WebSocket}
     *
     * @param listener a {@link WebSocketListener}
     * @return this
     */
    public Builder addWebSocketListener(WebSocketListener listener) {
      listeners.add(listener);
      return this;
    }

    /**
     * Remove a {@link WebSocketListener}
     *
     * @param listener a {@link WebSocketListener}
     * @return this
     */
    public Builder removeWebSocketListener(WebSocketListener listener) {
      listeners.remove(listener);
      return this;
    }

    /**
     * Build a {@link WebSocketUpgradeHandler}
     *
     * @return a {@link WebSocketUpgradeHandler}
     */
    public WebSocketUpgradeHandler build() {
      return new WebSocketUpgradeHandler(listeners);
    }
  }
}