syntax = "proto3";

import "error.proto";

package common;

message FlagsInConfig {
  string default_protocol = 1;
  string dev_name = 2;
  bool enable_encryption = 3;
  bool enable_ipv6 = 4;
  uint32 mtu = 5;
  bool latency_first = 6;
  bool enable_exit_node = 7;
  bool no_tun = 8;
  bool use_smoltcp = 9;
  string relay_network_whitelist = 10;
  bool disable_p2p = 11;
  bool relay_all_peer_rpc = 12;
  bool disable_udp_hole_punching = 13;
  // string ipv6_listener = 14; [deprecated = true]; use -l udp://[::]:12345 instead
  bool multi_thread = 15;
  CompressionAlgoPb data_compress_algo = 16;
  bool bind_device = 17;

  // should we convert all tcp streams into kcp streams
  bool enable_kcp_proxy = 18;
  // does this peer allow kcp input
  bool disable_kcp_input = 19;
  // allow relay kcp packets (for public server, this can reduce the throughput)
  bool disable_relay_kcp = 20;
  bool proxy_forward_by_system = 21;

  // enable magic dns or not
  bool accept_dns = 22;
}

message RpcDescriptor {
  // allow same service registered multiple times in different domain
  string domain_name = 1;

  string proto_name = 2;
  string service_name = 3;
  uint32 method_index = 4;
}

message RpcRequest {
  RpcDescriptor descriptor = 1 [ deprecated = true ];

  bytes request = 2;
  int32 timeout_ms = 3;
}

message RpcResponse {
  bytes response = 1;
  error.Error error = 2;

  uint64 runtime_us = 3;
}

enum CompressionAlgoPb {
  Invalid = 0;
  None = 1;
  Zstd = 2;
}

message RpcCompressionInfo {
  // use this to compress the content
  CompressionAlgoPb algo = 1;

  // tell the peer which compression algo is used to compress the next
  // response/request
  CompressionAlgoPb accepted_algo = 2;
}

message RpcPacket {
  uint32 from_peer = 1;
  uint32 to_peer = 2;
  int64 transaction_id = 3;

  RpcDescriptor descriptor = 4;
  bytes body = 5;
  bool is_request = 6;

  uint32 total_pieces = 7;
  uint32 piece_idx = 8;

  int32 trace_id = 9;

  RpcCompressionInfo compression_info = 10;
}

message Void {}

message UUID {
  uint32 part1 = 1;
  uint32 part2 = 2;
  uint32 part3 = 3;
  uint32 part4 = 4;
}

enum NatType {
  // has NAT; but own a single public IP, port is not changed
  Unknown = 0;
  OpenInternet = 1;
  NoPAT = 2;
  FullCone = 3;
  Restricted = 4;
  PortRestricted = 5;
  Symmetric = 6;
  SymUdpFirewall = 7;
  SymmetricEasyInc = 8;
  SymmetricEasyDec = 9;
}

message Ipv4Addr { uint32 addr = 1; }

message Ipv6Addr {
  uint32 part1 = 1;
  uint32 part2 = 2;
  uint32 part3 = 3;
  uint32 part4 = 4;
}

message Ipv4Inet {
  Ipv4Addr address = 1;
  uint32 network_length = 2;
}

message Url { string url = 1; }

message SocketAddr {
  oneof ip {
    Ipv4Addr ipv4 = 1;
    Ipv6Addr ipv6 = 2;
  };
  uint32 port = 3;
}

message TunnelInfo {
  string tunnel_type = 1;
  common.Url local_addr = 2;
  common.Url remote_addr = 3;
}

message StunInfo {
  NatType udp_nat_type = 1;
  NatType tcp_nat_type = 2;
  int64 last_update_time = 3;
  repeated string public_ip = 4;
  uint32 min_port = 5;
  uint32 max_port = 6;
}

message PeerFeatureFlag {
  bool is_public_server = 1;
  bool avoid_relay_data = 2;
  bool kcp_input = 3;
  bool no_relay_kcp  = 4;
}

enum SocketType {
  TCP = 0;
  UDP = 1;
}

message PortForwardConfigPb {
    SocketAddr bind_addr = 1;
    SocketAddr dst_addr = 2;
    SocketType socket_type = 3;
}
