@Test
  public void serverSessionBindRejectedWithInvalidPassword() throws Exception {
    DefaultSmppServer server0 = createSmppServer();
    server0.start();

    try {
      DefaultSmppClient client0 = new DefaultSmppClient();
      SmppSessionConfiguration sessionConfig0 = createDefaultConfiguration();
      sessionConfig0.setSystemId(SYSTEMID);
      sessionConfig0.setPassword("BADPASS");

      // this should fail (invalid password)
      try {
        SmppSession session0 = client0.bind(sessionConfig0);
        Assert.fail();
      } catch (SmppBindException e) {
        Assert.assertEquals(SmppConstants.STATUS_INVPASWD, e.getBindResponse().getCommandStatus());
      }

      Assert.assertEquals(0, serverHandler.sessions.size());
      Assert.assertEquals(0, server0.getChannels().size());
    } finally {
      server0.destroy();
    }
  }
  @Test
  public void serverSessionBindRejectedWithInvalidSystemId() throws Exception {
    DefaultSmppServer server0 = createSmppServer();
    server0.start();

    try {
      DefaultSmppClient client0 = new DefaultSmppClient();
      SmppSessionConfiguration sessionConfig0 = createDefaultConfiguration();
      sessionConfig0.setSystemId("TESTID");

      // this should fail (invalid system id)
      try {
        SmppSession session0 = client0.bind(sessionConfig0);
        Assert.fail();
      } catch (SmppBindException e) {
        Assert.assertEquals(SmppConstants.STATUS_INVSYSID, e.getBindResponse().getCommandStatus());
      }

      // give this a little time to catch up
      Thread.sleep(100);

      Assert.assertEquals(0, serverHandler.sessions.size());
      Assert.assertEquals(0, server0.getChannels().size());
    } finally {
      server0.destroy();
    }
  }
  @Test
  public void serverNotEnoughWorkerThreadsCausesBindTimerToCloseChannel() throws Exception {
    BlockThreadSmppServerHandler serverHandler0 = new BlockThreadSmppServerHandler();
    SmppServerConfiguration configuration = createSmppServerConfiguration();
    // permit up to 0.5 seconds to bind
    configuration.setBindTimeout(500);
    DefaultSmppServer server0 = new DefaultSmppServer(configuration, serverHandler0);
    server0.start();

    try {
      // there is an issue without telling the server how many worker threads
      // to create beforehand with starvation only Runtime.getRuntime().availableProcessors()
      // worker threads are created by default!!! (yikes)
      int workersToStarveWith = Runtime.getRuntime().availableProcessors();

      // initiate bind requests on all sessions we care about -- this should
      // technicaly "starve" the server of worker threads since they'll all
      // be blocked in a Thread.sleep
      for (int i = 0; i < workersToStarveWith; i++) {
        DefaultSmppClient client0 = new DefaultSmppClient();
        SmppSessionConfiguration sessionConfig0 = createDefaultConfiguration();
        sessionConfig0.setName("WorkerTest.Session." + i);
        // don't use default method of binding, connect the socket first
        DefaultSmppSession session0 =
            client0.doOpen(sessionConfig0, new DefaultSmppSessionHandler());
        // try to bind and execute a bind request and wait for a bind response
        BaseBind bindRequest = client0.createBindRequest(sessionConfig0);
        try {
          // just send the request without caring if it succeeds
          session0.sendRequestPdu(bindRequest, 2000, false);
        } catch (SmppChannelException e) {
          System.out.println(e.getMessage());
        }
      }

      // now try to bind normally -- since all previous workers are "starved"
      // this should fail to bind and the socket closed by the "BindTimer"
      DefaultSmppClient client0 = new DefaultSmppClient();
      SmppSessionConfiguration sessionConfig0 = createDefaultConfiguration();
      sessionConfig0.setName("WorkerTestChannelClosed.Session");
      sessionConfig0.setBindTimeout(750);

      try {
        client0.bind(sessionConfig0);
        Assert.fail();
      } catch (SmppTimeoutException e) {
        // the BindTimer should end up closing the connection since the
        // worker thread were "starved"
        logger.debug("Correctly received SmppChannelException during bind");
      }

    } finally {
      Thread.sleep(10500);
      Assert.assertEquals(0, server0.getChannels().size());
      Assert.assertEquals(3, server0.getCounters().getBindTimeouts());
      server0.destroy();
    }
  }
  @Test
  public void serverSessionBindVersion33() throws Exception {
    DefaultSmppServer server0 = createSmppServer();
    server0.start();

    try {
      DefaultSmppClient client0 = new DefaultSmppClient();
      SmppSessionConfiguration sessionConfig0 = createDefaultConfiguration();

      // set back to version 3.3
      sessionConfig0.setInterfaceVersion(SmppConstants.VERSION_3_3);

      // we will not use the proper method of binding since we need to
      // access the bind response to verify it's correct
      DefaultSmppSession session0 = client0.doOpen(sessionConfig0, new DefaultSmppSessionHandler());

      // create a bind request based on this config
      BaseBind bindRequest = client0.createBindRequest(sessionConfig0);

      // execute a bind request and wait for a bind response
      BaseBindResp bindResponse = session0.bind(bindRequest, 200);

      Thread.sleep(100);

      SmppServerSession serverSession0 = serverHandler.sessions.iterator().next();
      Assert.assertEquals(1, serverHandler.sessions.size());
      Assert.assertEquals(1, server0.getChannels().size());
      Assert.assertEquals(true, serverSession0.isBound());
      Assert.assertEquals(SmppBindType.TRANSCEIVER, serverSession0.getBindType());
      Assert.assertEquals(SmppSession.Type.SERVER, serverSession0.getLocalType());
      Assert.assertEquals(SmppSession.Type.CLIENT, serverSession0.getRemoteType());

      // verify "requested" version is still 3.3
      Assert.assertEquals(
          SmppConstants.VERSION_3_3, serverSession0.getConfiguration().getInterfaceVersion());
      // verify the session interface version is normalized to 3.3
      Assert.assertEquals(SmppConstants.VERSION_3_3, serverSession0.getInterfaceVersion());
      Assert.assertEquals(false, serverSession0.areOptionalParametersSupported());

      // verify client session version settings are correct
      Assert.assertEquals((byte) 0x33, session0.getConfiguration().getInterfaceVersion());
      Assert.assertEquals((byte) 0x33, session0.getInterfaceVersion());
      Assert.assertEquals(false, session0.areOptionalParametersSupported());

      // verify NO optional parameters were included in bind response
      Assert.assertEquals(0, bindResponse.getOptionalParameterCount());
      Assert.assertEquals("cloudhopper", bindResponse.getSystemId());

      serverSession0.close();
      Thread.sleep(200);
      Assert.assertEquals(0, serverHandler.sessions.size());
      Assert.assertEquals(0, server0.getChannels().size());
      Assert.assertEquals(false, serverSession0.isBound());
    } finally {
      server0.destroy();
    }
  }
    @Override
    public void sessionBindRequested(
        Long sessionId, SmppSessionConfiguration sessionConfiguration, final BaseBind bindRequest)
        throws SmppProcessingException {
      // test name change of sessions
      sessionConfiguration.setName("Test1");

      if (!SYSTEMID.equals(bindRequest.getSystemId())) {
        throw new SmppProcessingException(SmppConstants.STATUS_INVSYSID);
      }

      if (!PASSWORD.equals(bindRequest.getPassword())) {
        throw new SmppProcessingException(SmppConstants.STATUS_INVPASWD);
      }

      // throw new SmppProcessingException(SmppConstants.STATUS_BINDFAIL, null);
    }
 @Override
 public void sessionBindRequested(
     Long sessionId, SmppSessionConfiguration sessionConfiguration, final BaseBind bindRequest)
     throws SmppProcessingException {
   sessionConfiguration.setName("Application.SMPP." + sessionConfiguration.getSystemId());
 }
  protected void createSession(
      Long sessionId,
      Channel channel,
      SmppSessionConfiguration config,
      BaseBindResp preparedBindResponse)
      throws SmppProcessingException {
    // NOTE: exactly one PDU (bind request) was read from the channel, we
    // now need to delegate permitting this bind request by calling a method
    // further upstream.  Only after the server-side is completely ready to
    // start processing requests from this session, do we want to actually
    // return the bind response and start reading further requests -- we'll
    // initially block reading from the channel first -- this will be turned
    // back on via the "serverReady()" method call on the session object

    // make sure the channel is not being read/processed (until we flag we're ready later on)
    channel.config().setAutoRead(false);

    // auto negotiate the interface version in use based on the requested interface version
    byte interfaceVersion = this.autoNegotiateInterfaceVersion(config.getInterfaceVersion());

    // create a new server session associated with this server
    DefaultSmppSession session =
        new DefaultSmppSession(
            SmppSession.Type.SERVER,
            config,
            channel,
            this,
            sessionId,
            preparedBindResponse,
            interfaceVersion,
            monitorExecutor);

    // replace name of thread used for renaming
    SmppSessionThreadRenamer threadRenamer =
        (SmppSessionThreadRenamer)
            channel.pipeline().get(SmppChannelConstants.PIPELINE_SESSION_THREAD_RENAMER_NAME);
    threadRenamer.setThreadName(config.getName());

    // add a logging handler after the thread renamer
    SmppSessionLogger loggingHandler =
        new SmppSessionLogger(
            DefaultSmppSession.class.getCanonicalName(), config.getLoggingOptions());
    channel
        .pipeline()
        .addAfter(
            SmppChannelConstants.PIPELINE_SESSION_THREAD_RENAMER_NAME,
            SmppChannelConstants.PIPELINE_SESSION_LOGGER_NAME,
            loggingHandler);

    // decoder in pipeline is ok (keep it)

    // create a new wrapper around a session to pass the pdu up the chain
    channel.pipeline().remove(SmppChannelConstants.PIPELINE_SESSION_WRAPPER_NAME);
    channel
        .pipeline()
        .addLast(
            SmppChannelConstants.PIPELINE_SESSION_WRAPPER_NAME, new SmppSessionWrapper(session));

    // check if the # of channels exceeds maxConnections
    if (this.channels.size() > this.configuration.getMaxConnectionSize()) {
      logger.warn(
          "The current connection size [{}] exceeds the configured max connection size [{}]",
          this.channels.size(),
          this.configuration.getMaxConnectionSize());
    }

    // session created, now pass it upstream
    counters.incrementSessionCreatedAndGet();
    incrementSessionSizeCounters(session);
    this.serverHandler.sessionCreated(sessionId, session, preparedBindResponse);

    // register this session as an mbean
    if (configuration.isJmxEnabled()) {
      session.registerMBean(
          configuration.getJmxDomain()
              + ":type="
              + configuration.getName()
              + "Sessions,name="
              + sessionId);
    }
  }
 public SmppSessionConfiguration createDefaultConfiguration() {
   SmppSessionConfiguration configuration = new SmppSessionConfiguration();
   configuration.setWindowSize(1);
   configuration.setName("Tester.Session.0");
   configuration.setType(SmppBindType.TRANSCEIVER);
   configuration.setHost("localhost");
   configuration.setPort(PORT);
   configuration.setConnectTimeout(100);
   configuration.setBindTimeout(100);
   configuration.setSystemId(SYSTEMID);
   configuration.setPassword(PASSWORD);
   configuration.getLoggingOptions().setLogBytes(true);
   return configuration;
 }