All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.undertow.server.protocol.ParseTimeoutUpdater Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2014 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package io.undertow.server.protocol;

import io.undertow.UndertowLogger;
import io.undertow.server.ServerConnection;
import io.undertow.util.WorkerUtils;
import org.xnio.IoUtils;
import org.xnio.XnioExecutor;
import org.xnio.channels.ConnectedChannel;

import java.io.Closeable;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * Wrapper for parse timeout.
 *
 * @author Sebastian Laskawiec
 * @see io.undertow.UndertowOptions#REQUEST_PARSE_TIMEOUT
 */
public final class ParseTimeoutUpdater implements Runnable, ServerConnection.CloseListener, Closeable {

    private final ConnectedChannel connection;
    private final long requestParseTimeout;
    private final long requestIdleTimeout;
    private volatile XnioExecutor.Key handle;
    private volatile long expireTime = -1;
    private volatile boolean parsing = false;

    //we add 50ms to the timeout to make sure the underlying channel has actually timed out
    private static final int FUZZ_FACTOR = 50;

    private final Runnable closeTask;


    /**
     * Creates new instance of ParseTimeoutSourceConduit.
     *  @param channel             Channel which will be closed in case of timeout.
     * @param requestParseTimeout Timeout value. Negative value will indicate that this updated is disabled.
     * @param requestIdleTimeout
     */
    public ParseTimeoutUpdater(ConnectedChannel channel, long requestParseTimeout, long requestIdleTimeout) {
        this(channel, requestParseTimeout, requestIdleTimeout, new Runnable() {
            @Override
            public void run() {
                IoUtils.safeClose(channel);
            }
        });
    }

    /**
     * Creates new instance of ParseTimeoutSourceConduit.
     *  @param channel             Channel which will be closed in case of timeout.
     * @param requestParseTimeout Timeout value. Negative value will indicate that this updated is disabled.
     * @param requestIdleTimeout
     */
    public ParseTimeoutUpdater(ConnectedChannel channel, long requestParseTimeout, long requestIdleTimeout, Runnable closeTask) {
        this.connection = channel;
        this.requestParseTimeout = requestParseTimeout;
        this.requestIdleTimeout = requestIdleTimeout;
        this.closeTask = closeTask;
    }
    /**
     * Called when the connection goes idle
     */
    public void connectionIdle() {
        parsing = false;
        handleSchedule(requestIdleTimeout);
    }

    private void handleSchedule(long timeout) {
        //no current timeout, clear the expire time
        if(timeout == -1) {
            this.expireTime = -1;
            return;
        }
        //calculate the new expire time
        long newExpireTime = System.currentTimeMillis() + timeout;
        long oldExpireTime = this.expireTime;
        this.expireTime = newExpireTime;
        //if the new one is less than the current one we need to schedule a new timer, so cancel the old one
        if(newExpireTime < oldExpireTime) {
            if(handle != null) {
                handle.remove();
                handle = null;
            }
        }
        if(handle == null) {
            try {
                handle = WorkerUtils.executeAfter(connection.getIoThread(), this, timeout + FUZZ_FACTOR, TimeUnit.MILLISECONDS);
            } catch (RejectedExecutionException e) {
                UndertowLogger.REQUEST_LOGGER.debug("Failed to schedule parse timeout, server is probably shutting down", e);
            }
        }
    }

    /**
     * Called when a request is received, however it is not parsed in a single read() call. This starts a timer,
     * and if the request is not parsed within this time then the connection is closed.
     *
     */
    public void failedParse() {
        if(!parsing) {
            parsing = true;
            handleSchedule(requestParseTimeout);
        }
    }

    /**
     * Cancels timeout countdown.
     * 

* Should be called after parsing is complete (to avoid closing connection during other activities). *

*/ public void requestStarted() { expireTime = -1; parsing = false; } @Override public void run() { if(!connection.isOpen()) { return; } handle = null; if (expireTime > 0) { //timeout is not active long now = System.currentTimeMillis(); if(expireTime > now) { handle = WorkerUtils.executeAfter(connection.getIoThread(), this, (expireTime - now) + FUZZ_FACTOR, TimeUnit.MILLISECONDS); } else { if(parsing) { UndertowLogger.REQUEST_LOGGER.parseRequestTimedOut(connection.getPeerAddress()); } else { UndertowLogger.REQUEST_LOGGER.debugf("Timing out idle connection from %s", connection.getPeerAddress()); } closeTask.run(); } } } @Override public void closed(ServerConnection connection) { close(); } public void close() { if(handle != null) { handle.remove(); handle = null; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy