// Copyright 2020 The gRPC Authors
//
// 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.

// Local copy of Envoy xDS proto file, used for testing only.

syntax = "proto3";

package envoy.config.listener.v3;

import "src/proto/grpc/testing/xds/v3/address.proto";
import "src/proto/grpc/testing/xds/v3/base.proto";

import "google/protobuf/any.proto";
import "google/protobuf/wrappers.proto";

// [#protodoc-title: Listener configuration]
// Listener :ref:`configuration overview <config_listeners>`

// Describes a type of API listener, which is used in non-proxy clients. The type of API
// exposed to the non-proxy application depends on the type of API listener.
message ApiListener {
  // The type in this field determines the type of API listener. At present, the following
  // types are supported:
  // envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager (HTTP)
  // [#next-major-version: In the v3 API, replace this Any field with a oneof containing the
  // specific config message for each type of API listener. We could not do this in v2 because
  // it would have caused circular dependencies for go protos: lds.proto depends on this file,
  // and http_connection_manager.proto depends on rds.proto, which is in the same directory as
  // lds.proto, so lds.proto cannot depend on this file.]
  google.protobuf.Any api_listener = 1;
}

message Filter {
  reserved 3;

  // The name of the filter to instantiate. The name must match a
  // :ref:`supported filter <config_network_filters>`.
  string name = 1;

  // [#extension-category: envoy.filters.network]
  oneof config_type {
    // Filter specific configuration which depends on the filter being
    // instantiated. See the supported filters for further documentation.
    google.protobuf.Any typed_config = 4;
  }
}

message FilterChainMatch {
  enum ConnectionSourceType {
    // Any connection source matches.
    ANY = 0;

    // Match a connection originating from the same host.
    SAME_IP_OR_LOOPBACK = 1;

    // Match a connection originating from a different host.
    EXTERNAL = 2;
  }

  reserved 1;

  // Optional destination port to consider when use_original_dst is set on the
  // listener in determining a filter chain match.
  google.protobuf.UInt32Value destination_port = 8;

  // If non-empty, an IP address and prefix length to match addresses when the
  // listener is bound to 0.0.0.0/:: or when use_original_dst is specified.
  repeated core.v3.CidrRange prefix_ranges = 3;

  // Specifies the connection source IP match type. Can be any, local or external network.
  ConnectionSourceType source_type = 12;

  // The criteria is satisfied if the source IP address of the downstream
  // connection is contained in at least one of the specified subnets. If the
  // parameter is not specified or the list is empty, the source IP address is
  // ignored.
  repeated core.v3.CidrRange source_prefix_ranges = 6;

  // The criteria is satisfied if the source port of the downstream connection
  // is contained in at least one of the specified ports. If the parameter is
  // not specified, the source port is ignored.
  repeated uint32 source_ports = 7;

  // If non-empty, a list of server names (e.g. SNI for TLS protocol) to consider when determining
  // a filter chain match. Those values will be compared against the server names of a new
  // connection, when detected by one of the listener filters.
  //
  // The server name will be matched against all wildcard domains, i.e. ``www.example.com``
  // will be first matched against ``www.example.com``, then ``*.example.com``, then ``*.com``.
  //
  // Note that partial wildcards are not supported, and values like ``*w.example.com`` are invalid.
  //
  // .. attention::
  //
  //   See the :ref:`FAQ entry <faq_how_to_setup_sni>` on how to configure SNI for more
  //   information.
  repeated string server_names = 11;

  // If non-empty, a transport protocol to consider when determining a filter chain match.
  // This value will be compared against the transport protocol of a new connection, when
  // it's detected by one of the listener filters.
  //
  // Suggested values include:
  //
  // * ``raw_buffer`` - default, used when no transport protocol is detected,
  // * ``tls`` - set by :ref:`envoy.filters.listener.tls_inspector <config_listener_filters_tls_inspector>`
  //   when TLS protocol is detected.
  string transport_protocol = 9;

  // If non-empty, a list of application protocols (e.g. ALPN for TLS protocol) to consider when
  // determining a filter chain match. Those values will be compared against the application
  // protocols of a new connection, when detected by one of the listener filters.
  //
  // Suggested values include:
  //
  // * ``http/1.1`` - set by :ref:`envoy.filters.listener.tls_inspector
  //   <config_listener_filters_tls_inspector>`,
  // * ``h2`` - set by :ref:`envoy.filters.listener.tls_inspector <config_listener_filters_tls_inspector>`
  //
  // .. attention::
  //
  //   Currently, only :ref:`TLS Inspector <config_listener_filters_tls_inspector>` provides
  //   application protocol detection based on the requested
  //   `ALPN <https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation>`_ values.
  //
  //   However, the use of ALPN is pretty much limited to the HTTP/2 traffic on the Internet,
  //   and matching on values other than ``h2`` is going to lead to a lot of false negatives,
  //   unless all connecting clients are known to use ALPN.
  repeated string application_protocols = 10;
}

// A filter chain wraps a set of match criteria, an option TLS context, a set of filters, and
// various other parameters.
// [#next-free-field: 10]
message FilterChain {
  // The criteria to use when matching a connection to this filter chain.
  FilterChainMatch filter_chain_match = 1;

  // A list of individual network filters that make up the filter chain for
  // connections established with the listener. Order matters as the filters are
  // processed sequentially as connection events happen. Note: If the filter
  // list is empty, the connection will close by default.
  repeated Filter filters = 3; 

  // Optional custom transport socket implementation to use for downstream connections.
  // To setup TLS, set a transport socket with name `tls` and
  // :ref:`DownstreamTlsContext <envoy_api_msg_extensions.transport_sockets.tls.v3.DownstreamTlsContext>` in the `typed_config`.
  // If no transport socket configuration is specified, new connections
  // will be set up with plaintext.
  core.v3.TransportSocket transport_socket = 6;
}

// [#next-free-field: 23]
message Listener {
  // The unique name by which this listener is known. If no name is provided,
  // Envoy will allocate an internal UUID for the listener. If the listener is to be dynamically
  // updated or removed via :ref:`LDS <config_listeners_lds>` a unique name must be provided.
  string name = 1;

  // The address that the listener should listen on. In general, the address must be unique, though
  // that is governed by the bind rules of the OS. E.g., multiple listeners can listen on port 0 on
  // Linux as the actual port will be allocated by the OS.
  core.v3.Address address = 2;

  // A list of filter chains to consider for this listener. The
  // :ref:`FilterChain <envoy_api_msg_config.listener.v3.FilterChain>` with the most specific
  // :ref:`FilterChainMatch <envoy_api_msg_config.listener.v3.FilterChainMatch>` criteria is used on a
  // connection.
  //
  // Example using SNI for filter chain selection can be found in the
  // :ref:`FAQ entry <faq_how_to_setup_sni>`.
  repeated FilterChain filter_chains = 3;

  // If a connection is redirected using *iptables*, the port on which the proxy
  // receives it might be different from the original destination address. When this flag is set to
  // true, the listener hands off redirected connections to the listener associated with the
  // original destination address. If there is no listener associated with the original destination
  // address, the connection is handled by the listener that receives it. Defaults to false.
  google.protobuf.BoolValue use_original_dst = 4; 

  // The default filter chain if none of the filter chain matches. If no default filter chain is supplied,
  // the connection will be closed. The filter chain match is ignored in this field.
  FilterChain default_filter_chain = 25;

  // Used to represent an API listener, which is used in non-proxy clients. The type of API
  // exposed to the non-proxy application depends on the type of API listener.
  // When this field is set, no other field except for :ref:`name<envoy_api_field_config.listener.v3.Listener.name>`
  // should be set.
  //
  // .. note::
  //
  //  Currently only one ApiListener can be installed; and it can only be done via bootstrap config,
  //  not LDS.
  //
  // [#next-major-version: In the v3 API, instead of this messy approach where the socket
  // listener fields are directly in the top-level Listener message and the API listener types
  // are in the ApiListener message, the socket listener messages should be in their own message,
  // and the top-level Listener should essentially be a oneof that selects between the
  // socket listener and the various types of API listener. That way, a given Listener message
  // can structurally only contain the fields of the relevant type.]
  ApiListener api_listener = 19;
}
