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

com.jauntsdn.rsocket.RSocketFactory Maven / Gradle / Ivy

There is a newer version: 0.9.8
Show newest version
/*
 * Copyright 2015-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jauntsdn.rsocket;

import static com.jauntsdn.rsocket.StreamErrorMappers.*;
import static com.jauntsdn.rsocket.internal.ClientSetup.DefaultClientSetup;
import static com.jauntsdn.rsocket.internal.ClientSetup.ResumableClientSetup;

import com.jauntsdn.rsocket.exceptions.InvalidSetupException;
import com.jauntsdn.rsocket.exceptions.RejectedSetupException;
import com.jauntsdn.rsocket.fragmentation.FragmentationDuplexConnection;
import com.jauntsdn.rsocket.frame.*;
import com.jauntsdn.rsocket.frame.decoder.PayloadDecoder;
import com.jauntsdn.rsocket.internal.ClientServerInputMultiplexer;
import com.jauntsdn.rsocket.internal.ClientSetup;
import com.jauntsdn.rsocket.internal.ServerSetup;
import com.jauntsdn.rsocket.keepalive.KeepAliveHandler;
import com.jauntsdn.rsocket.resume.*;
import com.jauntsdn.rsocket.transport.ClientTransport;
import com.jauntsdn.rsocket.transport.ServerTransport;
import com.jauntsdn.rsocket.util.EmptyPayload;
import com.jauntsdn.rsocket.util.MultiSubscriberRSocket;
import com.jauntsdn.rsocket.util.Preconditions;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import java.time.Duration;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;

/** Factory for creating RSocket clients and servers. */
public class RSocketFactory {
  /**
   * Creates a factory that establishes client connections to other RSockets.
   *
   * @return a client factory
   */
  public static ClientRSocketFactory connect() {
    return new ClientRSocketFactory();
  }

  /**
   * Creates a factory that receives server connections from client RSockets.
   *
   * @return a server factory.
   */
  public static ServerRSocketFactory receive() {
    return new ServerRSocketFactory();
  }

  public interface Start {
    Mono start();
  }

  public interface ClientTransportAcceptor {
    Start transport(Supplier transport);

    default Start transport(ClientTransport transport) {
      return transport(() -> transport);
    }
  }

  public interface ServerTransportAcceptor {

     Start transport(Supplier> transport);

    default  Start transport(ServerTransport transport) {
      return transport(() -> transport);
    }
  }

  public static class ClientRSocketFactory implements ClientTransportAcceptor {
    private static final String CLIENT_TAG = "client";
    private static final int KEEPALIVE_MIN_INTERVAL_MILLIS = 100;

    private ClientSocketAcceptor acceptor = (setup, sendingSocket) -> new AbstractRSocket() {};

    private Consumer errorConsumer = Throwable::printStackTrace;
    private StreamErrorMappers errorMappers = StreamErrorMappers.create();
    private Interceptors.Configurer interceptorsConfigurer = setupPayload -> Interceptors.noop();

    private Payload setupPayload = EmptyPayload.INSTANCE;
    private PayloadDecoder payloadDecoder = PayloadDecoder.ZERO_COPY;

    private Duration tickPeriod = Duration.ofSeconds(15);
    private Duration ackTimeout = Duration.ofSeconds(90);

    private String metadataMimeType = "application/binary";
    private String dataMimeType = "application/binary";

    private boolean resumeEnabled;
    private boolean resumeCleanupStoreOnKeepAlive;
    private Supplier resumeTokenSupplier = ResumeFrameFlyweight::generateResumeToken;
    private Function resumeStoreFactory =
        token -> new InMemoryResumableFramesStore(CLIENT_TAG, 100_000);
    private Duration resumeSessionDuration = Duration.ofMinutes(2);
    private Duration resumeStreamTimeout = Duration.ofSeconds(10);
    private Supplier resumeStrategySupplier =
        () ->
            new ExponentialBackoffResumeStrategy(Duration.ofSeconds(1), Duration.ofSeconds(16), 2);

    private boolean multiSubscriberRequester = true;
    private boolean leaseEnabled;
    private Leases.ClientConfigurer leaseConfigurer = (rtt, scheduler) -> Leases.create();

    private ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
    private boolean acceptFragmentedFrames;
    private int frameSizeLimit = FrameLengthFlyweight.FRAME_LENGTH_MASK;

    public ClientRSocketFactory byteBufAllocator(ByteBufAllocator allocator) {
      Objects.requireNonNull(allocator);
      this.allocator = allocator;
      return this;
    }

    /**
     * Adds interceptors that are called in order: connection, RSocket requester, socket acceptor,
     * RSocket handler. Global interceptors are called first
     *
     * @param interceptorsConfigurer adds interceptors of connection, RSocket requester, client
     *     socket acceptor, RSocket handler
     * @return this {@link ClientRSocketFactory} instance
     */
    public ClientRSocketFactory interceptors(Interceptors.Configurer interceptorsConfigurer) {
      Objects.requireNonNull(interceptorsConfigurer);
      this.interceptorsConfigurer = interceptorsConfigurer;
      return this;
    }

    public ClientRSocketFactory keepAlive(Duration tickPeriod, Duration ackTimeout) {
      this.tickPeriod = tickPeriod;
      this.ackTimeout = ackTimeout;
      return this;
    }

    public ClientRSocketFactory keepAliveTickPeriod(Duration tickPeriod) {
      this.tickPeriod = tickPeriod;
      return this;
    }

    public ClientRSocketFactory keepAliveAckTimeout(Duration ackTimeout) {
      this.ackTimeout = ackTimeout;
      return this;
    }

    public ClientRSocketFactory mimeType(String metadataMimeType, String dataMimeType) {
      this.dataMimeType = dataMimeType;
      this.metadataMimeType = metadataMimeType;
      return this;
    }

    public ClientRSocketFactory dataMimeType(String dataMimeType) {
      this.dataMimeType = dataMimeType;
      return this;
    }

    public ClientRSocketFactory metadataMimeType(String metadataMimeType) {
      this.metadataMimeType = metadataMimeType;
      return this;
    }

    /**
     * Enable and configure requests lease support
     *
     * @param leaseConfigurer configures requests lease
     * @return this {@link ClientRSocketFactory} instance
     */
    public ClientRSocketFactory lease(Leases.ClientConfigurer leaseConfigurer) {
      this.leaseEnabled = true;
      this.leaseConfigurer = Objects.requireNonNull(leaseConfigurer, "leaseConfigurer");
      return this;
    }

    /**
     * Enables requests lease support. Responder will not accept any requests because {@link Leases}
     * is not configured
     *
     * @return this {@link ClientRSocketFactory} instance
     */
    public ClientRSocketFactory lease() {
      this.leaseEnabled = true;
      return this;
    }

    /**
     * Enables requests lease support. Responder will not accept any requests because {@link Leases}
     * is not configured
     *
     * @return this {@link ClientRSocketFactory} instance
     */
    public ClientRSocketFactory lease(boolean leaseEnabled) {
      this.leaseEnabled = leaseEnabled;
      return this;
    }

    public ClientRSocketFactory singleSubscriberRequester() {
      return singleSubscriberRequester(true);
    }

    public ClientRSocketFactory singleSubscriberRequester(boolean singleSubscriberRequester) {
      this.multiSubscriberRequester = !singleSubscriberRequester;
      return this;
    }

    public ClientRSocketFactory resume() {
      return resume(true);
    }

    public ClientRSocketFactory resume(boolean resumeEnabled) {
      this.resumeEnabled = resumeEnabled;
      return this;
    }

    public ClientRSocketFactory resumeToken(Supplier resumeTokenSupplier) {
      this.resumeTokenSupplier = Objects.requireNonNull(resumeTokenSupplier);
      return this;
    }

    public ClientRSocketFactory resumeStore(
        Function resumeStoreFactory) {
      this.resumeStoreFactory = resumeStoreFactory;
      return this;
    }

    public ClientRSocketFactory resumeSessionDuration(Duration sessionDuration) {
      this.resumeSessionDuration = Objects.requireNonNull(sessionDuration);
      return this;
    }

    public ClientRSocketFactory resumeStreamTimeout(Duration resumeStreamTimeout) {
      this.resumeStreamTimeout = Objects.requireNonNull(resumeStreamTimeout);
      return this;
    }

    public ClientRSocketFactory resumeStrategy(Supplier resumeStrategy) {
      this.resumeStrategySupplier = Objects.requireNonNull(resumeStrategy);
      return this;
    }

    public ClientRSocketFactory resumeCleanupOnKeepAlive() {
      resumeCleanupStoreOnKeepAlive = true;
      return this;
    }

    public ClientRSocketFactory frameSizeLimit(int frameSizeLimit) {
      this.frameSizeLimit = Preconditions.requireFrameSizeValid(frameSizeLimit);
      return this;
    }

    @Override
    public Start transport(Supplier transportClient) {
      return new StartClient(transportClient);
    }

    public ClientTransportAcceptor acceptor(ClientSocketAcceptor acceptor) {
      this.acceptor = acceptor;
      return StartClient::new;
    }

    public ClientRSocketFactory acceptFragmentedFrames() {
      this.acceptFragmentedFrames = true;
      return this;
    }

    public ClientRSocketFactory errorConsumer(Consumer errorConsumer) {
      this.errorConsumer = errorConsumer;
      return this;
    }

    /**
     * @param errorMappers configures custom error mappers of incoming and outgoing streams.
     * @return this {@link ClientRSocketFactory} instance
     */
    public ClientRSocketFactory streamErrorMapper(StreamErrorMappers errorMappers) {
      this.errorMappers = errorMappers;
      return this;
    }

    public ClientRSocketFactory setupPayload(Payload payload) {
      this.setupPayload = payload;
      return this;
    }

    public ClientRSocketFactory frameDecoder(PayloadDecoder payloadDecoder) {
      this.payloadDecoder = payloadDecoder;
      return this;
    }

    private class StartClient implements Start {
      private final Supplier transportClient;
      private final int keepAliveTickPeriod;
      private final int keepAliveTimeout;

      StartClient(Supplier transportClient) {
        this.transportClient = transportClient;
        this.keepAliveTickPeriod = keepAliveTickPeriod();
        this.keepAliveTimeout = keepAliveTimeout();
      }

      @Override
      public Mono start() {
        return newConnection()
            .flatMap(
                connection -> {
                  if (acceptFragmentedFrames) {
                    connection =
                        new FragmentationDuplexConnection(connection, allocator, frameSizeLimit);
                  }

                  ClientSetup clientSetup = clientSetup(connection);
                  boolean isLeaseEnabled = leaseEnabled;
                  ByteBuf resumeToken = clientSetup.resumeToken();

                  ByteBuf setupFrame =
                      SetupFrameFlyweight.encode(
                          allocator,
                          isLeaseEnabled,
                          keepAliveTickPeriod,
                          keepAliveTimeout,
                          resumeToken,
                          metadataMimeType,
                          dataMimeType,
                          setupPayload);

                  ConnectionSetupPayload connectionSetupPayload =
                      ConnectionSetupPayload.create(setupFrame);

                  Scheduler scheduler = connection.scheduler();
                  KeepAliveHandler keepAliveHandler = clientSetup.keepAliveHandler();
                  DuplexConnection clientConnection = clientSetup.connection();

                  Interceptors interceptors = interceptorsConfigurer.configure(scheduler);
                  DuplexConnection wrappedConnection =
                      interceptors.interceptConnection(clientConnection);

                  ClientServerInputMultiplexer multiplexer =
                      new ClientServerInputMultiplexer(wrappedConnection, true);

                  RSocketsFactory rSocketsFactory =
                      RSocketsFactory.createClient(
                          connectionSetupPayload.willClientHonorLease(),
                          scheduler,
                          leaseConfigurer);

                  final int keepAliveTimeout = this.keepAliveTimeout;
                  final int keepAliveTickPeriod = this.keepAliveTickPeriod;

                  ErrorFrameMapper errorFrameMapper =
                      errorMappers.createErrorFrameMapper(allocator);

                  RSocket rSocketRequester =
                      rSocketsFactory.createRequester(
                          allocator,
                          multiplexer.asClientConnection(),
                          payloadDecoder,
                          errorConsumer,
                          errorFrameMapper,
                          StreamIdSupplier.clientSupplier(),
                          keepAliveTickPeriod,
                          keepAliveTimeout,
                          keepAliveHandler);

                  if (multiSubscriberRequester) {
                    rSocketRequester = new MultiSubscriberRSocket(rSocketRequester);
                  }

                  RSocket wrappedRSocketRequester =
                      interceptors.interceptRequester(rSocketRequester);

                  RSocket rSocketHandler =
                      interceptors
                          .interceptClientAcceptor(acceptor)
                          .accept(connectionSetupPayload, wrappedRSocketRequester);

                  RSocket wrappedRSocketHandler = interceptors.interceptHandler(rSocketHandler);

                  RSocket rSocketResponder =
                      rSocketsFactory.createResponder(
                          allocator,
                          multiplexer.asServerConnection(),
                          wrappedRSocketHandler,
                          payloadDecoder,
                          errorConsumer,
                          errorFrameMapper);

                  return wrappedConnection.sendOne(setupFrame).thenReturn(wrappedRSocketRequester);
                });
      }

      private int keepAliveTickPeriod() {
        long interval = tickPeriod.toMillis();
        if (interval > Integer.MAX_VALUE) {
          throw new IllegalArgumentException(
              String.format("keep-alive interval millis exceeds INTEGER.MAX_VALUE: %d", interval));
        }

        int minInterval = KEEPALIVE_MIN_INTERVAL_MILLIS;
        if (interval < minInterval) {
          throw new IllegalArgumentException(
              String.format(
                  "keep-alive interval millis is less than minimum of %d: %d",
                  minInterval, interval));
        }

        return (int) interval;
      }

      private int keepAliveTimeout() {
        long timeout = ackTimeout.toMillis();
        if (timeout > Integer.MAX_VALUE) {
          throw new IllegalArgumentException(
              String.format("keep-alive timeout millis exceeds INTEGER.MAX_VALUE: %d", timeout));
        }
        return (int) timeout;
      }

      private ClientSetup clientSetup(DuplexConnection startConnection) {
        if (resumeEnabled) {
          ByteBuf resumeToken = resumeTokenSupplier.get();
          return new ResumableClientSetup(
              allocator,
              startConnection,
              newConnection(),
              resumeToken,
              resumeStoreFactory.apply(resumeToken),
              resumeSessionDuration,
              resumeStreamTimeout,
              resumeStrategySupplier,
              resumeCleanupStoreOnKeepAlive);
        } else {
          return new DefaultClientSetup(startConnection);
        }
      }

      private Mono newConnection() {
        return transportClient.get().connect(frameSizeLimit);
      }
    }
  }

  public static class ServerRSocketFactory {
    private static final String SERVER_TAG = "server";

    private ServerSocketAcceptor acceptor;
    private PayloadDecoder payloadDecoder = PayloadDecoder.ZERO_COPY;
    private Consumer errorConsumer = Throwable::printStackTrace;
    private StreamErrorMappers errorMappers = StreamErrorMappers.create();
    private Interceptors.Configurer interceptorsConfigurer = setupPayload -> Interceptors.noop();

    private boolean resumeSupported;
    private Duration resumeSessionDuration = Duration.ofSeconds(120);
    private Duration resumeStreamTimeout = Duration.ofSeconds(10);
    private Function resumeStoreFactory =
        token -> new InMemoryResumableFramesStore(SERVER_TAG, 100_000);

    private boolean multiSubscriberRequester = true;
    private boolean leaseEnabled;
    private Leases.ServerConfigurer leaseConfigurer = scheduler -> Leases.create();

    private ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
    private boolean resumeCleanupStoreOnKeepAlive;
    private boolean acceptFragmentedFrames;
    private int frameSizeLimit = FrameLengthFlyweight.FRAME_LENGTH_MASK;

    private ServerRSocketFactory() {}

    public ServerRSocketFactory byteBufAllocator(ByteBufAllocator allocator) {
      Objects.requireNonNull(allocator);
      this.allocator = allocator;
      return this;
    }

    /**
     * Adds interceptors that are called in order: connection, RSocket requester, socket acceptor,
     * RSocket handler. Global interceptors are called first
     *
     * @param interceptorsConfigurer adds interceptors of connection, RSocket requester, server
     *     socket acceptor, RSocket handler
     * @return this {@link ServerRSocketFactory} instance
     */
    public ServerRSocketFactory interceptors(Interceptors.Configurer interceptorsConfigurer) {
      Objects.requireNonNull(interceptorsConfigurer);
      this.interceptorsConfigurer = interceptorsConfigurer;
      return this;
    }

    public ServerTransportAcceptor acceptor(ServerSocketAcceptor acceptor) {
      this.acceptor = acceptor;
      return ServerStart::new;
    }

    public ServerRSocketFactory frameDecoder(PayloadDecoder payloadDecoder) {
      this.payloadDecoder = payloadDecoder;
      return this;
    }

    public ServerRSocketFactory acceptFragmentedFrames() {
      this.acceptFragmentedFrames = true;
      return this;
    }

    public ServerRSocketFactory errorConsumer(Consumer errorConsumer) {
      this.errorConsumer = errorConsumer;
      return this;
    }

    /**
     * @param errorMappers configures custom error mappers of incoming and outgoing streams.
     * @return this {@link ServerRSocketFactory} instance
     */
    public ServerRSocketFactory streamErrorMapper(StreamErrorMappers errorMappers) {
      this.errorMappers = errorMappers;
      return this;
    }

    /**
     * Enable and configure requests lease support
     *
     * @param leaseConfigurer configures requests lease
     * @return this {@link ServerRSocketFactory} instance
     */
    public ServerRSocketFactory lease(Leases.ServerConfigurer leaseConfigurer) {
      this.leaseEnabled = true;
      this.leaseConfigurer = Objects.requireNonNull(leaseConfigurer, "leaseConfigurer");
      return this;
    }

    /**
     * Enables requests lease support. Responder will not accept any requests because {@link Leases}
     * is not configured
     *
     * @return this {@link ServerRSocketFactory} instance
     */
    public ServerRSocketFactory lease() {
      this.leaseEnabled = true;
      return this;
    }

    /**
     * Enables requests lease support. Responder will not accept any requests because {@link Leases}
     * is not configured
     *
     * @return this {@link ServerRSocketFactory} instance
     */
    public ServerRSocketFactory lease(boolean leaseEnabled) {
      this.leaseEnabled = leaseEnabled;
      return this;
    }

    public ServerRSocketFactory singleSubscriberRequester() {
      this.multiSubscriberRequester = false;
      return this;
    }

    public ServerRSocketFactory resume() {
      this.resumeSupported = true;
      return this;
    }

    public ServerRSocketFactory resume(boolean resumeEnabled) {
      this.resumeSupported = resumeEnabled;
      return this;
    }

    public ServerRSocketFactory resumeStore(
        Function resumeStoreFactory) {
      this.resumeStoreFactory = resumeStoreFactory;
      return this;
    }

    public ServerRSocketFactory resumeSessionDuration(Duration sessionDuration) {
      this.resumeSessionDuration = Objects.requireNonNull(sessionDuration);
      return this;
    }

    public ServerRSocketFactory resumeStreamTimeout(Duration resumeStreamTimeout) {
      this.resumeStreamTimeout = Objects.requireNonNull(resumeStreamTimeout);
      return this;
    }

    public ServerRSocketFactory resumeCleanupOnKeepAlive() {
      resumeCleanupStoreOnKeepAlive = true;
      return this;
    }

    public ServerRSocketFactory frameSizeLimit(int frameSizeLimit) {
      this.frameSizeLimit = Preconditions.requireFrameSizeValid(frameSizeLimit);
      return this;
    }

    private class ServerStart implements Start {
      private final Supplier> transportServer;

      public ServerStart(Supplier> transportServer) {
        this.transportServer = transportServer;
      }

      @Override
      public Mono start() {
        return Mono.defer(
            new Supplier>() {

              ServerSetup serverSetup = serverSetup();

              @Override
              public Mono get() {
                return transportServer
                    .get()
                    .start(
                        duplexConnection -> {
                          if (acceptFragmentedFrames) {
                            duplexConnection =
                                new FragmentationDuplexConnection(
                                    duplexConnection, allocator, frameSizeLimit);
                          }
                          Interceptors interceptors =
                              interceptorsConfigurer.configure(duplexConnection.scheduler());

                          DuplexConnection wrappedConnection =
                              interceptors.interceptConnection(duplexConnection);

                          ClientServerInputMultiplexer multiplexer =
                              new ClientServerInputMultiplexer(wrappedConnection, false);

                          return multiplexer
                              .asSetupConnection()
                              .receive()
                              .next()
                              .flatMap(startFrame -> accept(startFrame, multiplexer, interceptors));
                        },
                        frameSizeLimit)
                    .doOnNext(c -> c.onClose().doFinally(v -> serverSetup.dispose()).subscribe());
              }

              private Mono accept(
                  ByteBuf startFrame,
                  ClientServerInputMultiplexer multiplexer,
                  Interceptors interceptors) {
                switch (FrameHeaderFlyweight.frameType(startFrame)) {
                  case SETUP:
                    return acceptSetup(serverSetup, startFrame, multiplexer, interceptors);
                  case RESUME:
                    return acceptResume(serverSetup, startFrame, multiplexer);
                  default:
                    return acceptUnknown(startFrame, multiplexer);
                }
              }

              private Mono acceptSetup(
                  ServerSetup serverSetup,
                  ByteBuf setupFrame,
                  ClientServerInputMultiplexer multiplexer,
                  Interceptors interceptors) {

                if (!SetupFrameFlyweight.isSupportedVersion(setupFrame)) {
                  return sendError(
                          multiplexer,
                          new InvalidSetupException(
                              "Unsupported version: "
                                  + SetupFrameFlyweight.humanReadableVersion(setupFrame)))
                      .doFinally(
                          signalType -> {
                            setupFrame.release();
                            multiplexer.dispose();
                          });
                }

                boolean isLeaseEnabled = leaseEnabled;

                if (SetupFrameFlyweight.honorLease(setupFrame) && !isLeaseEnabled) {
                  return sendError(multiplexer, new InvalidSetupException("lease is not supported"))
                      .doFinally(
                          signalType -> {
                            setupFrame.release();
                            multiplexer.dispose();
                          });
                }

                return serverSetup.acceptRSocketSetup(
                    setupFrame,
                    multiplexer,
                    (keepAliveHandler, wrappedMultiplexer) -> {
                      ConnectionSetupPayload setupPayload =
                          ConnectionSetupPayload.create(setupFrame);

                      DuplexConnection serverConnection = wrappedMultiplexer.asServerConnection();

                      RSocketsFactory rSocketsFactory =
                          RSocketsFactory.createServer(
                              setupPayload.willClientHonorLease(),
                              serverConnection.scheduler(),
                              leaseConfigurer);

                      ErrorFrameMapper errorFrameMapper =
                          errorMappers.createErrorFrameMapper(allocator);

                      RSocket rSocketRequester =
                          rSocketsFactory.createRequester(
                              allocator,
                              serverConnection,
                              payloadDecoder,
                              errorConsumer,
                              errorFrameMapper,
                              StreamIdSupplier.serverSupplier(),
                              0,
                              setupPayload.keepAliveMaxLifetime(),
                              keepAliveHandler);

                      if (multiSubscriberRequester) {
                        rSocketRequester = new MultiSubscriberRSocket(rSocketRequester);
                      }
                      RSocket wrappedRSocketRequester =
                          interceptors.interceptRequester(rSocketRequester);

                      return interceptors
                          .interceptServerAcceptor(acceptor)
                          .accept(setupPayload, wrappedRSocketRequester)
                          .onErrorResume(
                              err ->
                                  sendError(multiplexer, rejectedSetupError(err))
                                      .then(Mono.error(err)))
                          .doOnNext(
                              rSocketHandler -> {
                                RSocket wrappedRSocketHandler =
                                    interceptors.interceptHandler(rSocketHandler);

                                RSocket rSocketResponder =
                                    rSocketsFactory.createResponder(
                                        allocator,
                                        wrappedMultiplexer.asClientConnection(),
                                        wrappedRSocketHandler,
                                        payloadDecoder,
                                        errorConsumer,
                                        errorFrameMapper);
                              })
                          .doFinally(signalType -> setupPayload.release())
                          .then();
                    });
              }

              private Mono acceptResume(
                  ServerSetup serverSetup,
                  ByteBuf resumeFrame,
                  ClientServerInputMultiplexer multiplexer) {
                return serverSetup.acceptRSocketResume(resumeFrame, multiplexer);
              }
            });
      }

      private ServerSetup serverSetup() {
        return resumeSupported
            ? new ServerSetup.ResumableServerSetup(
                allocator,
                new SessionManager(),
                resumeSessionDuration,
                resumeStreamTimeout,
                resumeStoreFactory,
                resumeCleanupStoreOnKeepAlive)
            : new ServerSetup.DefaultServerSetup(allocator);
      }

      private Mono acceptUnknown(ByteBuf frame, ClientServerInputMultiplexer multiplexer) {
        return sendError(
                multiplexer,
                new InvalidSetupException(
                    "invalid setup frame: " + FrameHeaderFlyweight.frameType(frame)))
            .doFinally(
                signalType -> {
                  frame.release();
                  multiplexer.dispose();
                });
      }

      private Mono sendError(ClientServerInputMultiplexer multiplexer, Exception exception) {
        return multiplexer
            .asSetupConnection()
            .sendOne(ErrorFrameFlyweight.encode(allocator, 0, exception))
            .onErrorResume(err -> Mono.empty());
      }

      private Exception rejectedSetupError(Throwable err) {
        String msg = err.getMessage();
        return new RejectedSetupException(msg == null ? "rejected by server acceptor" : msg);
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy