/**
  * Creates a new default SmppServer. Window monitoring and automatic expiration of requests will
  * be disabled with no monitorExecutors. A "cachedDaemonThreadPool" will be used for IO worker
  * threads.
  *
  * @param configuration The server configuration to create this server with
  * @param serverHandler The handler implementation for handling bind requests and
  *     creating/destroying sessions.
  */
 public DefaultSmppServer(SmppServerConfiguration configuration, SmppServerHandler serverHandler) {
   this(
       configuration,
       serverHandler,
       null,
       configuration.isNonBlockingSocketsEnabled()
           ? new NioEventLoopGroup()
           : new OioEventLoopGroup(),
       configuration.isNonBlockingSocketsEnabled()
           ? new NioEventLoopGroup()
           : new OioEventLoopGroup());
 }
  /**
   * Creates a new default SmppServer.
   *
   * @param configuration The server configuration to create this server with
   * @param serverHandler The handler implementation for handling bind requests and
   *     creating/destroying sessions.
   * @param monitorExecutor The scheduled executor that all sessions will share to monitor
   *     themselves and expire requests. If null monitoring will be disabled.
   * @param bossGroup Specify the EventLoopGroup to accept new connections and handle accepted
   *     connections. The {@link EventLoopGroup} is used to handle all the events and IO for {@link
   *     SocketChannel}.
   * @param workerGroup The {@link EventLoopGroup} is used to handle all the events and IO for
   *     {@link Channel}.
   */
  public DefaultSmppServer(
      final SmppServerConfiguration configuration,
      SmppServerHandler serverHandler,
      ScheduledExecutorService monitorExecutor,
      EventLoopGroup bossGroup,
      EventLoopGroup workerGroup) {
    this.configuration = configuration;
    // the same group we'll put every server channel
    this.channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    this.serverHandler = serverHandler;

    // tie the server bootstrap to this server socket channel factory
    this.serverBootstrap = new ServerBootstrap();

    // a factory for creating channels (connections)
    if (configuration.isNonBlockingSocketsEnabled()) {
      this.serverBootstrap.channel(NioServerSocketChannel.class);
    } else {
      this.serverBootstrap.channel(OioServerSocketChannel.class);
    }

    this.bossGroup = bossGroup;
    this.workerGroup = workerGroup;
    this.serverBootstrap.group(this.bossGroup, this.workerGroup);

    // set options for the server socket that are useful
    this.serverBootstrap.option(ChannelOption.SO_REUSEADDR, configuration.isReuseAddress());

    // we use the same default pipeline for all new channels - no need for a factory
    this.serverConnector = new SmppServerConnector(channels, this);

    this.serverBootstrap.childHandler(
        new ChannelInitializer<SocketChannel>() {
          @Override
          public void initChannel(SocketChannel ch) throws Exception {
            ch.pipeline()
                .addLast(SmppChannelConstants.PIPELINE_SERVER_CONNECTOR_NAME, serverConnector);
          }
        });

    // a shared timer used to make sure new channels are bound within X milliseconds
    this.bindTimer = new Timer(configuration.getName() + "-BindTimer0", true);
    // NOTE: this would permit us to customize the "transcoding" context for a server if needed
    this.transcoder = new DefaultPduTranscoder(new DefaultPduTranscoderContext());
    this.sessionIdSequence = new AtomicLong(0);
    this.monitorExecutor = monitorExecutor;
    this.counters = new DefaultSmppServerCounters();
    if (configuration.isJmxEnabled()) {
      registerMBean();
    }
  }