code: /*
   * Copyright (c) 2019 the Eclipse Milo Authors
   *
   * This program and the accompanying materials are made
   * available under the terms of the Eclipse Public License 2.0
   * which is available at https://www.eclipse.org/legal/epl-2.0/
   *
   * SPDX-License-Identifier: EPL-2.0
   */
  
  package org.eclipse.milo.opcua.stack.server.transport.websocket;
  
  import io.netty.channel.ChannelHandlerContext;
  import io.netty.channel.SimpleChannelInboundHandler;
  import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
  import io.netty.handler.codec.http.websocketx.WebSocketFrame;
  import org.eclipse.milo.opcua.stack.core.Stack;
  import org.eclipse.milo.opcua.stack.core.transport.TransportProfile;
  import org.eclipse.milo.opcua.stack.server.UaStackServer;
  import org.eclipse.milo.opcua.stack.server.transport.uasc.UascServerHelloHandler;
  
  import static io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler.HandshakeComplete;
  
  public class OpcServerWebSocketFrameHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
  
      private String subprotocol;
  
      private final UaStackServer stackServer;
  
      public OpcServerWebSocketFrameHandler(UaStackServer stackServer) {
          this.stackServer = stackServer;
      }
  
      @Override
      public void userEventTriggered(ChannelHandlerContext ctx, Object event) throws Exception {
          if (event instanceof HandshakeComplete) {
              HandshakeComplete handshake = (HandshakeComplete) event;
  
              subprotocol = handshake.selectedSubprotocol();
  
              if (Stack.WSS_PROTOCOL_BINARY.equalsIgnoreCase(subprotocol)) {
                  UascServerHelloHandler helloHandler = new UascServerHelloHandler(
                      stackServer,
                      TransportProfile.WSS_UASC_UABINARY
                  );
  
                  ctx.channel().pipeline().addLast(helloHandler);
              } else {
                  throw new IllegalArgumentException("subprotocol: " + subprotocol);
              }
          }
  
          super.userEventTriggered(ctx, event);
      }
  
      @Override
      protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame msg) {
          if (Stack.WSS_PROTOCOL_BINARY.equalsIgnoreCase(subprotocol)) {
              // Pass the binary contents to the UA Secure Conversation handlers
  
              ctx.fireChannelRead(msg.content().retain());
          } else if (Stack.WSS_PROTOCOL_JSON.equalsIgnoreCase(subprotocol)) {
              // TODO End of the pipeline; decode and deliver
              String text = ((TextWebSocketFrame) msg).text();
  
              throw new IllegalArgumentException("subprotocol: " + subprotocol);
          } else {
              ctx.close();
          }
      }
  
  }
  