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