syntax = "proto3";

package envoy.config.core.v3;

import "envoy/config/core/v3/substitution_format_string.proto";

import "udpa/annotations/status.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.config.core.v3";
option java_outer_classname = "ProxyProtocolProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/config/core/v3;corev3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Proxy protocol]

message ProxyProtocolPassThroughTLVs {
  enum PassTLVsMatchType {
    // Pass all TLVs.
    INCLUDE_ALL = 0;

    // Pass specific TLVs defined in tlv_type.
    INCLUDE = 1;
  }

  // The strategy to pass through TLVs. Default is INCLUDE_ALL.
  // If INCLUDE_ALL is set, all TLVs will be passed through no matter the tlv_type field.
  PassTLVsMatchType match_type = 1;

  // The TLV types that are applied based on match_type.
  // TLV type is defined as uint8_t in proxy protocol. See `the spec
  // <https://www.haproxy.org/download/2.1/doc/proxy-protocol.txt>`_ for details.
  repeated uint32 tlv_type = 2 [(validate.rules).repeated = {items {uint32 {lt: 256}}}];
}

// Represents a single Type-Length-Value (TLV) entry.
message TlvEntry {
  // The type of the TLV. Must be a uint8 (0-255) as per the Proxy Protocol v2 specification.
  uint32 type = 1 [(validate.rules).uint32 = {lt: 256}];

  // The static value of the TLV.
  // Only one of ``value`` or ``format_string`` may be set.
  bytes value = 2;

  // Uses the :ref:`format string <config_access_log_format_strings>` to dynamically
  // populate the TLV value from stream information. This allows dynamic values
  // such as metadata, filter state, or other stream properties to be included in
  // the TLV.
  //
  // For example:
  //
  // .. code-block:: yaml
  //
  //   type: 0xF0
  //   format_string:
  //     text_format_source:
  //       inline_string: "%DYNAMIC_METADATA(envoy.filters.network:key)%"
  //
  // The formatted string will be used directly as the TLV value.
  // Only one of ``value`` or ``format_string`` may be set.
  SubstitutionFormatString format_string = 3;
}

message ProxyProtocolConfig {
  enum Version {
    // PROXY protocol version 1. Human readable format.
    V1 = 0;

    // PROXY protocol version 2. Binary format.
    V2 = 1;
  }

  // The PROXY protocol version to use. See https://www.haproxy.org/download/2.1/doc/proxy-protocol.txt for details
  Version version = 1;

  // This config controls which TLVs can be passed to upstream if it is Proxy Protocol
  // V2 header. If there is no setting for this field, no TLVs will be passed through.
  ProxyProtocolPassThroughTLVs pass_through_tlvs = 2;

  // This config allows additional TLVs to be included in the upstream PROXY protocol
  // V2 header. Unlike ``pass_through_tlvs``, which passes TLVs from the downstream request,
  // ``added_tlvs`` provides an extension mechanism for defining new TLVs that are included
  // with the upstream request. These TLVs may not be present in the downstream request and
  // can be defined at either the transport socket level or the host level to provide more
  // granular control over the TLVs that are included in the upstream request.
  //
  // Host-level TLVs are specified in the ``metadata.typed_filter_metadata`` field under the
  // ``envoy.transport_sockets.proxy_protocol`` namespace.
  //
  // .. literalinclude:: /_configs/repo/proxy_protocol.yaml
  //    :language: yaml
  //    :lines: 49-57
  //    :linenos:
  //    :lineno-start: 49
  //    :caption: :download:`proxy_protocol.yaml </_configs/repo/proxy_protocol.yaml>`
  //
  // **Precedence behavior**:
  //
  // - When a TLV is defined at both the host level and the transport socket level, the value
  //   from the host level configuration takes precedence. This allows users to define default TLVs
  //   at the transport socket level and override them at the host level.
  // - Any TLV defined in the ``pass_through_tlvs`` field will be overridden by either the host-level
  //   or transport socket-level TLV.
  //
  // If there are multiple TLVs with the same type, only the TLVs from the highest precedence level
  // will be used.
  repeated TlvEntry added_tlvs = 3;
}

message PerHostConfig {
  // Enables per-host configuration for Proxy Protocol.
  repeated TlvEntry added_tlvs = 1;
}
