private void processKey(SelectionKey key) {

    try {

      if (key.isReadable()) {
        final DatagramChannel socketChannel = (DatagramChannel) key.channel();
        reader.readAll(socketChannel);
      }

      if (key.isWritable()) {
        final DatagramChannel socketChannel = (DatagramChannel) key.channel();
        try {
          int bytesJustWritten = writer.writeAll(socketChannel);
          contemplateThrottleWrites(bytesJustWritten);
        } catch (NotYetConnectedException e) {
          if (LOG.isDebugEnabled()) LOG.debug("", e);
          serverConnector.connectLater();
        } catch (IOException e) {
          if (LOG.isDebugEnabled()) LOG.debug("", e);
          serverConnector.connectLater();
        }
      }
    } catch (Exception e) {
      LOG.error("", e);
      if (!isClosed) closeEarlyAndQuietly(key.channel());
    }
  }
  /** binds to the server socket and process data This method will block until interrupted */
  @Override
  void processEvent() throws IOException {
    try {

      connectClient().register(selector, OP_READ);
      serverConnector.connectLater();

      while (selector.isOpen()) {
        registerPendingRegistrations();

        // this may block for a long time, upon return the
        // selected set contains keys of the ready channels
        final int n = selector.select(100);

        if (shouldEnableOpWrite) enableWrites();

        checkThrottleInterval();

        if (n == 0) {
          continue; // nothing to do
        }

        if (useJavaNIOSelectionKeys) {
          // use the standard java nio selector

          final Set<SelectionKey> selectionKeys = selector.selectedKeys();
          for (final SelectionKey key : selectionKeys) {
            processKey(key);
          }
          selectionKeys.clear();
        } else {
          // use the netty like selector

          final SelectionKey[] keys = selectedKeys.flip();

          try {
            for (int i = 0; i < keys.length && keys[i] != null; i++) {
              final SelectionKey key = keys[i];

              try {
                processKey(key);
              } catch (BufferUnderflowException e) {
                if (!isClosed) LOG.error("", e);
              }
            }
          } finally {
            for (int i = 0; i < keys.length && keys[i] != null; i++) {
              keys[i] = null;
            }
          }
        }
      }
    } catch (CancelledKeyException
        | ConnectException
        | ClosedChannelException
        | ClosedSelectorException e) {
      if (LOG.isDebugEnabled()) LOG.debug("", e);
    } catch (Exception e) {
      LOG.error("", e);
    } catch (Throwable e) {
      LOG.error("", e);
      throw e;
    } finally {

      if (LOG.isDebugEnabled()) LOG.debug("closing name=" + this.name);
      if (!isClosed) {
        closeResources();
      }
    }
  }
  /**
   * Loads jetty configuration from the given URL.
   *
   * @param cfgUrl URL to load configuration from.
   * @throws GridException if load failed.
   */
  private void loadJettyConfiguration(@Nullable URL cfgUrl) throws GridException {
    if (cfgUrl == null) {
      HttpConfiguration httpCfg = new HttpConfiguration();

      httpCfg.setSecureScheme("https");
      httpCfg.setSecurePort(8443);
      httpCfg.setSendServerVersion(true);
      httpCfg.setSendDateHeader(true);

      String srvPortStr = System.getProperty(GG_JETTY_PORT, "8080");

      int srvPort;

      try {
        srvPort = Integer.valueOf(srvPortStr);
      } catch (NumberFormatException ignore) {
        throw new GridException(
            "Failed to start Jetty server because GRIDGAIN_JETTY_PORT system property "
                + "cannot be cast to integer: "
                + srvPortStr);
      }

      httpSrv = new Server(new QueuedThreadPool(20, 200));

      ServerConnector srvConn = new ServerConnector(httpSrv, new HttpConnectionFactory(httpCfg));

      srvConn.setHost(System.getProperty(GG_JETTY_HOST, "localhost"));
      srvConn.setPort(srvPort);
      srvConn.setIdleTimeout(30000L);
      srvConn.setReuseAddress(true);

      httpSrv.addConnector(srvConn);

      httpSrv.setStopAtShutdown(false);
    } else {
      XmlConfiguration cfg;

      try {
        cfg = new XmlConfiguration(cfgUrl);
      } catch (FileNotFoundException e) {
        throw new GridSpiException("Failed to find configuration file: " + cfgUrl, e);
      } catch (SAXException e) {
        throw new GridSpiException("Failed to parse configuration file: " + cfgUrl, e);
      } catch (IOException e) {
        throw new GridSpiException("Failed to load configuration file: " + cfgUrl, e);
      } catch (Exception e) {
        throw new GridSpiException(
            "Failed to start HTTP server with configuration file: " + cfgUrl, e);
      }

      try {
        httpSrv = (Server) cfg.configure();
      } catch (Exception e) {
        throw new GridException("Failed to start Jetty HTTP server.", e);
      }
    }

    assert httpSrv != null;

    httpSrv.setHandler(jettyHnd);

    override(getJettyConnector());
  }