Beispiel #1
0
 public void handleEvent(final ConnectedStreamChannel channel) {
   if (UndertowLogger.REQUEST_LOGGER.isTraceEnabled()) {
     UndertowLogger.REQUEST_LOGGER.tracef("Opened connection with %s", channel.getPeerAddress());
   }
   final PushBackStreamChannel pushBackStreamChannel = new PushBackStreamChannel(channel);
   HttpServerConnection connection =
       new HttpServerConnection(
           channel, bufferPool, rootHandler, maxConcurrentRequestsPerConnection);
   HttpReadListener readListener = new HttpReadListener(channel, connection);
   pushBackStreamChannel.getReadSetter().set(readListener);
   readListener.handleEvent(pushBackStreamChannel);
   channel.resumeReads();
 }
Beispiel #2
0
 public static void executeRootHandler(
     final HttpHandler handler, final HttpServerExchange exchange) {
   try {
     exchange.setInCall(true);
     handler.handleRequest(exchange);
     exchange.setInCall(false);
     if (exchange.isDispatched()) {
       final Runnable dispatchTask = exchange.getDispatchTask();
       Executor executor = exchange.getDispatchExecutor();
       exchange.unDispatch();
       if (dispatchTask != null) {
         executor = executor == null ? exchange.getConnection().getWorker() : executor;
         executor.execute(dispatchTask);
       }
     } else {
       exchange.endExchange();
     }
   } catch (Throwable t) {
     exchange.setInCall(false);
     if (!exchange.isResponseStarted()) {
       exchange.setResponseCode(500);
     }
     UndertowLogger.REQUEST_LOGGER.errorf(t, "Blocking request failed %s", exchange);
     exchange.endExchange();
   }
 }
 @Override
 public void run() {
   handle = null;
   if (expireTime == -1) {
     return;
   }
   long current = System.currentTimeMillis();
   if (current < expireTime) {
     // timeout has been bumped, re-schedule
     handle =
         WorkerUtils.executeAfter(
             connection.getIoThread(),
             timeoutCommand,
             (expireTime - current) + FUZZ_FACTOR,
             TimeUnit.MILLISECONDS);
     return;
   }
   UndertowLogger.REQUEST_LOGGER.tracef(
       "Timing out channel %s due to inactivity", connection.getSourceChannel());
   IoUtils.safeClose(connection);
   if (connection.getSourceChannel().isReadResumed()) {
     ChannelListeners.invokeChannelListener(
         connection.getSourceChannel(), connection.getSourceChannel().getReadListener());
   }
   if (connection.getSinkChannel().isWriteResumed()) {
     ChannelListeners.invokeChannelListener(
         connection.getSinkChannel(), connection.getSinkChannel().getWriteListener());
   }
 }
 @Override
 public void emitHeader(HttpString name, String value, boolean neverIndex) {
   headerMap.add(name, value);
   for (int i = 0; i < name.length(); ++i) {
     byte c = name.byteAt(i);
     if (c >= 'A' && c <= 'Z') {
       invalid = true;
       UndertowLogger.REQUEST_LOGGER.debugf(
           "Malformed request, header %s contains uppercase characters", name);
     }
   }
 }
 @Override
 public void handleEvent(final StreamSourceChannel channel) {
   try {
     doParse(channel);
     if (state == 4) {
       exchange.dispatch(SameThreadExecutor.INSTANCE, handler);
     }
   } catch (IOException e) {
     IoUtils.safeClose(channel);
     UndertowLogger.REQUEST_LOGGER.ioExceptionReadingFromChannel(e);
     exchange.endExchange();
   }
 }
 @Override
 public void run() {
   UndertowLogger.REQUEST_LOGGER.tracef("Timing out channel %s due to inactivity");
   IoUtils.safeClose(connection);
   if (connection.getSourceChannel().isReadResumed()) {
     ChannelListeners.invokeChannelListener(
         connection.getSourceChannel(), connection.getSourceChannel().getReadListener());
   }
   if (connection.getSinkChannel().isWriteResumed()) {
     ChannelListeners.invokeChannelListener(
         connection.getSinkChannel(), connection.getSinkChannel().getWriteListener());
   }
 }
    @Override
    public void handleEvent(SpdyChannel channel) {
      try {
        SpdyStreamSourceChannel result = channel.receive();
        if (result instanceof SpdySynReplyStreamSourceChannel) {
          final int streamId = ((SpdySynReplyStreamSourceChannel) result).getStreamId();
          SpdyClientExchange request = currentExchanges.get(streamId);
          result.addCloseTask(
              new ChannelListener<SpdyStreamSourceChannel>() {
                @Override
                public void handleEvent(SpdyStreamSourceChannel channel) {
                  currentExchanges.remove(streamId);
                }
              });
          if (request == null) {

            // server side initiated stream, we can't deal with that at the moment
            // just fail
            // TODO: either handle this properly or at the very least send RST_STREAM
            channel.sendGoAway(SpdyChannel.CLOSE_PROTOCOL_ERROR);
            IoUtils.safeClose(SpdyClientConnection.this);
            return;
          }
          request.responseReady((SpdySynReplyStreamSourceChannel) result);

        } else if (result instanceof SpdyPingStreamSourceChannel) {
          handlePing((SpdyPingStreamSourceChannel) result);
        } else if (result instanceof SpdyRstStreamStreamSourceChannel) {
          int stream = ((SpdyRstStreamStreamSourceChannel) result).getStreamId();
          UndertowLogger.REQUEST_LOGGER.debugf("Client received RST_STREAM for stream %s", stream);
          SpdyClientExchange exchange = currentExchanges.get(stream);
          if (exchange != null) {
            exchange.failed(UndertowMessages.MESSAGES.spdyStreamWasReset());
          }
        } else if (!channel.isOpen()) {
          throw UndertowMessages.MESSAGES.channelIsClosed();
        }

      } catch (IOException e) {
        UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
        IoUtils.safeClose(SpdyClientConnection.this);
        for (Map.Entry<Integer, SpdyClientExchange> entry : currentExchanges.entrySet()) {
          try {
            entry.getValue().failed(e);
          } catch (Exception ex) {
            UndertowLogger.REQUEST_IO_LOGGER.ioException(new IOException(ex));
          }
        }
      }
    }
 @Override
 public void requestDone(HttpServerExchange exchange) {
   // Batch may no longer be active if session was invalidated
   if (this.batch.isActive()) {
     try (BatchContext context =
         this.manager.getSessionManager().getBatcher().resumeBatch(this.batch)) {
       this.entry.getKey().close();
       this.batch.close();
     } catch (Throwable e) {
       // Don't propagate exceptions at the stage, since response was alread committed
       UndertowLogger.REQUEST_LOGGER.warn(e.getLocalizedMessage(), e);
     }
   }
 }
  @Override
  public void handleRequest(HttpServerExchange exchange) throws Exception {
    HeaderMap requestHeaders = exchange.getRequestHeaders();
    final String sessionId = requestHeaders.getFirst(SSL_SESSION_ID);
    if (sessionId != null) {
      final String cipher = requestHeaders.getFirst(SSL_CIPHER);
      String clientCert = requestHeaders.getFirst(SSL_CLIENT_CERT);
      // the proxy client replaces \n with ' '
      if (clientCert != null && clientCert.length() > 28) {
        StringBuilder sb = new StringBuilder(clientCert.length() + 1);
        sb.append(Certificates.BEGIN_CERT);
        sb.append('\n');
        sb.append(
            clientCert
                .replace(' ', '\n')
                .substring(28, clientCert.length() - 26)); // core certificate data
        sb.append('\n');
        sb.append(Certificates.END_CERT);
        clientCert = sb.toString();
      }

      try {
        SSLSessionInfo info = new BasicSSLSessionInfo(sessionId, cipher, clientCert);
        exchange.setRequestScheme(HTTPS);
        exchange.getConnection().setSslSessionInfo(info);
        exchange.addExchangeCompleteListener(CLEAR_SSL_LISTENER);
      } catch (java.security.cert.CertificateException e) {
        UndertowLogger.REQUEST_LOGGER.debugf(
            e, "Could not create certificate from header %s", clientCert);
      } catch (CertificateException e) {
        UndertowLogger.REQUEST_LOGGER.debugf(
            e, "Could not create certificate from header %s", clientCert);
      }
    }
    next.handleRequest(exchange);
  }
 @Override
 public void handleRequest(final HttpServerExchange exchange) {
   final Deque<String> origin = exchange.getRequestHeaders().get(Headers.ORIGIN);
   if (origin == null) {
     if (requireOriginHeader) {
       // TODO: Is 403 (Forbidden) the best response code
       if (UndertowLogger.REQUEST_LOGGER.isDebugEnabled()) {
         UndertowLogger.REQUEST_LOGGER.debugf(
             "Refusing request for %s due to lack of Origin: header", exchange.getRequestPath());
       }
       HttpHandlers.executeHandler(originFailedHandler, exchange);
       return;
     }
   } else {
     boolean found = false;
     final boolean requireAllOrigins = this.requireAllOrigins;
     for (final String header : origin) {
       if (allowedOrigins.contains(header)) {
         found = true;
         if (!requireAllOrigins) {
           break;
         }
       } else if (requireAllOrigins) {
         if (UndertowLogger.REQUEST_LOGGER.isDebugEnabled()) {
           UndertowLogger.REQUEST_LOGGER.debugf(
               "Refusing request for %s due to Origin %s not being in the allowed origins list",
               exchange.getRequestPath(), header);
         }
         HttpHandlers.executeHandler(originFailedHandler, exchange);
         return;
       }
     }
     if (!found) {
       if (UndertowLogger.REQUEST_LOGGER.isDebugEnabled()) {
         UndertowLogger.REQUEST_LOGGER.debugf(
             "Refusing request for %s as none of the specified origins %s were in the allowed origins list",
             exchange.getRequestPath(), origin);
       }
       HttpHandlers.executeHandler(originFailedHandler, exchange);
       return;
     }
   }
   HttpHandlers.executeHandler(next, exchange);
 }
  public void handleEvent(final StreamSourceChannel channel) {

    Pooled<ByteBuffer> existing = connection.getExtraBytes();

    final Pooled<ByteBuffer> pooled =
        existing == null ? connection.getBufferPool().allocate() : existing;
    final ByteBuffer buffer = pooled.getResource();
    boolean free = true;

    try {
      int res;
      do {
        if (existing == null) {
          buffer.clear();
          try {
            res = channel.read(buffer);
          } catch (IOException e) {
            UndertowLogger.REQUEST_IO_LOGGER.debug("Error reading request", e);
            IoUtils.safeClose(connection);
            return;
          }
        } else {
          res = buffer.remaining();
        }

        if (res == 0) {
          if (!channel.isReadResumed()) {
            channel.getReadSetter().set(this);
            channel.resumeReads();
          }
          return;
        } else if (res == -1) {
          try {
            channel.suspendReads();
            channel.shutdownReads();
            final StreamSinkChannel responseChannel = this.connection.getChannel().getSinkChannel();
            responseChannel.shutdownWrites();
            // will return false if there's a response queued ahead of this one, so we'll set up a
            // listener then
            if (!responseChannel.flush()) {
              responseChannel
                  .getWriteSetter()
                  .set(ChannelListeners.flushingChannelListener(null, null));
              responseChannel.resumeWrites();
            }
          } catch (IOException e) {
            UndertowLogger.REQUEST_IO_LOGGER.debug("Error reading request", e);
            // f**k it, it's all ruined
            IoUtils.safeClose(channel);
            return;
          }
          return;
        }
        if (existing != null) {
          existing = null;
          connection.setExtraBytes(null);
        } else {
          buffer.flip();
        }
        parser.handle(buffer, state, httpServerExchange);
        if (buffer.hasRemaining()) {
          free = false;
          connection.setExtraBytes(pooled);
        }
        int total = read + res;
        read = total;
        if (read > maxRequestSize) {
          UndertowLogger.REQUEST_LOGGER.requestHeaderWasTooLarge(
              connection.getPeerAddress(), maxRequestSize);
          IoUtils.safeClose(connection);
          return;
        }
      } while (!state.isComplete());

      // we remove ourselves as the read listener from the channel;
      // if the http handler doesn't set any then reads will suspend, which is the right thing to do
      channel.getReadSetter().set(null);
      channel.suspendReads();

      final HttpServerExchange httpServerExchange = this.httpServerExchange;
      httpServerExchange.putAttachment(
          UndertowOptions.ATTACHMENT_KEY, connection.getUndertowOptions());
      httpServerExchange.setRequestScheme(connection.getSslSession() != null ? "https" : "http");
      this.httpServerExchange = null;
      HttpTransferEncoding.setupRequest(httpServerExchange);
      HttpHandlers.executeRootHandler(
          connection.getRootHandler(),
          httpServerExchange,
          Thread.currentThread() instanceof XnioExecutor);
    } catch (Exception e) {
      sendBadRequestAndClose(connection.getChannel(), e);
      return;
    } finally {
      if (free) pooled.free();
    }
  }
  @Override
  public Session createSession(
      final HttpServerExchange serverExchange, final SessionConfig config) {
    if (evictionQueue != null) {
      if (expireOldestUnusedSessionOnMax) {
        while (sessions.size() >= maxSize && !evictionQueue.isEmpty()) {

          String key = evictionQueue.poll();
          UndertowLogger.REQUEST_LOGGER.debugf("Removing session %s as max size has been hit", key);
          SessionImpl toRemove = sessions.get(key);
          if (toRemove != null) {
            toRemove.invalidate(
                null, SessionListener.SessionDestroyedReason.TIMEOUT); // todo: better reason
          }
        }
      } else if (sessions.size() >= maxSize) {
        if (statisticsEnabled) {
          rejectedSessionCount.incrementAndGet();
        }
        throw UndertowMessages.MESSAGES.tooManySessions(maxSize);
      }
    }
    if (config == null) {
      throw UndertowMessages.MESSAGES.couldNotFindSessionCookieConfig();
    }
    String sessionID = config.findSessionId(serverExchange);
    int count = 0;
    while (sessionID == null) {
      sessionID = sessionIdGenerator.createSessionId();
      if (sessions.containsKey(sessionID)) {
        sessionID = null;
      }
      if (count++ == 100) {
        // this should never happen
        // but we guard against pathalogical session id generators to prevent an infinite loop
        throw UndertowMessages.MESSAGES.couldNotGenerateUniqueSessionId();
      }
    }
    Object evictionToken;
    if (evictionQueue != null) {
      evictionToken = evictionQueue.offerLastAndReturnToken(sessionID);
    } else {
      evictionToken = null;
    }
    if (statisticsEnabled) {
      createdSessionCount.incrementAndGet();
    }
    final SessionImpl session =
        new SessionImpl(
            this,
            sessionID,
            config,
            serverExchange.getIoThread(),
            serverExchange.getConnection().getWorker(),
            evictionToken,
            defaultSessionTimeout);
    sessions.put(sessionID, session);
    config.setSessionId(serverExchange, session.getId());
    session.lastAccessed = System.currentTimeMillis();
    session.bumpTimeout();
    sessionListeners.sessionCreated(session, serverExchange);
    serverExchange.putAttachment(NEW_SESSION, session);
    return session;
  }