Beispiel #1
0
 private IoHandler selectReadHandler(ResourceAddress readAddress) {
   Protocol protocol =
       bridgeServiceFactory.getTransportFactory().getProtocol(readAddress.getResource());
   if (protocol instanceof HttpProtocol) {
     return readHandler;
   }
   throw new RuntimeException("Cannot select read handler for address " + readAddress);
 }
Beispiel #2
0
        @Override
        protected void doSessionClosed(HttpSession createSession) throws Exception {
          final WsebSession wsebSession = WSE_SESSION_KEY.get(createSession);
          assert (wsebSession != null);

          IoBufferEx buf = CREATE_RESPONSE_KEY.remove(createSession);
          if (buf == null || createSession.getStatus() != HttpStatus.SUCCESS_CREATED) {
            throw new IllegalStateException("Create handshake failed: invalid response");
          }

          buf.flip();

          String responseText = buf.getString(UTF_8.newDecoder());
          String[] locations = responseText.split("\n");

          if (locations.length < 2) {
            throw new IllegalStateException("Create handshake failed: invalid response");
          }

          URI writeURI = URI.create(locations[0]);
          URI readURI = URI.create(locations[1]);

          ResourceAddress writeAddress = resourceAddressFactory.newResourceAddress(writeURI);
          ResourceAddress readAddress = resourceAddressFactory.newResourceAddress(readURI);

          if (!wsebSession.isClosing()) {
            wsebSession.setWriteAddress(writeAddress);
            wsebSession.setReadAddress(readAddress);

            sessionMap.put(writeAddress, wsebSession);
            sessionMap.put(readAddress, wsebSession);

            // attach downstream for read
            final BridgeConnector bridgeConnector =
                bridgeServiceFactory.newBridgeConnector(readAddress);
            bridgeConnector.connect(
                readAddress,
                selectReadHandler(readAddress),
                new IoSessionInitializer<ConnectFuture>() {
                  @Override
                  public void initializeSession(IoSession ioSession, ConnectFuture connectFuture) {
                    HttpSession httpSession = (HttpSession) ioSession;
                    httpSession.setWriteHeader(
                        HttpHeaders.HEADER_X_SEQUENCE_NO,
                        Long.toString(wsebSession.nextReaderSequenceNo()));
                  }
                });

            // activate upstream for write
            // TODO: Replace usage of suspendWrite/resumeWrite with a WSEB-specific "send queue"
            // upon which
            // TODO: locking of writes can be achieved.
            wsebSession.resumeWrite();
            // We are always aligned now. if (session.isIoAligned()) {
            wsebSession.getProcessor().flush(wsebSession);
          }
        }
Beispiel #3
0
 private IoHandler selectConnectHandler(ResourceAddress address) {
   Protocol protocol =
       bridgeServiceFactory.getTransportFactory().getProtocol(address.getResource());
   if (protocol instanceof HttpProtocol) {
     return createHandler;
   }
   throw new RuntimeException(
       getClass() + ": Cannot select a connect handler for address " + address);
 }
 private URI locateSecureAcceptURI(HttpAcceptSession session) throws Exception {
   // TODO: same-origin requests must consider cross-origin access control
   //       internal redirect to secure resource should not trigger 403 Forbidden
   ResourceAddress localAddress = session.getLocalAddress();
   URI resource = localAddress.getResource();
   Protocol resourceProtocol = bridgeServiceFactory.getTransportFactory().getProtocol(resource);
   if (WsebProtocol.WSEB_SSL == resourceProtocol || WsProtocol.WSS == resourceProtocol) {
     return resource;
   }
   return null;
 }
Beispiel #5
0
        @Override
        protected void doMessageReceived(HttpSession readSession, Object message) throws Exception {
          ResourceAddress readAddress = BridgeSession.REMOTE_ADDRESS.get(readSession);
          WsebSession wsebSession = sessionMap.get(readAddress);

          // handle parallel closure of WSE session during streaming read
          if (wsebSession == null) {
            if (logger.isDebugEnabled()) {
              logger.debug(
                  String.format("Could not find WsebSession for read address:\n" + readAddress));
            }
            return;
          }

          WsMessage wsebMessage = (WsMessage) message;
          IoBufferEx messageBytes = wsebMessage.getBytes();
          IoFilterChain filterChain = wsebSession.getTransportSession().getFilterChain();

          switch (wsebMessage.getKind()) {
            case COMMAND:
              for (Command command : ((WsCommandMessage) wsebMessage).getCommands()) {
                if (command == Command.reconnect()) {
                  // received a RECONNECT command
                  wsebSession.detachReader(readSession);
                  // re-attach downstream for read
                  final BridgeConnector bridgeConnector =
                      bridgeServiceFactory.newBridgeConnector(readAddress);
                  bridgeConnector.connect(readAddress, selectReadHandler(readAddress), null);
                  break;
                } else if (command == Command.close()) {
                  // Following should take care of sending CLOSE response and closing reader
                  // (downstream)
                  // Close case was not handled before 3.5.9
                  filterChain.fireMessageReceived(new WsCloseMessage());
                  break;
                }
                // no-op (0x00) - continue reading commands
              }
              break;
            default:
              filterChain.fireMessageReceived(wsebMessage);
              break;
          }
        }
Beispiel #6
0
  @Override
  protected <T extends ConnectFuture> ConnectFuture connectInternal(
      ResourceAddress connectAddress,
      IoHandler handler,
      final IoSessionInitializer<T> initializer) {
    final DefaultConnectFuture wseConnectFuture = new DefaultConnectFuture();

    // propagate connection failure, if necessary
    IoFutureListener<ConnectFuture> parentConnectListener =
        new IoFutureListener<ConnectFuture>() {
          @Override
          public void operationComplete(ConnectFuture future) {
            // fail bridge connect future if parent connect fails
            if (!future.isConnected()) {
              wseConnectFuture.setException(future.getException());
            }
          }
        };

    IoSessionInitializer<ConnectFuture> parentInitializer =
        createParentInitializer(connectAddress, handler, initializer, wseConnectFuture);

    ResourceAddress httpxeAddress = connectAddress.getTransport();

    URI createURI = appendURI(httpxeAddress.getExternalURI(), CREATE_SUFFIX);

    // default options but clear the transports so they get rebuilt by default
    ResourceOptions createOptions = ResourceOptions.FACTORY.newResourceOptions(httpxeAddress);
    createOptions.setOption(ResourceAddress.TRANSPORT, null);
    createOptions.setOption(ResourceAddress.TRANSPORT_URI, null);

    ResourceAddress createAddress =
        resourceAddressFactory.newResourceAddress(createURI, createOptions);
    BridgeConnector connector = bridgeServiceFactory.newBridgeConnector(createAddress);

    // TODO: proxy detection, append ?.ki=p on timeout
    connector
        .connect(createAddress, selectConnectHandler(createAddress), parentInitializer)
        .addListener(parentConnectListener);

    return wseConnectFuture;
  }
Beispiel #7
0
  private <T extends ConnectFuture> IoSessionInitializer<ConnectFuture> createParentInitializer(
      final ResourceAddress connectAddressNext,
      final IoHandler handler,
      final IoSessionInitializer<T> initializer,
      final DefaultConnectFuture wseConnectFuture) {

    final ResourceAddress connectAddress = connectAddressNext.getTransport();
    Protocol protocol =
        bridgeServiceFactory.getTransportFactory().getProtocol(connectAddress.getResource());
    if (!(protocol instanceof HttpProtocol)) {
      final String message =
          format(
              "Cannot create WSEB parent session initializer for address %s", connectAddressNext);
      if (logger.isInfoEnabled()) {
        logger.info(message);
      }
      throw new RuntimeException(message);
    }
    // initialize parent session before connection attempt
    return new IoSessionInitializer<ConnectFuture>() {
      @Override
      public void initializeSession(final IoSession parent, ConnectFuture future) {
        // initializer for bridge session to specify bridge handler,
        // and call user-defined bridge session initializer if present
        final IoSessionInitializer<T> wseSessionInitializer =
            new IoSessionInitializer<T>() {
              @Override
              public void initializeSession(IoSession session, T future) {
                WsebSession wseSession = (WsebSession) session;
                wseSession.setHandler(handler);

                // TODO: add extension filters when we adopt the new webSocket extension SPI
                wseSession.getTransportSession().getFilterChain().fireSessionCreated();
                wseSession.getTransportSession().getFilterChain().fireSessionOpened();

                if (initializer != null) {
                  initializer.initializeSession(session, future);
                }
              }
            };

        final long sequenceNo = 0;

        final HttpSession httpSession = (HttpSession) parent;
        httpSession.setWriteHeader(HEADER_X_ACCEPT_COMMANDS, "ping");
        httpSession.setWriteHeader(HttpHeaders.HEADER_X_SEQUENCE_NO, Long.toString(sequenceNo));
        final IoBufferAllocatorEx<WsBuffer> allocator =
            new WsebBufferAllocator(httpSession.getBufferAllocator());

        // factory to create a new bridge session
        Callable<WsebSession> createSession =
            new Callable<WsebSession>() {
              @Override
              public WsebSession call() throws Exception {

                Callable<WsebSession> wseSessionFactory =
                    new Callable<WsebSession>() {
                      @Override
                      public WsebSession call() throws Exception {
                        WsebSession wsebSession =
                            new WsebSession(
                                httpSession.getIoLayer(),
                                httpSession.getIoThread(),
                                httpSession.getIoExecutor(),
                                WsebConnector.this,
                                getProcessor(),
                                connectAddressNext,
                                connectAddressNext,
                                allocator,
                                null,
                                0,
                                connectAddressNext.getOption(INACTIVITY_TIMEOUT),
                                false, /* no sequence validation */
                                sequenceNo, /* starting sequence no */
                                null);

                        // ability to write will be reactivated when create response returns with
                        // write address
                        wsebSession.suspendWrite();

                        return wsebSession;
                      }
                    };

                return newSession(wseSessionInitializer, wseConnectFuture, wseSessionFactory);
              }
            };

        WSE_SESSION_FACTORY_KEY.set(httpSession, createSession);
        WSE_CONNECT_FUTURE_KEY.set(httpSession, wseConnectFuture);
      }
    };
  }