public void start() {
    final Xnio xnio;
    try {
      // Do what org.jboss.as.remoting.XnioUtil does
      xnio =
          Xnio.getInstance(
              null,
              Module.getModuleFromCallerModuleLoader(
                      ModuleIdentifier.fromString("org.jboss.xnio.nio"))
                  .getClassLoader());
    } catch (Exception e) {
      throw new IllegalStateException(e.getLocalizedMessage());
    }
    try {
      // TODO make this configurable
      worker =
          xnio.createWorker(
              OptionMap.builder()
                  .set(Options.WORKER_IO_THREADS, 4)
                  .set(Options.CONNECTION_HIGH_WATER, 1000000)
                  .set(Options.CONNECTION_LOW_WATER, 1000000)
                  .set(Options.WORKER_TASK_CORE_THREADS, 10)
                  .set(Options.WORKER_TASK_MAX_THREADS, 12)
                  .set(Options.TCP_NODELAY, true)
                  .set(Options.CORK, true)
                  .getMap());

      Builder serverOptionsBuilder =
          OptionMap.builder().set(Options.TCP_NODELAY, true).set(Options.REUSE_ADDRESSES, true);
      ChannelListener acceptListener = ChannelListeners.openListenerAdapter(openListener);
      if (httpAddress != null) {
        normalServer =
            worker.createStreamConnectionServer(
                httpAddress, acceptListener, serverOptionsBuilder.getMap());
        normalServer.resumeAccepts();
      }
      if (secureAddress != null) {
        SSLContext sslContext = securityRealm.getSSLContext();
        Set<AuthMechanism> supportedMechanisms =
            securityRealm.getSupportedAuthenticationMechanisms();
        if (supportedMechanisms.contains(AuthMechanism.CLIENT_CERT)) {
          if (supportedMechanisms.contains(AuthMechanism.DIGEST)
              || supportedMechanisms.contains(AuthMechanism.PLAIN)) {
            // Username / Password auth is possible so don't mandate a client certificate.
            serverOptionsBuilder.set(SSL_CLIENT_AUTH_MODE, REQUESTED);
          } else {
            serverOptionsBuilder.set(SSL_CLIENT_AUTH_MODE, REQUIRED);
          }
        }
        OptionMap secureOptions = serverOptionsBuilder.getMap();
        XnioSsl xnioSsl = new JsseXnioSsl(worker.getXnio(), secureOptions, sslContext);
        secureServer =
            xnioSsl.createSslConnectionServer(worker, secureAddress, acceptListener, secureOptions);
        secureServer.resumeAccepts();
      }
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
  private static HttpHandler secureDomainAccess(
      final HttpHandler domainHandler, final SecurityRealm securityRealm) {
    RealmIdentityManager rim = new RealmIdentityManager(securityRealm);
    List<AuthenticationMechanism> undertowMechanisms;
    if (securityRealm != null) {
      Set<AuthMechanism> mechanisms = securityRealm.getSupportedAuthenticationMechanisms();
      undertowMechanisms = new ArrayList<AuthenticationMechanism>(mechanisms.size());
      undertowMechanisms.add(wrap(new CachedAuthenticatedSessionMechanism(), null));
      for (AuthMechanism current : mechanisms) {
        switch (current) {
          case KERBEROS:
            undertowMechanisms.add(
                wrap(
                    new GSSAPIAuthenticationMechanism(new ServerSubjectFactory(securityRealm, rim)),
                    current));
            break;
          case CLIENT_CERT:
            undertowMechanisms.add(wrap(new ClientCertAuthenticationMechanism(), current));
            break;
          case DIGEST:
            List<DigestAlgorithm> digestAlgorithms = Collections.singletonList(DigestAlgorithm.MD5);
            List<DigestQop> digestQops = Collections.singletonList(DigestQop.AUTH);
            undertowMechanisms.add(
                wrap(
                    new DigestAuthenticationMechanism(
                        digestAlgorithms,
                        digestQops,
                        securityRealm.getName(),
                        "/management",
                        new SimpleNonceManager()),
                    current));
            break;
          case PLAIN:
            undertowMechanisms.add(
                wrap(new BasicAuthenticationMechanism(securityRealm.getName()), current));
            break;
          case LOCAL:
            break;
        }
      }
    } else {
      undertowMechanisms = Collections.singletonList(wrap(new AnonymousMechanism(), null));
    }

    // If the only mechanism is the cached mechanism then no need to add these.
    HttpHandler current = domainHandler;
    current = new AuthenticationCallHandler(current);
    // Currently the security handlers are being added after a PATH handler so we know
    // authentication is required by
    // this point.
    current = new AuthenticationConstraintHandler(current);
    current = new AuthenticationMechanismsHandler(current, undertowMechanisms);

    return new SecurityInitialHandler(AuthenticationMode.PRO_ACTIVE, rim, current);
  }
  private static HttpHandler secureDomainAccess(
      final HttpHandler domainHandler, final SecurityRealm securityRealm) {
    if (securityRealm != null) {
      Set<AuthMechanism> mechanisms = securityRealm.getSupportedAuthenticationMechanisms();
      List<AuthenticationMechanism> undertowMechanisms =
          new ArrayList<AuthenticationMechanism>(mechanisms.size());
      undertowMechanisms.add(wrap(new CachedAuthenticatedSessionMechanism(), null));
      for (AuthMechanism current : mechanisms) {
        switch (current) {
          case CLIENT_CERT:
            undertowMechanisms.add(wrap(new ClientCertAuthenticationMechanism(), current));
            break;
          case DIGEST:
            List<DigestAlgorithm> digestAlgorithms = Collections.singletonList(DigestAlgorithm.MD5);
            List<DigestQop> digestQops = Collections.emptyList();
            undertowMechanisms.add(
                wrap(
                    new DigestAuthenticationMechanism(
                        digestAlgorithms,
                        digestQops,
                        securityRealm.getName(),
                        "/management",
                        new SimpleNonceManager()),
                    current));
            break;
          case PLAIN:
            undertowMechanisms.add(
                wrap(new BasicAuthenticationMechanism(securityRealm.getName()), current));
            break;
        }
      }

      if (undertowMechanisms.size() > 1) {
        // If the only mechanism is the cached mechanism then no need to add these.
        HttpHandler current = domainHandler;
        current = new AuthenticationCallHandler(current);
        // Currently the security handlers are being added after a PATH handler so we know
        // authentication is required by
        // this point.
        current = new AuthenticationConstraintHandler(current);
        current = new AuthenticationMechanismsHandler(current, undertowMechanisms);
        current = new ConnectionAuthenticationCacheHandler(current);

        return new SecurityInitialHandler(
            AuthenticationMode.PRO_ACTIVE, new RealmIdentityManager(securityRealm), current);
      }
      // TODO - If there were no mechanisms to begin with requests should be represented as an
      // anonymous user.
      // If there were mechanisms but none suitable for HTTP reject all requests.
    }

    return domainHandler;
  }
  private AuthorizingCallbackHandler getAuthorizingCallbackHandler(final String realmName) {
    SecurityRealm realm;
    if (TEST_REALM.equals(realmName)) {
      realm = securityRealm;
    } else {
      ServiceContainer container = getContainer();
      ServiceController<?> service =
          container.getRequiredService(SecurityRealm.ServiceUtil.createServiceName(realmName));

      realm = (SecurityRealm) service.getValue();
    }

    return realm.getAuthorizingCallbackHandler(AuthMechanism.PLAIN);
  }
 public void start(HttpServer httpServer, SecurityRealm securityRealm) {
   HttpContext context = httpServer.createContext(DOMAIN_API_CONTEXT, this);
   if (securityRealm != null) {
     DomainCallbackHandler callbackHandler = securityRealm.getCallbackHandler();
     Class[] supportedCallbacks = callbackHandler.getSupportedCallbacks();
     if (DigestAuthenticator.requiredCallbacksSupported(supportedCallbacks)) {
       context.setAuthenticator(
           new DigestAuthenticator(
               callbackHandler,
               securityRealm.getName(),
               contains(DigestHashCallback.class, supportedCallbacks)));
     } else if (BasicAuthenticator.requiredCallbacksSupported(supportedCallbacks)) {
       context.setAuthenticator(new BasicAuthenticator(callbackHandler, securityRealm.getName()));
     }
   }
 }
 /**
  * Connect and register at the remote domain controller.
  *
  * @return connection the established connection
  * @throws IOException
  */
 protected Connection openConnection() throws IOException {
   // Perhaps this can just be done once?
   CallbackHandler callbackHandler = null;
   SSLContext sslContext = null;
   if (realm != null) {
     sslContext = realm.getSSLContext();
     CallbackHandlerFactory handlerFactory = realm.getSecretCallbackHandlerFactory();
     if (handlerFactory != null) {
       String username = this.username != null ? this.username : localHostName;
       callbackHandler = handlerFactory.getCallbackHandler(username);
     }
   }
   final ProtocolConnectionConfiguration config =
       ProtocolConnectionConfiguration.copy(configuration);
   config.setCallbackHandler(callbackHandler);
   config.setSslContext(sslContext);
   config.setUri(uri);
   // Connect
   return ProtocolConnectionUtils.connectSync(config);
 }
  private static void setupOpenListener(
      HttpOpenListener listener,
      ModelController modelController,
      ConsoleMode consoleMode,
      String consoleSlot,
      ControlledProcessStateService controlledProcessStateService,
      int securePort,
      SecurityRealm securityRealm,
      final ChannelUpgradeHandler upgradeHandler) {

    CanonicalPathHandler canonicalPathHandler = new CanonicalPathHandler();
    listener.setRootHandler(canonicalPathHandler);

    PathHandler pathHandler = new PathHandler();
    HttpHandler current = pathHandler;
    if (upgradeHandler != null) {
      upgradeHandler.setNonUpgradeHandler(current);
      current = upgradeHandler;
    }

    if (securePort > 0) {
      current = new SinglePortConfidentialityHandler(current, securePort);
    }
    // caching handler, used for static resources
    current =
        new CacheHandler(
            new DirectBufferCache(
                1024, 1024 * 10, 1024 * 1000, BufferAllocator.BYTE_BUFFER_ALLOCATOR),
            current);
    current = new SimpleErrorPageHandler(current);

    canonicalPathHandler.setNext(current);

    ResourceHandlerDefinition consoleHandler = null;
    try {
      consoleHandler = consoleMode.createConsoleHandler(consoleSlot);
    } catch (ModuleLoadException e) {
      ROOT_LOGGER.consoleModuleNotFound(consoleSlot == null ? "main" : consoleSlot);
    }

    try {
      pathHandler.addPrefixPath(
          ErrorContextHandler.ERROR_CONTEXT, ErrorContextHandler.createErrorContext(consoleSlot));
    } catch (ModuleLoadException e) {
      ROOT_LOGGER.errorContextModuleNotFound(consoleSlot == null ? "main" : consoleSlot);
    }

    ManagementRootConsoleRedirectHandler rootConsoleRedirectHandler =
        new ManagementRootConsoleRedirectHandler(consoleHandler);
    DomainApiCheckHandler domainApiHandler =
        new DomainApiCheckHandler(modelController, controlledProcessStateService);
    pathHandler.addPrefixPath("/", rootConsoleRedirectHandler);
    if (consoleHandler != null) {
      HttpHandler readinessHandler =
          new RedirectReadinessHandler(
              securityRealm, consoleHandler.getHandler(), ErrorContextHandler.ERROR_CONTEXT);
      pathHandler.addPrefixPath(consoleHandler.getContext(), readinessHandler);
    }

    HttpHandler readinessHandler =
        new DmrFailureReadinessHandler(
            securityRealm,
            secureDomainAccess(domainApiHandler, securityRealm),
            ErrorContextHandler.ERROR_CONTEXT);
    pathHandler.addPrefixPath(DomainApiCheckHandler.PATH, readinessHandler);
    pathHandler.addExactPath("management-upload", readinessHandler);

    if (securityRealm != null) {
      pathHandler.addPrefixPath(LogoutHandler.PATH, new LogoutHandler(securityRealm.getName()));
    }
  }
  public static ManagementHttpServer create(
      InetSocketAddress bindAddress,
      InetSocketAddress secureBindAddress,
      int backlog,
      ModelController modelController,
      SecurityRealm securityRealm,
      ControlledProcessStateService controlledProcessStateService,
      ConsoleMode consoleMode,
      String consoleSlot,
      final ChannelUpgradeHandler upgradeHandler,
      ManagementHttpRequestProcessor managementHttpRequestProcessor,
      Collection<String> allowedOrigins)
      throws IOException, StartException {

    SSLContext sslContext = null;
    SslClientAuthMode sslClientAuthMode = null;
    if (secureBindAddress != null) {
      sslContext = securityRealm.getSSLContext();
      if (sslContext == null) {
        throw ROOT_LOGGER.sslRequestedNoSslContext();
      }
      Set<AuthMechanism> supportedMechanisms = securityRealm.getSupportedAuthenticationMechanisms();
      if (supportedMechanisms.contains(AuthMechanism.CLIENT_CERT)) {
        if (supportedMechanisms.contains(AuthMechanism.DIGEST)
            || supportedMechanisms.contains(AuthMechanism.PLAIN)) {
          // Username / Password auth is possible so don't mandate a client certificate.
          sslClientAuthMode = REQUESTED;
        } else {
          sslClientAuthMode = REQUIRED;
        }
      }
    }

    HttpOpenListener openListener =
        new HttpOpenListener(
            new ByteBufferSlicePool(BufferAllocator.DIRECT_BYTE_BUFFER_ALLOCATOR, 4096, 10 * 4096));

    int secureRedirectPort = secureBindAddress != null ? secureBindAddress.getPort() : -1;
    // WFLY-2870 -- redirect not supported if bindAddress and secureBindAddress are using different
    // InetAddress
    boolean redirectSupported =
        (bindAddress == null
            || secureBindAddress == null
            || bindAddress.getAddress().equals(secureBindAddress.getAddress()));
    if (!redirectSupported && secureRedirectPort > 0) {
      HttpServerLogger.ROOT_LOGGER.httpsRedirectNotSupported(
          bindAddress.getAddress(), secureBindAddress.getAddress());
      secureRedirectPort = -1;
    }

    setupOpenListener(
        openListener,
        modelController,
        consoleMode,
        consoleSlot,
        controlledProcessStateService,
        secureRedirectPort,
        securityRealm,
        upgradeHandler,
        managementHttpRequestProcessor,
        allowedOrigins);
    return new ManagementHttpServer(
        openListener, bindAddress, secureBindAddress, sslContext, sslClientAuthMode);
  }
  @Override
  public synchronized void start(StartContext context) throws StartException {
    super.start(context);

    SecurityRealm realm = securityRealm.getOptionalValue();

    // TODO: SSL support for the client
    // TODO: wire up idle timeout when new version of undertow arrives
    final ModCluster.Builder modClusterBuilder;
    final XnioWorker worker = workerInjectedValue.getValue();
    if (realm == null) {
      modClusterBuilder = ModCluster.builder(worker);
    } else {
      SSLContext sslContext = realm.getSSLContext();
      OptionMap.Builder builder = OptionMap.builder();
      builder.set(Options.USE_DIRECT_BUFFERS, true);
      OptionMap combined = builder.getMap();

      XnioSsl xnioSsl = new UndertowXnioSsl(worker.getXnio(), combined, sslContext);
      modClusterBuilder = ModCluster.builder(worker, UndertowClient.getInstance(), xnioSsl);
    }
    modClusterBuilder
        .setHealthCheckInterval(healthCheckInterval)
        .setMaxRequestTime(maxRequestTime)
        .setCacheConnections(cachedConnections)
        .setQueueNewRequests(requestQueueSize > 0)
        .setRequestQueueSize(requestQueueSize)
        .setRemoveBrokenNodes(removeBrokenNodes)
        .setTtl(connectionIdleTimeout)
        .setMaxConnections(connectionsPerThread)
        .setUseAlias(useAlias);

    modCluster = modClusterBuilder.build();

    MCMPConfig.Builder builder = MCMPConfig.builder();
    InetAddress multicastAddress = advertiseSocketBinding.getValue().getMulticastAddress();
    if (multicastAddress == null) {
      throw UndertowLogger.ROOT_LOGGER.advertiseSocketBindingRequiresMulticastAddress();
    }
    if (advertiseFrequency > 0) {
      builder
          .enableAdvertise()
          .setAdvertiseAddress(
              advertiseSocketBinding.getValue().getSocketAddress().getAddress().getHostAddress())
          .setAdvertiseGroup(multicastAddress.getHostAddress())
          .setAdvertisePort(advertiseSocketBinding.getValue().getPort())
          .setAdvertiseFrequency(advertiseFrequency)
          .setPath(advertisePath)
          .setProtocol(advertiseProtocol)
          .setSecurityKey(securityKey);
    }
    builder.setManagementHost(managementSocketBinding.getValue().getSocketAddress().getHostName());
    builder.setManagementPort(managementSocketBinding.getValue().getSocketAddress().getPort());

    config = builder.build();

    if (advertiseFrequency > 0) {
      try {
        modCluster.advertise(config);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
    modCluster.start();
  }