//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.server.handler;

import java.io.Closeable;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;

import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.http.HostPortHttpField;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.QuotedCSV;
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.IncludeExcludeSet;
import org.eclipse.jetty.util.InetAddressSet;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedOperation;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Locker;


/**
 * <p>Handler to limit the threads per IP address for DOS protection</p>
 * <p>The ThreadLimitHandler applies a limit to the number of Threads 
 * that can be used simultaneously per remote IP address.
 * </p>
 * <p>The handler makes a determination of the remote IP separately to
 * any that may be made by the {@link ForwardedRequestCustomizer} or similar:
 * <ul>
 * <li>This handler will use either only a single style
 * of forwarded header.   This is on the assumption that a trusted local proxy
 * will produce only a single forwarded header and that any additional
 * headers are likely from untrusted client side proxies.</li>
 * <li>If multiple instances of a forwarded header are provided, this
 * handler will use the right-most instance, which will have been set from
 * the trusted local proxy</li>
 * </ul>
 * Requests in excess of the limit will be asynchronously suspended until
 * a thread is available.  
 * <p>This is a simpler alternative to DosFilter</p>
 */
public class ThreadLimitHandler extends HandlerWrapper
{
    private static final Logger LOG = Log.getLogger(ThreadLimitHandler.class);

    private final static String REMOTE = "o.e.j.s.h.TLH.REMOTE";
    private final static String PERMIT = "o.e.j.s.h.TLH.PASS";
    private final boolean _rfc7239;
    private final String _forwardedHeader;
    private final IncludeExcludeSet<String, InetAddress> _includeExcludeSet = new IncludeExcludeSet<>(InetAddressSet.class);
    private final ConcurrentMap<String, Remote> _remotes = new ConcurrentHashMap<>();
    private volatile boolean _enabled;
    private int _threadLimit=10;

    public ThreadLimitHandler()
    {
        this(null,false);
    }
    
    public ThreadLimitHandler(@Name("forwardedHeader") String forwardedHeader)
    {
        this(forwardedHeader,HttpHeader.FORWARDED.is(forwardedHeader));
    }

    public ThreadLimitHandler(@Name("forwardedHeader") String forwardedHeader, @Name("rfc7239")  boolean rfc7239)
    {
        super();
        _rfc7239 = rfc7239;
        _forwardedHeader = forwardedHeader;
        _enabled = true;
    }
    
    @Override
    protected void doStart() throws Exception
    {
        super.doStart();
        LOG.info(String.format("ThreadLimitHandler enable=%b limit=%d include=%s",_enabled,_threadLimit,_includeExcludeSet));
    }

    @ManagedAttribute("true if this handler is enabled")
    public boolean isEnabled()
    {
        return _enabled;
    }

    public void setEnabled(boolean enabled)
    {
        _enabled = enabled;
        LOG.info(String.format("ThreadLimitHandler enable=%b limit=%d include=%s",_enabled,_threadLimit,_includeExcludeSet));
    }

    @ManagedAttribute("The maximum threads that can be dispatched per remote IP")
    public int getThreadLimit()
    {
        return _threadLimit;
    }

    public void setThreadLimit(int threadLimit)
    {
        if (threadLimit<=0)
            throw new IllegalArgumentException("limit must be >0");
        _threadLimit = threadLimit;
    }
    
    @ManagedOperation("Include IP in thread limits")
    public void include(String inetAddressPattern)
    {
        _includeExcludeSet.include(inetAddressPattern);
    }

    @ManagedOperation("Exclude IP from thread limits")
    public void exclude(String inetAddressPattern)
    {
        _includeExcludeSet.exclude(inetAddressPattern);
    }
    
    @Override
    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        // Allow ThreadLimit to be enabled dynamically without restarting server
        if (!_enabled)
        {
            // if disabled, handle normally
            super.handle(target,baseRequest,request,response);
        }
        else
        {
            // Get the remote address of the request
            Remote remote = getRemote(baseRequest);
            if (remote==null)
            {
                // if remote is not known, handle normally
                super.handle(target,baseRequest,request,response);
            }
            else
            {
                // Do we already have a future permit from a previous invocation?
                Closeable permit = (Closeable)baseRequest.getAttribute(PERMIT);
                try
                {
                    if (permit!=null)
                    {
                        // Yes, remove it from any future async cycles.
                        baseRequest.removeAttribute(PERMIT);
                    }
                    else
                    {
                        // No, then lets try to acquire one
                        CompletableFuture<Closeable> future_permit=remote.acquire();

                        // Did we get a permit?
                        if (future_permit.isDone())
                        {
                            // yes
                            permit=future_permit.get();
                        }
                        else
                        {
                            if (LOG.isDebugEnabled())
                                LOG.debug("Threadlimited {} {}",remote,target);
                            // No, lets asynchronously suspend the request
                            AsyncContext async = baseRequest.startAsync();
                            // let's never timeout the async.  If this is a DOS, then good to make them wait, if this is not
                            // then give them maximum time to get a thread.
                            async.setTimeout(0);

                            // dispatch the request when we do eventually get a pass
                            future_permit.thenAccept(c->
                            {
                                baseRequest.setAttribute(PERMIT,c);
                                async.dispatch();
                            });
                            return;
                        }
                    }

                    // Use the permit
                    super.handle(target,baseRequest,request,response);
                }
                catch (InterruptedException | ExecutionException e)
                {
                    throw new ServletException(e);
                }
                finally
                {
                    if (permit!=null)
                        permit.close();
                }
            }
        }
    }
    
    protected int getThreadLimit(String ip)
    {
        if (!_includeExcludeSet.isEmpty())
        {
            try
            {
                if (!_includeExcludeSet.test(InetAddress.getByName(ip)))
                {
                    LOG.debug("excluded {}",ip);
                    return 0;
                }
            }
            catch(Exception e)
            {
                LOG.ignore(e);
            }
        }
        return _threadLimit;
    }

    protected Remote getRemote(Request baseRequest)
    {
        Remote remote = (Remote)baseRequest.getAttribute(REMOTE);
        if (remote!=null)
            return remote;
        
        String ip=getRemoteIP(baseRequest);
        LOG.debug("ip={}",ip);
        if (ip==null)
            return null;
        
        int limit = getThreadLimit(ip);
        if (limit<=0)
            return null;

        remote = _remotes.get(ip);
        if (remote==null)
        {
            Remote r = new Remote(ip,limit);
            remote = _remotes.putIfAbsent(ip,r);
            if (remote==null)
                remote = r;
        }
        
        baseRequest.setAttribute(REMOTE,remote);

        return remote;
    }
    
    
    protected String getRemoteIP(Request baseRequest)
    {
        // Do we have a forwarded header set?
        if (_forwardedHeader!=null && !_forwardedHeader.isEmpty())
        {
            // Yes, then try to get the remote IP from the header
            String remote = _rfc7239?getForwarded(baseRequest):getXForwardedFor(baseRequest);
            if (remote!=null && !remote.isEmpty())
                return remote;
        }
        
        // If no remote IP from a header, determine it directly from the channel
        // Do not use the request methods, as they may have been lied to by the 
        // RequestCustomizer!
        InetSocketAddress inet_addr = baseRequest.getHttpChannel().getRemoteAddress();
        if (inet_addr!=null && inet_addr.getAddress()!=null)
            return inet_addr.getAddress().getHostAddress();
        return null;
    }

    private String getForwarded(Request request)
    {
        // Get the right most Forwarded for value.
        // This is the value from the closest proxy and the only one that
        // can be trusted.
        RFC7239 rfc7239 = new RFC7239();
        HttpFields httpFields = request.getHttpFields();
        for (HttpField field : httpFields)
            if (_forwardedHeader.equalsIgnoreCase(field.getName()))
                rfc7239.addValue(field.getValue());
        
        if (rfc7239.getFor()!=null)
            return new HostPortHttpField(rfc7239.getFor()).getHost();
        
        return null;
    }
    
    private String getXForwardedFor(Request request)
    {
        // Get the right most XForwarded-For for value.
        // This is the value from the closest proxy and the only one that
        // can be trusted.
        String forwarded_for = null;
        HttpFields httpFields = request.getHttpFields();
        for (HttpField field : httpFields)
            if (_forwardedHeader.equalsIgnoreCase(field.getName()))
                forwarded_for = field.getValue();
        
        if (forwarded_for==null || forwarded_for.isEmpty())
            return null;
        
        int comma = forwarded_for.lastIndexOf(',');
        return (comma>=0)?forwarded_for.substring(comma+1).trim():forwarded_for;
    }


    private final class Remote implements Closeable
    {
        private final String _ip;
        private final int _limit;
        private final Locker _locker = new Locker();
        private int _permits;
        private Deque<CompletableFuture<Closeable>> _queue = new ArrayDeque<>();
        private final CompletableFuture<Closeable> _permitted = CompletableFuture.completedFuture(this);
        
        public Remote(String ip, int limit)
        {
            _ip=ip;
            _limit=limit;
        }
        
        public CompletableFuture<Closeable> acquire()
        {
            try(Locker.Lock lock = _locker.lock())
            {
                // Do we have available passes?
                if (_permits<_limit)
                {
                    // Yes - increment the allocated passes
                    _permits++;
                    // return the already completed future
                    return _permitted; // TODO is it OK to share/reuse this?
                }
                
                // No pass available, so queue a new future 
                CompletableFuture<Closeable> pass = new CompletableFuture<Closeable>();
                _queue.addLast(pass);
                return pass;
            }
        }
        
        @Override
        public void close() throws IOException
        {
            try(Locker.Lock lock = _locker.lock())
            {
                // reduce the allocated passes
                _permits--;
                while(true)
                {
                    // Are there any future passes waiting?
                    CompletableFuture<Closeable> permit = _queue.pollFirst();
                    
                    // No - we are done
                    if (permit==null)
                        break;
                    
                    // Yes - if we can complete them, we are done
                    if (permit.complete(this))
                    {
                        _permits++;
                        break;
                    }
                    
                    // Somebody else must have completed/failed that future pass,
                    // so let's try for another.
                }
            }
        }
        
        @Override
        public String toString()
        {
            try(Locker.Lock lock = _locker.lock())
            {
                return String.format("R[ip=%s,p=%d,l=%d,q=%d]",_ip,_permits,_limit,_queue.size());
            }
        }
    }

    private final class RFC7239 extends QuotedCSV
    {
        String _for;
        
        private RFC7239()
        {
            super(false);
        }
        
        String getFor()
        {
            return _for;
        }

        @Override
        protected void parsedParam(StringBuffer buffer, int valueLength, int paramName, int paramValue)
        {
            if (valueLength==0 && paramValue>paramName)
            {
                String name=StringUtil.asciiToLowerCase(buffer.substring(paramName,paramValue-1));
                if ("for".equalsIgnoreCase(name))
                {
                    String value=buffer.substring(paramValue);
                    
                    // if unknown, clear any leftward values
                    if ("unknown".equalsIgnoreCase(value))
                        _for = null;
                    // Otherwise accept IP or token(starting with '_') as remote keys
                    else
                        _for=value;
                }
            }
        }
    }
}
