/** @file

  ProtocolProbeSessionAccept

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you 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.
 */

#include "P_Net.h"
#include "I_Machine.h"
#include "ProtocolProbeSessionAccept.h"
#include "http2/HTTP2.h"
#include "ProxyProtocol.h"
#include "I_NetVConnection.h"

static bool
proto_is_http2(IOBufferReader *reader)
{
  char buf[HTTP2_CONNECTION_PREFACE_LEN];
  char *end;
  ptrdiff_t nbytes;

  end    = reader->memcpy(buf, sizeof(buf), 0 /* offset */);
  nbytes = end - buf;

  // Client must send at least 4 bytes to get a reasonable match.
  if (nbytes < 4) {
    return false;
  }

  ink_assert(nbytes <= (int64_t)HTTP2_CONNECTION_PREFACE_LEN);
  return memcmp(HTTP2_CONNECTION_PREFACE, buf, nbytes) == 0;
}

struct ProtocolProbeTrampoline : public Continuation, public ProtocolProbeSessionAcceptEnums {
  static const size_t minimum_read_size   = 1;
  static const unsigned buffer_size_index = CLIENT_CONNECTION_FIRST_READ_BUFFER_SIZE_INDEX;
  IOBufferReader *reader;

  explicit ProtocolProbeTrampoline(const ProtocolProbeSessionAccept *probe, Ptr<ProxyMutex> &mutex, MIOBuffer *buffer,
                                   IOBufferReader *reader)
    : Continuation(mutex), probeParent(probe)
  {
    this->iobuf  = buffer ? buffer : new_MIOBuffer(buffer_size_index);
    this->reader = reader ? reader : iobuf->alloc_reader(); // reader must be allocated only on a new MIOBuffer.
    SET_HANDLER(&ProtocolProbeTrampoline::ioCompletionEvent);
  }

  int
  ioCompletionEvent(int event, void *edata)
  {
    VIO *vio;
    NetVConnection *netvc;
    ProtoGroupKey key = N_PROTO_GROUPS; // use this as an invalid value.

    vio   = static_cast<VIO *>(edata);
    netvc = static_cast<NetVConnection *>(vio->vc_server);

    switch (event) {
    case VC_EVENT_EOS:
    case VC_EVENT_ERROR:
    case VC_EVENT_ACTIVE_TIMEOUT:
    case VC_EVENT_INACTIVITY_TIMEOUT:
      // Error ....
      goto done;
    case VC_EVENT_READ_READY:
    case VC_EVENT_READ_COMPLETE:
      break;
    default:
      return EVENT_ERROR;
    }

    ink_assert(netvc != nullptr);

    if (!reader->is_read_avail_more_than(minimum_read_size - 1)) {
      // Not enough data read. Well, that sucks.
      goto done;
    }

    // if proxy_protocol is enabled via port descriptor AND the src IP is in
    // the trusted whitelist for proxy protocol, then check to see if it is
    // present

    IpMap *pp_ipmap;
    pp_ipmap = probeParent->proxy_protocol_ipmap;

    if (netvc->get_is_proxy_protocol()) {
      Debug("proxyprotocol", "ioCompletionEvent: proxy protocol is enabled on this port");
      if (pp_ipmap->getCount() > 0) {
        Debug("proxyprotocol", "ioCompletionEvent: proxy protocol has a configured whitelist of trusted IPs - checking");
        void *payload = nullptr;
        if (!pp_ipmap->contains(netvc->get_remote_addr(), &payload)) {
          Debug("proxyprotocol",
                "ioCompletionEvent: proxy protocol src IP is NOT in the configured whitelist of trusted IPs - closing connection");
          goto done;
        } else {
          char new_host[INET6_ADDRSTRLEN];
          Debug("proxyprotocol", "ioCompletionEvent: Source IP [%s] is trusted in the whitelist for proxy protocol",
                ats_ip_ntop(netvc->get_remote_addr(), new_host, sizeof(new_host)));
        }
      } else {
        Debug("proxyprotocol",
              "ioCompletionEvent: proxy protocol DOES NOT have a configured whitelist of trusted IPs but proxy protocol is "
              "ernabled on this port - processing all connections");
      }

      if (http_has_proxy_v1(reader, netvc)) {
        Debug("proxyprotocol", "ioCompletionEvent: http has proxy_v1 header");
        netvc->set_remote_addr(netvc->get_proxy_protocol_src_addr());
      } else {
        Debug("proxyprotocol",
              "ioCompletionEvent: proxy protocol was enabled, but required header was not present in the transaction - "
              "closing connection");
        goto done;
      }
    } // end of Proxy Protocol processing

    if (proto_is_http2(reader)) {
      key = PROTO_HTTP2;
    } else {
      key = PROTO_HTTP;
    }

    netvc->do_io_read(nullptr, 0, nullptr); // Disable the read IO that we started.

    if (probeParent->endpoint[key] == nullptr) {
      Warning("Unregistered protocol type %d", key);
      goto done;
    }

    // Directly invoke the session acceptor, letting it take ownership of the input buffer.
    if (!probeParent->endpoint[key]->accept(netvc, this->iobuf, reader)) {
      // IPAllow check fails in XxxSessionAccept::accept() if false returned.
      goto done;
    }
    delete this;
    return EVENT_CONT;

  done:
    netvc->do_io_close();
    free_MIOBuffer(this->iobuf);
    this->iobuf = nullptr;
    delete this;
    return EVENT_CONT;
  }

  MIOBuffer *iobuf;
  const ProtocolProbeSessionAccept *probeParent;
};

int
ProtocolProbeSessionAccept::mainEvent(int event, void *data)
{
  if (event == NET_EVENT_ACCEPT) {
    ink_assert(data);

    VIO *vio;
    NetVConnection *netvc          = (NetVConnection *)data;
    ProtocolProbeTrampoline *probe = new ProtocolProbeTrampoline(this, netvc->mutex, nullptr, nullptr);

    // XXX we need to apply accept inactivity timeout here ...

    if (!probe->reader->is_read_avail_more_than(0)) {
      Debug("http", "probe needs data, read..");
      vio = netvc->do_io_read(probe, BUFFER_SIZE_FOR_INDEX(ProtocolProbeTrampoline::buffer_size_index), probe->iobuf);
      vio->reenable();
    } else {
      Debug("http", "probe already has data, call ioComplete directly..");
      vio = netvc->do_io_read(nullptr, 0, nullptr);
      probe->ioCompletionEvent(VC_EVENT_READ_COMPLETE, (void *)vio);
    }
    return EVENT_CONT;
  }

  ink_abort("Protocol probe received a fatal error: errno = %d", -((int)(intptr_t)data));
  return EVENT_CONT;
}

bool
ProtocolProbeSessionAccept::accept(NetVConnection *, MIOBuffer *, IOBufferReader *)
{
  ink_release_assert(0);
  return false;
}

void
ProtocolProbeSessionAccept::registerEndpoint(ProtoGroupKey key, SessionAccept *ap)
{
  ink_release_assert(endpoint[key] == nullptr);
  this->endpoint[key] = ap;
}
