Full Code of XTLS/Xray-core for AI

main 35800e953e07 cached
945 files
3.6 MB
990.8k tokens
8339 symbols
1 requests
Download .txt
Showing preview only (3,943K chars total). Download the full file or copy to clipboard to get everything.
Repository: XTLS/Xray-core
Branch: main
Commit: 35800e953e07
Files: 945
Total size: 3.6 MB

Directory structure:
gitextract_x2sy_bia/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── bug_report_zh.yml
│   │   └── config.yml
│   ├── build/
│   │   └── friendly-filenames.json
│   ├── dependabot.yml
│   ├── docker/
│   │   ├── Dockerfile
│   │   └── Dockerfile.usa
│   └── workflows/
│       ├── docker.yml
│       ├── release-win7.yml
│       ├── release.yml
│       ├── scheduled-assets-update.yml
│       └── test.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── SECURITY.md
├── app/
│   ├── app.go
│   ├── commander/
│   │   ├── commander.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── outbound.go
│   │   └── service.go
│   ├── dispatcher/
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── default.go
│   │   ├── dispatcher.go
│   │   ├── fakednssniffer.go
│   │   ├── sniffer.go
│   │   ├── stats.go
│   │   └── stats_test.go
│   ├── dns/
│   │   ├── cache_controller.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── dns.go
│   │   ├── dns_test.go
│   │   ├── dnscommon.go
│   │   ├── dnscommon_test.go
│   │   ├── fakedns/
│   │   │   ├── fake.go
│   │   │   ├── fakedns.go
│   │   │   ├── fakedns.pb.go
│   │   │   ├── fakedns.proto
│   │   │   └── fakedns_test.go
│   │   ├── hosts.go
│   │   ├── hosts_test.go
│   │   ├── nameserver.go
│   │   ├── nameserver_cached.go
│   │   ├── nameserver_doh.go
│   │   ├── nameserver_doh_test.go
│   │   ├── nameserver_fakedns.go
│   │   ├── nameserver_local.go
│   │   ├── nameserver_local_test.go
│   │   ├── nameserver_quic.go
│   │   ├── nameserver_quic_test.go
│   │   ├── nameserver_tcp.go
│   │   ├── nameserver_tcp_test.go
│   │   └── nameserver_udp.go
│   ├── log/
│   │   ├── command/
│   │   │   ├── command.go
│   │   │   ├── command_test.go
│   │   │   ├── config.pb.go
│   │   │   ├── config.proto
│   │   │   └── config_grpc.pb.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── log.go
│   │   ├── log_creator.go
│   │   └── log_test.go
│   ├── metrics/
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── metrics.go
│   │   └── outbound.go
│   ├── observatory/
│   │   ├── burst/
│   │   │   ├── burst.go
│   │   │   ├── burstobserver.go
│   │   │   ├── config.pb.go
│   │   │   ├── config.proto
│   │   │   ├── healthping.go
│   │   │   ├── healthping_result.go
│   │   │   ├── healthping_result_test.go
│   │   │   └── ping.go
│   │   ├── command/
│   │   │   ├── command.go
│   │   │   ├── command.pb.go
│   │   │   ├── command.proto
│   │   │   └── command_grpc.pb.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── explainErrors.go
│   │   ├── observatory.go
│   │   └── observer.go
│   ├── policy/
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── manager.go
│   │   ├── manager_test.go
│   │   └── policy.go
│   ├── proxyman/
│   │   ├── command/
│   │   │   ├── command.go
│   │   │   ├── command.pb.go
│   │   │   ├── command.proto
│   │   │   ├── command_grpc.pb.go
│   │   │   └── doc.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── inbound/
│   │   │   ├── always.go
│   │   │   ├── inbound.go
│   │   │   └── worker.go
│   │   └── outbound/
│   │       ├── handler.go
│   │       ├── handler_test.go
│   │       ├── outbound.go
│   │       └── uot.go
│   ├── reverse/
│   │   ├── bridge.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── portal.go
│   │   ├── portal_test.go
│   │   └── reverse.go
│   ├── router/
│   │   ├── balancing.go
│   │   ├── balancing_override.go
│   │   ├── command/
│   │   │   ├── command.go
│   │   │   ├── command.pb.go
│   │   │   ├── command.proto
│   │   │   ├── command_grpc.pb.go
│   │   │   ├── command_test.go
│   │   │   └── config.go
│   │   ├── condition.go
│   │   ├── condition_geoip.go
│   │   ├── condition_geoip_test.go
│   │   ├── condition_serialize_test.go
│   │   ├── condition_test.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── geosite_compact.go
│   │   ├── router.go
│   │   ├── router_test.go
│   │   ├── strategy_leastload.go
│   │   ├── strategy_leastload_test.go
│   │   ├── strategy_leastping.go
│   │   ├── strategy_random.go
│   │   ├── webhook.go
│   │   ├── weight.go
│   │   └── weight_test.go
│   ├── stats/
│   │   ├── channel.go
│   │   ├── channel_test.go
│   │   ├── command/
│   │   │   ├── command.go
│   │   │   ├── command.pb.go
│   │   │   ├── command.proto
│   │   │   ├── command_grpc.pb.go
│   │   │   └── command_test.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── counter.go
│   │   ├── counter_test.go
│   │   ├── online_map.go
│   │   ├── stats.go
│   │   └── stats_test.go
│   └── version/
│       ├── config.pb.go
│       ├── config.proto
│       └── version.go
├── common/
│   ├── antireplay/
│   │   ├── antireplay_test.go
│   │   └── mapfilter.go
│   ├── bitmask/
│   │   ├── byte.go
│   │   └── byte_test.go
│   ├── buf/
│   │   ├── buf.go
│   │   ├── buffer.go
│   │   ├── buffer_test.go
│   │   ├── copy.go
│   │   ├── copy_test.go
│   │   ├── io.go
│   │   ├── io_test.go
│   │   ├── multi_buffer.go
│   │   ├── multi_buffer_test.go
│   │   ├── override.go
│   │   ├── reader.go
│   │   ├── reader_test.go
│   │   ├── readv_posix.go
│   │   ├── readv_reader.go
│   │   ├── readv_reader_wasm.go
│   │   ├── readv_test.go
│   │   ├── readv_unix.go
│   │   ├── readv_windows.go
│   │   ├── writer.go
│   │   └── writer_test.go
│   ├── bytespool/
│   │   └── pool.go
│   ├── cache/
│   │   ├── lru.go
│   │   └── lru_test.go
│   ├── cmdarg/
│   │   └── cmdarg.go
│   ├── common.go
│   ├── common_test.go
│   ├── crypto/
│   │   ├── aes.go
│   │   ├── auth.go
│   │   ├── auth_test.go
│   │   ├── benchmark_test.go
│   │   ├── chacha20.go
│   │   ├── chacha20_test.go
│   │   ├── chunk.go
│   │   ├── chunk_test.go
│   │   ├── crypto.go
│   │   ├── internal/
│   │   │   ├── chacha.go
│   │   │   ├── chacha_core.generated.go
│   │   │   └── chacha_core_gen.go
│   │   └── io.go
│   ├── ctx/
│   │   └── context.go
│   ├── dice/
│   │   ├── dice.go
│   │   └── dice_test.go
│   ├── drain/
│   │   ├── drain.go
│   │   └── drainer.go
│   ├── errors/
│   │   ├── errors.go
│   │   ├── errors_test.go
│   │   ├── feature_errors.go
│   │   └── multi_error.go
│   ├── interfaces.go
│   ├── log/
│   │   ├── access.go
│   │   ├── dns.go
│   │   ├── log.go
│   │   ├── log.pb.go
│   │   ├── log.proto
│   │   ├── log_test.go
│   │   ├── logger.go
│   │   └── logger_test.go
│   ├── mux/
│   │   ├── client.go
│   │   ├── client_test.go
│   │   ├── frame.go
│   │   ├── frame_test.go
│   │   ├── mux.go
│   │   ├── mux_test.go
│   │   ├── reader.go
│   │   ├── server.go
│   │   ├── server_test.go
│   │   ├── session.go
│   │   ├── session_test.go
│   │   └── writer.go
│   ├── net/
│   │   ├── address.go
│   │   ├── address.pb.go
│   │   ├── address.proto
│   │   ├── address_test.go
│   │   ├── cnc/
│   │   │   └── connection.go
│   │   ├── destination.go
│   │   ├── destination.pb.go
│   │   ├── destination.proto
│   │   ├── destination_test.go
│   │   ├── find_process_linux.go
│   │   ├── find_process_others.go
│   │   ├── find_process_windows.go
│   │   ├── net.go
│   │   ├── network.go
│   │   ├── network.pb.go
│   │   ├── network.proto
│   │   ├── port.go
│   │   ├── port.pb.go
│   │   ├── port.proto
│   │   ├── port_test.go
│   │   └── system.go
│   ├── ocsp/
│   │   └── ocsp.go
│   ├── peer/
│   │   ├── latency.go
│   │   └── peer.go
│   ├── platform/
│   │   ├── filesystem/
│   │   │   └── file.go
│   │   ├── others.go
│   │   ├── platform.go
│   │   ├── platform_test.go
│   │   └── windows.go
│   ├── protocol/
│   │   ├── account.go
│   │   ├── address.go
│   │   ├── address_test.go
│   │   ├── bittorrent/
│   │   │   └── bittorrent.go
│   │   ├── context.go
│   │   ├── dns/
│   │   │   └── io.go
│   │   ├── headers.go
│   │   ├── headers.pb.go
│   │   ├── headers.proto
│   │   ├── http/
│   │   │   ├── headers.go
│   │   │   ├── headers_test.go
│   │   │   ├── sniff.go
│   │   │   └── sniff_test.go
│   │   ├── id.go
│   │   ├── id_test.go
│   │   ├── payload.go
│   │   ├── protocol.go
│   │   ├── quic/
│   │   │   ├── qtls_go118.go
│   │   │   ├── sniff.go
│   │   │   └── sniff_test.go
│   │   ├── server_spec.go
│   │   ├── server_spec.pb.go
│   │   ├── server_spec.proto
│   │   ├── time.go
│   │   ├── time_test.go
│   │   ├── tls/
│   │   │   ├── cert/
│   │   │   │   ├── cert.go
│   │   │   │   ├── cert_test.go
│   │   │   │   └── privateKey.go
│   │   │   ├── sniff.go
│   │   │   └── sniff_test.go
│   │   ├── udp/
│   │   │   ├── packet.go
│   │   │   └── udp.go
│   │   ├── user.go
│   │   ├── user.pb.go
│   │   └── user.proto
│   ├── reflect/
│   │   ├── marshal.go
│   │   └── marshal_test.go
│   ├── retry/
│   │   ├── retry.go
│   │   └── retry_test.go
│   ├── serial/
│   │   ├── serial.go
│   │   ├── serial_test.go
│   │   ├── string.go
│   │   ├── string_test.go
│   │   ├── typed_message.go
│   │   ├── typed_message.pb.go
│   │   ├── typed_message.proto
│   │   └── typed_message_test.go
│   ├── session/
│   │   ├── context.go
│   │   └── session.go
│   ├── signal/
│   │   ├── done/
│   │   │   └── done.go
│   │   ├── notifier.go
│   │   ├── notifier_test.go
│   │   ├── pubsub/
│   │   │   ├── pubsub.go
│   │   │   └── pubsub_test.go
│   │   ├── semaphore/
│   │   │   └── semaphore.go
│   │   ├── timer.go
│   │   └── timer_test.go
│   ├── singbridge/
│   │   ├── destination.go
│   │   ├── dialer.go
│   │   ├── error.go
│   │   ├── handler.go
│   │   ├── logger.go
│   │   ├── packet.go
│   │   ├── pipe.go
│   │   └── reader.go
│   ├── strmatcher/
│   │   ├── ac_automaton_matcher.go
│   │   ├── benchmark_test.go
│   │   ├── domain_matcher.go
│   │   ├── domain_matcher_test.go
│   │   ├── full_matcher.go
│   │   ├── full_matcher_test.go
│   │   ├── matchers.go
│   │   ├── matchers_test.go
│   │   ├── mph_matcher.go
│   │   ├── mph_matcher_compact.go
│   │   ├── strmatcher.go
│   │   └── strmatcher_test.go
│   ├── task/
│   │   ├── common.go
│   │   ├── periodic.go
│   │   ├── periodic_test.go
│   │   ├── task.go
│   │   └── task_test.go
│   ├── type.go
│   ├── type_test.go
│   ├── units/
│   │   ├── bytesize.go
│   │   └── bytesize_test.go
│   ├── utils/
│   │   ├── access_field.go
│   │   ├── browser.go
│   │   ├── padding.go
│   │   └── typed_sync_map.go
│   ├── uuid/
│   │   ├── uuid.go
│   │   └── uuid_test.go
│   └── xudp/
│       ├── xudp.go
│       └── xudp_test.go
├── core/
│   ├── annotations.go
│   ├── config.go
│   ├── config.pb.go
│   ├── config.proto
│   ├── context.go
│   ├── context_test.go
│   ├── core.go
│   ├── format.go
│   ├── functions.go
│   ├── functions_test.go
│   ├── mocks.go
│   ├── proto.go
│   ├── xray.go
│   └── xray_test.go
├── features/
│   ├── dns/
│   │   ├── client.go
│   │   ├── fakedns.go
│   │   └── localdns/
│   │       └── client.go
│   ├── extension/
│   │   ├── contextreceiver.go
│   │   └── observatory.go
│   ├── feature.go
│   ├── inbound/
│   │   └── inbound.go
│   ├── outbound/
│   │   └── outbound.go
│   ├── policy/
│   │   ├── default.go
│   │   └── policy.go
│   ├── routing/
│   │   ├── balancer.go
│   │   ├── context.go
│   │   ├── dispatcher.go
│   │   ├── dns/
│   │   │   └── context.go
│   │   ├── router.go
│   │   └── session/
│   │       └── context.go
│   └── stats/
│       └── stats.go
├── go.mod
├── go.sum
├── infra/
│   ├── conf/
│   │   ├── api.go
│   │   ├── blackhole.go
│   │   ├── blackhole_test.go
│   │   ├── buildable.go
│   │   ├── cfgcommon/
│   │   │   └── duration/
│   │   │       ├── duration.go
│   │   │       └── duration_test.go
│   │   ├── common.go
│   │   ├── common_test.go
│   │   ├── conf.go
│   │   ├── dns.go
│   │   ├── dns_proxy.go
│   │   ├── dns_proxy_test.go
│   │   ├── dns_test.go
│   │   ├── dokodemo.go
│   │   ├── dokodemo_test.go
│   │   ├── fakedns.go
│   │   ├── freedom.go
│   │   ├── freedom_test.go
│   │   ├── general_test.go
│   │   ├── grpc.go
│   │   ├── http.go
│   │   ├── http_test.go
│   │   ├── hysteria.go
│   │   ├── init.go
│   │   ├── json/
│   │   │   ├── reader.go
│   │   │   └── reader_test.go
│   │   ├── lint.go
│   │   ├── loader.go
│   │   ├── log.go
│   │   ├── loopback.go
│   │   ├── metrics.go
│   │   ├── observatory.go
│   │   ├── policy.go
│   │   ├── policy_test.go
│   │   ├── reverse.go
│   │   ├── reverse_test.go
│   │   ├── router.go
│   │   ├── router_strategy.go
│   │   ├── router_test.go
│   │   ├── serial/
│   │   │   ├── builder.go
│   │   │   ├── loader.go
│   │   │   ├── loader_test.go
│   │   │   └── serial.go
│   │   ├── shadowsocks.go
│   │   ├── shadowsocks_test.go
│   │   ├── socks.go
│   │   ├── socks_test.go
│   │   ├── transport_authenticators.go
│   │   ├── transport_internet.go
│   │   ├── transport_test.go
│   │   ├── trojan.go
│   │   ├── tun.go
│   │   ├── version.go
│   │   ├── vless.go
│   │   ├── vless_test.go
│   │   ├── vmess.go
│   │   ├── vmess_test.go
│   │   ├── wireguard.go
│   │   ├── wireguard_test.go
│   │   ├── xray.go
│   │   └── xray_test.go
│   └── vformat/
│       └── main.go
├── main/
│   ├── commands/
│   │   ├── all/
│   │   │   ├── api/
│   │   │   │   ├── api.go
│   │   │   │   ├── balancer_info.go
│   │   │   │   ├── balancer_override.go
│   │   │   │   ├── inbound_user.go
│   │   │   │   ├── inbound_user_add.go
│   │   │   │   ├── inbound_user_count.go
│   │   │   │   ├── inbound_user_remove.go
│   │   │   │   ├── inbounds_add.go
│   │   │   │   ├── inbounds_list.go
│   │   │   │   ├── inbounds_remove.go
│   │   │   │   ├── logger_restart.go
│   │   │   │   ├── outbounds_add.go
│   │   │   │   ├── outbounds_list.go
│   │   │   │   ├── outbounds_remove.go
│   │   │   │   ├── rules_add.go
│   │   │   │   ├── rules_list.go
│   │   │   │   ├── rules_remove.go
│   │   │   │   ├── shared.go
│   │   │   │   ├── source_ip_block.go
│   │   │   │   ├── stats_get.go
│   │   │   │   ├── stats_get_all_online_users.go
│   │   │   │   ├── stats_online.go
│   │   │   │   ├── stats_online_ip_list.go
│   │   │   │   ├── stats_query.go
│   │   │   │   └── stats_sys.go
│   │   │   ├── buildmphcache.go
│   │   │   ├── commands.go
│   │   │   ├── convert/
│   │   │   │   ├── convert.go
│   │   │   │   ├── json.go
│   │   │   │   └── protobuf.go
│   │   │   ├── curve25519.go
│   │   │   ├── mldsa65.go
│   │   │   ├── mlkem768.go
│   │   │   ├── tls/
│   │   │   │   ├── cert.go
│   │   │   │   ├── ech.go
│   │   │   │   ├── hash.go
│   │   │   │   ├── ping.go
│   │   │   │   └── tls.go
│   │   │   ├── uuid.go
│   │   │   ├── vlessenc.go
│   │   │   ├── wg.go
│   │   │   └── x25519.go
│   │   └── base/
│   │       ├── command.go
│   │       ├── env.go
│   │       ├── execute.go
│   │       ├── help.go
│   │       └── root.go
│   ├── confloader/
│   │   ├── confloader.go
│   │   └── external/
│   │       └── external.go
│   ├── distro/
│   │   └── all/
│   │       └── all.go
│   ├── json/
│   │   └── json.go
│   ├── main.go
│   ├── main_test.go
│   ├── run.go
│   ├── toml/
│   │   └── toml.go
│   ├── version.go
│   └── yaml/
│       └── yaml.go
├── proxy/
│   ├── blackhole/
│   │   ├── blackhole.go
│   │   ├── blackhole_test.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   └── config_test.go
│   ├── dns/
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── dns.go
│   │   └── dns_test.go
│   ├── dokodemo/
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── dokodemo.go
│   │   ├── fakeudp_linux.go
│   │   └── fakeudp_other.go
│   ├── freedom/
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   └── freedom.go
│   ├── http/
│   │   ├── client.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── http.go
│   │   └── server.go
│   ├── hysteria/
│   │   ├── account/
│   │   │   ├── config.go
│   │   │   ├── config.pb.go
│   │   │   └── config.proto
│   │   ├── client.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── ctx/
│   │   │   └── ctx.go
│   │   ├── frag.go
│   │   ├── protocol.go
│   │   └── server.go
│   ├── loopback/
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   └── loopback.go
│   ├── proxy.go
│   ├── shadowsocks/
│   │   ├── client.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── config_test.go
│   │   ├── protocol.go
│   │   ├── protocol_test.go
│   │   ├── server.go
│   │   ├── shadowsocks.go
│   │   └── validator.go
│   ├── shadowsocks_2022/
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── inbound.go
│   │   ├── inbound_multi.go
│   │   ├── inbound_relay.go
│   │   ├── outbound.go
│   │   └── shadowsocks_2022.go
│   ├── socks/
│   │   ├── client.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── protocol.go
│   │   ├── protocol_test.go
│   │   ├── server.go
│   │   ├── socks.go
│   │   └── udpfilter.go
│   ├── trojan/
│   │   ├── client.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── protocol.go
│   │   ├── protocol_test.go
│   │   ├── server.go
│   │   ├── trojan.go
│   │   └── validator.go
│   ├── tun/
│   │   ├── README.md
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── handler.go
│   │   ├── stack.go
│   │   ├── stack_gvisor.go
│   │   ├── stack_gvisor_endpoint.go
│   │   ├── tun.go
│   │   ├── tun_android.go
│   │   ├── tun_darwin.go
│   │   ├── tun_default.go
│   │   ├── tun_linux.go
│   │   ├── tun_windows.go
│   │   └── udp_fullcone.go
│   ├── vless/
│   │   ├── account.go
│   │   ├── account.pb.go
│   │   ├── account.proto
│   │   ├── encoding/
│   │   │   ├── addons.go
│   │   │   ├── addons.pb.go
│   │   │   ├── addons.proto
│   │   │   ├── encoding.go
│   │   │   └── encoding_test.go
│   │   ├── encryption/
│   │   │   ├── client.go
│   │   │   ├── common.go
│   │   │   ├── server.go
│   │   │   └── xor.go
│   │   ├── inbound/
│   │   │   ├── config.go
│   │   │   ├── config.pb.go
│   │   │   ├── config.proto
│   │   │   └── inbound.go
│   │   ├── outbound/
│   │   │   ├── config.go
│   │   │   ├── config.pb.go
│   │   │   ├── config.proto
│   │   │   └── outbound.go
│   │   ├── validator.go
│   │   └── vless.go
│   ├── vmess/
│   │   ├── account.go
│   │   ├── account.pb.go
│   │   ├── account.proto
│   │   ├── aead/
│   │   │   ├── authid.go
│   │   │   ├── authid_test.go
│   │   │   ├── consts.go
│   │   │   ├── encrypt.go
│   │   │   ├── encrypt_test.go
│   │   │   └── kdf.go
│   │   ├── encoding/
│   │   │   ├── auth.go
│   │   │   ├── client.go
│   │   │   ├── commands.go
│   │   │   ├── encoding.go
│   │   │   ├── encoding_test.go
│   │   │   └── server.go
│   │   ├── inbound/
│   │   │   ├── config.go
│   │   │   ├── config.pb.go
│   │   │   ├── config.proto
│   │   │   └── inbound.go
│   │   ├── outbound/
│   │   │   ├── command.go
│   │   │   ├── config.go
│   │   │   ├── config.pb.go
│   │   │   ├── config.proto
│   │   │   └── outbound.go
│   │   ├── validator.go
│   │   ├── validator_test.go
│   │   └── vmess.go
│   └── wireguard/
│       ├── bind.go
│       ├── client.go
│       ├── config.go
│       ├── config.pb.go
│       ├── config.proto
│       ├── gvisortun/
│       │   └── tun.go
│       ├── server.go
│       ├── server_test.go
│       ├── tun.go
│       ├── tun_default.go
│       ├── tun_linux.go
│       └── wireguard.go
├── testing/
│   ├── coverage/
│   │   ├── coverall
│   │   └── coverall2
│   ├── mocks/
│   │   ├── dns.go
│   │   ├── io.go
│   │   ├── log.go
│   │   ├── mux.go
│   │   ├── outbound.go
│   │   └── proxy.go
│   ├── scenarios/
│   │   ├── command_test.go
│   │   ├── common.go
│   │   ├── common_coverage.go
│   │   ├── common_regular.go
│   │   ├── dns_test.go
│   │   ├── dokodemo_test.go
│   │   ├── feature_test.go
│   │   ├── http_test.go
│   │   ├── main_test.go
│   │   ├── metrics_test.go
│   │   ├── policy_test.go
│   │   ├── reverse_test.go
│   │   ├── shadowsocks_2022_test.go
│   │   ├── shadowsocks_test.go
│   │   ├── socks_test.go
│   │   ├── tls_test.go
│   │   ├── transport_test.go
│   │   ├── vless_test.go
│   │   ├── vmess_test.go
│   │   └── wireguard_test.go
│   └── servers/
│       ├── http/
│       │   └── http.go
│       ├── tcp/
│       │   ├── port.go
│       │   └── tcp.go
│       └── udp/
│           ├── port.go
│           └── udp.go
└── transport/
    ├── internet/
    │   ├── browser_dialer/
    │   │   ├── dialer.go
    │   │   └── dialer.html
    │   ├── config.go
    │   ├── config.pb.go
    │   ├── config.proto
    │   ├── dialer.go
    │   ├── dialer_test.go
    │   ├── filelocker.go
    │   ├── filelocker_other.go
    │   ├── filelocker_windows.go
    │   ├── finalmask/
    │   │   ├── finalmask.go
    │   │   ├── fragment/
    │   │   │   ├── config.go
    │   │   │   ├── config.pb.go
    │   │   │   ├── config.proto
    │   │   │   └── conn.go
    │   │   ├── header/
    │   │   │   ├── custom/
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   ├── tcp.go
    │   │   │   │   └── udp.go
    │   │   │   ├── dns/
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   └── conn.go
    │   │   │   ├── dtls/
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   └── conn.go
    │   │   │   ├── srtp/
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   └── conn.go
    │   │   │   ├── utp/
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   └── conn.go
    │   │   │   ├── wechat/
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   └── conn.go
    │   │   │   └── wireguard/
    │   │   │       ├── config.go
    │   │   │       ├── config.pb.go
    │   │   │       ├── config.proto
    │   │   │       └── conn.go
    │   │   ├── mkcp/
    │   │   │   ├── aes128gcm/
    │   │   │   │   ├── aes128gcm_test.go
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   └── conn.go
    │   │   │   └── original/
    │   │   │       ├── config.go
    │   │   │       ├── config.pb.go
    │   │   │       ├── config.proto
    │   │   │       ├── conn.go
    │   │   │       ├── simple_test.go
    │   │   │       ├── xor.go
    │   │   │       ├── xor_amd64.go
    │   │   │       └── xor_amd64.s
    │   │   ├── noise/
    │   │   │   ├── config.go
    │   │   │   ├── config.pb.go
    │   │   │   ├── config.proto
    │   │   │   └── conn.go
    │   │   ├── salamander/
    │   │   │   ├── config.go
    │   │   │   ├── config.pb.go
    │   │   │   ├── config.proto
    │   │   │   ├── conn.go
    │   │   │   ├── salamander.go
    │   │   │   └── salamander_test.go
    │   │   ├── sudoku/
    │   │   │   ├── codec.go
    │   │   │   ├── config.go
    │   │   │   ├── config.pb.go
    │   │   │   ├── config.proto
    │   │   │   ├── conn_tcp.go
    │   │   │   ├── conn_tcp_packed.go
    │   │   │   ├── conn_udp.go
    │   │   │   ├── sudoku_test.go
    │   │   │   └── table.go
    │   │   ├── tcp_test.go
    │   │   ├── udp_test.go
    │   │   ├── xdns/
    │   │   │   ├── client.go
    │   │   │   ├── config.go
    │   │   │   ├── config.pb.go
    │   │   │   ├── config.proto
    │   │   │   ├── dns.go
    │   │   │   ├── dns_test.go
    │   │   │   └── server.go
    │   │   └── xicmp/
    │   │       ├── client.go
    │   │       ├── config.go
    │   │       ├── config.pb.go
    │   │       ├── config.proto
    │   │       ├── server.go
    │   │       └── xicmp_test.go
    │   ├── grpc/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── config_test.go
    │   │   ├── dial.go
    │   │   ├── encoding/
    │   │   │   ├── customSeviceName.go
    │   │   │   ├── encoding.go
    │   │   │   ├── hunkconn.go
    │   │   │   ├── multiconn.go
    │   │   │   ├── stream.pb.go
    │   │   │   ├── stream.proto
    │   │   │   └── stream_grpc.pb.go
    │   │   ├── grpc.go
    │   │   └── hub.go
    │   ├── happy_eyeballs.go
    │   ├── header.go
    │   ├── headers/
    │   │   ├── http/
    │   │   │   ├── config.go
    │   │   │   ├── config.pb.go
    │   │   │   ├── config.proto
    │   │   │   ├── http.go
    │   │   │   ├── http_test.go
    │   │   │   ├── linkedreadRequest.go
    │   │   │   └── resp.go
    │   │   └── noop/
    │   │       ├── config.pb.go
    │   │       ├── config.proto
    │   │       └── noop.go
    │   ├── httpupgrade/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── connection.go
    │   │   ├── dialer.go
    │   │   ├── httpupgrade.go
    │   │   ├── httpupgrade_test.go
    │   │   └── hub.go
    │   ├── hysteria/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── congestion/
    │   │   │   ├── bbr/
    │   │   │   │   ├── bandwidth.go
    │   │   │   │   ├── bandwidth_sampler.go
    │   │   │   │   ├── bbr_sender.go
    │   │   │   │   ├── clock.go
    │   │   │   │   ├── packet_number_indexed_queue.go
    │   │   │   │   ├── ringbuffer.go
    │   │   │   │   └── windowed_filter.go
    │   │   │   ├── brutal/
    │   │   │   │   └── brutal.go
    │   │   │   ├── common/
    │   │   │   │   └── pacer.go
    │   │   │   └── utils.go
    │   │   ├── conn.go
    │   │   ├── dialer.go
    │   │   ├── hub.go
    │   │   ├── padding/
    │   │   │   └── padding.go
    │   │   └── udphop/
    │   │       ├── addr.go
    │   │       └── conn.go
    │   ├── internet.go
    │   ├── kcp/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── connection.go
    │   │   ├── connection_test.go
    │   │   ├── dialer.go
    │   │   ├── io.go
    │   │   ├── io_test.go
    │   │   ├── kcp.go
    │   │   ├── kcp_test.go
    │   │   ├── listener.go
    │   │   ├── output.go
    │   │   ├── receiving.go
    │   │   ├── segment.go
    │   │   ├── segment_test.go
    │   │   └── sending.go
    │   ├── memory_settings.go
    │   ├── reality/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   └── reality.go
    │   ├── sockopt.go
    │   ├── sockopt_darwin.go
    │   ├── sockopt_freebsd.go
    │   ├── sockopt_linux.go
    │   ├── sockopt_linux_test.go
    │   ├── sockopt_other.go
    │   ├── sockopt_test.go
    │   ├── sockopt_windows.go
    │   ├── splithttp/
    │   │   ├── browser_client.go
    │   │   ├── client.go
    │   │   ├── common.go
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── config_test.go
    │   │   ├── connection.go
    │   │   ├── dialer.go
    │   │   ├── h1_conn.go
    │   │   ├── hub.go
    │   │   ├── mux.go
    │   │   ├── mux_test.go
    │   │   ├── splithttp.go
    │   │   ├── splithttp_test.go
    │   │   ├── upload_queue.go
    │   │   ├── upload_queue_test.go
    │   │   └── xpadding.go
    │   ├── stat/
    │   │   └── connection.go
    │   ├── system_dialer.go
    │   ├── system_listener.go
    │   ├── system_listener_test.go
    │   ├── tagged/
    │   │   ├── tagged.go
    │   │   └── taggedimpl/
    │   │       ├── impl.go
    │   │       └── taggedimpl.go
    │   ├── tcp/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── dialer.go
    │   │   ├── hub.go
    │   │   ├── sockopt_darwin.go
    │   │   ├── sockopt_freebsd.go
    │   │   ├── sockopt_linux.go
    │   │   ├── sockopt_linux_test.go
    │   │   ├── sockopt_other.go
    │   │   └── tcp.go
    │   ├── tcp_hub.go
    │   ├── tls/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── config_other.go
    │   │   ├── config_test.go
    │   │   ├── config_windows.go
    │   │   ├── ech.go
    │   │   ├── ech_test.go
    │   │   ├── grpc.go
    │   │   ├── pin.go
    │   │   ├── pin_test.go
    │   │   ├── tls.go
    │   │   └── unsafe.go
    │   ├── udp/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── dialer.go
    │   │   ├── dispatcher.go
    │   │   ├── dispatcher_test.go
    │   │   ├── hub.go
    │   │   ├── hub_darwin.go
    │   │   ├── hub_freebsd.go
    │   │   ├── hub_linux.go
    │   │   ├── hub_other.go
    │   │   └── udp.go
    │   └── websocket/
    │       ├── config.go
    │       ├── config.pb.go
    │       ├── config.proto
    │       ├── connection.go
    │       ├── dialer.go
    │       ├── hub.go
    │       ├── ws.go
    │       └── ws_test.go
    ├── link.go
    └── pipe/
        ├── impl.go
        ├── pipe.go
        ├── pipe_test.go
        ├── reader.go
        └── writer.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug report
description: "Submit Xray-core bug"
body:
  - type: checkboxes
    attributes:
      label: Integrity requirements
      description: |-
        Please check all of the following options to prove that you have read and understood the requirements, otherwise this issue will be closed.
      options:
        - label: I have read all the comments in the issue template and ensured that this issue meet the requirements.
          required: true
        - label: I confirm that I have read the documentation, understand the meaning of all the configuration items I wrote, and did not pile up seemingly useful options or default values.
          required: true
        - label: I provided the complete config and logs, rather than just providing the truncated parts based on my own judgment.
          required: true
        - label: I searched issues and did not find any similar issues.
          required: true
        - label: The problem can be successfully reproduced in the latest Release
          required: true
  - type: textarea
    attributes:
      label: Description
      description: |-
        Please provide a detailed description of the error. And the information you think valuable.
        If the problem occurs after the update, please provide the **specific** version
    validations:
      required: true
  - type: textarea
    attributes:
      label: Reproduction Method
      description: |-
        Based on the configuration you provided below, provide the method to reproduce the bug.
    validations:
      required: true
  - type: markdown
    attributes:
      value: |-
        ## Configuration and Log Section
        
        ### For config
        Please provide the configuration files that can reproduce the problem, including the server and client.
        Don't just paste a big exported config file here. Eliminate useless inbound/outbound, rules, options, this can help determine the problem, if you really want to get help.
        After removing parts that do not affect reproduction, provide the actual running **complete** file.
        meaning of complete: This config can be directly used to start the core, **not a truncated part of the config**. For fields like keys, use newly generated valid parameters that have not been actually used to fill in.

        ### For logs
        Please set the log level to debug and dnsLog to true first.
        Restart Xray-core, then operate according to the reproduction method, try to reduce the irrelevant part in the log.
        Remember to delete parts with personal information (such as UUID and IP).
        Provide the log of Xray-core, not the log output by the panel or other things.

        ### Finally
        The specific content to be filled in each of the following text boxes needs to be placed between ```<details><pre><code>``` and ```</code></pre></details>```, like this
        ```
        <details><pre><code>
        (config)
        </code></pre></details>
        ```
  - type: textarea
    attributes:
      label: Client config
    validations:
      required: true
  - type: textarea
    attributes:
      label: Server config
    validations:
      required: true
  - type: textarea
    attributes:
      label: Client log
    validations:
      required: true
  - type: textarea
    attributes:
      label: Server log
    validations:
      required: true

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report_zh.yml
================================================
name: bug反馈
description: "提交 Xray-core bug"
body:
  - type: checkboxes
    attributes:
      label: 完整性要求
      description: |-
        请勾选以下所有选项以证明您已经阅读并理解了以下要求,否则该 issue 将被关闭。
      options:
        - label: 我读完了 issue 模板中的所有注释,确保填写符合要求。
          required: true
        - label: 我保证阅读了文档,了解所有我编写的配置文件项的含义,而不是大量堆砌看似有用的选项或默认值。
          required: true
        - label: 我提供了完整的配置文件和日志,而不是出于自己的判断只给出截取的部分。
          required: true
        - label: 我搜索了 issues, 没有发现已提出的类似问题。
          required: true
        - label: 问题在 Release 最新的版本上可以成功复现
          required: true
  - type: textarea
    attributes:
      label: 描述
      description: |-
        请提供错误的详细描述。以及你认为有价值的信息。
        如果问题在更新后出现,请提供**具体**出现问题的版本号。
    validations:
      required: true
  - type: textarea
    attributes:
      label: 重现方式
      description: |-
        基于你下面提供的配置,提供重现BUG方法。
    validations:
      required: true
  - type: markdown
    attributes:
      value: |-
        ## 配置与日志部分
        
        ### 对于配置文件
        请提供可以重现问题的配置文件,包括服务端和客户端。
        不要直接在这里黏贴一大段导出的 config 文件。去掉无用的出入站、规则、选项,这可以帮助确定问题,如果你真的想得到帮助。
        在去掉不影响复现的部分后,提供实际运行的**完整**文件。
        完整的含义:可以直接使用这个配置启动核心,**不是截取的部分配置**。对于密钥等参数使用重新生成未实际使用的有效参数填充。
        
        ### 对于日志
        请先将日志等级设置为 debug, dnsLog 设置为true.
        重启 Xray-core ,再按复现方式操作,尽量减少日志中的无关部分。
        记得删除有关个人信息(如UUID与IP)的部分。
        提供 Xray-core 的日志,而不是面板或者别的东西输出的日志。

        ### 最后
        把下面的每格具体内容需要放在 ```<details><pre><code>``` 和 ```</code></pre></details>``` 中间,如
        ```
        <details><pre><code>
        (config)
        </code></pre></details>
        ```
  - type: textarea
    attributes:
      label: 客户端配置
    validations:
      required: true
  - type: textarea
    attributes:
      label: 服务端配置
    validations:
      required: true
  - type: textarea
    attributes:
      label: 客户端日志
    validations:
      required: true
  - type: textarea
    attributes:
      label: 服务端日志
    validations:
      required: true


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
contact_links:
  - name: Community Support and Questions
    url: https://github.com/XTLS/Xray-core/discussions
    about: Please ask and answer questions there. The issue tracker is for issues with core.


================================================
FILE: .github/build/friendly-filenames.json
================================================
{
  "android-arm64": { "friendlyName": "android-arm64-v8a" },
  "darwin-amd64": { "friendlyName": "macos-64" },
  "darwin-arm64": { "friendlyName": "macos-arm64-v8a" },
  "freebsd-386": { "friendlyName": "freebsd-32" },
  "freebsd-amd64": { "friendlyName": "freebsd-64" },
  "freebsd-arm64": { "friendlyName": "freebsd-arm64-v8a" },
  "freebsd-arm7": { "friendlyName": "freebsd-arm32-v7a" },
  "linux-386": { "friendlyName": "linux-32" },
  "linux-amd64": { "friendlyName": "linux-64" },
  "linux-arm5": { "friendlyName": "linux-arm32-v5" },
  "linux-arm64": { "friendlyName": "linux-arm64-v8a" },
  "linux-arm6": { "friendlyName": "linux-arm32-v6" },
  "linux-arm7": { "friendlyName": "linux-arm32-v7a" },
  "linux-mips64le": { "friendlyName": "linux-mips64le" },
  "linux-mips64": { "friendlyName": "linux-mips64" },
  "linux-mipslesoftfloat": { "friendlyName": "linux-mips32le-softfloat" },
  "linux-mipsle": { "friendlyName": "linux-mips32le" },
  "linux-mipssoftfloat": { "friendlyName": "linux-mips32-softfloat" },
  "linux-mips": { "friendlyName": "linux-mips32" },
  "linux-ppc64le": { "friendlyName": "linux-ppc64le" },
  "linux-ppc64": { "friendlyName": "linux-ppc64" },
  "linux-riscv64": { "friendlyName": "linux-riscv64" },
  "linux-loong64": { "friendlyName": "linux-loong64" },
  "linux-s390x": { "friendlyName": "linux-s390x" },
  "openbsd-386": { "friendlyName": "openbsd-32" },
  "openbsd-amd64": { "friendlyName": "openbsd-64" },
  "openbsd-arm64": { "friendlyName": "openbsd-arm64-v8a" },
  "openbsd-arm7": { "friendlyName": "openbsd-arm32-v7a" },
  "windows-386": { "friendlyName": "windows-32" },
  "windows-amd64": { "friendlyName": "windows-64" },
  "windows-arm64": { "friendlyName": "windows-arm64-v8a" }
}


================================================
FILE: .github/dependabot.yml
================================================
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
  - package-ecosystem: "gomod"
    directory: "/" # Location of package manifests
    schedule:
      interval: "daily"
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "daily"


================================================
FILE: .github/docker/Dockerfile
================================================
# syntax=docker/dockerfile:latest
FROM --platform=$BUILDPLATFORM golang:latest AS build

# Build xray-core
WORKDIR /src
COPY . .
ARG TARGETOS
ARG TARGETARCH
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags "-s -w -buildid=" ./main

# Download geodat into a staging directory
ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geoip.dat /tmp/geodat/geoip.dat
ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geosite.dat /tmp/geodat/geosite.dat

RUN mkdir -p /tmp/empty

# Create config files with empty JSON content
RUN mkdir -p /tmp/usr/local/etc/xray
RUN cat <<EOF >/tmp/usr/local/etc/xray/00_log.json
{
  "log": {
    "error": "/var/log/xray/error.log",
    "loglevel": "warning",
    "access": "none",
    "dnsLog": false
  }
}
EOF
RUN echo '{}' >/tmp/usr/local/etc/xray/01_api.json
RUN echo '{}' >/tmp/usr/local/etc/xray/02_dns.json
RUN echo '{}' >/tmp/usr/local/etc/xray/03_routing.json
RUN echo '{}' >/tmp/usr/local/etc/xray/04_policy.json
RUN echo '{}' >/tmp/usr/local/etc/xray/05_inbounds.json
RUN echo '{}' >/tmp/usr/local/etc/xray/06_outbounds.json
RUN echo '{}' >/tmp/usr/local/etc/xray/07_transport.json
RUN echo '{}' >/tmp/usr/local/etc/xray/08_stats.json
RUN echo '{}' >/tmp/usr/local/etc/xray/09_reverse.json

# Create log files
RUN mkdir -p /tmp/var/log/xray && touch \
  /tmp/var/log/xray/access.log \
  /tmp/var/log/xray/error.log

# Build finally image
FROM gcr.io/distroless/static:nonroot

COPY --from=build --chown=0:0 --chmod=755 /src/xray /usr/local/bin/xray
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/share/xray
COPY --from=build --chown=0:0 --chmod=644 /tmp/geodat/*.dat /usr/local/share/xray/
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/etc/xray
COPY --from=build --chown=0:0 --chmod=644 /tmp/usr/local/etc/xray/*.json /usr/local/etc/xray/
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /var/log/xray
COPY --from=build --chown=65532:65532 --chmod=600 /tmp/var/log/xray/*.log /var/log/xray/

VOLUME /usr/local/etc/xray
VOLUME /var/log/xray

ARG TZ=Etc/UTC
ENV TZ=$TZ

ENTRYPOINT [ "/usr/local/bin/xray" ]
CMD [ "-confdir", "/usr/local/etc/xray/" ]


================================================
FILE: .github/docker/Dockerfile.usa
================================================
# syntax=docker/dockerfile:latest
FROM --platform=$BUILDPLATFORM golang:latest AS build

# Build xray-core
WORKDIR /src
COPY . .
ARG TARGETOS
ARG TARGETARCH
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags "-s -w -buildid=" ./main

# Download geodat into a staging directory
ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geoip.dat /tmp/geodat/geoip.dat
ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geosite.dat /tmp/geodat/geosite.dat

RUN mkdir -p /tmp/empty

# Create config files with empty JSON content
RUN mkdir -p /tmp/usr/local/etc/xray
RUN cat <<EOF >/tmp/usr/local/etc/xray/00_log.json
{
  "log": {
    "error": "/var/log/xray/error.log",
    "loglevel": "warning",
    "access": "none",
    "dnsLog": false
  }
}
EOF
RUN echo '{}' >/tmp/usr/local/etc/xray/01_api.json
RUN echo '{}' >/tmp/usr/local/etc/xray/02_dns.json
RUN echo '{}' >/tmp/usr/local/etc/xray/03_routing.json
RUN echo '{}' >/tmp/usr/local/etc/xray/04_policy.json
RUN echo '{}' >/tmp/usr/local/etc/xray/05_inbounds.json
RUN echo '{}' >/tmp/usr/local/etc/xray/06_outbounds.json
RUN echo '{}' >/tmp/usr/local/etc/xray/07_transport.json
RUN echo '{}' >/tmp/usr/local/etc/xray/08_stats.json
RUN echo '{}' >/tmp/usr/local/etc/xray/09_reverse.json

# Create log files
RUN mkdir -p /tmp/var/log/xray && touch \
  /tmp/var/log/xray/access.log \
  /tmp/var/log/xray/error.log

# Build finally image
# Note on Distroless Base Image and Architecture Support:
# - The official 'gcr.io/distroless/static' image provided by Google only supports a limited set of architectures for Linux:
#   - linux/amd64
#   - linux/arm/v7
#   - linux/arm64/v8
#   - linux/ppc64le
#   - linux/s390x
# - Upon inspection, the blob contents of the Distroless images across these architectures are nearly identical, with only minor differences in metadata (e.g., 'Architecture' field in the manifest).
# - Due to this similarity in content, it is feasible to forcibly specify a single platform (e.g., '--platform=linux/amd64') for unsupported architectures, as the core image content remains compatible with statically compiled binaries like Go applications.
FROM --platform=linux/amd64 gcr.io/distroless/static:nonroot

COPY --from=build --chown=0:0 --chmod=755 /src/xray /usr/local/bin/xray
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/share/xray
COPY --from=build --chown=0:0 --chmod=644 /tmp/geodat/*.dat /usr/local/share/xray/
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/etc/xray
COPY --from=build --chown=0:0 --chmod=644 /tmp/usr/local/etc/xray/*.json /usr/local/etc/xray/
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /var/log/xray
COPY --from=build --chown=65532:65532 --chmod=600 /tmp/var/log/xray/*.log /var/log/xray/

VOLUME /usr/local/etc/xray
VOLUME /var/log/xray

ARG TZ=Etc/UTC
ENV TZ=$TZ

ENTRYPOINT [ "/usr/local/bin/xray" ]
CMD [ "-confdir", "/usr/local/etc/xray/" ]


================================================
FILE: .github/workflows/docker.yml
================================================
name: Build and Push Docker Image

on:
  release:
    types:
      - published
      - released

  workflow_dispatch:
    inputs:
      tag:
        description: "Docker image tag:"
        required: true
      latest:
        description: "Set to latest"
        type: boolean
        default: false

jobs:
  build-and-push:
    if: (github.event.action != 'published') || (github.event.action == 'published' && github.event.release.prerelease == true)
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Set repository and image name to lowercase
        env:
          IMAGE_NAME: "${{ github.repository }}"
        run: |
          echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
          echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}

      - name: Validate and extract tag
        run: |
          SOURCE_TAG="${{ github.event.inputs.tag }}"
          if [[ -z "$SOURCE_TAG" ]]; then
            SOURCE_TAG="${{ github.ref_name }}"
          fi
          if [[ -z "$SOURCE_TAG" ]]; then
            SOURCE_TAG="${{ github.event.release.tag_name }}"
          fi

          if [[ -z "$SOURCE_TAG" ]]; then
            echo "Error: Could not determine a valid tag source. Input tag and context tag (github.ref_name) are both empty."
            exit 1
          fi

          if [[ "$SOURCE_TAG" =~ ^v[0-9]+\.[0-9] ]]; then
            IMAGE_TAG="${SOURCE_TAG#v}"
          else
            IMAGE_TAG="$SOURCE_TAG"
          fi

          echo "Docker image tag: '$IMAGE_TAG'."
          echo "IMAGE_TAG=$IMAGE_TAG" >>${GITHUB_ENV}

          LATEST=false
          if [[ "${{ github.event_name }}" == "release" && "${{ github.event.release.prerelease }}" == "false" ]] || [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.latest }}" == "true" ]]; then
            LATEST=true
          fi

          echo "Latest: '$LATEST'."
          echo "LATEST=$LATEST" >>${GITHUB_ENV}

      - name: Checkout code
        uses: actions/checkout@v6

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v4
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build Docker image (main architectures)
        id: build_main_arches
        uses: docker/build-push-action@v7
        with:
          context: .
          file: .github/docker/Dockerfile
          platforms: |
            linux/amd64
            linux/arm/v7
            linux/arm64/v8
            linux/ppc64le
            linux/s390x
          provenance: false
          outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true

      - name: Build Docker image (additional architectures)
        id: build_additional_arches
        uses: docker/build-push-action@v7
        with:
          context: .
          file: .github/docker/Dockerfile.usa
          platforms: |
            linux/386
            linux/arm/v6
            linux/riscv64
            linux/loong64
          provenance: false
          outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true

      - name: Create manifest list and push
        run: |
          echo "Creating multi-arch manifest with tag: '${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG }}'."
          docker buildx imagetools create \
            --tag ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG }} \
            ${{ env.FULL_IMAGE_NAME }}@${{ steps.build_main_arches.outputs.digest }} \
            ${{ env.FULL_IMAGE_NAME }}@${{ steps.build_additional_arches.outputs.digest }}

          if [[ "${{ env.LATEST }}" == "true" ]]; then
            echo "Adding 'latest' tag to manifest: '${{ env.FULL_IMAGE_NAME }}:latest'."
            docker buildx imagetools create \
            --tag ${{ env.FULL_IMAGE_NAME }}:latest \
            ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG }}
          fi

      - name: Inspect image
        run: |
          docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG }}

          if [[ "${{ env.LATEST }}" == "true" ]]; then
            docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:latest
          fi


================================================
FILE: .github/workflows/release-win7.yml
================================================
name: Build and Release for Windows 7

on:
  workflow_dispatch:
  release:
    types: [published]
  push:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  check-assets:
    runs-on: ubuntu-latest
    steps:
      - name: Restore Geodat Cache
        uses: actions/cache/restore@v5
        with:
          path: resources
          key: xray-geodat-

      - name: Restore Wintun Cache
        uses: actions/cache/restore@v5
        with:
          path: resources
          key: xray-wintun-

      - name: Check Assets Existence
        id: check-assets
        run: |
          [ -d 'resources' ] || mkdir resources
          LIST=('geoip.dat' 'geosite.dat')
          for FILE_NAME in "${LIST[@]}"
          do
            echo -e "Checking ${FILE_NAME}..."
            if [ -s "./resources/${FILE_NAME}" ]; then
              echo -e "${FILE_NAME} exists."
            else
              echo -e "${FILE_NAME} does not exist."
              echo "missing=true" >> $GITHUB_OUTPUT
              break
            fi
          done
          LIST=('amd64' 'x86')
          for ARCHITECTURE in "${LIST[@]}"
          do
            echo -e "Checking wintun.dll for ${ARCHITECTURE}..."
            if [ -s "./resources/wintun/bin/${ARCHITECTURE}/wintun.dll" ]; then
              echo -e "wintun.dll for ${ARCHITECTURE} exists."
            else
              echo -e "wintun.dll for ${ARCHITECTURE} is missing."
              echo "missing=true" >> $GITHUB_OUTPUT
              break
            fi
          done

      - name: Sleep for 90 seconds if Assets Missing
        if: steps.check-assets.outputs.missing == 'true'
        run: sleep 90

  build:
    needs: check-assets
    permissions:
      contents: write
    strategy:
      matrix:
        include:
          # BEGIN Windows 7
          - goos: windows
            goarch: amd64
            assetname: win7-64
          - goos: windows
            goarch: 386
            assetname: win7-32
          # END Windows 7
      fail-fast: false

    runs-on: ubuntu-latest
    env:
      GOOS: ${{ matrix.goos}}
      GOARCH: ${{ matrix.goarch }}
      CGO_ENABLED: 0
    steps:
      - name: Checkout codebase
        uses: actions/checkout@v6

      - name: Show workflow information
        run: |
          _NAME=${{ matrix.assetname }}
          echo "GOOS: ${{ matrix.goos }}, GOARCH: ${{ matrix.goarch }}, RELEASE_NAME: $_NAME"
          echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version-file: go.mod
          check-latest: true

      - name: Setup patched builder
        run: |
          GOSDK=$(go env GOROOT)
          rm -r $GOSDK/*
          cd $GOSDK
          curl -O -L -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" https://github.com/XTLS/go-win7/releases/latest/download/go-for-win7-linux-amd64.zip
          unzip ./go-for-win7-linux-amd64.zip -d $GOSDK
          rm ./go-for-win7-linux-amd64.zip

      - name: Get project dependencies
        run: go mod download

      - name: Build Xray
        run: |
          mkdir -p build_assets
          COMMID=$(git describe --always --dirty)
          echo 'Building Xray for Windows 7...'
          go build -o build_assets/xray.exe -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
          # The line below is for without running conhost.exe version. Commented for not being used. Provided for reference.
          # go build -o build_assets/wxray.exe -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main

      - name: Restore Geodat Cache
        uses: actions/cache/restore@v5
        with:
          path: resources
          key: xray-geodat-

      - name: Restore Wintun Cache
        uses: actions/cache/restore@v5
        with:
          path: resources
          key: xray-wintun-

      - name: Add additional assets into package
        run: |
          mv -f resources/geo* build_assets/
          if [[ ${GOOS} == 'windows' ]]; then
            echo 'CreateObject("Wscript.Shell").Run "xray.exe -config config.json",0' > build_assets/xray_no_window.vbs
            echo 'Start-Process -FilePath ".\xray.exe" -ArgumentList "-config .\config.json" -WindowStyle Hidden' > build_assets/xray_no_window.ps1
            if [[ ${GOARCH} == 'amd64' ]]; then
              mv resources/wintun/bin/amd64/wintun.dll build_assets/
            fi
            if [[ ${GOARCH} == '386' ]]; then
              mv resources/wintun/bin/x86/wintun.dll build_assets/
            fi
            mv resources/wintun/LICENSE.txt build_assets/LICENSE-wintun.txt
          fi

      - name: Copy README.md & LICENSE
        run: |
          cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md
          cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE

      - name: Create ZIP archive
        if: github.event_name == 'release'
        shell: bash
        run: |
          pushd build_assets || exit 1
          touch -mt $(date +%Y01010000) *
          zip -9vr ../Xray-${{ env.ASSET_NAME }}.zip .
          popd || exit 1
          FILE=./Xray-${{ env.ASSET_NAME }}.zip
          DGST=$FILE.dgst
          for METHOD in {"md5","sha1","sha256","sha512"}
          do
            openssl dgst -$METHOD $FILE | sed 's/([^)]*)//g' >>$DGST
          done

      - name: Upload binaries to release
        uses: svenstaro/upload-release-action@v2
        if: github.event_name == 'release'
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: ./Xray-${{ env.ASSET_NAME }}.zip*
          tag: ${{ github.ref }}
          file_glob: true

      - name: Upload files to Artifacts
        uses: actions/upload-artifact@v7
        with:
          name: Xray-${{ env.ASSET_NAME }}
          path: |
            ./build_assets/*


================================================
FILE: .github/workflows/release.yml
================================================
name: Build and Release

on:
  workflow_dispatch:
  release:
    types: [published]
  push:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  check-assets:
    runs-on: ubuntu-latest
    steps:
      - name: Restore Geodat Cache
        uses: actions/cache/restore@v5
        with:
          path: resources
          key: xray-geodat-

      - name: Restore Wintun Cache
        uses: actions/cache/restore@v5
        with:
          path: resources
          key: xray-wintun-

      - name: Check Assets Existence
        id: check-assets
        run: |
          [ -d 'resources' ] || mkdir resources
          LIST=('geoip.dat' 'geosite.dat')
          for FILE_NAME in "${LIST[@]}"
          do
            echo -e "Checking ${FILE_NAME}..."
            if [ -s "./resources/${FILE_NAME}" ]; then
              echo -e "${FILE_NAME} exists."
            else
              echo -e "${FILE_NAME} does not exist."
              echo "missing=true" >> $GITHUB_OUTPUT
              break
            fi
          done
          LIST=('amd64' 'x86' 'arm64')
          for ARCHITECTURE in "${LIST[@]}"
          do
            echo -e "Checking wintun.dll for ${ARCHITECTURE}..."
            if [ -s "./resources/wintun/bin/${ARCHITECTURE}/wintun.dll" ]; then
              echo -e "wintun.dll for ${ARCHITECTURE} exists."
            else
              echo -e "wintun.dll for ${ARCHITECTURE} is missing."
              echo "missing=true" >> $GITHUB_OUTPUT
              break
            fi
          done

      - name: Trigger Asset Update Workflow if Assets Missing
        if: steps.check-assets.outputs.missing == 'true'
        uses: actions/github-script@v8
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const { owner, repo } = context.repo;
            await github.rest.actions.createWorkflowDispatch({
              owner,
              repo,
              workflow_id: 'scheduled-assets-update.yml',
              ref: context.ref
            });
            console.log('Triggered scheduled-assets-update.yml due to missing assets on branch:', context.ref);

      - name: Sleep for 90 seconds if Assets Missing
        if: steps.check-assets.outputs.missing == 'true'
        run: sleep 90

  build:
    needs: check-assets
    permissions:
      contents: write
    strategy:
      matrix:
        # Include amd64 on all platforms.
        goos: [windows, freebsd, openbsd, linux, darwin]
        goarch: [amd64, 386]
        patch-assetname: [""]
        exclude:
          # Exclude i386 on darwin
          - goarch: 386
            goos: darwin
        include:
          # BEGIN MacOS ARM64
          - goos: darwin
            goarch: arm64
          # END MacOS ARM64
          # BEGIN Linux ARM 5 6 7
          - goos: linux
            goarch: arm
            goarm: 7
          - goos: linux
            goarch: arm
            goarm: 6
          - goos: linux
            goarch: arm
            goarm: 5
          # END Linux ARM 5 6 7
          # BEGIN Android ARM 8
          - goos: android
            goarch: arm64
          # END Android ARM 8
          # BEGIN Android AMD64
          - goos: android
            goarch: amd64
            patch-assetname: android-amd64
          # END Android AMD64
          # Windows ARM
          - goos: windows
            goarch: arm64
          # BEGIN Other architectures
          # BEGIN riscv64 & ARM64 & LOONG64
          - goos: linux
            goarch: arm64
          - goos: linux
            goarch: riscv64
          - goos: linux
            goarch: loong64
          # END riscv64 & ARM64 & LOONG64
          # BEGIN MIPS
          - goos: linux
            goarch: mips64
          - goos: linux
            goarch: mips64le
          - goos: linux
            goarch: mipsle
          - goos: linux
            goarch: mips
          # END MIPS
          # BEGIN PPC
          - goos: linux
            goarch: ppc64
          - goos: linux
            goarch: ppc64le
          # END PPC
          # BEGIN FreeBSD ARM
          - goos: freebsd
            goarch: arm64
          - goos: freebsd
            goarch: arm
            goarm: 7
          # END FreeBSD ARM
          # BEGIN S390X
          - goos: linux
            goarch: s390x
          # END S390X
          # END Other architectures
          # BEGIN OPENBSD ARM
          - goos: openbsd
            goarch: arm64
          - goos: openbsd
            goarch: arm
            goarm: 7
          # END OPENBSD ARM
      fail-fast: false

    runs-on: ubuntu-latest
    env:
      GOOS: ${{ matrix.goos }}
      GOARCH: ${{ matrix.goarch }}
      GOARM: ${{ matrix.goarm }}
      CGO_ENABLED: 0
    steps:
      - name: Checkout codebase
        uses: actions/checkout@v6

      - name: Set up NDK
        if: matrix.goos == 'android'
        run: |
          wget -qO android-ndk.zip https://dl.google.com/android/repository/android-ndk-r28b-linux.zip
          unzip android-ndk.zip
          rm android-ndk.zip
          declare -A arches=(
            ["amd64"]="x86_64-linux-android24-clang"
            ["arm64"]="aarch64-linux-android24-clang"
          )
          echo CC="$(realpath android-ndk-*/toolchains/llvm/prebuilt/linux-x86_64/bin)/${arches[${{ matrix.goarch }}]}" >> $GITHUB_ENV
          echo CGO_ENABLED=1 >> $GITHUB_ENV

      - name: Show workflow information
        run: |
          _NAME=${{ matrix.patch-assetname }}
          [ -n "$_NAME" ] || _NAME=$(jq ".[\"$GOOS-$GOARCH$GOARM$GOMIPS\"].friendlyName" -r < .github/build/friendly-filenames.json)
          echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME"
          echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV

      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version-file: go.mod
          check-latest: true

      - name: Get project dependencies
        run: go mod download

      - name: Build Xray
        run: |
          mkdir -p build_assets
          COMMID=$(git describe --always --dirty)
          if [[ ${GOOS} == 'windows' ]]; then
            echo 'Building Xray for Windows...'
            go build -o build_assets/xray.exe -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
            # The line below is for without running conhost.exe version. Commented for not being used. Provided for reference.
            # go build -o build_assets/wxray.exe -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
          else
            echo 'Building Xray...'
            if [[ ${GOARCH} == 'mips' || ${GOARCH} == 'mipsle' ]]; then
              go build -o build_assets/xray -trimpath -buildvcs=false -gcflags="-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
              echo 'Building soft-float Xray for MIPS/MIPSLE 32-bit...'
              GOMIPS=softfloat go build -o build_assets/xray_softfloat -trimpath -buildvcs=false -gcflags="-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
            else
              go build -o build_assets/xray -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
            fi
          fi

      - name: Restore Geodat Cache
        uses: actions/cache/restore@v5
        with:
          path: resources
          key: xray-geodat-

      - name: Restore Wintun Cache
        if: matrix.goos == 'windows'
        uses: actions/cache/restore@v5
        with:
          path: resources
          key: xray-wintun-

      - name: Add additional assets into package
        run: |
          mv -f resources/geo* build_assets/
          if [[ ${GOOS} == 'windows' ]]; then
            echo 'CreateObject("Wscript.Shell").Run "xray.exe -config config.json",0' > build_assets/xray_no_window.vbs
            echo 'Start-Process -FilePath ".\xray.exe" -ArgumentList "-config .\config.json" -WindowStyle Hidden' > build_assets/xray_no_window.ps1
            if [[ ${GOARCH} == 'amd64' ]]; then
              mv resources/wintun/bin/amd64/wintun.dll build_assets/
            fi
            if [[ ${GOARCH} == '386' ]]; then
              mv resources/wintun/bin/x86/wintun.dll build_assets/
            fi
            if [[ ${GOARCH} == 'arm64' ]]; then
              mv resources/wintun/bin/arm64/wintun.dll build_assets/
            fi
            mv resources/wintun/LICENSE.txt build_assets/LICENSE-wintun.txt
          fi

      - name: Copy README.md & LICENSE
        run: |
          cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md
          cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE

      - name: Create ZIP archive
        if: github.event_name == 'release'
        shell: bash
        run: |
          pushd build_assets || exit 1
          touch -mt $(date +%Y01010000) *
          zip -9vr ../Xray-${{ env.ASSET_NAME }}.zip .
          popd || exit 1
          FILE=./Xray-${{ env.ASSET_NAME }}.zip
          DGST=$FILE.dgst
          for METHOD in {"md5","sha1","sha256","sha512"}
          do
            openssl dgst -$METHOD $FILE | sed 's/([^)]*)//g' >>$DGST
          done

      - name: Upload binaries to release
        uses: svenstaro/upload-release-action@v2
        if: github.event_name == 'release'
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: ./Xray-${{ env.ASSET_NAME }}.zip*
          tag: ${{ github.ref }}
          file_glob: true

      - name: Upload files to Artifacts
        uses: actions/upload-artifact@v7
        with:
          name: Xray-${{ env.ASSET_NAME }}
          path: |
            ./build_assets/*


================================================
FILE: .github/workflows/scheduled-assets-update.yml
================================================
name: Scheduled assets update

# NOTE: This Github Actions is required by other actions, for preparing other packaging assets in a
#       routine manner, for example: GeoIP/GeoSite.
#       Currently updating:
#       - Geodat (GeoIP/Geosite)
#       - Wintun (wintun.dll)

on:
  workflow_dispatch:
  schedule:
    # Update GeoData on every day (22:30 UTC)
    - cron: "30 22 * * *"
  push:
    # Prevent triggering update request storm
    paths:
      - ".github/workflows/scheduled-assets-update.yml"
  pull_request:
    # Prevent triggering update request storm
    paths:
      - ".github/workflows/scheduled-assets-update.yml"

jobs:
  geodat:
    if: github.event.schedule == '30 22 * * *' || github.event_name == 'push' || github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
    runs-on: ubuntu-latest
    steps:
      - name: Restore Geodat Cache
        uses: actions/cache/restore@v5
        with:
          path: resources
          key: xray-geodat-

      - name: Update Geodat
        id: update
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 60
          retry_wait_seconds: 60
          max_attempts: 60
          command: |
            [ -d 'resources' ] || mkdir resources
            LIST=('Loyalsoldier v2ray-rules-dat geoip geoip' 'Loyalsoldier v2ray-rules-dat geosite geosite')
            for i in "${LIST[@]}"
            do
              INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3,$4}'))
              FILE_NAME="${INFO[3]}.dat"
              echo -e "Verifying HASH key..."
              HASH="$(curl -sL -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat.sha256sum" | awk -F ' ' '{print $1}')"
              if [ -s "./resources/${FILE_NAME}" ] && [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ]; then
                  continue
              else
                  echo -e "Downloading https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat..."
                  curl -L -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat" -o ./resources/${FILE_NAME}
                  echo -e "Verifying HASH key..."
                  [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; }
                  echo "unhit=true" >> $GITHUB_OUTPUT
              fi
            done

      - name: Save Geodat Cache
        uses: actions/cache/save@v5
        if: ${{ steps.update.outputs.unhit }}
        with:
          path: resources
          key: xray-geodat-${{ github.sha }}-${{ github.run_number }}

  wintun:
    if: github.event.schedule == '30 22 * * *' || github.event_name == 'push' || github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
    runs-on: ubuntu-latest
    steps:
      - name: Restore Wintun Cache
        uses: actions/cache/restore@v5
        with:
          path: resources
          key: xray-wintun-

      - name: Force downloading if run manually or on file update
        if: github.event_name == 'workflow_dispatch' || github.event_name == 'push'
        run: |
          echo "FORCE_UPDATE=true" >> $GITHUB_ENV

      - name: Update Wintun
        id: update
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 60
          retry_wait_seconds: 60
          max_attempts: 60
          command: |
            [ -d 'resources' ] || mkdir resources
            LIST=('amd64' 'x86' 'arm64')
            for ARCHITECTURE in "${LIST[@]}"
            do
              FILE_PATH="resources/wintun/bin/${ARCHITECTURE}/wintun.dll"
              echo -e "Checking if wintun.dll for ${ARCHITECTURE} exists..."
              if [ -s "./resources/wintun/bin/${ARCHITECTURE}/wintun.dll" ]; then
                  echo -e "wintun.dll for ${ARCHITECTURE} exists"
                  continue
              else
                  echo -e "wintun.dll for ${ARCHITECTURE} is missing"
                  missing=true
              fi
            done
            if [ -s "./resources/wintun/LICENSE.txt" ]; then
              echo -e "LICENSE for Wintun exists"
            else
              echo -e "LICENSE for Wintun is missing"
              missing=true
            fi
            if [[ -v FORCE_UPDATE ]]; then
              missing=true
            fi
            if [[ "$missing" == true ]]; then
              FILENAME=wintun.zip
              DOWNLOAD_FILE=wintun-0.14.1.zip
              echo -e "Downloading https://www.wintun.net/builds/${DOWNLOAD_FILE}..."
              curl -L "https://www.wintun.net/builds/${DOWNLOAD_FILE}" -o "${FILENAME}"
              echo -e "Unpacking wintun..."
              unzip -u ${FILENAME} -d resources/
              echo "unhit=true" >> $GITHUB_OUTPUT
            fi

      - name: Save Wintun Cache
        uses: actions/cache/save@v5
        if: ${{ steps.update.outputs.unhit }}
        with:
          path: resources
          key: xray-wintun-${{ github.sha }}-${{ github.run_number }}


================================================
FILE: .github/workflows/test.yml
================================================
name: Test

on:
  push:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  check-assets:
    runs-on: ubuntu-latest
    steps:
      - name: Restore Geodat Cache
        uses: actions/cache/restore@v5
        with:
          path: resources
          key: xray-geodat-
      - name: Check Assets Existence
        id: check-assets
        run: |
          [ -d 'resources' ] || mkdir resources
          LIST=('geoip.dat' 'geosite.dat')
          for FILE_NAME in "${LIST[@]}"
          do
            echo -e "Checking ${FILE_NAME}..."
            if [ -s "./resources/${FILE_NAME}" ]; then
              echo -e "${FILE_NAME} exists."
            else
              echo -e "${FILE_NAME} does not exist."
              echo "missing=true" >> $GITHUB_OUTPUT
              break
            fi
          done
      - name: Sleep for 90 seconds if Assets Missing
        if: steps.check-assets.outputs.missing == 'true'
        run: sleep 90

  check-proto:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout codebase
        uses: actions/checkout@v6
      - name: Check Proto Version Header
        run: |
          head -n 4 core/config.pb.go > ref.txt
          find . -name "*.pb.go" ! -name "*_grpc.pb.go" -print0 | while IFS= read -r -d '' file; do
            if ! cmp -s ref.txt <(head -n 4 "$file"); then
              echo "Error: Header mismatch in $file"
              head -n 4 "$file"
              exit 1
            fi
          done

  test:
    needs: check-assets
    permissions:
      contents: read
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [windows-latest, ubuntu-latest, macos-latest]
    steps:
      - name: Checkout codebase
        uses: actions/checkout@v6
      - name: Set up Go
        uses: actions/setup-go@v6
        with:
          go-version-file: go.mod
          check-latest: true
      - name: Restore Geodat Cache
        uses: actions/cache/restore@v5
        with:
          path: resources
          key: xray-geodat-
          enableCrossOsArchive: true
      - name: Test
        run: go test -timeout 1h -v ./...


================================================
FILE: .gitignore
================================================
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# macOS specific files
.DS_Store

# IDE/editor specific files
.idea/
.vscode/
*.swp
*.swo

# Archives and compressed files
*.zip
*.tar.gz
*.tar
*.gz
*.bz2

# Go build binaries
xray
xray_softfloat
mockgen
vprotogen
!infra/vprotogen/
errorgen
!common/errors/errorgen/
*.dat

# Build assets
/build_assets/

# Output from dlv test
**/debug.*

# Certificates and keys
*.crt
*.key

# Dependency directories (uncomment if needed)
# vendor/

# Logs
*.log

# Coverage reports
coverage.*

# Node modules (in case of frontend assets)
node_modules/

# System files
Thumbs.db
ehthumbs.db

# Other common ignores
*.bak
*.tmp


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
https://t.me/projectXtls.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior,  harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.


================================================
FILE: LICENSE
================================================
Mozilla Public License Version 2.0
==================================

1. Definitions
--------------

1.1. "Contributor"
    means each individual or legal entity that creates, contributes to
    the creation of, or owns Covered Software.

1.2. "Contributor Version"
    means the combination of the Contributions of others (if any) used
    by a Contributor and that particular Contributor's Contribution.

1.3. "Contribution"
    means Covered Software of a particular Contributor.

1.4. "Covered Software"
    means Source Code Form to which the initial Contributor has attached
    the notice in Exhibit A, the Executable Form of such Source Code
    Form, and Modifications of such Source Code Form, in each case
    including portions thereof.

1.5. "Incompatible With Secondary Licenses"
    means

    (a) that the initial Contributor has attached the notice described
        in Exhibit B to the Covered Software; or

    (b) that the Covered Software was made available under the terms of
        version 1.1 or earlier of the License, but not also under the
        terms of a Secondary License.

1.6. "Executable Form"
    means any form of the work other than Source Code Form.

1.7. "Larger Work"
    means a work that combines Covered Software with other material, in
    a separate file or files, that is not Covered Software.

1.8. "License"
    means this document.

1.9. "Licensable"
    means having the right to grant, to the maximum extent possible,
    whether at the time of the initial grant or subsequently, any and
    all of the rights conveyed by this License.

1.10. "Modifications"
    means any of the following:

    (a) any file in Source Code Form that results from an addition to,
        deletion from, or modification of the contents of Covered
        Software; or

    (b) any new file in Source Code Form that contains any Covered
        Software.

1.11. "Patent Claims" of a Contributor
    means any patent claim(s), including without limitation, method,
    process, and apparatus claims, in any patent Licensable by such
    Contributor that would be infringed, but for the grant of the
    License, by the making, using, selling, offering for sale, having
    made, import, or transfer of either its Contributions or its
    Contributor Version.

1.12. "Secondary License"
    means either the GNU General Public License, Version 2.0, the GNU
    Lesser General Public License, Version 2.1, the GNU Affero General
    Public License, Version 3.0, or any later versions of those
    licenses.

1.13. "Source Code Form"
    means the form of the work preferred for making modifications.

1.14. "You" (or "Your")
    means an individual or a legal entity exercising rights under this
    License. For legal entities, "You" includes any entity that
    controls, is controlled by, or is under common control with You. For
    purposes of this definition, "control" means (a) the power, direct
    or indirect, to cause the direction or management of such entity,
    whether by contract or otherwise, or (b) ownership of more than
    fifty percent (50%) of the outstanding shares or beneficial
    ownership of such entity.

2. License Grants and Conditions
--------------------------------

2.1. Grants

Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:

(a) under intellectual property rights (other than patent or trademark)
    Licensable by such Contributor to use, reproduce, make available,
    modify, display, perform, distribute, and otherwise exploit its
    Contributions, either on an unmodified basis, with Modifications, or
    as part of a Larger Work; and

(b) under Patent Claims of such Contributor to make, use, sell, offer
    for sale, have made, import, and otherwise transfer either its
    Contributions or its Contributor Version.

2.2. Effective Date

The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.

2.3. Limitations on Grant Scope

The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:

(a) for any code that a Contributor has removed from Covered Software;
    or

(b) for infringements caused by: (i) Your and any other third party's
    modifications of Covered Software, or (ii) the combination of its
    Contributions with other software (except as part of its Contributor
    Version); or

(c) under Patent Claims infringed by Covered Software in the absence of
    its Contributions.

This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).

2.4. Subsequent Licenses

No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).

2.5. Representation

Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.

2.6. Fair Use

This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.

2.7. Conditions

Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.

3. Responsibilities
-------------------

3.1. Distribution of Source Form

All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.

3.2. Distribution of Executable Form

If You distribute Covered Software in Executable Form then:

(a) such Covered Software must also be made available in Source Code
    Form, as described in Section 3.1, and You must inform recipients of
    the Executable Form how they can obtain a copy of such Source Code
    Form by reasonable means in a timely manner, at a charge no more
    than the cost of distribution to the recipient; and

(b) You may distribute such Executable Form under the terms of this
    License, or sublicense it under different terms, provided that the
    license for the Executable Form does not attempt to limit or alter
    the recipients' rights in the Source Code Form under this License.

3.3. Distribution of a Larger Work

You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).

3.4. Notices

You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.

3.5. Application of Additional Terms

You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.

4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------

If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.

5. Termination
--------------

5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.

5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.

5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.

************************************************************************
*                                                                      *
*  6. Disclaimer of Warranty                                           *
*  -------------------------                                           *
*                                                                      *
*  Covered Software is provided under this License on an "as is"       *
*  basis, without warranty of any kind, either expressed, implied, or  *
*  statutory, including, without limitation, warranties that the       *
*  Covered Software is free of defects, merchantable, fit for a        *
*  particular purpose or non-infringing. The entire risk as to the     *
*  quality and performance of the Covered Software is with You.        *
*  Should any Covered Software prove defective in any respect, You     *
*  (not any Contributor) assume the cost of any necessary servicing,   *
*  repair, or correction. This disclaimer of warranty constitutes an   *
*  essential part of this License. No use of any Covered Software is   *
*  authorized under this License except under this disclaimer.         *
*                                                                      *
************************************************************************

************************************************************************
*                                                                      *
*  7. Limitation of Liability                                          *
*  --------------------------                                          *
*                                                                      *
*  Under no circumstances and under no legal theory, whether tort      *
*  (including negligence), contract, or otherwise, shall any           *
*  Contributor, or anyone who distributes Covered Software as          *
*  permitted above, be liable to You for any direct, indirect,         *
*  special, incidental, or consequential damages of any character      *
*  including, without limitation, damages for lost profits, loss of    *
*  goodwill, work stoppage, computer failure or malfunction, or any    *
*  and all other commercial damages or losses, even if such party      *
*  shall have been informed of the possibility of such damages. This   *
*  limitation of liability shall not apply to liability for death or   *
*  personal injury resulting from such party's negligence to the       *
*  extent applicable law prohibits such limitation. Some               *
*  jurisdictions do not allow the exclusion or limitation of           *
*  incidental or consequential damages, so this exclusion and          *
*  limitation may not apply to You.                                    *
*                                                                      *
************************************************************************

8. Litigation
-------------

Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.

9. Miscellaneous
----------------

This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.

10. Versions of the License
---------------------------

10.1. New Versions

Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.

10.2. Effect of New Versions

You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.

10.3. Modified Versions

If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).

10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses

If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.

Exhibit A - Source Code Form License Notice
-------------------------------------------

  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.

If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.

You may add additional accurate notices of copyright ownership.

Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------

  This Source Code Form is "Incompatible With Secondary Licenses", as
  defined by the Mozilla Public License, v. 2.0.


================================================
FILE: README.md
================================================
# Project X

[Project X](https://github.com/XTLS) originates from XTLS protocol, providing a set of network tools such as [Xray-core](https://github.com/XTLS/Xray-core) and [REALITY](https://github.com/XTLS/REALITY).

[README](https://github.com/XTLS/Xray-core#readme) is open, so feel free to submit your project [here](https://github.com/XTLS/Xray-core/pulls).

## Sponsors

[![Remnawave](https://github.com/user-attachments/assets/a22d34ae-01ee-441c-843a-85356748ed1e)](https://docs.rw)

[![Happ](https://github.com/user-attachments/assets/14055dab-e8bb-48bd-89e8-962709e4098e)](https://happ.su)

[**Sponsor Xray-core**](https://github.com/XTLS/Xray-core/issues/3668)

## Donation & NFTs

### [Collect a Project X NFT to support the development of Project X!](https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1)

[<img alt="Project X NFT" width="150px" src="https://raw2.seadn.io/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/7fa9ce900fb39b44226348db330e32/8b7fa9ce900fb39b44226348db330e32.svg" />](https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1)

- **TRX(Tron)/USDT/USDC: `TNrDh5VSfwd4RPrwsohr6poyNTfFefNYan`**
- **TON: `UQApeV-u2gm43aC1uP76xAC1m6vCylstaN1gpfBmre_5IyTH`**
- **BTC: `1JpqcziZZuqv3QQJhZGNGBVdCBrGgkL6cT`**
- **XMR: `4ABHQZ3yJZkBnLoqiKvb3f8eqUnX4iMPb6wdant5ZLGQELctcerceSGEfJnoCk6nnyRZm73wrwSgvZ2WmjYLng6R7sR67nq`**
- **SOL/USDT/USDC: `3x5NuXHzB5APG6vRinPZcsUv5ukWUY1tBGRSJiEJWtZa`**
- **ETH/USDT/USDC: `0xDc3Fe44F0f25D13CACb1C4896CD0D321df3146Ee`**
- **Project X NFT: https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1**
- **VLESS NFT: https://opensea.io/collection/vless**
- **REALITY NFT: https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2**
- **Related links: [VLESS Post-Quantum Encryption](https://github.com/XTLS/Xray-core/pull/5067), [XHTTP: Beyond REALITY](https://github.com/XTLS/Xray-core/discussions/4113), [Announcement of NFTs by Project X](https://github.com/XTLS/Xray-core/discussions/3633)**

## License

[Mozilla Public License Version 2.0](https://github.com/XTLS/Xray-core/blob/main/LICENSE)

## Documentation

[Project X Official Website](https://xtls.github.io)

## Telegram

[Project X](https://t.me/projectXray)

[Project X Channel](https://t.me/projectXtls)

[Project VLESS](https://t.me/projectVless) (Русский)

[Project XHTTP](https://t.me/projectXhttp) (Persian)

## Installation

- Linux Script
  - [XTLS/Xray-install](https://github.com/XTLS/Xray-install) (**Official**)
  - [tempest](https://github.com/team-cloudchaser/tempest) (supports [`systemd`](https://systemd.io) and [OpenRC](https://github.com/OpenRC/openrc); Linux-only)
- Docker
  - [ghcr.io/xtls/xray-core](https://ghcr.io/xtls/xray-core) (**Official**)
  - [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
  - [wulabing/xray_docker](https://github.com/wulabing/xray_docker)
- Web Panel
  - [Remnawave](https://github.com/remnawave/panel)
  - [3X-UI](https://github.com/MHSanaei/3x-ui)
  - [PasarGuard](https://github.com/PasarGuard/panel)
  - [Xray-UI](https://github.com/qist/xray-ui)
  - [X-Panel](https://github.com/xeefei/X-Panel)
  - [Marzban](https://github.com/Gozargah/Marzban)
  - [Hiddify](https://github.com/hiddify/Hiddify-Manager)
  - [TX-UI](https://github.com/AghayeCoder/tx-ui)
- One Click
  - [Xray-REALITY](https://github.com/zxcvos/Xray-script), [xray-reality](https://github.com/sajjaddg/xray-reality), [reality-ezpz](https://github.com/aleskxyz/reality-ezpz)
  - [Xray_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool), [VPainLess](https://github.com/vpainless/vpainless)
  - [v2ray-agent](https://github.com/mack-a/v2ray-agent), [Xray_onekey](https://github.com/wulabing/Xray_onekey), [ProxySU](https://github.com/proxysu/ProxySU)
- Magisk
  - [NetProxy-Magisk](https://github.com/Fanju6/NetProxy-Magisk)
  - [Xray4Magisk](https://github.com/Asterisk4Magisk/Xray4Magisk)
  - [Xray_For_Magisk](https://github.com/E7KMbb/Xray_For_Magisk)
- Homebrew
  - `brew install xray`

## Usage

- Example
  - [VLESS-XTLS-uTLS-REALITY](https://github.com/XTLS/REALITY#readme)
  - [VLESS-TCP-XTLS-Vision](https://github.com/XTLS/Xray-examples/tree/main/VLESS-TCP-XTLS-Vision)
  - [All-in-One-fallbacks-Nginx](https://github.com/XTLS/Xray-examples/tree/main/All-in-One-fallbacks-Nginx)
- Xray-examples
  - [XTLS/Xray-examples](https://github.com/XTLS/Xray-examples)
  - [chika0801/Xray-examples](https://github.com/chika0801/Xray-examples)
  - [lxhao61/integrated-examples](https://github.com/lxhao61/integrated-examples)
- Tutorial
  - [XTLS Vision](https://github.com/chika0801/Xray-install)
  - [REALITY (English)](https://cscot.pages.dev/2023/03/02/Xray-REALITY-tutorial/)
  - [XTLS-Iran-Reality (English)](https://github.com/SasukeFreestyle/XTLS-Iran-Reality)
  - [Xray REALITY with 'steal oneself' (English)](https://computerscot.github.io/vless-xtls-utls-reality-steal-oneself.html)
  - [Xray with WireGuard inbound (English)](https://g800.pages.dev/wireguard)

## GUI Clients

- OpenWrt
  - [PassWall](https://github.com/Openwrt-Passwall/openwrt-passwall), [PassWall 2](https://github.com/Openwrt-Passwall/openwrt-passwall2)
  - [ShadowSocksR Plus+](https://github.com/fw876/helloworld)
  - [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray))
- Asuswrt-Merlin
  - [XRAYUI](https://github.com/DanielLavrushin/asuswrt-merlin-xrayui)
  - [fancyss](https://github.com/hq450/fancyss)
- Windows
  - [v2rayN](https://github.com/2dust/v2rayN)
  - [Furious](https://github.com/LorenEteval/Furious)
  - [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient)
  - [AnyPortal](https://github.com/AnyPortal/AnyPortal)
  - [GenyConnect](https://github.com/genyleap/GenyConnect)
- Android
  - [v2rayNG](https://github.com/2dust/v2rayNG)
  - [X-flutter](https://github.com/XTLS/X-flutter)
  - [SaeedDev94/Xray](https://github.com/SaeedDev94/Xray)
  - [SimpleXray](https://github.com/lhear/SimpleXray)
  - [XrayFA](https://github.com/Q7DF1/XrayFA)
  - [AnyPortal](https://github.com/AnyPortal/AnyPortal)
  - [NetProxy-Magisk](https://github.com/Fanju6/NetProxy-Magisk)
- iOS & macOS arm64 & tvOS
  - [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215) | [Happ RU](https://apps.apple.com/ru/app/happ-proxy-utility-plus/id6746188973) | [Happ tvOS](https://apps.apple.com/us/app/happ-proxy-utility-for-tv/id6748297274)
  - [Streisand](https://apps.apple.com/app/streisand/id6450534064)
  - [OneXray](https://github.com/OneXray/OneXray)
- macOS arm64 & x64
  - [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215) | [Happ RU](https://apps.apple.com/ru/app/happ-proxy-utility-plus/id6746188973)
  - [V2rayU](https://github.com/yanue/V2rayU)
  - [V2RayXS](https://github.com/tzmax/V2RayXS)
  - [Furious](https://github.com/LorenEteval/Furious)
  - [OneXray](https://github.com/OneXray/OneXray)
  - [GoXRay](https://github.com/goxray/desktop)
  - [AnyPortal](https://github.com/AnyPortal/AnyPortal)
  - [v2rayN](https://github.com/2dust/v2rayN)
  - [GenyConnect](https://github.com/genyleap/GenyConnect)
- Linux
  - [v2rayA](https://github.com/v2rayA/v2rayA)
  - [Furious](https://github.com/LorenEteval/Furious)
  - [GorzRay](https://github.com/ketetefid/GorzRay)
  - [GoXRay](https://github.com/goxray/desktop)
  - [AnyPortal](https://github.com/AnyPortal/AnyPortal)
  - [v2rayN](https://github.com/2dust/v2rayN)
  - [GenyConnect](https://github.com/genyleap/GenyConnect)

## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...

- iOS & macOS arm64 & tvOS
  - [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
  - [Loon](https://apps.apple.com/us/app/loon/id1373567447)
  - [Egern](https://apps.apple.com/us/app/egern/id1616105820)
  - [Quantumult X](https://apps.apple.com/us/app/quantumult-x/id1443988620)
- Xray Tools
  - [xray-knife](https://github.com/lilendian0x00/xray-knife)
  - [xray-checker](https://github.com/kutovoys/xray-checker)
- Xray Wrapper
  - [XTLS/libXray](https://github.com/XTLS/libXray)
  - [xtls-sdk](https://github.com/remnawave/xtls-sdk)
  - [xtlsapi](https://github.com/hiddify/xtlsapi)
  - [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite)
  - [Xray-core-python](https://github.com/LorenEteval/Xray-core-python)
  - [xray-api](https://github.com/XVGuardian/xray-api)
- [XrayR](https://github.com/XrayR-project/XrayR)
  - [XrayR-release](https://github.com/XrayR-project/XrayR-release)
  - [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board)
- Cores
  - [Amnezia VPN](https://github.com/amnezia-vpn)
  - [mihomo](https://github.com/MetaCubeX/mihomo)
  - [sing-box](https://github.com/SagerNet/sing-box)

## Contributing

[Code of Conduct](https://github.com/XTLS/Xray-core/blob/main/CODE_OF_CONDUCT.md)

[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/XTLS/Xray-core)

## Credits

- [Xray-core v1.0.0](https://github.com/XTLS/Xray-core/releases/tag/v1.0.0) was forked from [v2fly-core 9a03cc5](https://github.com/v2fly/v2ray-core/commit/9a03cc5c98d04cc28320fcee26dbc236b3291256), and we have made & accumulated a huge number of enhancements over time, check [the release notes for each version](https://github.com/XTLS/Xray-core/releases).
- For third-party projects used in [Xray-core](https://github.com/XTLS/Xray-core), check your local or [the latest go.mod](https://github.com/XTLS/Xray-core/blob/main/go.mod).

## One-line Compilation

### Windows (PowerShell)

```powershell
$env:CGO_ENABLED=0
go build -o xray.exe -trimpath -buildvcs=false -ldflags="-s -w -buildid=" -v ./main
```

### Linux / macOS

```bash
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -ldflags="-s -w -buildid=" -v ./main
```

### Reproducible Releases

Make sure that you are using the same Go version, and remember to set the git commit id (7 bytes):

```bash
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=REPLACE -s -w -buildid=" -v ./main
```

If you are compiling a 32-bit MIPS/MIPSLE target, use this command instead:

```bash
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -gcflags="-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=REPLACE -s -w -buildid=" -v ./main
```

## Stargazers over time

[![Stargazers over time](https://starchart.cc/XTLS/Xray-core.svg)](https://starchart.cc/XTLS/Xray-core)


================================================
FILE: SECURITY.md
================================================
# Security Policy

If you found an issue related to security vulnerability or protocol-identification problem, please report it to us via "[Report a vulnerability](https://github.com/XTLS/Xray-core/security/advisories/new)" privately, instead of publish it publicly before we release the fixed version.

Thanks for your contribution to the FREE Internet!


================================================
FILE: app/app.go
================================================
// Package app contains feature implementations of Xray. The features may be enabled during runtime.
package app


================================================
FILE: app/commander/commander.go
================================================
package commander

import (
	"context"
	"net"
	"sync"

	"github.com/xtls/xray-core/common"
	"github.com/xtls/xray-core/common/errors"
	"github.com/xtls/xray-core/common/signal/done"
	core "github.com/xtls/xray-core/core"
	"github.com/xtls/xray-core/features/outbound"
	"google.golang.org/grpc"
)

// Commander is a Xray feature that provides gRPC methods to external clients.
type Commander struct {
	sync.Mutex
	server   *grpc.Server
	services []Service
	ohm      outbound.Manager
	tag      string
	listen   string
}

// NewCommander creates a new Commander based on the given config.
func NewCommander(ctx context.Context, config *Config) (*Commander, error) {
	c := &Commander{
		tag:    config.Tag,
		listen: config.Listen,
	}

	common.Must(core.RequireFeatures(ctx, func(om outbound.Manager) {
		c.ohm = om
	}))

	for _, rawConfig := range config.Service {
		config, err := rawConfig.GetInstance()
		if err != nil {
			return nil, err
		}
		rawService, err := common.CreateObject(ctx, config)
		if err != nil {
			return nil, err
		}
		service, ok := rawService.(Service)
		if !ok {
			return nil, errors.New("not a Service.")
		}
		c.services = append(c.services, service)
	}

	return c, nil
}

// Type implements common.HasType.
func (c *Commander) Type() interface{} {
	return (*Commander)(nil)
}

// Start implements common.Runnable.
func (c *Commander) Start() error {
	c.Lock()
	c.server = grpc.NewServer()
	for _, service := range c.services {
		service.Register(c.server)
	}
	c.Unlock()

	var listen = func(listener net.Listener) {
		if err := c.server.Serve(listener); err != nil {
			errors.LogErrorInner(context.Background(), err, "failed to start grpc server")
		}
	}

	if len(c.listen) > 0 {
		if l, err := net.Listen("tcp", c.listen); err != nil {
			errors.LogErrorInner(context.Background(), err, "API server failed to listen on ", c.listen)
			return err
		} else {
			errors.LogInfo(context.Background(), "API server listening on ", l.Addr())
			go listen(l)
		}
		return nil
	}

	listener := &OutboundListener{
		buffer: make(chan net.Conn, 4),
		done:   done.New(),
	}

	go listen(listener)

	if err := c.ohm.RemoveHandler(context.Background(), c.tag); err != nil {
		errors.LogInfoInner(context.Background(), err, "failed to remove existing handler")
	}

	return c.ohm.AddHandler(context.Background(), &Outbound{
		tag:      c.tag,
		listener: listener,
	})
}

// Close implements common.Closable.
func (c *Commander) Close() error {
	c.Lock()
	defer c.Unlock()

	if c.server != nil {
		c.server.Stop()
		c.server = nil
	}

	return nil
}

func init() {
	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
		return NewCommander(ctx, cfg.(*Config))
	}))
}


================================================
FILE: app/commander/config.pb.go
================================================
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.36.11
// 	protoc        v6.33.5
// source: app/commander/config.proto

package commander

import (
	serial "github.com/xtls/xray-core/common/serial"
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
	unsafe "unsafe"
)

const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

// Config is the settings for Commander.
type Config struct {
	state protoimpl.MessageState `protogen:"open.v1"`
	// Tag of the outbound handler that handles grpc connections.
	Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
	// Network address of commander grpc service.
	Listen string `protobuf:"bytes,3,opt,name=listen,proto3" json:"listen,omitempty"`
	// Services that supported by this server. All services must implement Service
	// interface.
	Service       []*serial.TypedMessage `protobuf:"bytes,2,rep,name=service,proto3" json:"service,omitempty"`
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

func (x *Config) Reset() {
	*x = Config{}
	mi := &file_app_commander_config_proto_msgTypes[0]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *Config) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*Config) ProtoMessage() {}

func (x *Config) ProtoReflect() protoreflect.Message {
	mi := &file_app_commander_config_proto_msgTypes[0]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
	return file_app_commander_config_proto_rawDescGZIP(), []int{0}
}

func (x *Config) GetTag() string {
	if x != nil {
		return x.Tag
	}
	return ""
}

func (x *Config) GetListen() string {
	if x != nil {
		return x.Listen
	}
	return ""
}

func (x *Config) GetService() []*serial.TypedMessage {
	if x != nil {
		return x.Service
	}
	return nil
}

// ReflectionConfig is the placeholder config for ReflectionService.
type ReflectionConfig struct {
	state         protoimpl.MessageState `protogen:"open.v1"`
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

func (x *ReflectionConfig) Reset() {
	*x = ReflectionConfig{}
	mi := &file_app_commander_config_proto_msgTypes[1]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *ReflectionConfig) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*ReflectionConfig) ProtoMessage() {}

func (x *ReflectionConfig) ProtoReflect() protoreflect.Message {
	mi := &file_app_commander_config_proto_msgTypes[1]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use ReflectionConfig.ProtoReflect.Descriptor instead.
func (*ReflectionConfig) Descriptor() ([]byte, []int) {
	return file_app_commander_config_proto_rawDescGZIP(), []int{1}
}

var File_app_commander_config_proto protoreflect.FileDescriptor

const file_app_commander_config_proto_rawDesc = "" +
	"\n" +
	"\x1aapp/commander/config.proto\x12\x12xray.app.commander\x1a!common/serial/typed_message.proto\"n\n" +
	"\x06Config\x12\x10\n" +
	"\x03tag\x18\x01 \x01(\tR\x03tag\x12\x16\n" +
	"\x06listen\x18\x03 \x01(\tR\x06listen\x12:\n" +
	"\aservice\x18\x02 \x03(\v2 .xray.common.serial.TypedMessageR\aservice\"\x12\n" +
	"\x10ReflectionConfigBX\n" +
	"\x16com.xray.app.commanderP\x01Z'github.com/xtls/xray-core/app/commander\xaa\x02\x12Xray.App.Commanderb\x06proto3"

var (
	file_app_commander_config_proto_rawDescOnce sync.Once
	file_app_commander_config_proto_rawDescData []byte
)

func file_app_commander_config_proto_rawDescGZIP() []byte {
	file_app_commander_config_proto_rawDescOnce.Do(func() {
		file_app_commander_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_commander_config_proto_rawDesc), len(file_app_commander_config_proto_rawDesc)))
	})
	return file_app_commander_config_proto_rawDescData
}

var file_app_commander_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_app_commander_config_proto_goTypes = []any{
	(*Config)(nil),              // 0: xray.app.commander.Config
	(*ReflectionConfig)(nil),    // 1: xray.app.commander.ReflectionConfig
	(*serial.TypedMessage)(nil), // 2: xray.common.serial.TypedMessage
}
var file_app_commander_config_proto_depIdxs = []int32{
	2, // 0: xray.app.commander.Config.service:type_name -> xray.common.serial.TypedMessage
	1, // [1:1] is the sub-list for method output_type
	1, // [1:1] is the sub-list for method input_type
	1, // [1:1] is the sub-list for extension type_name
	1, // [1:1] is the sub-list for extension extendee
	0, // [0:1] is the sub-list for field type_name
}

func init() { file_app_commander_config_proto_init() }
func file_app_commander_config_proto_init() {
	if File_app_commander_config_proto != nil {
		return
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_commander_config_proto_rawDesc), len(file_app_commander_config_proto_rawDesc)),
			NumEnums:      0,
			NumMessages:   2,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_app_commander_config_proto_goTypes,
		DependencyIndexes: file_app_commander_config_proto_depIdxs,
		MessageInfos:      file_app_commander_config_proto_msgTypes,
	}.Build()
	File_app_commander_config_proto = out.File
	file_app_commander_config_proto_goTypes = nil
	file_app_commander_config_proto_depIdxs = nil
}


================================================
FILE: app/commander/config.proto
================================================
syntax = "proto3";

package xray.app.commander;
option csharp_namespace = "Xray.App.Commander";
option go_package = "github.com/xtls/xray-core/app/commander";
option java_package = "com.xray.app.commander";
option java_multiple_files = true;

import "common/serial/typed_message.proto";

// Config is the settings for Commander.
message Config {
  // Tag of the outbound handler that handles grpc connections.
  string tag = 1;

  // Network address of commander grpc service.
  string listen = 3;

  // Services that supported by this server. All services must implement Service
  // interface.
  repeated xray.common.serial.TypedMessage service = 2;
}

// ReflectionConfig is the placeholder config for ReflectionService.
message ReflectionConfig {}


================================================
FILE: app/commander/outbound.go
================================================
package commander

import (
	"context"
	"sync"

	"github.com/xtls/xray-core/common"
	"github.com/xtls/xray-core/common/errors"
	"github.com/xtls/xray-core/common/net"
	"github.com/xtls/xray-core/common/net/cnc"
	"github.com/xtls/xray-core/common/serial"
	"github.com/xtls/xray-core/common/signal/done"
	"github.com/xtls/xray-core/transport"
)

// OutboundListener is a net.Listener for listening gRPC connections.
type OutboundListener struct {
	buffer chan net.Conn
	done   *done.Instance
}

func (l *OutboundListener) add(conn net.Conn) {
	select {
	case l.buffer <- conn:
	case <-l.done.Wait():
		conn.Close()
	default:
		conn.Close()
	}
}

// Accept implements net.Listener.
func (l *OutboundListener) Accept() (net.Conn, error) {
	select {
	case <-l.done.Wait():
		return nil, errors.New("listen closed")
	case c := <-l.buffer:
		return c, nil
	}
}

// Close implements net.Listener.
func (l *OutboundListener) Close() error {
	common.Must(l.done.Close())
L:
	for {
		select {
		case c := <-l.buffer:
			c.Close()
		default:
			break L
		}
	}
	return nil
}

// Addr implements net.Listener.
func (l *OutboundListener) Addr() net.Addr {
	return &net.TCPAddr{
		IP:   net.IP{0, 0, 0, 0},
		Port: 0,
	}
}

// Outbound is a outbound.Handler that handles gRPC connections.
type Outbound struct {
	tag      string
	listener *OutboundListener
	access   sync.RWMutex
	closed   bool
}

// Dispatch implements outbound.Handler.
func (co *Outbound) Dispatch(ctx context.Context, link *transport.Link) {
	co.access.RLock()

	if co.closed {
		common.Interrupt(link.Reader)
		common.Interrupt(link.Writer)
		co.access.RUnlock()
		return
	}

	closeSignal := done.New()
	c := cnc.NewConnection(cnc.ConnectionInputMulti(link.Writer), cnc.ConnectionOutputMulti(link.Reader), cnc.ConnectionOnClose(closeSignal))
	co.listener.add(c)
	co.access.RUnlock()
	<-closeSignal.Wait()
}

// Tag implements outbound.Handler.
func (co *Outbound) Tag() string {
	return co.tag
}

// Start implements common.Runnable.
func (co *Outbound) Start() error {
	co.access.Lock()
	co.closed = false
	co.access.Unlock()
	return nil
}

// Close implements common.Closable.
func (co *Outbound) Close() error {
	co.access.Lock()
	defer co.access.Unlock()

	co.closed = true
	return co.listener.Close()
}

// SenderSettings implements outbound.Handler.
func (co *Outbound) SenderSettings() *serial.TypedMessage {
	return nil
}

// ProxySettings implements outbound.Handler.
func (co *Outbound) ProxySettings() *serial.TypedMessage {
	return nil
}


================================================
FILE: app/commander/service.go
================================================
package commander

import (
	"context"

	"github.com/xtls/xray-core/common"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

// Service is a Commander service.
type Service interface {
	// Register registers the service itself to a gRPC server.
	Register(*grpc.Server)
}

type reflectionService struct{}

func (r reflectionService) Register(s *grpc.Server) {
	reflection.Register(s)
}

func init() {
	common.Must(common.RegisterConfig((*ReflectionConfig)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
		return reflectionService{}, nil
	}))
}


================================================
FILE: app/dispatcher/config.pb.go
================================================
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.36.11
// 	protoc        v6.33.5
// source: app/dispatcher/config.proto

package dispatcher

import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
	unsafe "unsafe"
)

const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

type SessionConfig struct {
	state         protoimpl.MessageState `protogen:"open.v1"`
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

func (x *SessionConfig) Reset() {
	*x = SessionConfig{}
	mi := &file_app_dispatcher_config_proto_msgTypes[0]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *SessionConfig) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*SessionConfig) ProtoMessage() {}

func (x *SessionConfig) ProtoReflect() protoreflect.Message {
	mi := &file_app_dispatcher_config_proto_msgTypes[0]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use SessionConfig.ProtoReflect.Descriptor instead.
func (*SessionConfig) Descriptor() ([]byte, []int) {
	return file_app_dispatcher_config_proto_rawDescGZIP(), []int{0}
}

type Config struct {
	state         protoimpl.MessageState `protogen:"open.v1"`
	Settings      *SessionConfig         `protobuf:"bytes,1,opt,name=settings,proto3" json:"settings,omitempty"`
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

func (x *Config) Reset() {
	*x = Config{}
	mi := &file_app_dispatcher_config_proto_msgTypes[1]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *Config) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*Config) ProtoMessage() {}

func (x *Config) ProtoReflect() protoreflect.Message {
	mi := &file_app_dispatcher_config_proto_msgTypes[1]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
	return file_app_dispatcher_config_proto_rawDescGZIP(), []int{1}
}

func (x *Config) GetSettings() *SessionConfig {
	if x != nil {
		return x.Settings
	}
	return nil
}

var File_app_dispatcher_config_proto protoreflect.FileDescriptor

const file_app_dispatcher_config_proto_rawDesc = "" +
	"\n" +
	"\x1bapp/dispatcher/config.proto\x12\x13xray.app.dispatcher\"\x15\n" +
	"\rSessionConfigJ\x04\b\x01\x10\x02\"H\n" +
	"\x06Config\x12>\n" +
	"\bsettings\x18\x01 \x01(\v2\".xray.app.dispatcher.SessionConfigR\bsettingsB[\n" +
	"\x17com.xray.app.dispatcherP\x01Z(github.com/xtls/xray-core/app/dispatcher\xaa\x02\x13Xray.App.Dispatcherb\x06proto3"

var (
	file_app_dispatcher_config_proto_rawDescOnce sync.Once
	file_app_dispatcher_config_proto_rawDescData []byte
)

func file_app_dispatcher_config_proto_rawDescGZIP() []byte {
	file_app_dispatcher_config_proto_rawDescOnce.Do(func() {
		file_app_dispatcher_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_dispatcher_config_proto_rawDesc), len(file_app_dispatcher_config_proto_rawDesc)))
	})
	return file_app_dispatcher_config_proto_rawDescData
}

var file_app_dispatcher_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_app_dispatcher_config_proto_goTypes = []any{
	(*SessionConfig)(nil), // 0: xray.app.dispatcher.SessionConfig
	(*Config)(nil),        // 1: xray.app.dispatcher.Config
}
var file_app_dispatcher_config_proto_depIdxs = []int32{
	0, // 0: xray.app.dispatcher.Config.settings:type_name -> xray.app.dispatcher.SessionConfig
	1, // [1:1] is the sub-list for method output_type
	1, // [1:1] is the sub-list for method input_type
	1, // [1:1] is the sub-list for extension type_name
	1, // [1:1] is the sub-list for extension extendee
	0, // [0:1] is the sub-list for field type_name
}

func init() { file_app_dispatcher_config_proto_init() }
func file_app_dispatcher_config_proto_init() {
	if File_app_dispatcher_config_proto != nil {
		return
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_dispatcher_config_proto_rawDesc), len(file_app_dispatcher_config_proto_rawDesc)),
			NumEnums:      0,
			NumMessages:   2,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_app_dispatcher_config_proto_goTypes,
		DependencyIndexes: file_app_dispatcher_config_proto_depIdxs,
		MessageInfos:      file_app_dispatcher_config_proto_msgTypes,
	}.Build()
	File_app_dispatcher_config_proto = out.File
	file_app_dispatcher_config_proto_goTypes = nil
	file_app_dispatcher_config_proto_depIdxs = nil
}


================================================
FILE: app/dispatcher/config.proto
================================================
syntax = "proto3";

package xray.app.dispatcher;
option csharp_namespace = "Xray.App.Dispatcher";
option go_package = "github.com/xtls/xray-core/app/dispatcher";
option java_package = "com.xray.app.dispatcher";
option java_multiple_files = true;

message SessionConfig {
  reserved 1;
}

message Config {
  SessionConfig settings = 1;
}


================================================
FILE: app/dispatcher/default.go
================================================
package dispatcher

import (
	"context"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/xtls/xray-core/common"
	"github.com/xtls/xray-core/common/buf"
	"github.com/xtls/xray-core/common/errors"
	"github.com/xtls/xray-core/common/log"
	"github.com/xtls/xray-core/common/net"
	"github.com/xtls/xray-core/common/protocol"
	"github.com/xtls/xray-core/common/session"
	"github.com/xtls/xray-core/core"
	"github.com/xtls/xray-core/features/dns"
	"github.com/xtls/xray-core/features/outbound"
	"github.com/xtls/xray-core/features/policy"
	"github.com/xtls/xray-core/features/routing"
	routing_session "github.com/xtls/xray-core/features/routing/session"
	"github.com/xtls/xray-core/features/stats"
	"github.com/xtls/xray-core/transport"
	"github.com/xtls/xray-core/transport/pipe"
)

var errSniffingTimeout = errors.New("timeout on sniffing")

type cachedReader struct {
	sync.Mutex
	reader buf.TimeoutReader // *pipe.Reader or *buf.TimeoutWrapperReader
	cache  buf.MultiBuffer
}

func (r *cachedReader) Cache(b *buf.Buffer, deadline time.Duration) error {
	mb, err := r.reader.ReadMultiBufferTimeout(deadline)
	if err != nil {
		return err
	}
	r.Lock()
	if !mb.IsEmpty() {
		r.cache, _ = buf.MergeMulti(r.cache, mb)
	}
	b.Clear()
	rawBytes := b.Extend(min(r.cache.Len(), b.Cap()))
	n := r.cache.Copy(rawBytes)
	b.Resize(0, int32(n))
	r.Unlock()
	return nil
}

func (r *cachedReader) readInternal() buf.MultiBuffer {
	r.Lock()
	defer r.Unlock()

	if r.cache != nil && !r.cache.IsEmpty() {
		mb := r.cache
		r.cache = nil
		return mb
	}

	return nil
}

func (r *cachedReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
	mb := r.readInternal()
	if mb != nil {
		return mb, nil
	}

	return r.reader.ReadMultiBuffer()
}

func (r *cachedReader) ReadMultiBufferTimeout(timeout time.Duration) (buf.MultiBuffer, error) {
	mb := r.readInternal()
	if mb != nil {
		return mb, nil
	}

	return r.reader.ReadMultiBufferTimeout(timeout)
}

func (r *cachedReader) Interrupt() {
	r.Lock()
	if r.cache != nil {
		r.cache = buf.ReleaseMulti(r.cache)
	}
	r.Unlock()
	if p, ok := r.reader.(*pipe.Reader); ok {
		p.Interrupt()
	}
}

// DefaultDispatcher is a default implementation of Dispatcher.
type DefaultDispatcher struct {
	ohm    outbound.Manager
	router routing.Router
	policy policy.Manager
	stats  stats.Manager
	fdns   dns.FakeDNSEngine
}

func init() {
	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
		d := new(DefaultDispatcher)
		if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dc dns.Client) error {
			core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) {
				d.fdns = fdns
			})
			return d.Init(config.(*Config), om, router, pm, sm)
		}); err != nil {
			return nil, err
		}
		return d, nil
	}))
}

// Init initializes DefaultDispatcher.
func (d *DefaultDispatcher) Init(config *Config, om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager) error {
	d.ohm = om
	d.router = router
	d.policy = pm
	d.stats = sm
	return nil
}

// Type implements common.HasType.
func (*DefaultDispatcher) Type() interface{} {
	return routing.DispatcherType()
}

// Start implements common.Runnable.
func (*DefaultDispatcher) Start() error {
	return nil
}

// Close implements common.Closable.
func (*DefaultDispatcher) Close() error { return nil }

func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *transport.Link) {
	opt := pipe.OptionsFromContext(ctx)
	uplinkReader, uplinkWriter := pipe.New(opt...)
	downlinkReader, downlinkWriter := pipe.New(opt...)

	inboundLink := &transport.Link{
		Reader: downlinkReader,
		Writer: uplinkWriter,
	}

	outboundLink := &transport.Link{
		Reader: uplinkReader,
		Writer: downlinkWriter,
	}

	sessionInbound := session.InboundFromContext(ctx)
	var user *protocol.MemoryUser
	if sessionInbound != nil {
		user = sessionInbound.User
	}

	if user != nil && len(user.Email) > 0 {
		p := d.policy.ForLevel(user.Level)
		if p.Stats.UserUplink {
			name := "user>>>" + user.Email + ">>>traffic>>>uplink"
			if c, _ := stats.GetOrRegisterCounter(d.stats, name); c != nil {
				inboundLink.Writer = &SizeStatWriter{
					Counter: c,
					Writer:  inboundLink.Writer,
				}
			}
		}
		if p.Stats.UserDownlink {
			name := "user>>>" + user.Email + ">>>traffic>>>downlink"
			if c, _ := stats.GetOrRegisterCounter(d.stats, name); c != nil {
				outboundLink.Writer = &SizeStatWriter{
					Counter: c,
					Writer:  outboundLink.Writer,
				}
			}
		}

		if p.Stats.UserOnline {
			name := "user>>>" + user.Email + ">>>online"
			if om, _ := stats.GetOrRegisterOnlineMap(d.stats, name); om != nil {
				userIP := sessionInbound.Source.Address.String()
				om.AddIP(userIP)
				context.AfterFunc(ctx, func() { om.RemoveIP(userIP) })
			}
		}
	}

	return inboundLink, outboundLink
}

func WrapLink(ctx context.Context, policyManager policy.Manager, statsManager stats.Manager, link *transport.Link) *transport.Link {
	sessionInbound := session.InboundFromContext(ctx)
	var user *protocol.MemoryUser
	if sessionInbound != nil {
		user = sessionInbound.User
	}

	link.Reader = &buf.TimeoutWrapperReader{Reader: link.Reader}

	if user != nil && len(user.Email) > 0 {
		p := policyManager.ForLevel(user.Level)
		if p.Stats.UserUplink {
			name := "user>>>" + user.Email + ">>>traffic>>>uplink"
			if c, _ := stats.GetOrRegisterCounter(statsManager, name); c != nil {
				link.Reader.(*buf.TimeoutWrapperReader).Counter = c
			}
		}
		if p.Stats.UserDownlink {
			name := "user>>>" + user.Email + ">>>traffic>>>downlink"
			if c, _ := stats.GetOrRegisterCounter(statsManager, name); c != nil {
				link.Writer = &SizeStatWriter{
					Counter: c,
					Writer:  link.Writer,
				}
			}
		}
		if p.Stats.UserOnline {
			name := "user>>>" + user.Email + ">>>online"
			if om, _ := stats.GetOrRegisterOnlineMap(statsManager, name); om != nil {
				userIP := sessionInbound.Source.Address.String()
				om.AddIP(userIP)
				context.AfterFunc(ctx, func() { om.RemoveIP(userIP) })
			}
		}
	}

	return link
}

func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResult, request session.SniffingRequest, destination net.Destination) bool {
	domain := result.Domain()
	if domain == "" {
		return false
	}
	for _, d := range request.ExcludeForDomain {
		if strings.HasPrefix(d, "regexp:") {
			pattern := d[7:]
			re, err := regexp.Compile(pattern)
			if err != nil {
				errors.LogInfo(ctx, "Unable to compile regex")
				continue
			}
			if re.MatchString(domain) {
				return false
			}
		} else {
			if strings.ToLower(domain) == d {
				return false
			}
		}
	}
	protocolString := result.Protocol()
	if resComp, ok := result.(SnifferResultComposite); ok {
		protocolString = resComp.ProtocolForDomainResult()
	}
	for _, p := range request.OverrideDestinationForProtocol {
		if strings.HasPrefix(protocolString, p) || strings.HasPrefix(p, protocolString) {
			return true
		}
		if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && protocolString != "bittorrent" && p == "fakedns" &&
			fkr0.IsIPInIPPool(destination.Address) {
			errors.LogInfo(ctx, "Using sniffer ", protocolString, " since the fake DNS missed")
			return true
		}
		if resultSubset, ok := result.(SnifferIsProtoSubsetOf); ok {
			if resultSubset.IsProtoSubsetOf(p) {
				return true
			}
		}
	}

	return false
}

// Dispatch implements routing.Dispatcher.
func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destination) (*transport.Link, error) {
	if !destination.IsValid() {
		panic("Dispatcher: Invalid destination.")
	}
	outbounds := session.OutboundsFromContext(ctx)
	if len(outbounds) == 0 {
		outbounds = []*session.Outbound{{}}
		ctx = session.ContextWithOutbounds(ctx, outbounds)
	}
	ob := outbounds[len(outbounds)-1]
	ob.OriginalTarget = destination
	ob.Target = destination
	content := session.ContentFromContext(ctx)
	if content == nil {
		content = new(session.Content)
		ctx = session.ContextWithContent(ctx, content)
	}

	sniffingRequest := content.SniffingRequest
	inbound, outbound := d.getLink(ctx)
	if !sniffingRequest.Enabled {
		go d.routedDispatch(ctx, outbound, destination)
	} else {
		go func() {
			cReader := &cachedReader{
				reader: outbound.Reader.(*pipe.Reader),
			}
			outbound.Reader = cReader
			result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly, destination.Network)
			if err == nil {
				content.Protocol = result.Protocol()
			}
			if err == nil && d.shouldOverride(ctx, result, sniffingRequest, destination) {
				domain := result.Domain()
				errors.LogInfo(ctx, "sniffed domain: ", domain)
				destination.Address = net.ParseAddress(domain)
				protocol := result.Protocol()
				if resComp, ok := result.(SnifferResultComposite); ok {
					protocol = resComp.ProtocolForDomainResult()
				}
				isFakeIP := false
				if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && fkr0.IsIPInIPPool(ob.Target.Address) {
					isFakeIP = true
				}
				if sniffingRequest.RouteOnly && protocol != "fakedns" && protocol != "fakedns+others" && !isFakeIP {
					ob.RouteTarget = destination
				} else {
					ob.Target = destination
				}
			}
			d.routedDispatch(ctx, outbound, destination)
		}()
	}
	return inbound, nil
}

// DispatchLink implements routing.Dispatcher.
func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.Destination, outbound *transport.Link) error {
	if !destination.IsValid() {
		return errors.New("Dispatcher: Invalid destination.")
	}
	outbounds := session.OutboundsFromContext(ctx)
	if len(outbounds) == 0 {
		outbounds = []*session.Outbound{{}}
		ctx = session.ContextWithOutbounds(ctx, outbounds)
	}
	ob := outbounds[len(outbounds)-1]
	ob.OriginalTarget = destination
	ob.Target = destination
	content := session.ContentFromContext(ctx)
	if content == nil {
		content = new(session.Content)
		ctx = session.ContextWithContent(ctx, content)
	}
	outbound = WrapLink(ctx, d.policy, d.stats, outbound)
	sniffingRequest := content.SniffingRequest
	if !sniffingRequest.Enabled {
		d.routedDispatch(ctx, outbound, destination)
	} else {
		cReader := &cachedReader{
			reader: outbound.Reader.(buf.TimeoutReader),
		}
		outbound.Reader = cReader
		result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly, destination.Network)
		if err == nil {
			content.Protocol = result.Protocol()
		}
		if err == nil && d.shouldOverride(ctx, result, sniffingRequest, destination) {
			domain := result.Domain()
			errors.LogInfo(ctx, "sniffed domain: ", domain)
			destination.Address = net.ParseAddress(domain)
			protocol := result.Protocol()
			if resComp, ok := result.(SnifferResultComposite); ok {
				protocol = resComp.ProtocolForDomainResult()
			}
			isFakeIP := false
			if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && fkr0.IsIPInIPPool(ob.Target.Address) {
				isFakeIP = true
			}
			if sniffingRequest.RouteOnly && protocol != "fakedns" && protocol != "fakedns+others" && !isFakeIP {
				ob.RouteTarget = destination
			} else {
				ob.Target = destination
			}
		}
		d.routedDispatch(ctx, outbound, destination)
	}

	return nil
}

func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, network net.Network) (SniffResult, error) {
	payload := buf.NewWithSize(32767)
	defer payload.Release()

	sniffer := NewSniffer(ctx)

	metaresult, metadataErr := sniffer.SniffMetadata(ctx)

	if metadataOnly {
		return metaresult, metadataErr
	}

	contentResult, contentErr := func() (SniffResult, error) {
		cacheDeadline := 200 * time.Millisecond
		totalAttempt := 0
		for {
			select {
			case <-ctx.Done():
				return nil, ctx.Err()
			default:
				cachingStartingTimeStamp := time.Now()
				err := cReader.Cache(payload, cacheDeadline)
				if err != nil {
					return nil, err
				}
				cachingTimeElapsed := time.Since(cachingStartingTimeStamp)
				cacheDeadline -= cachingTimeElapsed

				if !payload.IsEmpty() {
					result, err := sniffer.Sniff(ctx, payload.Bytes(), network)
					switch err {
					case common.ErrNoClue: // No Clue: protocol not matches, and sniffer cannot determine whether there will be a match or not
						totalAttempt++
					case protocol.ErrProtoNeedMoreData: // Protocol Need More Data: protocol matches, but need more data to complete sniffing
						// in this case, do not add totalAttempt(allow to read until timeout)
					default:
						return result, err
					}
				} else {
					totalAttempt++
				}
				if totalAttempt >= 2 || cacheDeadline <= 0 {
					return nil, errSniffingTimeout
				}
			}
		}
	}()
	if contentErr != nil && metadataErr == nil {
		return metaresult, nil
	}
	if contentErr == nil && metadataErr == nil {
		return CompositeResult(metaresult, contentResult), nil
	}
	return contentResult, contentErr
}

func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
	outbounds := session.OutboundsFromContext(ctx)
	ob := outbounds[len(outbounds)-1]

	var handler outbound.Handler

	routingLink := routing_session.AsRoutingContext(ctx)
	inTag := routingLink.GetInboundTag()
	isPickRoute := 0
	if forcedOutboundTag := session.GetForcedOutboundTagFromContext(ctx); forcedOutboundTag != "" {
		ctx = session.SetForcedOutboundTagToContext(ctx, "")
		if h := d.ohm.GetHandler(forcedOutboundTag); h != nil {
			isPickRoute = 1
			errors.LogInfo(ctx, "taking platform initialized detour [", forcedOutboundTag, "] for [", destination, "]")
			handler = h
		} else {
			errors.LogError(ctx, "non existing tag for platform initialized detour: ", forcedOutboundTag)
			common.Close(link.Writer)
			common.Interrupt(link.Reader)
			return
		}
	} else if d.router != nil {
		if route, err := d.router.PickRoute(routingLink); err == nil {
			outTag := route.GetOutboundTag()
			if h := d.ohm.GetHandler(outTag); h != nil {
				isPickRoute = 2
				if route.GetRuleTag() == "" {
					errors.LogInfo(ctx, "taking detour [", outTag, "] for [", destination, "]")
				} else {
					errors.LogInfo(ctx, "Hit route rule: [", route.GetRuleTag(), "] so taking detour [", outTag, "] for [", destination, "]")
				}
				handler = h
			} else {
				errors.LogWarning(ctx, "non existing outTag: ", outTag)
				common.Close(link.Writer)
				common.Interrupt(link.Reader)
				return // DO NOT CHANGE: the traffic shouldn't be processed by default outbound if the specified outbound tag doesn't exist (yet), e.g., VLESS Reverse Proxy
			}
		} else {
			errors.LogInfo(ctx, "default route for ", destination)
		}
	}

	if handler == nil {
		handler = d.ohm.GetDefaultHandler()
	}

	if handler == nil {
		errors.LogInfo(ctx, "default outbound handler not exist")
		common.Close(link.Writer)
		common.Interrupt(link.Reader)
		return
	}

	ob.Tag = handler.Tag()
	if accessMessage := log.AccessMessageFromContext(ctx); accessMessage != nil {
		if tag := handler.Tag(); tag != "" {
			if inTag == "" {
				accessMessage.Detour = tag
			} else if isPickRoute == 1 {
				accessMessage.Detour = inTag + " ==> " + tag
			} else if isPickRoute == 2 {
				accessMessage.Detour = inTag + " -> " + tag
			} else {
				accessMessage.Detour = inTag + " >> " + tag
			}
		}
		log.Record(accessMessage)
	}

	handler.Dispatch(ctx, link)
}


================================================
FILE: app/dispatcher/dispatcher.go
================================================
package dispatcher


================================================
FILE: app/dispatcher/fakednssniffer.go
================================================
package dispatcher

import (
	"context"
	"strings"

	"github.com/xtls/xray-core/common"
	"github.com/xtls/xray-core/common/errors"
	"github.com/xtls/xray-core/common/net"
	"github.com/xtls/xray-core/common/session"
	"github.com/xtls/xray-core/core"
	"github.com/xtls/xray-core/features/dns"
)

// newFakeDNSSniffer Creates a Fake DNS metadata sniffer
func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error) {
	var fakeDNSEngine dns.FakeDNSEngine
	{
		fakeDNSEngineFeat := core.MustFromContext(ctx).GetFeature((*dns.FakeDNSEngine)(nil))
		if fakeDNSEngineFeat != nil {
			fakeDNSEngine = fakeDNSEngineFeat.(dns.FakeDNSEngine)
		}
	}

	if fakeDNSEngine == nil {
		errNotInit := errors.New("FakeDNSEngine is not initialized, but such a sniffer is used").AtError()
		return protocolSnifferWithMetadata{}, errNotInit
	}
	return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
		outbounds := session.OutboundsFromContext(ctx)
		ob := outbounds[len(outbounds)-1]
		if ob.Target.Network == net.Network_TCP || ob.Target.Network == net.Network_UDP {
			domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(ob.Target.Address)
			if domainFromFakeDNS != "" {
				errors.LogInfo(ctx, "fake dns got domain: ", domainFromFakeDNS, " for ip: ", ob.Target.Address.String())
				return &fakeDNSSniffResult{domainName: domainFromFakeDNS}, nil
			}
		}

		if ipAddressInRangeValueI := ctx.Value(ipAddressInRange); ipAddressInRangeValueI != nil {
			ipAddressInRangeValue := ipAddressInRangeValueI.(*ipAddressInRangeOpt)
			if fkr0, ok := fakeDNSEngine.(dns.FakeDNSEngineRev0); ok {
				inPool := fkr0.IsIPInIPPool(ob.Target.Address)
				ipAddressInRangeValue.addressInRange = &inPool
			}
		}

		return nil, common.ErrNoClue
	}, metadataSniffer: true}, nil
}

type fakeDNSSniffResult struct {
	domainName string
}

func (fakeDNSSniffResult) Protocol() string {
	return "fakedns"
}

func (f fakeDNSSniffResult) Domain() string {
	return f.domainName
}

type fakeDNSExtraOpts int

const ipAddressInRange fakeDNSExtraOpts = 1

type ipAddressInRangeOpt struct {
	addressInRange *bool
}

type DNSThenOthersSniffResult struct {
	domainName           string
	protocolOriginalName string
}

func (f DNSThenOthersSniffResult) IsProtoSubsetOf(protocolName string) bool {
	return strings.HasPrefix(protocolName, f.protocolOriginalName)
}

func (DNSThenOthersSniffResult) Protocol() string {
	return "fakedns+others"
}

func (f DNSThenOthersSniffResult) Domain() string {
	return f.domainName
}

func newFakeDNSThenOthers(ctx context.Context, fakeDNSSniffer protocolSnifferWithMetadata, others []protocolSnifferWithMetadata) (
	protocolSnifferWithMetadata, error,
) { // nolint: unparam
	// ctx may be used in the future
	_ = ctx
	return protocolSnifferWithMetadata{
		protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
			ipAddressInRangeValue := &ipAddressInRangeOpt{}
			ctx = context.WithValue(ctx, ipAddressInRange, ipAddressInRangeValue)
			result, err := fakeDNSSniffer.protocolSniffer(ctx, bytes)
			if err == nil {
				return result, nil
			}
			if ipAddressInRangeValue.addressInRange != nil {
				if *ipAddressInRangeValue.addressInRange {
					for _, v := range others {
						if v.metadataSniffer || bytes != nil {
							if result, err := v.protocolSniffer(ctx, bytes); err == nil {
								return DNSThenOthersSniffResult{domainName: result.Domain(), protocolOriginalName: result.Protocol()}, nil
							}
						}
					}
					return nil, common.ErrNoClue
				}
				errors.LogDebug(ctx, "ip address not in fake dns range, return as is")
				return nil, common.ErrNoClue
			}
			errors.LogWarning(ctx, "fake dns sniffer did not set address in range option, assume false.")
			return nil, common.ErrNoClue
		},
		metadataSniffer: false,
	}, nil
}


================================================
FILE: app/dispatcher/sniffer.go
================================================
package dispatcher

import (
	"context"

	"github.com/xtls/xray-core/common"
	"github.com/xtls/xray-core/common/errors"
	"github.com/xtls/xray-core/common/net"
	"github.com/xtls/xray-core/common/protocol"
	"github.com/xtls/xray-core/common/protocol/bittorrent"
	"github.com/xtls/xray-core/common/protocol/http"
	"github.com/xtls/xray-core/common/protocol/quic"
	"github.com/xtls/xray-core/common/protocol/tls"
)

type SniffResult interface {
	Protocol() string
	Domain() string
}

type protocolSniffer func(context.Context, []byte) (SniffResult, error)

type protocolSnifferWithMetadata struct {
	protocolSniffer protocolSniffer
	// A Metadata sniffer will be invoked on connection establishment only, with nil body,
	// for both TCP and UDP connections
	// It will not be shown as a traffic type for routing unless there is no other successful sniffing.
	metadataSniffer bool
	network         net.Network
}

type Sniffer struct {
	sniffer []protocolSnifferWithMetadata
}

func NewSniffer(ctx context.Context) *Sniffer {
	ret := &Sniffer{
		sniffer: []protocolSnifferWithMetadata{
			{func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b, c) }, false, net.Network_TCP},
			{func(c context.Context, b []byte) (SniffResult, error) { return tls.SniffTLS(b) }, false, net.Network_TCP},
			{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false, net.Network_TCP},
			{func(c context.Context, b []byte) (SniffResult, error) { return quic.SniffQUIC(b) }, false, net.Network_UDP},
			{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffUTP(b) }, false, net.Network_UDP},
		},
	}
	if sniffer, err := newFakeDNSSniffer(ctx); err == nil {
		others := ret.sniffer
		ret.sniffer = append(ret.sniffer, sniffer)
		fakeDNSThenOthers, err := newFakeDNSThenOthers(ctx, sniffer, others)
		if err == nil {
			ret.sniffer = append([]protocolSnifferWithMetadata{fakeDNSThenOthers}, ret.sniffer...)
		}
	}
	return ret
}

var errUnknownContent = errors.New("unknown content")

func (s *Sniffer) Sniff(c context.Context, payload []byte, network net.Network) (SniffResult, error) {
	var pendingSniffer []protocolSnifferWithMetadata
	for _, si := range s.sniffer {
		protocolSniffer := si.protocolSniffer
		if si.metadataSniffer || si.network != network {
			continue
		}
		result, err := protocolSniffer(c, payload)
		if err == common.ErrNoClue {
			pendingSniffer = append(pendingSniffer, si)
			continue
		} else if err == protocol.ErrProtoNeedMoreData { // Sniffer protocol matched, but need more data to complete sniffing
			s.sniffer = []protocolSnifferWithMetadata{si}
			return nil, err
		}

		if err == nil && result != nil {
			return result, nil
		}
	}

	if len(pendingSniffer) > 0 {
		s.sniffer = pendingSniffer
		return nil, common.ErrNoClue
	}

	return nil, errUnknownContent
}

func (s *Sniffer) SniffMetadata(c context.Context) (SniffResult, error) {
	var pendingSniffer []protocolSnifferWithMetadata
	for _, si := range s.sniffer {
		s := si.protocolSniffer
		if !si.metadataSniffer {
			pendingSniffer = append(pendingSniffer, si)
			continue
		}
		result, err := s(c, nil)
		if err == common.ErrNoClue {
			pendingSniffer = append(pendingSniffer, si)
			continue
		}

		if err == nil && result != nil {
			return result, nil
		}
	}

	if len(pendingSniffer) > 0 {
		s.sniffer = pendingSniffer
		return nil, common.ErrNoClue
	}

	return nil, errUnknownContent
}

func CompositeResult(domainResult SniffResult, protocolResult SniffResult) SniffResult {
	return &compositeResult{domainResult: domainResult, protocolResult: protocolResult}
}

type compositeResult struct {
	domainResult   SniffResult
	protocolResult SniffResult
}

func (c compositeResult) Protocol() string {
	return c.protocolResult.Protocol()
}

func (c compositeResult) Domain() string {
	return c.domainResult.Domain()
}

func (c compositeResult) ProtocolForDomainResult() string {
	return c.domainResult.Protocol()
}

type SnifferResultComposite interface {
	ProtocolForDomainResult() string
}

type SnifferIsProtoSubsetOf interface {
	IsProtoSubsetOf(protocolName string) bool
}


================================================
FILE: app/dispatcher/stats.go
================================================
package dispatcher

import (
	"github.com/xtls/xray-core/common"
	"github.com/xtls/xray-core/common/buf"
	"github.com/xtls/xray-core/features/stats"
)

type SizeStatWriter struct {
	Counter stats.Counter
	Writer  buf.Writer
}

func (w *SizeStatWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
	w.Counter.Add(int64(mb.Len()))
	return w.Writer.WriteMultiBuffer(mb)
}

func (w *SizeStatWriter) Close() error {
	return common.Close(w.Writer)
}

func (w *SizeStatWriter) Interrupt() {
	common.Interrupt(w.Writer)
}


================================================
FILE: app/dispatcher/stats_test.go
================================================
package dispatcher_test

import (
	"testing"

	. "github.com/xtls/xray-core/app/dispatcher"
	"github.com/xtls/xray-core/common"
	"github.com/xtls/xray-core/common/buf"
)

type TestCounter int64

func (c *TestCounter) Value() int64 {
	return int64(*c)
}

func (c *TestCounter) Add(v int64) int64 {
	x := int64(*c) + v
	*c = TestCounter(x)
	return x
}

func (c *TestCounter) Set(v int64) int64 {
	*c = TestCounter(v)
	return v
}

func TestStatsWriter(t *testing.T) {
	var c TestCounter
	writer := &SizeStatWriter{
		Counter: &c,
		Writer:  buf.Discard,
	}

	mb := buf.MergeBytes(nil, []byte("abcd"))
	common.Must(writer.WriteMultiBuffer(mb))

	mb = buf.MergeBytes(nil, []byte("efg"))
	common.Must(writer.WriteMultiBuffer(mb))

	if c.Value() != 7 {
		t.Fatal("unexpected counter value. want 7, but got ", c.Value())
	}
}


================================================
FILE: app/dns/cache_controller.go
================================================
package dns

import (
	"context"
	go_errors "errors"
	"runtime"
	"sync"
	"time"

	"github.com/xtls/xray-core/common"
	"github.com/xtls/xray-core/common/errors"
	"github.com/xtls/xray-core/common/signal/pubsub"
	"github.com/xtls/xray-core/common/task"
	dns_feature "github.com/xtls/xray-core/features/dns"

	"golang.org/x/net/dns/dnsmessage"
	"golang.org/x/sync/singleflight"
)

const (
	minSizeForEmptyRebuild  = 512
	shrinkAbsoluteThreshold = 10240
	shrinkRatioThreshold    = 0.65
	migrationBatchSize      = 4096
)

type CacheController struct {
	name            string
	disableCache    bool
	serveStale      bool
	serveExpiredTTL int32

	ips      map[string]*record
	dirtyips map[string]*record

	sync.RWMutex
	pub           *pubsub.Service
	cacheCleanup  *task.Periodic
	highWatermark int
	requestGroup  singleflight.Group
}

func NewCacheController(name string, disableCache bool, serveStale bool, serveExpiredTTL uint32) *CacheController {
	c := &CacheController{
		name:            name,
		disableCache:    disableCache,
		serveStale:      serveStale,
		serveExpiredTTL: -int32(serveExpiredTTL),
		ips:             make(map[string]*record),
		pub:             pubsub.NewService(),
	}

	c.cacheCleanup = &task.Periodic{
		Interval: 300 * time.Second,
		Execute:  c.CacheCleanup,
	}
	return c
}

// CacheCleanup clears expired items from cache
func (c *CacheController) CacheCleanup() error {
	expiredKeys, err := c.collectExpiredKeys()
	if err != nil {
		return err
	}
	if len(expiredKeys) == 0 {
		return nil
	}
	c.writeAndShrink(expiredKeys)
	return nil
}

func (c *CacheController) collectExpiredKeys() ([]string, error) {
	c.RLock()
	defer c.RUnlock()

	if len(c.ips) == 0 {
		return nil, errors.New("nothing to do. stopping...")
	}

	// skip collection if a migration is in progress
	if c.dirtyips != nil {
		return nil, nil
	}

	now := time.Now()
	if c.serveStale && c.serveExpiredTTL != 0 {
		now = now.Add(time.Duration(c.serveExpiredTTL) * time.Second)
	}

	expiredKeys := make([]string, 0, len(c.ips)/4) // pre-allocate

	for domain, rec := range c.ips {
		if (rec.A != nil && rec.A.Expire.Before(now)) ||
			(rec.AAAA != nil && rec.AAAA.Expire.Before(now)) {
			expiredKeys = append(expiredKeys, domain)
		}
	}

	return expiredKeys, nil
}

func (c *CacheController) writeAndShrink(expiredKeys []string) {
	c.Lock()
	defer c.Unlock()

	// double check to prevent upper call multiple cleanup tasks
	if c.dirtyips != nil {
		return
	}

	lenBefore := len(c.ips)
	if lenBefore > c.highWatermark {
		c.highWatermark = lenBefore
	}

	now := time.Now()
	if c.serveStale && c.serveExpiredTTL != 0 {
		now = now.Add(time.Duration(c.serveExpiredTTL) * time.Second)
	}

	for _, domain := range expiredKeys {
		rec := c.ips[domain]
		if rec == nil {
			continue
		}
		if rec.A != nil && rec.A.Expire.Before(now) {
			rec.A = nil
		}
		if rec.AAAA != nil && rec.AAAA.Expire.Before(now) {
			rec.AAAA = nil
		}
		if rec.A == nil && rec.AAAA == nil {
			delete(c.ips, domain)
		}
	}

	lenAfter := len(c.ips)

	if lenAfter == 0 {
		if c.highWatermark >= minSizeForEmptyRebuild {
			errors.LogDebug(context.Background(), c.name,
				" rebuilding empty cache map to reclaim memory.",
				" size_before_cleanup=", lenBefore,
				" peak_size_before_rebuild=", c.highWatermark,
			)

			c.ips = make(map[string]*record)
			c.highWatermark = 0
		}
		return
	}

	if reductionFromPeak := c.highWatermark - lenAfter; reductionFromPeak > shrinkAbsoluteThreshold &&
		float64(reductionFromPeak) > float64(c.highWatermark)*shrinkRatioThreshold {
		errors.LogDebug(context.Background(), c.name,
			" shrinking cache map to reclaim memory.",
			" new_size=", lenAfter,
			" peak_size_before_shrink=", c.highWatermark,
			" reduction_since_peak=", reductionFromPeak,
		)

		c.dirtyips = c.ips
		c.ips = make(map[string]*record, int(float64(lenAfter)*1.1))
		c.highWatermark = lenAfter
		go c.migrate()
	}

}

type migrationEntry struct {
	key   string
	value *record
}

func (c *CacheController) migrate() {
	defer func() {
		if r := recover(); r != nil {
			errors.LogError(context.Background(), c.name, " panic during cache migration: ", r)
			c.Lock()
			c.dirtyips = nil
			// c.ips = make(map[string]*record)
			// c.highWatermark = 0
			c.Unlock()
		}
	}()

	c.RLock()
	dirtyips := c.dirtyips
	c.RUnlock()

	// double check to prevent upper call multiple cleanup tasks
	if dirtyips == nil {
		return
	}

	errors.LogDebug(context.Background(), c.name, " starting background cache migration for ", len(dirtyips), " items")

	batch := make([]migrationEntry, 0, migrationBatchSize)
	for domain, recD := range dirtyips {
		batch = append(batch, migrationEntry{domain, recD})

		if len(batch) >= migrationBatchSize {
			c.flush(batch)
			batch = batch[:0]
			runtime.Gosched()
		}
	}
	if len(batch) > 0 {
		c.flush(batch)
	}

	c.Lock()
	c.dirtyips = nil
	c.Unlock()

	errors.LogDebug(context.Background(), c.name, " cache migration completed")
}

func (c *CacheController) flush(batch []migrationEntry) {
	c.Lock()
	defer c.Unlock()

	for _, dirty := range batch {
		if cur := c.ips[dirty.key]; cur != nil {
			merge := &record{}
			if cur.A == nil {
				merge.A = dirty.value.A
			} else {
				merge.A = cur.A
			}
			if cur.AAAA == nil {
				merge.AAAA = dirty.value.AAAA
			} else {
				merge.AAAA = cur.AAAA
			}
			c.ips[dirty.key] = merge
		} else {
			c.ips[dirty.key] = dirty.value
		}
	}
}

func (c *CacheController) updateRecord(req *dnsRequest, rep *IPRecord) {
	rtt := time.Since(req.start)

	switch req.reqType {
	case dnsmessage.TypeA:
		c.pub.Publish(req.domain+"4", rep)
	case dnsmessage.TypeAAAA:
		c.pub.Publish(req.domain+"6", rep)
	}

	if c.disableCache {
		errors.LogInfo(context.Background(), c.name, " got answer: ", req.domain, " ", req.reqType, " -> ", rep.IP, ", rtt: ", rtt)
		return
	}

	c.Lock()
	lockWait := time.Since(req.start) - rtt

	newRec := &record{}
	oldRec := c.ips[req.domain]
	var dirtyRec *record
	if c.dirtyips != nil {
		dirtyRec = c.dirtyips[req.domain]
	}

	var pubRecord *IPRecord
	var pubSuffix string

	switch req.reqType {
	case dnsmessage.TypeA:
		newRec.A = rep
		if oldRec != nil && oldRec.AAAA != nil {
			newRec.AAAA = oldRec.AAAA
			pubRecord = oldRec.AAAA
		} else if dirtyRec != nil && dirtyRec.AAAA != nil {
			pubRecord = dirtyRec.AAAA
		}
		pubSuffix = "6"
	case dnsmessage.TypeAAAA:
		newRec.AAAA = rep
		if oldRec != nil && oldRec.A != nil {
			newRec.A = oldRec.A
			pubRecord = oldRec.A
		} else if dirtyRec != nil && dirtyRec.A != nil {
			pubRecord = dirtyRec.A
		}
		pubSuffix = "4"
	}

	c.ips[req.domain] = newRec
	c.Unlock()

	if pubRecord != nil {
		_, ttl, err := pubRecord.getIPs()
		if ttl > 0 && !go_errors.Is(err, errRecordNotFound) {
			c.pub.Publish(req.domain+pubSuffix, pubRecord)
		}
	}

	errors.LogInfo(context.Background(), c.name, " got answer: ", req.domain, " ", req.reqType, " -> ", rep.IP, ", rtt: ", rtt, ", lock: ", lockWait)

	if !c.serveStale || c.serveExpiredTTL != 0 {
		common.Must(c.cacheCleanup.Start())
	}
}

func (c *CacheController) findRecords(domain string) *record {
	c.RLock()
	defer c.RUnlock()

	rec := c.ips[domain]
	if rec == nil && c.dirtyips != nil {
		rec = c.dirtyips[domain]
	}
	return rec
}

func (c *CacheController) registerSubscribers(domain string, option dns_feature.IPOption) (sub4 *pubsub.Subscriber, sub6 *pubsub.Subscriber) {
	// ipv4 and ipv6 belong to different subscription groups
	if option.IPv4Enable {
		sub4 = c.pub.Subscribe(domain + "4")
	}
	if option.IPv6Enable {
		sub6 = c.pub.Subscribe(domain + "6")
	}
	return
}

func closeSubscribers(sub4 *pubsub.Subscriber, sub6 *pubsub.Subscriber) {
	if sub4 != nil {
		sub4.Close()
	}
	if sub6 != nil {
		sub6.Close()
	}
}


================================================
FILE: app/dns/config.go
================================================
package dns

import (
	"github.com/xtls/xray-core/common/errors"
	"github.com/xtls/xray-core/common/net"
	"github.com/xtls/xray-core/common/strmatcher"
	"github.com/xtls/xray-core/common/uuid"
)

var typeMap = map[DomainMatchingType]strmatcher.Type{
	DomainMatchingType_Full:      strmatcher.Full,
	DomainMatchingType_Subdomain: strmatcher.Domain,
	DomainMatchingType_Keyword:   strmatcher.Substr,
	DomainMatchingType_Regex:     strmatcher.Regex,
}

// References:
// https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml
// https://unix.stackexchange.com/questions/92441/whats-the-difference-between-local-home-and-lan
var localTLDsAndDotlessDomains = []*NameServer_PriorityDomain{
	{Type: DomainMatchingType_Regex, Domain: "^[^.]+$"}, // This will only match domains without any dot
	{Type: DomainMatchingType_Subdomain, Domain: "local"},
	{Type: DomainMatchingType_Subdomain, Domain: "localdomain"},
	{Type: DomainMatchingType_Subdomain, Domain: "localhost"},
	{Type: DomainMatchingType_Subdomain, Domain: "lan"},
	{Type: DomainMatchingType_Subdomain, Domain: "home.arpa"},
	{Type: DomainMatchingType_Subdomain, Domain: "example"},
	{Type: DomainMatchingType_Subdomain, Domain: "invalid"},
	{Type: DomainMatchingType_Subdomain, Domain: "test"},
}

var localTLDsAndDotlessDomainsRule = &NameServer_OriginalRule{
	Rule: "geosite:private",
	Size: uint32(len(localTLDsAndDotlessDomains)),
}

func toStrMatcher(t DomainMatchingType, domain string) (strmatcher.Matcher, error) {
	strMType, f := typeMap[t]
	if !f {
		return nil, errors.New("unknown mapping type", t).AtWarning()
	}
	matcher, err := strMType.New(domain)
	if err != nil {
		return nil, errors.New("failed to create str matcher").Base(err)
	}
	return matcher, nil
}

func toNetIP(addrs []net.Address) ([]net.IP, error) {
	ips := make([]net.IP, 0, len(addrs))
	for _, addr := range addrs {
		if addr.Family().IsIP() {
			ips = append(ips, addr.IP())
		} else {
			return nil, errors.New("Failed to convert address", addr, "to Net IP.").AtWarning()
		}
	}
	return ips, nil
}

func generateRandomTag() string {
	id := uuid.New()
	return "xray.system." + id.String()
}


================================================
FILE: app/dns/config.pb.go
================================================
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.36.11
// 	protoc        v6.33.5
// source: app/dns/config.proto

package dns

import (
	router "github.com/xtls/xray-core/app/router"
	net "github.com/xtls/xray-core/common/net"
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
	unsafe "unsafe"
)

const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

type DomainMatchingType int32

const (
	DomainMatchingType_Full      DomainMatchingType = 0
	DomainMatchingType_Subdomain DomainMatchingType = 1
	DomainMatchingType_Keyword   DomainMatchingType = 2
	DomainMatchingType_Regex     DomainMatchingType = 3
)

// Enum value maps for DomainMatchingType.
var (
	DomainMatchingType_name = map[int32]string{
		0: "Full",
		1: "Subdomain",
		2: "Keyword",
		3: "Regex",
	}
	DomainMatchingType_value = map[string]int32{
		"Full":      0,
		"Subdomain": 1,
		"Keyword":   2,
		"Regex":     3,
	}
)

func (x DomainMatchingType) Enum() *DomainMatchingType {
	p := new(DomainMatchingType)
	*p = x
	return p
}

func (x DomainMatchingType) String() string {
	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}

func (DomainMatchingType) Descriptor() protoreflect.EnumDescriptor {
	return file_app_dns_config_proto_enumTypes[0].Descriptor()
}

func (DomainMatchingType) Type() protoreflect.EnumType {
	return &file_app_dns_config_proto_enumTypes[0]
}

func (x DomainMatchingType) Number() protoreflect.EnumNumber {
	return protoreflect.EnumNumber(x)
}

// Deprecated: Use DomainMatchingType.Descriptor instead.
func (DomainMatchingType) EnumDescriptor() ([]byte, []int) {
	return file_app_dns_config_proto_rawDescGZIP(), []int{0}
}

type QueryStrategy int32

const (
	QueryStrategy_USE_IP  QueryStrategy = 0
	QueryStrategy_USE_IP4 QueryStrategy = 1
	QueryStrategy_USE_IP6 QueryStrategy = 2
	QueryStrategy_USE_SYS QueryStrategy = 3
)

// Enum value maps for QueryStrategy.
var (
	QueryStrategy_name = map[int32]string{
		0: "USE_IP",
		1: "USE_IP4",
		2: "USE_IP6",
		3: "USE_SYS",
	}
	QueryStrategy_value = map[string]int32{
		"USE_IP":  0,
		"USE_IP4": 1,
		"USE_IP6": 2,
		"USE_SYS": 3,
	}
)

func (x QueryStrategy) Enum() *QueryStrategy {
	p := new(QueryStrategy)
	*p = x
	return p
}

func (x QueryStrategy) String() string {
	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}

func (QueryStrategy) Descriptor() protoreflect.EnumDescriptor {
	return file_app_dns_config_proto_enumTypes[1].Descriptor()
}

func (QueryStrategy) Type() protoreflect.EnumType {
	return &file_app_dns_config_proto_enumTypes[1]
}

func (x QueryStrategy) Number() protoreflect.EnumNumber {
	return protoreflect.EnumNumber(x)
}

// Deprecated: Use QueryStrategy.Descriptor instead.
func (QueryStrategy) EnumDescriptor() ([]byte, []int) {
	return file_app_dns_config_proto_rawDescGZIP(), []int{1}
}

type NameServer struct {
	state             protoimpl.MessageState       `protogen:"open.v1"`
	Address           *net.Endpoint                `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
	ClientIp          []byte                       `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"`
	SkipFallback      bool                         `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"`
	PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
	ExpectedGeoip     []*router.GeoIP              `protobuf:"bytes,3,rep,name=expected_geoip,json=expectedGeoip,proto3" json:"expected_geoip,omitempty"`
	OriginalRules     []*NameServer_OriginalRule   `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
	QueryStrategy     QueryStrategy                `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
	ActPrior          bool                         `protobuf:"varint,8,opt,name=actPrior,proto3" json:"actPrior,omitempty"`
	Tag               string                       `protobuf:"bytes,9,opt,name=tag,proto3" json:"tag,omitempty"`
	TimeoutMs         uint64                       `protobuf:"varint,10,opt,name=timeoutMs,proto3" json:"timeoutMs,omitempty"`
	DisableCache      *bool                        `protobuf:"varint,11,opt,name=disableCache,proto3,oneof" json:"disableCache,omitempty"`
	ServeStale        *bool                        `protobuf:"varint,15,opt,name=serveStale,proto3,oneof" json:"serveStale,omitempty"`
	ServeExpiredTTL   *uint32                      `protobuf:"varint,16,opt,name=serveExpiredTTL,proto3,oneof" json:"serveExpiredTTL,omitempty"`
	FinalQuery        bool                         `protobuf:"varint,12,opt,name=finalQuery,proto3" json:"finalQuery,omitempty"`
	UnexpectedGeoip   []*router.GeoIP              `protobuf:"bytes,13,rep,name=unexpected_geoip,json=unexpectedGeoip,proto3" json:"unexpected_geoip,omitempty"`
	ActUnprior        bool                         `protobuf:"varint,14,opt,name=actUnprior,proto3" json:"actUnprior,omitempty"`
	PolicyID          uint32                       `protobuf:"varint,17,opt,name=policyID,proto3" json:"policyID,omitempty"`
	unknownFields     protoimpl.UnknownFields
	sizeCache         protoimpl.SizeCache
}

func (x *NameServer) Reset() {
	*x = NameServer{}
	mi := &file_app_dns_config_proto_msgTypes[0]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *NameServer) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*NameServer) ProtoMessage() {}

func (x *NameServer) ProtoReflect() protoreflect.Message {
	mi := &file_app_dns_config_proto_msgTypes[0]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use NameServer.ProtoReflect.Descriptor instead.
func (*NameServer) Descriptor() ([]byte, []int) {
	return file_app_dns_config_proto_rawDescGZIP(), []int{0}
}

func (x *NameServer) GetAddress() *net.Endpoint {
	if x != nil {
		return x.Address
	}
	return nil
}

func (x *NameServer) GetClientIp() []byte {
	if x != nil {
		return x.ClientIp
	}
	return nil
}

func (x *NameServer) GetSkipFallback() bool {
	if x != nil {
		return x.SkipFallback
	}
	return false
}

func (x *NameServer) GetPrioritizedDomain() []*NameServer_PriorityDomain {
	if x != nil {
		return x.PrioritizedDomain
	}
	return nil
}

func (x *NameServer) GetExpectedGeoip() []*router.GeoIP {
	if x != nil {
		return x.ExpectedGeoip
	}
	return nil
}

func (x *NameServer) GetOriginalRules() []*NameServer_OriginalRule {
	if x != nil {
		return x.OriginalRules
	}
	return nil
}

func (x *NameServer) GetQueryStrategy() QueryStrategy {
	if x != nil {
		return x.QueryStrategy
	}
	return QueryStrategy_USE_IP
}

func (x *NameServer) GetActPrior() bool {
	if x != nil {
		return x.ActPrior
	}
	return false
}

func (x *NameServer) GetTag() string {
	if x != nil {
		return x.Tag
	}
	return ""
}

func (x *NameServer) GetTimeoutMs() uint64 {
	if x != nil {
		return x.TimeoutMs
	}
	return 0
}

func (x *NameServer) GetDisableCache() bool {
	if x != nil && x.DisableCache != nil {
		return *x.DisableCache
	}
	return false
}

func (x *NameServer) GetServeStale() bool {
	if x != nil && x.ServeStale != nil {
		return *x.ServeStale
	}
	return false
}

func (x *NameServer) GetServeExpiredTTL() uint32 {
	if x != nil && x.ServeExpiredTTL != nil {
		return *x.ServeExpiredTTL
	}
	return 0
}

func (x *NameServer) GetFinalQuery() bool {
	if x != nil {
		return x.FinalQuery
	}
	return false
}

func (x *NameServer) GetUnexpectedGeoip() []*router.GeoIP {
	if x != nil {
		return x.UnexpectedGeoip
	}
	return nil
}

func (x *NameServer) GetActUnprior() bool {
	if x != nil {
		return x.ActUnprior
	}
	return false
}

func (x *NameServer) GetPolicyID() uint32 {
	if x != nil {
		return x.PolicyID
	}
	return 0
}

type Config struct {
	state protoimpl.MessageState `protogen:"open.v1"`
	// NameServer list used by this DNS client.
	// A special value 'localhost' as a domain address can be set to use DNS on local system.
	NameServer []*NameServer `protobuf:"bytes,5,rep,name=name_server,json=nameServer,proto3" json:"name_server,omitempty"`
	// Client IP for EDNS client subnet. Must be 4 bytes (IPv4) or 16 bytes
	// (IPv6).
	ClientIp    []byte                `protobuf:"bytes,3,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"`
	StaticHosts []*Config_HostMapping `protobuf:"bytes,4,rep,name=static_hosts,json=staticHosts,proto3" json:"static_hosts,omitempty"`
	// Tag is the inbound tag of DNS client.
	Tag string `protobuf:"bytes,6,opt,name=tag,proto3" json:"tag,omitempty"`
	// DisableCache disables DNS cache
	DisableCache           bool          `protobuf:"varint,8,opt,name=disableCache,proto3" json:"disableCache,omitempty"`
	ServeStale             bool          `protobuf:"varint,12,opt,name=serveStale,proto3" json:"serveStale,omitempty"`
	ServeExpiredTTL        uint32        `protobuf:"varint,13,opt,name=serveExpiredTTL,proto3" json:"serveExpiredTTL,omitempty"`
	QueryStrategy          QueryStrategy `protobuf:"varint,9,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
	DisableFallback        bool          `protobuf:"varint,10,opt,name=disableFallback,proto3" json:"disableFallback,omitempty"`
	DisableFallbackIfMatch bool          `protobuf:"varint,11,opt,name=disableFallbackIfMatch,proto3" json:"disableFallbackIfMatch,omitempty"`
	EnableParallelQuery    bool          `protobuf:"varint,14,opt,name=enableParallelQuery,proto3" json:"enableParallelQuery,omitempty"`
	unknownFields          protoimpl.UnknownFields
	sizeCache              protoimpl.SizeCache
}

func (x *Config) Reset() {
	*x = Config{}
	mi := &file_app_dns_config_proto_msgTypes[1]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *Config) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*Config) ProtoMessage() {}

func (x *Config) ProtoReflect() protoreflect.Message {
	mi := &file_app_dns_config_proto_msgTypes[1]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
	return file_app_dns_config_proto_rawDescGZIP(), []int{1}
}

func (x *Config) GetNameServer() []*NameServer {
	if x != nil {
		return x.NameServer
	}
	return nil
}

func (x *Config) GetClientIp() []byte {
	if x != nil {
		return x.ClientIp
	}
	return nil
}

func (x *Config) GetStaticHosts() []*Config_HostMapping {
	if x != nil {
		return x.StaticHosts
	}
	return nil
}

func (x *Config) GetTag() string {
	if x != nil {
		return x.Tag
	}
	return ""
}

func (x *Config) GetDisableCache() bool {
	if x != nil {
		return x.DisableCache
	}
	return false
}

func (x *Config) GetServeStale() bool {
	if x != nil {
		return x.ServeStale
	}
	return false
}

func (x *Config) GetServeExpiredTTL() uint32 {
	if x != nil {
		return x.ServeExpiredTTL
	}
	return 0
}

func (x *Config) GetQueryStrategy() QueryStrategy {
	if x != nil {
		return x.QueryStrategy
	}
	return QueryStrategy_USE_IP
}

func (x *Config) GetDisableFallback() bool {
	if x != nil {
		return x.DisableFallback
	}
	return false
}

func (x *Config) GetDisableFallbackIfMatch() bool {
	if x != nil {
		return x.DisableFallbackIfMatch
	}
	return false
}

func (x *Config) GetEnableParallelQuery() bool {
	if x != nil {
		return x.EnableParallelQuery
	}
	return false
}

type NameServer_PriorityDomain struct {
	state         protoimpl.MessageState `protogen:"open.v1"`
	Type          DomainMatchingType     `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.dns.DomainMatchingType" json:"type,omitempty"`
	Domain        string                 `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

func (x *NameServer_PriorityDomain) Reset() {
	*x = NameServer_PriorityDomain{}
	mi := &file_app_dns_config_proto_msgTypes[2]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *NameServer_PriorityDomain) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*NameServer_PriorityDomain) ProtoMessage() {}

func (x *NameServer_PriorityDomain) ProtoReflect() protoreflect.Message {
	mi := &file_app_dns_config_proto_msgTypes[2]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use NameServer_PriorityDomain.ProtoReflect.Descriptor instead.
func (*NameServer_PriorityDomain) Descriptor() ([]byte, []int) {
	return file_app_dns_config_proto_rawDescGZIP(), []int{0, 0}
}

func (x *NameServer_PriorityDomain) GetType() DomainMatchingType {
	if x != nil {
		return x.Type
	}
	return DomainMatchingType_Full
}

func (x *NameServer_PriorityDomain) GetDomain() string {
	if x != nil {
		return x.Domain
	}
	return ""
}

type NameServer_OriginalRule struct {
	state         protoimpl.MessageState `protogen:"open.v1"`
	Rule          string                 `protobuf:"bytes,1,opt,name=rule,proto3" json:"rule,omitempty"`
	Size          uint32                 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"`
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

func (x *NameServer_OriginalRule) Reset() {
	*x = NameServer_OriginalRule{}
	mi := &file_app_dns_config_proto_msgTypes[3]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *NameServer_OriginalRule) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*NameServer_OriginalRule) ProtoMessage() {}

func (x *NameServer_OriginalRule) ProtoReflect() protoreflect.Message {
	mi := &file_app_dns_config_proto_msgTypes[3]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use NameServer_OriginalRule.ProtoReflect.Descriptor instead.
func (*NameServer_OriginalRule) Descriptor() ([]byte, []int) {
	return file_app_dns_config_proto_rawDescGZIP(), []int{0, 1}
}

func (x *NameServer_OriginalRule) GetRule() string {
	if x != nil {
		return x.Rule
	}
	return ""
}

func (x *NameServer_OriginalRule) GetSize() uint32 {
	if x != nil {
		return x.Size
	}
	return 0
}

type Config_HostMapping struct {
	state  protoimpl.MessageState `protogen:"open.v1"`
	Type   DomainMatchingType     `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.dns.DomainMatchingType" json:"type,omitempty"`
	Domain string                 `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
	Ip     [][]byte               `protobuf:"bytes,3,rep,name=ip,proto3" json:"ip,omitempty"`
	// ProxiedDomain indicates the mapped domain has the same IP address on this
	// domain. Xray will use this domain for IP queries.
	ProxiedDomain string `protobuf:"bytes,4,opt,name=proxied_domain,json=proxiedDomain,proto3" json:"proxied_domain,omitempty"`
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

func (x *Config_HostMapping) Reset() {
	*x = Config_HostMapping{}
	mi := &file_app_dns_config_proto_msgTypes[4]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
}

func (x *Config_HostMapping) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*Config_HostMapping) ProtoMessage() {}

func (x *Config_HostMapping) ProtoReflect() protoreflect.Message {
	mi := &file_app_dns_config_proto_msgTypes[4]
	if x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use Config_HostMapping.ProtoReflect.Descriptor instead.
func (*Config_HostMapping) Descriptor() ([]byte, []int) {
	return file_app_dns_config_proto_rawDescGZIP(), []int{1, 0}
}

func (x *Config_HostMapping) GetType() DomainMatchingType {
	if x != nil {
		return x.Type
	}
	return DomainMatchingType_Full
}

func (x *Config_HostMapping) GetDomain() string {
	if x != nil {
		return x.Domain
	}
	return ""
}

func (x *Config_HostMapping) GetIp() [][]byte {
	if x != nil {
		return x.Ip
	}
	return nil
}

func (x *Config_HostMapping) GetProxiedDomain() string {
	if x != nil {
		return x.ProxiedDomain
	}
	return ""
}

var File_app_dns_config_proto protoreflect.FileDescriptor

const file_app_dns_config_proto_rawDesc = "" +
	"\n" +
	"\x14app/dns/config.proto\x12\fxray.app.dns\x1a\x1ccommon/net/destination.proto\x1a\x17app/router/config.proto\"\xdf\a\n" +
	"\n" +
	"NameServer\x123\n" +
	"\aaddress\x18\x01 \x01(\v2\x19.xray.common.net.EndpointR\aaddress\x12\x1b\n" +
	"\tclient_ip\x18\x05 \x01(\fR\bclientIp\x12\"\n" +
	"\fskipFallback\x18\x06 \x01(\bR\fskipFallback\x12V\n" +
	"\x12prioritized_domain\x18\x02 \x03(\v2'.xray.app.dns.NameServer.PriorityDomainR\x11prioritizedDomain\x12=\n" +
	"\x0eexpected_geoip\x18\x03 \x03(\v2\x16.xray.app.router.GeoIPR\rexpectedGeoip\x12L\n" +
	"\x0eoriginal_rules\x18\x04 \x03(\v2%.xray.app.dns.NameServer.OriginalRuleR\roriginalRules\x12B\n" +
	"\x0equery_strategy\x18\a \x01(\x0e2\x1b.xray.app.dns.QueryStrategyR\rqueryStrategy\x12\x1a\n" +
	"\bactPrior\x18\b \x01(\bR\bactPrior\x12\x10\n" +
	"\x03tag\x18\t \x01(\tR\x03tag\x12\x1c\n" +
	"\ttimeoutMs\x18\n" +
	" \x01(\x04R\ttimeoutMs\x12'\n" +
	"\fdisableCache\x18\v \x01(\bH\x00R\fdisableCache\x88\x01\x01\x12#\n" +
	"\n" +
	"serveStale\x18\x0f \x01(\bH\x01R\n" +
	"serveStale\x88\x01\x01\x12-\n" +
	"\x0fserveExpiredTTL\x18\x10 \x01(\rH\x02R\x0fserveExpiredTTL\x88\x01\x01\x12\x1e\n" +
	"\n" +
	"finalQuery\x18\f \x01(\bR\n" +
	"finalQuery\x12A\n" +
	"\x10unexpected_geoip\x18\r \x03(\v2\x16.xray.app.router.GeoIPR\x0funexpectedGeoip\x12\x1e\n" +
	"\n" +
	"actUnprior\x18\x0e \x01(\bR\n" +
	"actUnprior\x12\x1a\n" +
	"\bpolicyID\x18\x11 \x01(\rR\bpolicyID\x1a^\n" +
	"\x0ePriorityDomain\x124\n" +
	"\x04type\x18\x01 \x01(\x0e2 .xray.app.dns.DomainMatchingTypeR\x04type\x12\x16\n" +
	"\x06domain\x18\x02 \x01(\tR\x06domain\x1a6\n" +
	"\fOriginalRule\x12\x12\n" +
	"\x04rule\x18\x01 \x01(\tR\x04rule\x12\x12\n" +
	"\x04size\x18\x02 \x01(\rR\x04sizeB\x0f\n" +
	"\r_disableCacheB\r\n" +
	"\v_serveStaleB\x12\n" +
	"\x10_serveExpiredTTL\"\x98\x05\n" +
	"\x06Config\x129\n" +
	"\vname_server\x18\x05 \x03(\v2\x18.xray.app.dns.NameServerR\n" +
	"nameServer\x12\x1b\n" +
	"\tclient_ip\x18\x03 \x01(\fR\bclientIp\x12C\n" +
	"\fstatic_hosts\x18\x04 \x03(\v2 .xray.app.dns.Config.HostMappingR\vstaticHosts\x12\x10\n" +
	"\x03tag\x18\x06 \x01(\tR\x03tag\x12\"\n" +
	"\fdisableCache\x18\b \x01(\bR\fdisableCache\x12\x1e\n" +
	"\n" +
	"serveStale\x18\f \x01(\bR\n" +
	"serveStale\x12(\n" +
	"\x0fserveExpiredTTL\x18\r \x01(\rR\x0fserveExpiredTTL\x12B\n" +
	"\x0equery_strategy\x18\t \x01(\x0e2\x1b.xray.app.dns.QueryStrategyR\rqueryStrategy\x12(\n" +
	"\x0fdisableFallback\x18\n" +
	" \x01(\bR\x0fdisableFallback\x126\n" +
	"\x16disableFallbackIfMatch\x18\v \x01(\bR\x16disableFallbackIfMatch\x120\n" +
	"\x13enableParallelQuery\x18\x0e \x01(\bR\x13enableParallelQuery\x1a\x92\x01\n" +
	"\vHostMapping\x124\n" +
	"\x04type\x18\x01 \x01(\x0e2 .xray.app.dns.DomainMatchingTypeR\x04type\x12\x16\n" +
	"\x06domain\x18\x02 \x01(\tR\x06domain\x12\x0e\n" +
	"\x02ip\x18\x03 \x03(\fR\x02ip\x12%\n" +
	"\x0eproxied_domain\x18\x04 \x01(\tR\rproxiedDomainJ\x04\b\a\x10\b*E\n" +
	"\x12DomainMatchingType\x12\b\n" +
	"\x04Full\x10\x00\x12\r\n" +
	"\tSubdomain\x10\x01\x12\v\n" +
	"\aKeyword\x10\x02\x12\t\n" +
	"\x05Regex\x10\x03*B\n" +
	"\rQueryStrategy\x12\n" +
	"\n" +
	"\x06USE_IP\x10\x00\x12\v\n" +
	"\aUSE_IP4\x10\x01\x12\v\n" +
	"\aUSE_IP6\x10\x02\x12\v\n" +
	"\aUSE_SYS\x10\x03BF\n" +
	"\x10com.xray.app.dnsP\x01Z!github.com/xtls/xray-core/app/dns\xaa\x02\fXray.App.Dnsb\x06proto3"

var (
	file_app_dns_config_proto_rawDescOnce sync.Once
	file_app_dns_config_proto_rawDescData []byte
)

func file_app_dns_config_proto_rawDescGZIP() []byte {
	file_app_dns_config_proto_rawDescOnce.Do(func() {
		file_app_dns_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_dns_config_proto_rawDesc), len(file_app_dns_config_proto_rawDesc)))
	})
	return file_app_dns_config_proto_rawDescData
}

var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_app_dns_config_proto_goTypes = []any{
	(DomainMatchingType)(0),           // 0: xray.app.dns.DomainMatchingType
	(QueryStrategy)(0),                // 1: xray.app.dns.QueryStrategy
	(*NameServer)(nil),                // 2: xray.app.dns.NameServer
	(*Config)(nil),                    // 3: xray.app.dns.Config
	(*NameServer_PriorityDomain)(nil), // 4: xray.app.dns.NameServer.PriorityDomain
	(*NameServer_OriginalRule)(nil),   // 5: xray.app.dns.NameServer.OriginalRule
	(*Config_HostMapping)(nil),        // 6: xray.app.dns.Config.HostMapping
	(*net.Endpoint)(nil),              // 7: xray.common.net.Endpoint
	(*router.GeoIP)(nil),              // 8: xray.app.router.GeoIP
}
var file_app_dns_config_proto_depIdxs = []int32{
	7,  // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint
	4,  // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.app.dns.NameServer.PriorityDomain
	8,  // 2: xray.app.dns.NameServer.expected_geoip:type_name -> xray.app.router.GeoIP
	5,  // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule
	1,  // 4: xray.app.dns.NameServer.query_strategy:type_name -> xray.app.dns.QueryStrategy
	8,  // 5: xray.app.dns.NameServer.unexpected_geoip:type_name -> xray.app.router.GeoIP
	2,  // 6: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
	6,  // 7: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
	1,  // 8: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
	0,  // 9: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
	0,  // 10: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
	11, // [11:11] is the sub-list for method output_type
	11, // [11:11] is the sub-list for method input_type
	11, // [11:11] is the sub-list for extension type_name
	11, // [11:11] is the sub-list for extension extendee
	0,  // [0:11] is the sub-list for field type_name
}

func init() { file_app_dns_config_proto_init() }
func file_app_dns_config_proto_init() {
	if File_app_dns_config_proto != nil {
		return
	}
	file_app_dns_config_proto_msgTypes[0].OneofWrappers = []any{}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_dns_config_proto_rawDesc), len(file_app_dns_config_proto_rawDesc)),
			NumEnums:      2,
			NumMessages:   5,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_app_dns_config_proto_goTypes,
		DependencyIndexes: file_app_dns_config_proto_depIdxs,
		EnumInfos:         file_app_dns_config_proto_enumTypes,
		MessageInfos:      file_app_dns_config_proto_msgTypes,
	}.Build()
	File_app_dns_config_proto = out.File
	file_app_dns_config_proto_goTypes = nil
	file_app_dns_config_proto_depIdxs = nil
}


================================================
FILE: app/dns/config.proto
================================================
syntax = "proto3";

package xray.app.dns;
option csharp_namespace = "Xray.App.Dns";
option go_package = "github.com/xtls/xray-core/app/dns";
option java_package = "com.xray.app.dns";
option java_multiple_files = true;

import "common/net/destination.proto";
import "app/router/config.proto";

message NameServer {
  xray.common.net.Endpoint address = 1;
  bytes client_ip = 5;
  bool skipFallback = 6;

  message PriorityDomain {
    DomainMatchingType type = 1;
    string domain = 2;
  }

  message OriginalRule {
    string rule = 1;
    uint32 size = 2;
  }

  repeated PriorityDomain prioritized_domain = 2;
  repeated xray.app.router.GeoIP expected_geoip = 3;
  repeated OriginalRule original_rules = 4;
  QueryStrategy query_strategy = 7;
  bool actPrior = 8;
  string tag = 9;
  uint64 timeoutMs = 10;
  optional bool disableCache = 11;
  optional bool serveStale = 15;
  optional uint32 serveExpiredTTL = 16;
  bool finalQuery = 12;
  repeated xray.app.router.GeoIP unexpected_geoip = 13;
  bool actUnprior = 14;
  uint32 policyID = 17;
}

enum DomainMatchingType {
  Full = 0;
  Subdomain = 1;
  Keyword = 2;
  Regex = 3;
}

enum QueryStrategy {
  USE_IP = 0;
  USE_IP4 = 1;
  USE_IP6 = 2;
  USE_SYS = 3;
}

message Config {
  // NameServer list used by this DNS client.
  // A special value 'localhost' as a domain address can be set to use DNS on local system.
  repeated NameServer name_server = 5;

  // Client IP for EDNS client subnet. Must be 4 bytes (IPv4) or 16 bytes
  // (IPv6).
  bytes client_ip = 3;

  message HostMapping {
    DomainMatchingType type = 1;
    string domain = 2;

    repeated bytes ip = 3;

    // ProxiedDomain indicates the mapped domain has the same IP address on this
    // domain. Xray will use this domain for IP queries.
    string proxied_domain = 4;
  }

  repeated HostMapping static_hosts = 4;

  // Tag is the inbound tag of DNS client.
  string tag = 6;

  reserved 7;

  // DisableCache disables DNS cache
  bool disableCache = 8;
  bool serveStale = 12;
  uint32 serveExpiredTTL = 13;

  QueryStrategy query_strategy = 9;

  bool disableFallback = 10;
  bool disableFallbackIfMatch = 11;

  bool enableParallelQuery = 14;
}


================================================
FILE: app/dns/dns.go
================================================
// Package dns is an implementation of core.DNS feature.
package dns

import (
	"context"
	go_errors "errors"
	"fmt"
	"os"
	"runtime"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/xtls/xray-core/app/router"
	"github.com/xtls/xray-core/common"
	"github.com/xtls/xray-core/common/errors"
	"github.com/xtls/xray-core/common/net"
	"github.com/xtls/xray-core/common/platform"
	"github.com/xtls/xray-core/common/session"
	"github.com/xtls/xray-core/common/strmatcher"
	"github.com/xtls/xray-core/features/dns"
)

// DNS is a DNS rely server.
type DNS struct {
	sync.Mutex
	disableFallback        bool
	disableFallbackIfMatch bool
	enableParallelQuery    bool
	ipOption               *dns.IPOption
	hosts                  *StaticHosts
	clients                []*Client
	ctx                    context.Context
	domainMatcher          strmatcher.IndexMatcher
	matcherInfos           []*DomainMatcherInfo
	checkSystem            bool
}

// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher
type DomainMatcherInfo struct {
	clientIdx     uint16
	domainRuleIdx uint16
}

// New creates a new DNS server with given configuration.
func New(ctx context.Context, config *Config) (*DNS, error) {
	var clientIP net.IP
	switch len(config.ClientIp) {
	case 0, net.IPv4len, net.IPv6len:
		clientIP = net.IP(config.ClientIp)
	default:
		return nil, errors.New("unexpected client IP length ", len(config.ClientIp))
	}

	var ipOption dns.IPOption
	checkSystem := false
	switch config.QueryStrategy {
	case QueryStrategy_USE_IP:
		ipOption = dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		}
	case QueryStrategy_USE_SYS:
		ipOption = dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		}
		checkSystem = true
	case QueryStrategy_USE_IP4:
		ipOption = dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: false,
			FakeEnable: false,
		}
	case QueryStrategy_USE_IP6:
		ipOption = dns.IPOption{
			IPv4Enable: false,
			IPv6Enable: true,
			FakeEnable: false,
		}
	default:
		return nil, errors.New("unexpected query strategy ", config.QueryStrategy)
	}

	var hosts *StaticHosts
	mphLoaded := false
	domainMatcherPath := platform.NewEnvFlag(platform.MphCachePath).GetValue(func() string { return "" })
	if domainMatcherPath != "" {
		if f, err := os.Open(domainMatcherPath); err == nil {
			defer f.Close()
			if m, err := router.LoadGeoSiteMatcher(f, "HOSTS"); err == nil {
				f.Seek(0, 0)
				if hostIPs, err := router.LoadGeoSiteHosts(f); err == nil {
					if sh, err := NewStaticHostsFromCache(m, hostIPs); err == nil {
						hosts = sh
						mphLoaded = true
						errors.LogDebug(ctx, "MphDomainMatcher loaded from cache for DNS hosts, size: ", sh.matchers.Size())
					}
				}
			}
		}
	}

	if !mphLoaded {
		sh, err := NewStaticHosts(config.StaticHosts)
		if err != nil {
			return nil, errors.New("failed to create hosts").Base(err)
		}
		hosts = sh
	}

	var clients []*Client
	domainRuleCount := 0

	var defaultTag = config.Tag
	if len(config.Tag) == 0 {
		defaultTag = generateRandomTag()
	}

	for _, ns := range config.NameServer {
		domainRuleCount += len(ns.PrioritizedDomain)
	}

	// MatcherInfos is ensured to cover the maximum index domainMatcher could return, where matcher's index starts from 1
	matcherInfos := make([]*DomainMatcherInfo, domainRuleCount+1)
	domainMatcher := &strmatcher.MatcherGroup{}

	for _, ns := range config.NameServer {
		clientIdx := len(clients)
		updateDomain := func(domainRule strmatcher.Matcher, originalRuleIdx int, matcherInfos []*DomainMatcherInfo) {
			midx := domainMatcher.Add(domainRule)
			matcherInfos[midx] = &DomainMatcherInfo{
				clientIdx:     uint16(clientIdx),
				domainRuleIdx: uint16(originalRuleIdx),
			}
		}

		myClientIP := clientIP
		switch len(ns.ClientIp) {
		case net.IPv4len, net.IPv6len:
			myClientIP = net.IP(ns.ClientIp)
		}

		disableCache := config.DisableCache
		if ns.DisableCache != nil {
			disableCache = *ns.DisableCache
		}

		serveStale := config.ServeStale
		if ns.ServeStale != nil {
			serveStale = *ns.ServeStale
		}

		serveExpiredTTL := config.ServeExpiredTTL
		if ns.ServeExpiredTTL != nil {
			serveExpiredTTL = *ns.ServeExpiredTTL
		}

		var tag = defaultTag
		if len(ns.Tag) > 0 {
			tag = ns.Tag
		}
		clientIPOption := ResolveIpOptionOverride(ns.QueryStrategy, ipOption)
		if !clientIPOption.IPv4Enable && !clientIPOption.IPv6Enable {
			return nil, errors.New("no QueryStrategy available for ", ns.Address)
		}

		client, err := NewClient(ctx, ns, myClientIP, disableCache, serveStale, serveExpiredTTL, tag, clientIPOption, &matcherInfos, updateDomain)
		if err != nil {
			return nil, errors.New("failed to create client").Base(err)
		}
		clients = append(clients, client)
	}

	// If there is no DNS client in config, add a `localhost` DNS client
	if len(clients) == 0 {
		clients = append(clients, NewLocalDNSClient(ipOption))
	}

	return &DNS{
		hosts:                  hosts,
		ipOption:               &ipOption,
		clients:                clients,
		ctx:                    ctx,
		domainMatcher:          domainMatcher,
		matcherInfos:           matcherInfos,
		disableFallback:        config.DisableFallback,
		disableFallbackIfMatch: config.DisableFallbackIfMatch,
		enableParallelQuery:    config.EnableParallelQuery,
		checkSystem:            checkSystem,
	}, nil
}

// Type implements common.HasType.
func (*DNS) Type() interface{} {
	return dns.ClientType()
}

// Start implements common.Runnable.
func (s *DNS) Start() error {
	return nil
}

// Close implements common.Closable.
func (s *DNS) Close() error {
	return nil
}

// IsOwnLink implements proxy.dns.ownLinkVerifier
func (s *DNS) IsOwnLink(ctx context.Context) bool {
	inbound := session.InboundFromContext(ctx)
	if inbound == nil {
		return false
	}
	for _, client := range s.clients {
		if client.tag == inbound.Tag {
			return true
		}
	}
	return false
}

// LookupIP implements dns.Client.
func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, uint32, error) {
	// Normalize the FQDN form query
	domain = strings.TrimSuffix(domain, ".")
	if domain == "" {
		return nil, 0, errors.New("empty domain name")
	}

	if s.checkSystem {
		supportIPv4, supportIPv6 := checkRoutes()
		option.IPv4Enable = option.IPv4Enable && supportIPv4
		option.IPv6Enable = option.IPv6Enable && supportIPv6
	} else {
		option.IPv4Enable = option.IPv4Enable && s.ipOption.IPv4Enable
		option.IPv6Enable = option.IPv6Enable && s.ipOption.IPv6Enable
	}

	if !option.IPv4Enable && !option.IPv6Enable {
		return nil, 0, dns.ErrEmptyResponse
	}

	// Static host lookup
	switch addrs, err := s.hosts.Lookup(domain, option); {
	case err != nil:
		if go_errors.Is(err, dns.ErrEmptyResponse) {
			return nil, 0, dns.ErrEmptyResponse
		}
		return nil, 0, errors.New("returning nil for domain ", domain).Base(err)
	case addrs == nil: // Domain not recorded in static host
		break
	case len(addrs) == 0: // Domain recorded, but no valid IP returned (e.g. IPv4 address with only IPv6 enabled)
		return nil, 0, dns.ErrEmptyResponse
	case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Domain replacement
		errors.LogInfo(s.ctx, "domain replaced: ", domain, " -> ", addrs[0].Domain())
		domain = addrs[0].Domain()
	default: // Successfully found ip records in static host
		errors.LogInfo(s.ctx, "returning ", len(addrs), " IP(s) for domain ", domain, " -> ", addrs)
		ips, err := toNetIP(addrs)
		if err != nil {
			return nil, 0, err
		}
		return ips, 10, nil // Hosts ttl is 10
	}

	// Name servers lookup
	if s.enableParallelQuery {
		return s.parallelQuery(domain, option)
	} else {
		return s.serialQuery(domain, option)
	}
}

func (s *DNS) sortClients(domain string) []*Client {
	clients := make([]*Client, 0, len(s.clients))
	clientUsed := make([]bool, len(s.clients))
	clientNames := make([]string, 0, len(s.clients))
	domainRules := []string{}

	// Priority domain matching
	hasMatch := false
	MatchSlice := s.domainMatcher.Match(domain)
	sort.Slice(MatchSlice, func(i, j int) bool {
		return MatchSlice[i] < MatchSlice[j]
	})
	for _, match := range MatchSlice {
		info := s.matcherInfos[match]
		client := s.clients[info.clientIdx]
		domainRule := client.domains[info.domainRuleIdx]
		domainRules = append(domainRules, fmt.Sprintf("%s(DNS idx:%d)", domainRule, info.clientIdx))
		if clientUsed[info.clientIdx] {
			continue
		}
		clientUsed[info.clientIdx] = true
		clients = append(clients, client)
		clientNames = append(clientNames, client.Name())
		hasMatch = true
		if client.finalQuery {
			return clients
		}
	}

	if !(s.disableFallback || s.disableFallbackIfMatch && hasMatch) {
		// Default round-robin query
		for idx, client := range s.clients {
			if clientUsed[idx] || client.skipFallback {
				continue
			}
			clientUsed[idx] = true
			clients = append(clients, client)
			clientNames = append(clientNames, client.Name())
			if client.finalQuery {
				return clients
			}
		}
	}

	if len(domainRules) > 0 {
		errors.LogDebug(s.ctx, "domain ", domain, " matches following rules: ", domainRules)
	}
	if len(clientNames) > 0 {
		errors.LogDebug(s.ctx, "domain ", domain, " will use DNS in order: ", clientNames)
	}

	if len(clients) == 0 {
		if len(s.clients) > 0 {
			clients = append(clients, s.clients[0])
			clientNames = append(clientNames, s.clients[0].Name())
			errors.LogWarning(s.ctx, "domain ", domain, " will use the first DNS: ", clientNames)
		} else {
			errors.LogError(s.ctx, "no DNS clients available for domain ", domain, " and no default clients configured")
		}
	}

	return clients
}

func mergeQueryErrors(domain string, errs []error) error {
	if len(errs) == 0 {
		return dns.ErrEmptyResponse
	}

	var noRNF error
	for _, err := range errs {
		if go_errors.Is(err, errRecordNotFound) {
			continue // server no response, ignore
		} else if noRNF == nil {
			noRNF = err
		} else if !go_errors.Is(err, noRNF) {
			return errors.New("returning nil for domain ", domain).Base(errors.Combine(errs...))
		}
	}
	if go_errors.Is(noRNF, dns.ErrEmptyResponse) {
		return dns.ErrEmptyResponse
	}
	if noRNF == nil {
		noRNF = errRecordNotFound
	}
	return errors.New("returning nil for domain ", domain).Base(noRNF)
}

func (s *DNS) serialQuery(domain string, option dns.IPOption) ([]net.IP, uint32, error) {
	var errs []error
	for _, client := range s.sortClients(domain) {
		if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
			errors.LogDebug(s.ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name())
			continue
		}

		ips, ttl, err := client.QueryIP(s.ctx, domain, option)

		if len(ips) > 0 {
			return ips, ttl, nil
		}

		errors.LogInfoInner(s.ctx, err, "failed to lookup ip for domain ", domain, " at server ", client.Name(), " in serial query mode")
		if err == nil {
			err = dns.ErrEmptyResponse
		}
		errs = append(errs, err)
	}
	return nil, 0, mergeQueryErrors(domain, errs)
}

func (s *DNS) parallelQuery(domain string, option dns.IPOption) ([]net.IP, uint32, error) {
	var errs []error
	clients := s.sortClients(domain)

	resultsChan := asyncQueryAll(domain, option, clients, s.ctx)

	groups, groupOf := makeGroups( /*s.ctx,*/ clients)
	results := make([]*queryResult, len(clients))
	pending := make([]int, len(groups))
	for gi, g := range groups {
		pending[gi] = g.end - g.start + 1
	}

	nextGroup := 0
	for range clients {
		result := <-resultsChan
		results[result.index] = &result

		gi := groupOf[result.index]
		pending[gi]--

		for nextGroup < len(groups) {
			g := groups[nextGroup]

			// group race, minimum rtt -> return
			for j := g.start; j <= g.end; j++ {
				r := results[j]
				if r != nil && r.err == nil && len(r.ips) > 0 {
					return r.ips, r.ttl, nil
				}
			}

			// current group is incomplete and no one success -> continue pending
			if pending[nextGroup] > 0 {
				break
			}

			// all failed -> log and continue next group
			for j := g.start; j <= g.end; j++ {
				r := results[j]
				e := r.err
				if e == nil {
					e = dns.ErrEmptyResponse
				}
				errors.LogInfoInner(s.ctx, e, "failed to lookup ip for domain ", domain, " at server ", clients[j].Name(), " in parallel query mode")
				errs = append(errs, e)
			}
			nextGroup++
		}
	}

	return nil, 0, mergeQueryErrors(domain, errs)
}

type queryResult struct {
	ips   []net.IP
	ttl   uint32
	err   error
	index int
}

func asyncQueryAll(domain string, option dns.IPOption, clients []*Client, ctx context.Context) chan queryResult {
	if len(clients) == 0 {
		ch := make(chan queryResult)
		close(ch)
		return ch
	}

	ch := make(chan queryResult, len(clients))
	for i, client := range clients {
		if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
			errors.LogDebug(ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name())
			ch <- queryResult{err: dns.ErrEmptyResponse, index: i}
			continue
		}

		go func(i int, c *Client) {
			qctx := ctx
			if !c.server.IsDisableCache() {
				nctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), c.timeoutMs*2)
				qctx = nctx
				defer cancel()
			}
			ips, ttl, err := c.QueryIP(qctx, domain, option)
			ch <- queryResult{ips: ips, ttl: ttl, err: err, index: i}
		}(i, client)
	}
	return ch
}

type group struct{ start, end int }

// merge only adjacent and rule-equivalent Client into a single group
func makeGroups( /*ctx context.Context,*/ clients []*Client) ([]group, []int) {
	n := len(clients)
	if n == 0 {
		return nil, nil
	}
	groups := make([]group, 0, n)
	groupOf := make([]int, n)

	s, e := 0, 0
	for i := 1; i < n; i++ {
		if clients[i-1].policyID == clients[i].policyID {
			e = i
		} else {
			for k := s; k <= e; k++ {
				groupOf[k] = len(groups)
			}
			groups = append(groups, group{start: s, end: e})
			s, e = i, i
		}
	}
	for k := s; k <= e; k++ {
		groupOf[k] = len(groups)
	}
	groups = append(groups, group{start: s, end: e})

	// var b strings.Builder
	// b.WriteString("dns grouping: total clients=")
	// b.WriteString(strconv.Itoa(n))
	// b.WriteString(", groups=")
	// b.WriteString(strconv.Itoa(len(groups)))

	// for gi, g := range groups {
	// 	b.WriteString("\n  [")
	// 	b.WriteString(strconv.Itoa(g.start))
	// 	b.WriteString("..")
	// 	b.WriteString(strconv.Itoa(g.end))
	// 	b.WriteString("] gid=")
	// 	b.WriteString(strconv.Itoa(gi))
	// 	b.WriteString(" pid=")
	// 	b.WriteString(strconv.FormatUint(uint64(clients[g.start].policyID), 10))
	// 	b.WriteString(" members: ")

	// 	for i := g.start; i <= g.end; i++ {
	// 		if i > g.start {
	// 			b.WriteString(", ")
	// 		}
	// 		b.WriteString(strconv.Itoa(i))
	// 		b.WriteByte(':')
	// 		b.WriteString(clients[i].Name())
	// 	}
	// }
	// errors.LogDebug(ctx, b.String())

	return groups, groupOf
}

func init() {
	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
		return New(ctx, config.(*Config))
	}))
}

func probeRoutes() (ipv4 bool, ipv6 bool) {
	if conn, err := net.Dial("udp4", "192.33.4.12:53"); err == nil {
		ipv4 = true
		conn.Close()
	}
	if conn, err := net.Dial("udp6", "[2001:500:2::c]:53"); err == nil {
		ipv6 = true
		conn.Close()
	}
	return
}

var routeCache struct {
	sync.Once
	sync.RWMutex
	expire     time.Time
	ipv4, ipv6 bool
}

func checkRoutes() (bool, bool) {
	if !isGUIPlatform {
		routeCache.Once.Do(func() {
			routeCache.ipv4, routeCache.ipv6 = probeRoutes()
		})
		return routeCache.ipv4, routeCache.ipv6
	}

	routeCache.RWMutex.RLock()
	now := time.Now()
	if routeCache.expire.After(now) {
		routeCache.RWMutex.RUnlock()
		return routeCache.ipv4, routeCache.ipv6
	}
	routeCache.RWMutex.RUnlock()

	routeCache.RWMutex.Lock()
	defer routeCache.RWMutex.Unlock()

	now = time.Now()
	if routeCache.expire.After(now) { // double-check
		return routeCache.ipv4, routeCache.ipv6
	}
	routeCache.ipv4, routeCache.ipv6 = probeRoutes()    // ~2ms
	routeCache.expire = now.Add(100 * time.Millisecond) // ttl
	return routeCache.ipv4, routeCache.ipv6
}

var isGUIPlatform = detectGUIPlatform()

func detectGUIPlatform() bool {
	switch runtime.GOOS {
	case "android", "ios", "windows", "darwin":
		return true
	case "linux", "freebsd", "openbsd":
		if t := os.Getenv("XDG_SESSION_TYPE"); t == "wayland" || t == "x11" {
			return true
		}
		if os.Getenv("DISPLAY") != "" || os.Getenv("WAYLAND_DISPLAY") != "" {
			return true
		}
	}
	return false
}


================================================
FILE: app/dns/dns_test.go
================================================
package dns_test

import (
	"testing"
	"time"

	"github.com/google/go-cmp/cmp"
	"github.com/miekg/dns"
	"github.com/xtls/xray-core/app/dispatcher"
	. "github.com/xtls/xray-core/app/dns"
	"github.com/xtls/xray-core/app/policy"
	"github.com/xtls/xray-core/app/proxyman"
	_ "github.com/xtls/xray-core/app/proxyman/outbound"
	"github.com/xtls/xray-core/app/router"
	"github.com/xtls/xray-core/common"
	"github.com/xtls/xray-core/common/errors"
	"github.com/xtls/xray-core/common/net"
	"github.com/xtls/xray-core/common/serial"
	"github.com/xtls/xray-core/core"
	feature_dns "github.com/xtls/xray-core/features/dns"
	"github.com/xtls/xray-core/proxy/freedom"
	"github.com/xtls/xray-core/testing/servers/udp"
)

type staticHandler struct{}

func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
	ans := new(dns.Msg)
	ans.Id = r.Id

	var clientIP net.IP

	opt := r.IsEdns0()
	if opt != nil {
		for _, o := range opt.Option {
			if o.Option() == dns.EDNS0SUBNET {
				subnet := o.(*dns.EDNS0_SUBNET)
				clientIP = subnet.Address
			}
		}
	}

	for _, q := range r.Question {
		switch {
		case q.Name == "google.com." && q.Qtype == dns.TypeA:
			if clientIP == nil {
				rr, _ := dns.NewRR("google.com. IN A 8.8.8.8")
				ans.Answer = append(ans.Answer, rr)
			} else {
				rr, _ := dns.NewRR("google.com. IN A 8.8.4.4")
				ans.Answer = append(ans.Answer, rr)
			}

		case q.Name == "api.google.com." && q.Qtype == dns.TypeA:
			rr, _ := dns.NewRR("api.google.com. IN A 8.8.7.7")
			ans.Answer = append(ans.Answer, rr)

		case q.Name == "v2.api.google.com." && q.Qtype == dns.TypeA:
			rr, _ := dns.NewRR("v2.api.google.com. IN A 8.8.7.8")
			ans.Answer = append(ans.Answer, rr)

		case q.Name == "facebook.com." && q.Qtype == dns.TypeA:
			rr, _ := dns.NewRR("facebook.com. IN A 9.9.9.9")
			ans.Answer = append(ans.Answer, rr)

		case q.Name == "ipv6.google.com." && q.Qtype == dns.TypeA:
			rr, err := dns.NewRR("ipv6.google.com. IN A 8.8.8.7")
			common.Must(err)
			ans.Answer = append(ans.Answer, rr)

		case q.Name == "ipv6.google.com." && q.Qtype == dns.TypeAAAA:
			rr, err := dns.NewRR("ipv6.google.com. IN AAAA 2001:4860:4860::8888")
			common.Must(err)
			ans.Answer = append(ans.Answer, rr)

		case q.Name == "notexist.google.com." && q.Qtype == dns.TypeAAAA:
			ans.MsgHdr.Rcode = dns.RcodeNameError

		case q.Name == "notexist.google.com." && q.Qtype == dns.TypeA:
			ans.MsgHdr.Rcode = dns.RcodeNameError

		case q.Name == "hostname." && q.Qtype == dns.TypeA:
			rr, _ := dns.NewRR("hostname. IN A 127.0.0.1")
			ans.Answer = append(ans.Answer, rr)

		case q.Name == "hostname.local." && q.Qtype == dns.TypeA:
			rr, _ := dns.NewRR("hostname.local. IN A 127.0.0.1")
			ans.Answer = append(ans.Answer, rr)

		case q.Name == "hostname.localdomain." && q.Qtype == dns.TypeA:
			rr, _ := dns.NewRR("hostname.localdomain. IN A 127.0.0.1")
			ans.Answer = append(ans.Answer, rr)

		case q.Name == "localhost." && q.Qtype == dns.TypeA:
			rr, _ := dns.NewRR("localhost. IN A 127.0.0.2")
			ans.Answer = append(ans.Answer, rr)

		case q.Name == "localhost-a." && q.Qtype == dns.TypeA:
			rr, _ := dns.NewRR("localhost-a. IN A 127.0.0.3")
			ans.Answer = append(ans.Answer, rr)

		case q.Name == "localhost-b." && q.Qtype == dns.TypeA:
			rr, _ := dns.NewRR("localhost-b. IN A 127.0.0.4")
			ans.Answer = append(ans.Answer, rr)

		case q.Name == "Mijia\\ Cloud." && q.Qtype == dns.TypeA:
			rr, _ := dns.NewRR("Mijia\\ Cloud. IN A 127.0.0.1")
			ans.Answer = append(ans.Answer, rr)
		}
	}
	w.WriteMsg(ans)
}

func TestUDPServerSubnet(t *testing.T) {
	port := udp.PickPort()

	dnsServer := dns.Server{
		Addr:    "127.0.0.1:" + port.String(),
		Net:     "udp",
		Handler: &staticHandler{},
		UDPSize: 1200,
	}
	go dnsServer.ListenAndServe()
	time.Sleep(time.Second)

	config := &core.Config{
		App: []*serial.TypedMessage{
			serial.ToTypedMessage(&Config{
				NameServer: []*NameServer{
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
					},
				},
				ClientIp: []byte{7, 8, 9, 10},
			}),
			serial.ToTypedMessage(&dispatcher.Config{}),
			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
			serial.ToTypedMessage(&policy.Config{}),
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
			},
		},
	}

	v, err := core.New(config)
	common.Must(err)

	client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)

	ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
		IPv4Enable: true,
		IPv6Enable: true,
		FakeEnable: false,
	})
	if err != nil {
		t.Fatal("unexpected error: ", err)
	}

	if r := cmp.Diff(ips, []net.IP{{8, 8, 4, 4}}); r != "" {
		t.Fatal(r)
	}
}

func TestUDPServer(t *testing.T) {
	port := udp.PickPort()

	dnsServer := dns.Server{
		Addr:    "127.0.0.1:" + port.String(),
		Net:     "udp",
		Handler: &staticHandler{},
		UDPSize: 1200,
	}

	go dnsServer.ListenAndServe()
	time.Sleep(time.Second)

	config := &core.Config{
		App: []*serial.TypedMessage{
			serial.ToTypedMessage(&Config{
				NameServer: []*NameServer{
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
					},
				},
			}),
			serial.ToTypedMessage(&dispatcher.Config{}),
			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
			serial.ToTypedMessage(&policy.Config{}),
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
			},
		},
	}

	v, err := core.New(config)
	common.Must(err)

	client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)

	{
		ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
			t.Fatal(r)
		}
	}

	{
		ips, _, err := client.LookupIP("facebook.com", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{9, 9, 9, 9}}); r != "" {
			t.Fatal(r)
		}
	}

	{
		_, _, err := client.LookupIP("notexist.google.com", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err == nil {
			t.Fatal("nil error")
		}
		if r := feature_dns.RCodeFromError(err); r != uint16(dns.RcodeNameError) {
			t.Fatal("expected NameError, but got ", r)
		}
	}

	{
		ips, _, err := client.LookupIP("ipv4only.google.com", feature_dns.IPOption{
			IPv4Enable: false,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if !errors.AllEqual(feature_dns.ErrEmptyResponse, errors.Cause(err)) {
			t.Fatal("error: ", err)
		}
		if len(ips) != 0 {
			t.Fatal("ips: ", ips)
		}
	}

	dnsServer.Shutdown()

	{
		ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
			t.Fatal(r)
		}
	}
}

func TestPrioritizedDomain(t *testing.T) {
	port := udp.PickPort()

	dnsServer := dns.Server{
		Addr:    "127.0.0.1:" + port.String(),
		Net:     "udp",
		Handler: &staticHandler{},
		UDPSize: 1200,
	}

	go dnsServer.ListenAndServe()
	time.Sleep(time.Second)

	config := &core.Config{
		App: []*serial.TypedMessage{
			serial.ToTypedMessage(&Config{
				NameServer: []*NameServer{
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: 9999, /* unreachable */
						},
					},
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
						PrioritizedDomain: []*NameServer_PriorityDomain{
							{
								Type:   DomainMatchingType_Full,
								Domain: "google.com",
							},
						},
					},
				},
			}),
			serial.ToTypedMessage(&dispatcher.Config{}),
			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
			serial.ToTypedMessage(&policy.Config{}),
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
			},
		},
	}

	v, err := core.New(config)
	common.Must(err)

	client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)

	startTime := time.Now()

	{
		ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
			t.Fatal(r)
		}
	}

	endTime := time.Now()
	if startTime.After(endTime.Add(time.Second * 2)) {
		t.Error("DNS query doesn't finish in 2 seconds.")
	}
}

func TestUDPServerIPv6(t *testing.T) {
	port := udp.PickPort()

	dnsServer := dns.Server{
		Addr:    "127.0.0.1:" + port.String(),
		Net:     "udp",
		Handler: &staticHandler{},
		UDPSize: 1200,
	}

	go dnsServer.ListenAndServe()
	time.Sleep(time.Second)

	config := &core.Config{
		App: []*serial.TypedMessage{
			serial.ToTypedMessage(&Config{
				NameServer: []*NameServer{
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
					},
				},
			}),
			serial.ToTypedMessage(&dispatcher.Config{}),
			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
			serial.ToTypedMessage(&policy.Config{}),
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
			},
		},
	}

	v, err := core.New(config)
	common.Must(err)

	client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
	{
		ips, _, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
			IPv4Enable: false,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{32, 1, 72, 96, 72, 96, 0, 0, 0, 0, 0, 0, 0, 0, 136, 136}}); r != "" {
			t.Fatal(r)
		}
	}
}

func TestStaticHostDomain(t *testing.T) {
	port := udp.PickPort()

	dnsServer := dns.Server{
		Addr:    "127.0.0.1:" + port.String(),
		Net:     "udp",
		Handler: &staticHandler{},
		UDPSize: 1200,
	}

	go dnsServer.ListenAndServe()
	time.Sleep(time.Second)

	config := &core.Config{
		App: []*serial.TypedMessage{
			serial.ToTypedMessage(&Config{
				NameServer: []*NameServer{
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
					},
				},
				StaticHosts: []*Config_HostMapping{
					{
						Type:          DomainMatchingType_Full,
						Domain:        "example.com",
						ProxiedDomain: "google.com",
					},
				},
			}),
			serial.ToTypedMessage(&dispatcher.Config{}),
			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
			serial.ToTypedMessage(&policy.Config{}),
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
			},
		},
	}

	v, err := core.New(config)
	common.Must(err)

	client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)

	{
		ips, _, err := client.LookupIP("example.com", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
			t.Fatal(r)
		}
	}

	dnsServer.Shutdown()
}

func TestIPMatch(t *testing.T) {
	port := udp.PickPort()

	dnsServer := dns.Server{
		Addr:    "127.0.0.1:" + port.String(),
		Net:     "udp",
		Handler: &staticHandler{},
		UDPSize: 1200,
	}

	go dnsServer.ListenAndServe()
	time.Sleep(time.Second)

	config := &core.Config{
		App: []*serial.TypedMessage{
			serial.ToTypedMessage(&Config{
				NameServer: []*NameServer{
					// private dns, not match
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
						ExpectedGeoip: []*router.GeoIP{
							{
								CountryCode: "local",
								Cidr: []*router.CIDR{
									{
										// inner ip, will not match
										Ip:     []byte{192, 168, 11, 1},
										Prefix: 32,
									},
								},
							},
						},
					},
					// second dns, match ip
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
						ExpectedGeoip: []*router.GeoIP{
							{
								CountryCode: "test",
								Cidr: []*router.CIDR{
									{
										Ip:     []byte{8, 8, 8, 8},
										Prefix: 32,
									},
								},
							},
							{
								CountryCode: "test",
								Cidr: []*router.CIDR{
									{
										Ip:     []byte{8, 8, 8, 4},
										Prefix: 32,
									},
								},
							},
						},
					},
				},
			}),
			serial.ToTypedMessage(&dispatcher.Config{}),
			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
			serial.ToTypedMessage(&policy.Config{}),
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
			},
		},
	}

	v, err := core.New(config)
	common.Must(err)

	client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)

	startTime := time.Now()

	{
		ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
			t.Fatal(r)
		}
	}

	endTime := time.Now()
	if startTime.After(endTime.Add(time.Second * 2)) {
		t.Error("DNS query doesn't finish in 2 seconds.")
	}
}

func TestLocalDomain(t *testing.T) {
	port := udp.PickPort()

	dnsServer := dns.Server{
		Addr:    "127.0.0.1:" + port.String(),
		Net:     "udp",
		Handler: &staticHandler{},
		UDPSize: 1200,
	}

	go dnsServer.ListenAndServe()
	time.Sleep(time.Second)

	config := &core.Config{
		App: []*serial.TypedMessage{
			serial.ToTypedMessage(&Config{
				NameServer: []*NameServer{
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: 9999, /* unreachable */
						},
					},
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
						PrioritizedDomain: []*NameServer_PriorityDomain{
							// Equivalent of dotless:localhost
							{Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
						},
						ExpectedGeoip: []*router.GeoIP{
							{ // Will match localhost, localhost-a and localhost-b,
								CountryCode: "local",
								Cidr: []*router.CIDR{
									{Ip: []byte{127, 0, 0, 2}, Prefix: 32},
									{Ip: []byte{127, 0, 0, 3}, Prefix: 32},
									{Ip: []byte{127, 0, 0, 4}, Prefix: 32},
								},
							},
						},
					},
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
						PrioritizedDomain: []*NameServer_PriorityDomain{
							// Equivalent of dotless: and domain:local
							{Type: DomainMatchingType_Regex, Domain: "^[^.]*$"},
							{Type: DomainMatchingType_Subdomain, Domain: "local"},
							{Type: DomainMatchingType_Subdomain, Domain: "localdomain"},
						},
					},
				},
				StaticHosts: []*Config_HostMapping{
					{
						Type:   DomainMatchingType_Full,
						Domain: "hostnamestatic",
						Ip:     [][]byte{{127, 0, 0, 53}},
					},
					{
						Type:          DomainMatchingType_Full,
						Domain:        "hostnamealias",
						ProxiedDomain: "hostname.localdomain",
					},
				},
			}),
			serial.ToTypedMessage(&dispatcher.Config{}),
			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
			serial.ToTypedMessage(&policy.Config{}),
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
			},
		},
	}

	v, err := core.New(config)
	common.Must(err)

	client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)

	startTime := time.Now()

	{ // Will match dotless:
		ips, _, err := client.LookupIP("hostname", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 1}}); r != "" {
			t.Fatal(r)
		}
	}

	{ // Will match domain:local
		ips, _, err := client.LookupIP("hostname.local", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 1}}); r != "" {
			t.Fatal(r)
		}
	}

	{ // Will match static ip
		ips, _, err := client.LookupIP("hostnamestatic", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 53}}); r != "" {
			t.Fatal(r)
		}
	}

	{ // Will match domain replacing
		ips, _, err := client.LookupIP("hostnamealias", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 1}}); r != "" {
			t.Fatal(r)
		}
	}

	{ // Will match dotless:localhost, but not expectedIPs: 127.0.0.2, 127.0.0.3, then matches at dotless:
		ips, _, err := client.LookupIP("localhost", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 2}}); r != "" {
			t.Fatal(r)
		}
	}

	{ // Will match dotless:localhost, and expectedIPs: 127.0.0.2, 127.0.0.3
		ips, _, err := client.LookupIP("localhost-a", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 3}}); r != "" {
			t.Fatal(r)
		}
	}

	{ // Will match dotless:localhost, and expectedIPs: 127.0.0.2, 127.0.0.3
		ips, _, err := client.LookupIP("localhost-b", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 4}}); r != "" {
			t.Fatal(r)
		}
	}

	{ // Will match dotless:
		ips, _, err := client.LookupIP("Mijia Cloud", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{127, 0, 0, 1}}); r != "" {
			t.Fatal(r)
		}
	}

	endTime := time.Now()
	if startTime.After(endTime.Add(time.Second * 2)) {
		t.Error("DNS query doesn't finish in 2 seconds.")
	}
}

func TestMultiMatchPrioritizedDomain(t *testing.T) {
	port := udp.PickPort()

	dnsServer := dns.Server{
		Addr:    "127.0.0.1:" + port.String(),
		Net:     "udp",
		Handler: &staticHandler{},
		UDPSize: 1200,
	}

	go dnsServer.ListenAndServe()
	time.Sleep(time.Second)

	config := &core.Config{
		App: []*serial.TypedMessage{
			serial.ToTypedMessage(&Config{
				NameServer: []*NameServer{
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: 9999, /* unreachable */
						},
					},
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
						PrioritizedDomain: []*NameServer_PriorityDomain{
							{
								Type:   DomainMatchingType_Subdomain,
								Domain: "google.com",
							},
						},
						ExpectedGeoip: []*router.GeoIP{
							{ // Will only match 8.8.8.8 and 8.8.4.4
								Cidr: []*router.CIDR{
									{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
									{Ip: []byte{8, 8, 4, 4}, Prefix: 32},
								},
							},
						},
					},
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
						PrioritizedDomain: []*NameServer_PriorityDomain{
							{
								Type:   DomainMatchingType_Subdomain,
								Domain: "google.com",
							},
						},
						ExpectedGeoip: []*router.GeoIP{
							{ // Will match 8.8.8.8 and 8.8.8.7, etc
								Cidr: []*router.CIDR{
									{Ip: []byte{8, 8, 8, 7}, Prefix: 24},
								},
							},
						},
					},
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
						PrioritizedDomain: []*NameServer_PriorityDomain{
							{
								Type:   DomainMatchingType_Subdomain,
								Domain: "api.google.com",
							},
						},
						ExpectedGeoip: []*router.GeoIP{
							{ // Will only match 8.8.7.7 (api.google.com)
								Cidr: []*router.CIDR{
									{Ip: []byte{8, 8, 7, 7}, Prefix: 32},
								},
							},
						},
					},
					{
						Address: &net.Endpoint{
							Network: net.Network_UDP,
							Address: &net.IPOrDomain{
								Address: &net.IPOrDomain_Ip{
									Ip: []byte{127, 0, 0, 1},
								},
							},
							Port: uint32(port),
						},
						PrioritizedDomain: []*NameServer_PriorityDomain{
							{
								Type:   DomainMatchingType_Full,
								Domain: "v2.api.google.com",
							},
						},
						ExpectedGeoip: []*router.GeoIP{
							{ // Will only match 8.8.7.8 (v2.api.google.com)
								Cidr: []*router.CIDR{
									{Ip: []byte{8, 8, 7, 8}, Prefix: 32},
								},
							},
						},
					},
				},
			}),
			serial.ToTypedMessage(&dispatcher.Config{}),
			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
			serial.ToTypedMessage(&policy.Config{}),
		},
		Outbound: []*core.OutboundHandlerConfig{
			{
				ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
			},
		},
	}

	v, err := core.New(config)
	common.Must(err)

	client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)

	startTime := time.Now()

	{ // Will match server 1,2 and server 1 returns expected ip
		ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 8}}); r != "" {
			t.Fatal(r)
		}
	}

	{ // Will match server 1,2 and server 1 returns unexpected ip, then server 2 returns expected one
		ips, _, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: false,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{8, 8, 8, 7}}); r != "" {
			t.Fatal(r)
		}
	}

	{ // Will match server 3,1,2 and server 3 returns expected one
		ips, _, err := client.LookupIP("api.google.com", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{8, 8, 7, 7}}); r != "" {
			t.Fatal(r)
		}
	}

	{ // Will match server 4,3,1,2 and server 4 returns expected one
		ips, _, err := client.LookupIP("v2.api.google.com", feature_dns.IPOption{
			IPv4Enable: true,
			IPv6Enable: true,
			FakeEnable: false,
		})
		if err != nil {
			t.Fatal("unexpected error: ", err)
		}

		if r := cmp.Diff(ips, []net.IP{{8, 8, 7, 8}}); r != "" {
			t.Fatal(r)
		}
	}

	endTime := time.Now()
	if startTime.After(endTime.Add(time.Second * 2)) {
		t.Error("DNS query doesn't finish in 2 seconds.")
	}
}


================================================
FILE: app/dns/dnscommon.go
================================================
package dns

import (
	"context"
	"encoding/binary"
	"math"
	"strings"
	"time"

	"github.com/xtls/xray-core/common"
	"github.com/xtls/xray-core/common/errors"
	"github.com/xtls/xray-core/common/log"
	"github.com/xtls/xray-core/common/net"
	"github.com/xtls/xray-core/common/session"
	"github.com/xtls/xray-core/core"
	dns_feature "github.com/xtls/xray-core/features/d
Download .txt
gitextract_x2sy_bia/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── bug_report_zh.yml
│   │   └── config.yml
│   ├── build/
│   │   └── friendly-filenames.json
│   ├── dependabot.yml
│   ├── docker/
│   │   ├── Dockerfile
│   │   └── Dockerfile.usa
│   └── workflows/
│       ├── docker.yml
│       ├── release-win7.yml
│       ├── release.yml
│       ├── scheduled-assets-update.yml
│       └── test.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── SECURITY.md
├── app/
│   ├── app.go
│   ├── commander/
│   │   ├── commander.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── outbound.go
│   │   └── service.go
│   ├── dispatcher/
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── default.go
│   │   ├── dispatcher.go
│   │   ├── fakednssniffer.go
│   │   ├── sniffer.go
│   │   ├── stats.go
│   │   └── stats_test.go
│   ├── dns/
│   │   ├── cache_controller.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── dns.go
│   │   ├── dns_test.go
│   │   ├── dnscommon.go
│   │   ├── dnscommon_test.go
│   │   ├── fakedns/
│   │   │   ├── fake.go
│   │   │   ├── fakedns.go
│   │   │   ├── fakedns.pb.go
│   │   │   ├── fakedns.proto
│   │   │   └── fakedns_test.go
│   │   ├── hosts.go
│   │   ├── hosts_test.go
│   │   ├── nameserver.go
│   │   ├── nameserver_cached.go
│   │   ├── nameserver_doh.go
│   │   ├── nameserver_doh_test.go
│   │   ├── nameserver_fakedns.go
│   │   ├── nameserver_local.go
│   │   ├── nameserver_local_test.go
│   │   ├── nameserver_quic.go
│   │   ├── nameserver_quic_test.go
│   │   ├── nameserver_tcp.go
│   │   ├── nameserver_tcp_test.go
│   │   └── nameserver_udp.go
│   ├── log/
│   │   ├── command/
│   │   │   ├── command.go
│   │   │   ├── command_test.go
│   │   │   ├── config.pb.go
│   │   │   ├── config.proto
│   │   │   └── config_grpc.pb.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── log.go
│   │   ├── log_creator.go
│   │   └── log_test.go
│   ├── metrics/
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── metrics.go
│   │   └── outbound.go
│   ├── observatory/
│   │   ├── burst/
│   │   │   ├── burst.go
│   │   │   ├── burstobserver.go
│   │   │   ├── config.pb.go
│   │   │   ├── config.proto
│   │   │   ├── healthping.go
│   │   │   ├── healthping_result.go
│   │   │   ├── healthping_result_test.go
│   │   │   └── ping.go
│   │   ├── command/
│   │   │   ├── command.go
│   │   │   ├── command.pb.go
│   │   │   ├── command.proto
│   │   │   └── command_grpc.pb.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── explainErrors.go
│   │   ├── observatory.go
│   │   └── observer.go
│   ├── policy/
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── manager.go
│   │   ├── manager_test.go
│   │   └── policy.go
│   ├── proxyman/
│   │   ├── command/
│   │   │   ├── command.go
│   │   │   ├── command.pb.go
│   │   │   ├── command.proto
│   │   │   ├── command_grpc.pb.go
│   │   │   └── doc.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── inbound/
│   │   │   ├── always.go
│   │   │   ├── inbound.go
│   │   │   └── worker.go
│   │   └── outbound/
│   │       ├── handler.go
│   │       ├── handler_test.go
│   │       ├── outbound.go
│   │       └── uot.go
│   ├── reverse/
│   │   ├── bridge.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── portal.go
│   │   ├── portal_test.go
│   │   └── reverse.go
│   ├── router/
│   │   ├── balancing.go
│   │   ├── balancing_override.go
│   │   ├── command/
│   │   │   ├── command.go
│   │   │   ├── command.pb.go
│   │   │   ├── command.proto
│   │   │   ├── command_grpc.pb.go
│   │   │   ├── command_test.go
│   │   │   └── config.go
│   │   ├── condition.go
│   │   ├── condition_geoip.go
│   │   ├── condition_geoip_test.go
│   │   ├── condition_serialize_test.go
│   │   ├── condition_test.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── geosite_compact.go
│   │   ├── router.go
│   │   ├── router_test.go
│   │   ├── strategy_leastload.go
│   │   ├── strategy_leastload_test.go
│   │   ├── strategy_leastping.go
│   │   ├── strategy_random.go
│   │   ├── webhook.go
│   │   ├── weight.go
│   │   └── weight_test.go
│   ├── stats/
│   │   ├── channel.go
│   │   ├── channel_test.go
│   │   ├── command/
│   │   │   ├── command.go
│   │   │   ├── command.pb.go
│   │   │   ├── command.proto
│   │   │   ├── command_grpc.pb.go
│   │   │   └── command_test.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── counter.go
│   │   ├── counter_test.go
│   │   ├── online_map.go
│   │   ├── stats.go
│   │   └── stats_test.go
│   └── version/
│       ├── config.pb.go
│       ├── config.proto
│       └── version.go
├── common/
│   ├── antireplay/
│   │   ├── antireplay_test.go
│   │   └── mapfilter.go
│   ├── bitmask/
│   │   ├── byte.go
│   │   └── byte_test.go
│   ├── buf/
│   │   ├── buf.go
│   │   ├── buffer.go
│   │   ├── buffer_test.go
│   │   ├── copy.go
│   │   ├── copy_test.go
│   │   ├── io.go
│   │   ├── io_test.go
│   │   ├── multi_buffer.go
│   │   ├── multi_buffer_test.go
│   │   ├── override.go
│   │   ├── reader.go
│   │   ├── reader_test.go
│   │   ├── readv_posix.go
│   │   ├── readv_reader.go
│   │   ├── readv_reader_wasm.go
│   │   ├── readv_test.go
│   │   ├── readv_unix.go
│   │   ├── readv_windows.go
│   │   ├── writer.go
│   │   └── writer_test.go
│   ├── bytespool/
│   │   └── pool.go
│   ├── cache/
│   │   ├── lru.go
│   │   └── lru_test.go
│   ├── cmdarg/
│   │   └── cmdarg.go
│   ├── common.go
│   ├── common_test.go
│   ├── crypto/
│   │   ├── aes.go
│   │   ├── auth.go
│   │   ├── auth_test.go
│   │   ├── benchmark_test.go
│   │   ├── chacha20.go
│   │   ├── chacha20_test.go
│   │   ├── chunk.go
│   │   ├── chunk_test.go
│   │   ├── crypto.go
│   │   ├── internal/
│   │   │   ├── chacha.go
│   │   │   ├── chacha_core.generated.go
│   │   │   └── chacha_core_gen.go
│   │   └── io.go
│   ├── ctx/
│   │   └── context.go
│   ├── dice/
│   │   ├── dice.go
│   │   └── dice_test.go
│   ├── drain/
│   │   ├── drain.go
│   │   └── drainer.go
│   ├── errors/
│   │   ├── errors.go
│   │   ├── errors_test.go
│   │   ├── feature_errors.go
│   │   └── multi_error.go
│   ├── interfaces.go
│   ├── log/
│   │   ├── access.go
│   │   ├── dns.go
│   │   ├── log.go
│   │   ├── log.pb.go
│   │   ├── log.proto
│   │   ├── log_test.go
│   │   ├── logger.go
│   │   └── logger_test.go
│   ├── mux/
│   │   ├── client.go
│   │   ├── client_test.go
│   │   ├── frame.go
│   │   ├── frame_test.go
│   │   ├── mux.go
│   │   ├── mux_test.go
│   │   ├── reader.go
│   │   ├── server.go
│   │   ├── server_test.go
│   │   ├── session.go
│   │   ├── session_test.go
│   │   └── writer.go
│   ├── net/
│   │   ├── address.go
│   │   ├── address.pb.go
│   │   ├── address.proto
│   │   ├── address_test.go
│   │   ├── cnc/
│   │   │   └── connection.go
│   │   ├── destination.go
│   │   ├── destination.pb.go
│   │   ├── destination.proto
│   │   ├── destination_test.go
│   │   ├── find_process_linux.go
│   │   ├── find_process_others.go
│   │   ├── find_process_windows.go
│   │   ├── net.go
│   │   ├── network.go
│   │   ├── network.pb.go
│   │   ├── network.proto
│   │   ├── port.go
│   │   ├── port.pb.go
│   │   ├── port.proto
│   │   ├── port_test.go
│   │   └── system.go
│   ├── ocsp/
│   │   └── ocsp.go
│   ├── peer/
│   │   ├── latency.go
│   │   └── peer.go
│   ├── platform/
│   │   ├── filesystem/
│   │   │   └── file.go
│   │   ├── others.go
│   │   ├── platform.go
│   │   ├── platform_test.go
│   │   └── windows.go
│   ├── protocol/
│   │   ├── account.go
│   │   ├── address.go
│   │   ├── address_test.go
│   │   ├── bittorrent/
│   │   │   └── bittorrent.go
│   │   ├── context.go
│   │   ├── dns/
│   │   │   └── io.go
│   │   ├── headers.go
│   │   ├── headers.pb.go
│   │   ├── headers.proto
│   │   ├── http/
│   │   │   ├── headers.go
│   │   │   ├── headers_test.go
│   │   │   ├── sniff.go
│   │   │   └── sniff_test.go
│   │   ├── id.go
│   │   ├── id_test.go
│   │   ├── payload.go
│   │   ├── protocol.go
│   │   ├── quic/
│   │   │   ├── qtls_go118.go
│   │   │   ├── sniff.go
│   │   │   └── sniff_test.go
│   │   ├── server_spec.go
│   │   ├── server_spec.pb.go
│   │   ├── server_spec.proto
│   │   ├── time.go
│   │   ├── time_test.go
│   │   ├── tls/
│   │   │   ├── cert/
│   │   │   │   ├── cert.go
│   │   │   │   ├── cert_test.go
│   │   │   │   └── privateKey.go
│   │   │   ├── sniff.go
│   │   │   └── sniff_test.go
│   │   ├── udp/
│   │   │   ├── packet.go
│   │   │   └── udp.go
│   │   ├── user.go
│   │   ├── user.pb.go
│   │   └── user.proto
│   ├── reflect/
│   │   ├── marshal.go
│   │   └── marshal_test.go
│   ├── retry/
│   │   ├── retry.go
│   │   └── retry_test.go
│   ├── serial/
│   │   ├── serial.go
│   │   ├── serial_test.go
│   │   ├── string.go
│   │   ├── string_test.go
│   │   ├── typed_message.go
│   │   ├── typed_message.pb.go
│   │   ├── typed_message.proto
│   │   └── typed_message_test.go
│   ├── session/
│   │   ├── context.go
│   │   └── session.go
│   ├── signal/
│   │   ├── done/
│   │   │   └── done.go
│   │   ├── notifier.go
│   │   ├── notifier_test.go
│   │   ├── pubsub/
│   │   │   ├── pubsub.go
│   │   │   └── pubsub_test.go
│   │   ├── semaphore/
│   │   │   └── semaphore.go
│   │   ├── timer.go
│   │   └── timer_test.go
│   ├── singbridge/
│   │   ├── destination.go
│   │   ├── dialer.go
│   │   ├── error.go
│   │   ├── handler.go
│   │   ├── logger.go
│   │   ├── packet.go
│   │   ├── pipe.go
│   │   └── reader.go
│   ├── strmatcher/
│   │   ├── ac_automaton_matcher.go
│   │   ├── benchmark_test.go
│   │   ├── domain_matcher.go
│   │   ├── domain_matcher_test.go
│   │   ├── full_matcher.go
│   │   ├── full_matcher_test.go
│   │   ├── matchers.go
│   │   ├── matchers_test.go
│   │   ├── mph_matcher.go
│   │   ├── mph_matcher_compact.go
│   │   ├── strmatcher.go
│   │   └── strmatcher_test.go
│   ├── task/
│   │   ├── common.go
│   │   ├── periodic.go
│   │   ├── periodic_test.go
│   │   ├── task.go
│   │   └── task_test.go
│   ├── type.go
│   ├── type_test.go
│   ├── units/
│   │   ├── bytesize.go
│   │   └── bytesize_test.go
│   ├── utils/
│   │   ├── access_field.go
│   │   ├── browser.go
│   │   ├── padding.go
│   │   └── typed_sync_map.go
│   ├── uuid/
│   │   ├── uuid.go
│   │   └── uuid_test.go
│   └── xudp/
│       ├── xudp.go
│       └── xudp_test.go
├── core/
│   ├── annotations.go
│   ├── config.go
│   ├── config.pb.go
│   ├── config.proto
│   ├── context.go
│   ├── context_test.go
│   ├── core.go
│   ├── format.go
│   ├── functions.go
│   ├── functions_test.go
│   ├── mocks.go
│   ├── proto.go
│   ├── xray.go
│   └── xray_test.go
├── features/
│   ├── dns/
│   │   ├── client.go
│   │   ├── fakedns.go
│   │   └── localdns/
│   │       └── client.go
│   ├── extension/
│   │   ├── contextreceiver.go
│   │   └── observatory.go
│   ├── feature.go
│   ├── inbound/
│   │   └── inbound.go
│   ├── outbound/
│   │   └── outbound.go
│   ├── policy/
│   │   ├── default.go
│   │   └── policy.go
│   ├── routing/
│   │   ├── balancer.go
│   │   ├── context.go
│   │   ├── dispatcher.go
│   │   ├── dns/
│   │   │   └── context.go
│   │   ├── router.go
│   │   └── session/
│   │       └── context.go
│   └── stats/
│       └── stats.go
├── go.mod
├── go.sum
├── infra/
│   ├── conf/
│   │   ├── api.go
│   │   ├── blackhole.go
│   │   ├── blackhole_test.go
│   │   ├── buildable.go
│   │   ├── cfgcommon/
│   │   │   └── duration/
│   │   │       ├── duration.go
│   │   │       └── duration_test.go
│   │   ├── common.go
│   │   ├── common_test.go
│   │   ├── conf.go
│   │   ├── dns.go
│   │   ├── dns_proxy.go
│   │   ├── dns_proxy_test.go
│   │   ├── dns_test.go
│   │   ├── dokodemo.go
│   │   ├── dokodemo_test.go
│   │   ├── fakedns.go
│   │   ├── freedom.go
│   │   ├── freedom_test.go
│   │   ├── general_test.go
│   │   ├── grpc.go
│   │   ├── http.go
│   │   ├── http_test.go
│   │   ├── hysteria.go
│   │   ├── init.go
│   │   ├── json/
│   │   │   ├── reader.go
│   │   │   └── reader_test.go
│   │   ├── lint.go
│   │   ├── loader.go
│   │   ├── log.go
│   │   ├── loopback.go
│   │   ├── metrics.go
│   │   ├── observatory.go
│   │   ├── policy.go
│   │   ├── policy_test.go
│   │   ├── reverse.go
│   │   ├── reverse_test.go
│   │   ├── router.go
│   │   ├── router_strategy.go
│   │   ├── router_test.go
│   │   ├── serial/
│   │   │   ├── builder.go
│   │   │   ├── loader.go
│   │   │   ├── loader_test.go
│   │   │   └── serial.go
│   │   ├── shadowsocks.go
│   │   ├── shadowsocks_test.go
│   │   ├── socks.go
│   │   ├── socks_test.go
│   │   ├── transport_authenticators.go
│   │   ├── transport_internet.go
│   │   ├── transport_test.go
│   │   ├── trojan.go
│   │   ├── tun.go
│   │   ├── version.go
│   │   ├── vless.go
│   │   ├── vless_test.go
│   │   ├── vmess.go
│   │   ├── vmess_test.go
│   │   ├── wireguard.go
│   │   ├── wireguard_test.go
│   │   ├── xray.go
│   │   └── xray_test.go
│   └── vformat/
│       └── main.go
├── main/
│   ├── commands/
│   │   ├── all/
│   │   │   ├── api/
│   │   │   │   ├── api.go
│   │   │   │   ├── balancer_info.go
│   │   │   │   ├── balancer_override.go
│   │   │   │   ├── inbound_user.go
│   │   │   │   ├── inbound_user_add.go
│   │   │   │   ├── inbound_user_count.go
│   │   │   │   ├── inbound_user_remove.go
│   │   │   │   ├── inbounds_add.go
│   │   │   │   ├── inbounds_list.go
│   │   │   │   ├── inbounds_remove.go
│   │   │   │   ├── logger_restart.go
│   │   │   │   ├── outbounds_add.go
│   │   │   │   ├── outbounds_list.go
│   │   │   │   ├── outbounds_remove.go
│   │   │   │   ├── rules_add.go
│   │   │   │   ├── rules_list.go
│   │   │   │   ├── rules_remove.go
│   │   │   │   ├── shared.go
│   │   │   │   ├── source_ip_block.go
│   │   │   │   ├── stats_get.go
│   │   │   │   ├── stats_get_all_online_users.go
│   │   │   │   ├── stats_online.go
│   │   │   │   ├── stats_online_ip_list.go
│   │   │   │   ├── stats_query.go
│   │   │   │   └── stats_sys.go
│   │   │   ├── buildmphcache.go
│   │   │   ├── commands.go
│   │   │   ├── convert/
│   │   │   │   ├── convert.go
│   │   │   │   ├── json.go
│   │   │   │   └── protobuf.go
│   │   │   ├── curve25519.go
│   │   │   ├── mldsa65.go
│   │   │   ├── mlkem768.go
│   │   │   ├── tls/
│   │   │   │   ├── cert.go
│   │   │   │   ├── ech.go
│   │   │   │   ├── hash.go
│   │   │   │   ├── ping.go
│   │   │   │   └── tls.go
│   │   │   ├── uuid.go
│   │   │   ├── vlessenc.go
│   │   │   ├── wg.go
│   │   │   └── x25519.go
│   │   └── base/
│   │       ├── command.go
│   │       ├── env.go
│   │       ├── execute.go
│   │       ├── help.go
│   │       └── root.go
│   ├── confloader/
│   │   ├── confloader.go
│   │   └── external/
│   │       └── external.go
│   ├── distro/
│   │   └── all/
│   │       └── all.go
│   ├── json/
│   │   └── json.go
│   ├── main.go
│   ├── main_test.go
│   ├── run.go
│   ├── toml/
│   │   └── toml.go
│   ├── version.go
│   └── yaml/
│       └── yaml.go
├── proxy/
│   ├── blackhole/
│   │   ├── blackhole.go
│   │   ├── blackhole_test.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   └── config_test.go
│   ├── dns/
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── dns.go
│   │   └── dns_test.go
│   ├── dokodemo/
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── dokodemo.go
│   │   ├── fakeudp_linux.go
│   │   └── fakeudp_other.go
│   ├── freedom/
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   └── freedom.go
│   ├── http/
│   │   ├── client.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── http.go
│   │   └── server.go
│   ├── hysteria/
│   │   ├── account/
│   │   │   ├── config.go
│   │   │   ├── config.pb.go
│   │   │   └── config.proto
│   │   ├── client.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── ctx/
│   │   │   └── ctx.go
│   │   ├── frag.go
│   │   ├── protocol.go
│   │   └── server.go
│   ├── loopback/
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   └── loopback.go
│   ├── proxy.go
│   ├── shadowsocks/
│   │   ├── client.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── config_test.go
│   │   ├── protocol.go
│   │   ├── protocol_test.go
│   │   ├── server.go
│   │   ├── shadowsocks.go
│   │   └── validator.go
│   ├── shadowsocks_2022/
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── inbound.go
│   │   ├── inbound_multi.go
│   │   ├── inbound_relay.go
│   │   ├── outbound.go
│   │   └── shadowsocks_2022.go
│   ├── socks/
│   │   ├── client.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── protocol.go
│   │   ├── protocol_test.go
│   │   ├── server.go
│   │   ├── socks.go
│   │   └── udpfilter.go
│   ├── trojan/
│   │   ├── client.go
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── protocol.go
│   │   ├── protocol_test.go
│   │   ├── server.go
│   │   ├── trojan.go
│   │   └── validator.go
│   ├── tun/
│   │   ├── README.md
│   │   ├── config.go
│   │   ├── config.pb.go
│   │   ├── config.proto
│   │   ├── handler.go
│   │   ├── stack.go
│   │   ├── stack_gvisor.go
│   │   ├── stack_gvisor_endpoint.go
│   │   ├── tun.go
│   │   ├── tun_android.go
│   │   ├── tun_darwin.go
│   │   ├── tun_default.go
│   │   ├── tun_linux.go
│   │   ├── tun_windows.go
│   │   └── udp_fullcone.go
│   ├── vless/
│   │   ├── account.go
│   │   ├── account.pb.go
│   │   ├── account.proto
│   │   ├── encoding/
│   │   │   ├── addons.go
│   │   │   ├── addons.pb.go
│   │   │   ├── addons.proto
│   │   │   ├── encoding.go
│   │   │   └── encoding_test.go
│   │   ├── encryption/
│   │   │   ├── client.go
│   │   │   ├── common.go
│   │   │   ├── server.go
│   │   │   └── xor.go
│   │   ├── inbound/
│   │   │   ├── config.go
│   │   │   ├── config.pb.go
│   │   │   ├── config.proto
│   │   │   └── inbound.go
│   │   ├── outbound/
│   │   │   ├── config.go
│   │   │   ├── config.pb.go
│   │   │   ├── config.proto
│   │   │   └── outbound.go
│   │   ├── validator.go
│   │   └── vless.go
│   ├── vmess/
│   │   ├── account.go
│   │   ├── account.pb.go
│   │   ├── account.proto
│   │   ├── aead/
│   │   │   ├── authid.go
│   │   │   ├── authid_test.go
│   │   │   ├── consts.go
│   │   │   ├── encrypt.go
│   │   │   ├── encrypt_test.go
│   │   │   └── kdf.go
│   │   ├── encoding/
│   │   │   ├── auth.go
│   │   │   ├── client.go
│   │   │   ├── commands.go
│   │   │   ├── encoding.go
│   │   │   ├── encoding_test.go
│   │   │   └── server.go
│   │   ├── inbound/
│   │   │   ├── config.go
│   │   │   ├── config.pb.go
│   │   │   ├── config.proto
│   │   │   └── inbound.go
│   │   ├── outbound/
│   │   │   ├── command.go
│   │   │   ├── config.go
│   │   │   ├── config.pb.go
│   │   │   ├── config.proto
│   │   │   └── outbound.go
│   │   ├── validator.go
│   │   ├── validator_test.go
│   │   └── vmess.go
│   └── wireguard/
│       ├── bind.go
│       ├── client.go
│       ├── config.go
│       ├── config.pb.go
│       ├── config.proto
│       ├── gvisortun/
│       │   └── tun.go
│       ├── server.go
│       ├── server_test.go
│       ├── tun.go
│       ├── tun_default.go
│       ├── tun_linux.go
│       └── wireguard.go
├── testing/
│   ├── coverage/
│   │   ├── coverall
│   │   └── coverall2
│   ├── mocks/
│   │   ├── dns.go
│   │   ├── io.go
│   │   ├── log.go
│   │   ├── mux.go
│   │   ├── outbound.go
│   │   └── proxy.go
│   ├── scenarios/
│   │   ├── command_test.go
│   │   ├── common.go
│   │   ├── common_coverage.go
│   │   ├── common_regular.go
│   │   ├── dns_test.go
│   │   ├── dokodemo_test.go
│   │   ├── feature_test.go
│   │   ├── http_test.go
│   │   ├── main_test.go
│   │   ├── metrics_test.go
│   │   ├── policy_test.go
│   │   ├── reverse_test.go
│   │   ├── shadowsocks_2022_test.go
│   │   ├── shadowsocks_test.go
│   │   ├── socks_test.go
│   │   ├── tls_test.go
│   │   ├── transport_test.go
│   │   ├── vless_test.go
│   │   ├── vmess_test.go
│   │   └── wireguard_test.go
│   └── servers/
│       ├── http/
│       │   └── http.go
│       ├── tcp/
│       │   ├── port.go
│       │   └── tcp.go
│       └── udp/
│           ├── port.go
│           └── udp.go
└── transport/
    ├── internet/
    │   ├── browser_dialer/
    │   │   ├── dialer.go
    │   │   └── dialer.html
    │   ├── config.go
    │   ├── config.pb.go
    │   ├── config.proto
    │   ├── dialer.go
    │   ├── dialer_test.go
    │   ├── filelocker.go
    │   ├── filelocker_other.go
    │   ├── filelocker_windows.go
    │   ├── finalmask/
    │   │   ├── finalmask.go
    │   │   ├── fragment/
    │   │   │   ├── config.go
    │   │   │   ├── config.pb.go
    │   │   │   ├── config.proto
    │   │   │   └── conn.go
    │   │   ├── header/
    │   │   │   ├── custom/
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   ├── tcp.go
    │   │   │   │   └── udp.go
    │   │   │   ├── dns/
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   └── conn.go
    │   │   │   ├── dtls/
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   └── conn.go
    │   │   │   ├── srtp/
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   └── conn.go
    │   │   │   ├── utp/
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   └── conn.go
    │   │   │   ├── wechat/
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   └── conn.go
    │   │   │   └── wireguard/
    │   │   │       ├── config.go
    │   │   │       ├── config.pb.go
    │   │   │       ├── config.proto
    │   │   │       └── conn.go
    │   │   ├── mkcp/
    │   │   │   ├── aes128gcm/
    │   │   │   │   ├── aes128gcm_test.go
    │   │   │   │   ├── config.go
    │   │   │   │   ├── config.pb.go
    │   │   │   │   ├── config.proto
    │   │   │   │   └── conn.go
    │   │   │   └── original/
    │   │   │       ├── config.go
    │   │   │       ├── config.pb.go
    │   │   │       ├── config.proto
    │   │   │       ├── conn.go
    │   │   │       ├── simple_test.go
    │   │   │       ├── xor.go
    │   │   │       ├── xor_amd64.go
    │   │   │       └── xor_amd64.s
    │   │   ├── noise/
    │   │   │   ├── config.go
    │   │   │   ├── config.pb.go
    │   │   │   ├── config.proto
    │   │   │   └── conn.go
    │   │   ├── salamander/
    │   │   │   ├── config.go
    │   │   │   ├── config.pb.go
    │   │   │   ├── config.proto
    │   │   │   ├── conn.go
    │   │   │   ├── salamander.go
    │   │   │   └── salamander_test.go
    │   │   ├── sudoku/
    │   │   │   ├── codec.go
    │   │   │   ├── config.go
    │   │   │   ├── config.pb.go
    │   │   │   ├── config.proto
    │   │   │   ├── conn_tcp.go
    │   │   │   ├── conn_tcp_packed.go
    │   │   │   ├── conn_udp.go
    │   │   │   ├── sudoku_test.go
    │   │   │   └── table.go
    │   │   ├── tcp_test.go
    │   │   ├── udp_test.go
    │   │   ├── xdns/
    │   │   │   ├── client.go
    │   │   │   ├── config.go
    │   │   │   ├── config.pb.go
    │   │   │   ├── config.proto
    │   │   │   ├── dns.go
    │   │   │   ├── dns_test.go
    │   │   │   └── server.go
    │   │   └── xicmp/
    │   │       ├── client.go
    │   │       ├── config.go
    │   │       ├── config.pb.go
    │   │       ├── config.proto
    │   │       ├── server.go
    │   │       └── xicmp_test.go
    │   ├── grpc/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── config_test.go
    │   │   ├── dial.go
    │   │   ├── encoding/
    │   │   │   ├── customSeviceName.go
    │   │   │   ├── encoding.go
    │   │   │   ├── hunkconn.go
    │   │   │   ├── multiconn.go
    │   │   │   ├── stream.pb.go
    │   │   │   ├── stream.proto
    │   │   │   └── stream_grpc.pb.go
    │   │   ├── grpc.go
    │   │   └── hub.go
    │   ├── happy_eyeballs.go
    │   ├── header.go
    │   ├── headers/
    │   │   ├── http/
    │   │   │   ├── config.go
    │   │   │   ├── config.pb.go
    │   │   │   ├── config.proto
    │   │   │   ├── http.go
    │   │   │   ├── http_test.go
    │   │   │   ├── linkedreadRequest.go
    │   │   │   └── resp.go
    │   │   └── noop/
    │   │       ├── config.pb.go
    │   │       ├── config.proto
    │   │       └── noop.go
    │   ├── httpupgrade/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── connection.go
    │   │   ├── dialer.go
    │   │   ├── httpupgrade.go
    │   │   ├── httpupgrade_test.go
    │   │   └── hub.go
    │   ├── hysteria/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── congestion/
    │   │   │   ├── bbr/
    │   │   │   │   ├── bandwidth.go
    │   │   │   │   ├── bandwidth_sampler.go
    │   │   │   │   ├── bbr_sender.go
    │   │   │   │   ├── clock.go
    │   │   │   │   ├── packet_number_indexed_queue.go
    │   │   │   │   ├── ringbuffer.go
    │   │   │   │   └── windowed_filter.go
    │   │   │   ├── brutal/
    │   │   │   │   └── brutal.go
    │   │   │   ├── common/
    │   │   │   │   └── pacer.go
    │   │   │   └── utils.go
    │   │   ├── conn.go
    │   │   ├── dialer.go
    │   │   ├── hub.go
    │   │   ├── padding/
    │   │   │   └── padding.go
    │   │   └── udphop/
    │   │       ├── addr.go
    │   │       └── conn.go
    │   ├── internet.go
    │   ├── kcp/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── connection.go
    │   │   ├── connection_test.go
    │   │   ├── dialer.go
    │   │   ├── io.go
    │   │   ├── io_test.go
    │   │   ├── kcp.go
    │   │   ├── kcp_test.go
    │   │   ├── listener.go
    │   │   ├── output.go
    │   │   ├── receiving.go
    │   │   ├── segment.go
    │   │   ├── segment_test.go
    │   │   └── sending.go
    │   ├── memory_settings.go
    │   ├── reality/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   └── reality.go
    │   ├── sockopt.go
    │   ├── sockopt_darwin.go
    │   ├── sockopt_freebsd.go
    │   ├── sockopt_linux.go
    │   ├── sockopt_linux_test.go
    │   ├── sockopt_other.go
    │   ├── sockopt_test.go
    │   ├── sockopt_windows.go
    │   ├── splithttp/
    │   │   ├── browser_client.go
    │   │   ├── client.go
    │   │   ├── common.go
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── config_test.go
    │   │   ├── connection.go
    │   │   ├── dialer.go
    │   │   ├── h1_conn.go
    │   │   ├── hub.go
    │   │   ├── mux.go
    │   │   ├── mux_test.go
    │   │   ├── splithttp.go
    │   │   ├── splithttp_test.go
    │   │   ├── upload_queue.go
    │   │   ├── upload_queue_test.go
    │   │   └── xpadding.go
    │   ├── stat/
    │   │   └── connection.go
    │   ├── system_dialer.go
    │   ├── system_listener.go
    │   ├── system_listener_test.go
    │   ├── tagged/
    │   │   ├── tagged.go
    │   │   └── taggedimpl/
    │   │       ├── impl.go
    │   │       └── taggedimpl.go
    │   ├── tcp/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── dialer.go
    │   │   ├── hub.go
    │   │   ├── sockopt_darwin.go
    │   │   ├── sockopt_freebsd.go
    │   │   ├── sockopt_linux.go
    │   │   ├── sockopt_linux_test.go
    │   │   ├── sockopt_other.go
    │   │   └── tcp.go
    │   ├── tcp_hub.go
    │   ├── tls/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── config_other.go
    │   │   ├── config_test.go
    │   │   ├── config_windows.go
    │   │   ├── ech.go
    │   │   ├── ech_test.go
    │   │   ├── grpc.go
    │   │   ├── pin.go
    │   │   ├── pin_test.go
    │   │   ├── tls.go
    │   │   └── unsafe.go
    │   ├── udp/
    │   │   ├── config.go
    │   │   ├── config.pb.go
    │   │   ├── config.proto
    │   │   ├── dialer.go
    │   │   ├── dispatcher.go
    │   │   ├── dispatcher_test.go
    │   │   ├── hub.go
    │   │   ├── hub_darwin.go
    │   │   ├── hub_freebsd.go
    │   │   ├── hub_linux.go
    │   │   ├── hub_other.go
    │   │   └── udp.go
    │   └── websocket/
    │       ├── config.go
    │       ├── config.pb.go
    │       ├── config.proto
    │       ├── connection.go
    │       ├── dialer.go
    │       ├── hub.go
    │       ├── ws.go
    │       └── ws_test.go
    ├── link.go
    └── pipe/
        ├── impl.go
        ├── pipe.go
        ├── pipe_test.go
        ├── reader.go
        └── writer.go
Download .txt
Showing preview only (729K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (8339 symbols across 804 files)

FILE: app/commander/commander.go
  type Commander (line 17) | type Commander struct
    method Type (line 57) | func (c *Commander) Type() interface{} {
    method Start (line 62) | func (c *Commander) Start() error {
    method Close (line 105) | func (c *Commander) Close() error {
  function NewCommander (line 27) | func NewCommander(ctx context.Context, config *Config) (*Commander, erro...
  function init (line 117) | func init() {

FILE: app/commander/config.pb.go
  constant _ (line 20) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 22) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type Config (line 26) | type Config struct
    method Reset (line 39) | func (x *Config) Reset() {
    method String (line 46) | func (x *Config) String() string {
    method ProtoMessage (line 50) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 52) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 65) | func (*Config) Descriptor() ([]byte, []int) {
    method GetTag (line 69) | func (x *Config) GetTag() string {
    method GetListen (line 76) | func (x *Config) GetListen() string {
    method GetService (line 83) | func (x *Config) GetService() []*serial.TypedMessage {
  type ReflectionConfig (line 91) | type ReflectionConfig struct
    method Reset (line 97) | func (x *ReflectionConfig) Reset() {
    method String (line 104) | func (x *ReflectionConfig) String() string {
    method ProtoMessage (line 108) | func (*ReflectionConfig) ProtoMessage() {}
    method ProtoReflect (line 110) | func (x *ReflectionConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 123) | func (*ReflectionConfig) Descriptor() ([]byte, []int) {
  constant file_app_commander_config_proto_rawDesc (line 129) | file_app_commander_config_proto_rawDesc = "" +
  function file_app_commander_config_proto_rawDescGZIP (line 144) | func file_app_commander_config_proto_rawDescGZIP() []byte {
  function init (line 166) | func init() { file_app_commander_config_proto_init() }
  function file_app_commander_config_proto_init (line 167) | func file_app_commander_config_proto_init() {

FILE: app/commander/outbound.go
  type OutboundListener (line 17) | type OutboundListener struct
    method add (line 22) | func (l *OutboundListener) add(conn net.Conn) {
    method Accept (line 33) | func (l *OutboundListener) Accept() (net.Conn, error) {
    method Close (line 43) | func (l *OutboundListener) Close() error {
    method Addr (line 58) | func (l *OutboundListener) Addr() net.Addr {
  type Outbound (line 66) | type Outbound struct
    method Dispatch (line 74) | func (co *Outbound) Dispatch(ctx context.Context, link *transport.Link) {
    method Tag (line 92) | func (co *Outbound) Tag() string {
    method Start (line 97) | func (co *Outbound) Start() error {
    method Close (line 105) | func (co *Outbound) Close() error {
    method SenderSettings (line 114) | func (co *Outbound) SenderSettings() *serial.TypedMessage {
    method ProxySettings (line 119) | func (co *Outbound) ProxySettings() *serial.TypedMessage {

FILE: app/commander/service.go
  type Service (line 12) | type Service interface
  type reflectionService (line 17) | type reflectionService struct
    method Register (line 19) | func (r reflectionService) Register(s *grpc.Server) {
  function init (line 23) | func init() {

FILE: app/dispatcher/config.pb.go
  constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type SessionConfig (line 24) | type SessionConfig struct
    method Reset (line 30) | func (x *SessionConfig) Reset() {
    method String (line 37) | func (x *SessionConfig) String() string {
    method ProtoMessage (line 41) | func (*SessionConfig) ProtoMessage() {}
    method ProtoReflect (line 43) | func (x *SessionConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 56) | func (*SessionConfig) Descriptor() ([]byte, []int) {
  type Config (line 60) | type Config struct
    method Reset (line 67) | func (x *Config) Reset() {
    method String (line 74) | func (x *Config) String() string {
    method ProtoMessage (line 78) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 80) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 93) | func (*Config) Descriptor() ([]byte, []int) {
    method GetSettings (line 97) | func (x *Config) GetSettings() *SessionConfig {
  constant file_app_dispatcher_config_proto_rawDesc (line 106) | file_app_dispatcher_config_proto_rawDesc = "" +
  function file_app_dispatcher_config_proto_rawDescGZIP (line 119) | func file_app_dispatcher_config_proto_rawDescGZIP() []byte {
  function init (line 140) | func init() { file_app_dispatcher_config_proto_init() }
  function file_app_dispatcher_config_proto_init (line 141) | func file_app_dispatcher_config_proto_init() {

FILE: app/dispatcher/default.go
  type cachedReader (line 30) | type cachedReader struct
    method Cache (line 36) | func (r *cachedReader) Cache(b *buf.Buffer, deadline time.Duration) er...
    method readInternal (line 53) | func (r *cachedReader) readInternal() buf.MultiBuffer {
    method ReadMultiBuffer (line 66) | func (r *cachedReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
    method ReadMultiBufferTimeout (line 75) | func (r *cachedReader) ReadMultiBufferTimeout(timeout time.Duration) (...
    method Interrupt (line 84) | func (r *cachedReader) Interrupt() {
  type DefaultDispatcher (line 96) | type DefaultDispatcher struct
    method Init (line 120) | func (d *DefaultDispatcher) Init(config *Config, om outbound.Manager, ...
    method Type (line 129) | func (*DefaultDispatcher) Type() interface{} {
    method Start (line 134) | func (*DefaultDispatcher) Start() error {
    method Close (line 139) | func (*DefaultDispatcher) Close() error { return nil }
    method getLink (line 141) | func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.L...
    method shouldOverride (line 235) | func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result...
    method Dispatch (line 281) | func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination ...
    method DispatchLink (line 338) | func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destinat...
    method routedDispatch (line 448) | func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *...
  function init (line 104) | func init() {
  function WrapLink (line 196) | func WrapLink(ctx context.Context, policyManager policy.Manager, statsMa...
  function sniffer (line 392) | func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bo...

FILE: app/dispatcher/fakednssniffer.go
  function newFakeDNSSniffer (line 16) | func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata...
  type fakeDNSSniffResult (line 52) | type fakeDNSSniffResult struct
    method Protocol (line 56) | func (fakeDNSSniffResult) Protocol() string {
    method Domain (line 60) | func (f fakeDNSSniffResult) Domain() string {
  type fakeDNSExtraOpts (line 64) | type fakeDNSExtraOpts
  constant ipAddressInRange (line 66) | ipAddressInRange fakeDNSExtraOpts = 1
  type ipAddressInRangeOpt (line 68) | type ipAddressInRangeOpt struct
  type DNSThenOthersSniffResult (line 72) | type DNSThenOthersSniffResult struct
    method IsProtoSubsetOf (line 77) | func (f DNSThenOthersSniffResult) IsProtoSubsetOf(protocolName string)...
    method Protocol (line 81) | func (DNSThenOthersSniffResult) Protocol() string {
    method Domain (line 85) | func (f DNSThenOthersSniffResult) Domain() string {
  function newFakeDNSThenOthers (line 89) | func newFakeDNSThenOthers(ctx context.Context, fakeDNSSniffer protocolSn...

FILE: app/dispatcher/sniffer.go
  type SniffResult (line 16) | type SniffResult interface
  type protocolSniffer (line 21) | type protocolSniffer
  type protocolSnifferWithMetadata (line 23) | type protocolSnifferWithMetadata struct
  type Sniffer (line 32) | type Sniffer struct
    method Sniff (line 59) | func (s *Sniffer) Sniff(c context.Context, payload []byte, network net...
    method SniffMetadata (line 88) | func (s *Sniffer) SniffMetadata(c context.Context) (SniffResult, error) {
  function NewSniffer (line 36) | func NewSniffer(ctx context.Context) *Sniffer {
  function CompositeResult (line 115) | func CompositeResult(domainResult SniffResult, protocolResult SniffResul...
  type compositeResult (line 119) | type compositeResult struct
    method Protocol (line 124) | func (c compositeResult) Protocol() string {
    method Domain (line 128) | func (c compositeResult) Domain() string {
    method ProtocolForDomainResult (line 132) | func (c compositeResult) ProtocolForDomainResult() string {
  type SnifferResultComposite (line 136) | type SnifferResultComposite interface
  type SnifferIsProtoSubsetOf (line 140) | type SnifferIsProtoSubsetOf interface

FILE: app/dispatcher/stats.go
  type SizeStatWriter (line 9) | type SizeStatWriter struct
    method WriteMultiBuffer (line 14) | func (w *SizeStatWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
    method Close (line 19) | func (w *SizeStatWriter) Close() error {
    method Interrupt (line 23) | func (w *SizeStatWriter) Interrupt() {

FILE: app/dispatcher/stats_test.go
  type TestCounter (line 11) | type TestCounter
    method Value (line 13) | func (c *TestCounter) Value() int64 {
    method Add (line 17) | func (c *TestCounter) Add(v int64) int64 {
    method Set (line 23) | func (c *TestCounter) Set(v int64) int64 {
  function TestStatsWriter (line 28) | func TestStatsWriter(t *testing.T) {

FILE: app/dns/cache_controller.go
  constant minSizeForEmptyRebuild (line 21) | minSizeForEmptyRebuild  = 512
  constant shrinkAbsoluteThreshold (line 22) | shrinkAbsoluteThreshold = 10240
  constant shrinkRatioThreshold (line 23) | shrinkRatioThreshold    = 0.65
  constant migrationBatchSize (line 24) | migrationBatchSize      = 4096
  type CacheController (line 27) | type CacheController struct
    method CacheCleanup (line 61) | func (c *CacheController) CacheCleanup() error {
    method collectExpiredKeys (line 73) | func (c *CacheController) collectExpiredKeys() ([]string, error) {
    method writeAndShrink (line 103) | func (c *CacheController) writeAndShrink(expiredKeys []string) {
    method migrate (line 176) | func (c *CacheController) migrate() {
    method flush (line 220) | func (c *CacheController) flush(batch []migrationEntry) {
    method updateRecord (line 244) | func (c *CacheController) updateRecord(req *dnsRequest, rep *IPRecord) {
    method findRecords (line 310) | func (c *CacheController) findRecords(domain string) *record {
    method registerSubscribers (line 321) | func (c *CacheController) registerSubscribers(domain string, option dn...
  function NewCacheController (line 43) | func NewCacheController(name string, disableCache bool, serveStale bool,...
  type migrationEntry (line 171) | type migrationEntry struct
  function closeSubscribers (line 332) | func closeSubscribers(sub4 *pubsub.Subscriber, sub6 *pubsub.Subscriber) {

FILE: app/dns/config.go
  function toStrMatcher (line 37) | func toStrMatcher(t DomainMatchingType, domain string) (strmatcher.Match...
  function toNetIP (line 49) | func toNetIP(addrs []net.Address) ([]net.IP, error) {
  function generateRandomTag (line 61) | func generateRandomTag() string {

FILE: app/dns/config.pb.go
  constant _ (line 21) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 23) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type DomainMatchingType (line 26) | type DomainMatchingType
    method Enum (line 51) | func (x DomainMatchingType) Enum() *DomainMatchingType {
    method String (line 57) | func (x DomainMatchingType) String() string {
    method Descriptor (line 61) | func (DomainMatchingType) Descriptor() protoreflect.EnumDescriptor {
    method Type (line 65) | func (DomainMatchingType) Type() protoreflect.EnumType {
    method Number (line 69) | func (x DomainMatchingType) Number() protoreflect.EnumNumber {
    method EnumDescriptor (line 74) | func (DomainMatchingType) EnumDescriptor() ([]byte, []int) {
  constant DomainMatchingType_Full (line 29) | DomainMatchingType_Full      DomainMatchingType = 0
  constant DomainMatchingType_Subdomain (line 30) | DomainMatchingType_Subdomain DomainMatchingType = 1
  constant DomainMatchingType_Keyword (line 31) | DomainMatchingType_Keyword   DomainMatchingType = 2
  constant DomainMatchingType_Regex (line 32) | DomainMatchingType_Regex     DomainMatchingType = 3
  type QueryStrategy (line 78) | type QueryStrategy
    method Enum (line 103) | func (x QueryStrategy) Enum() *QueryStrategy {
    method String (line 109) | func (x QueryStrategy) String() string {
    method Descriptor (line 113) | func (QueryStrategy) Descriptor() protoreflect.EnumDescriptor {
    method Type (line 117) | func (QueryStrategy) Type() protoreflect.EnumType {
    method Number (line 121) | func (x QueryStrategy) Number() protoreflect.EnumNumber {
    method EnumDescriptor (line 126) | func (QueryStrategy) EnumDescriptor() ([]byte, []int) {
  constant QueryStrategy_USE_IP (line 81) | QueryStrategy_USE_IP  QueryStrategy = 0
  constant QueryStrategy_USE_IP4 (line 82) | QueryStrategy_USE_IP4 QueryStrategy = 1
  constant QueryStrategy_USE_IP6 (line 83) | QueryStrategy_USE_IP6 QueryStrategy = 2
  constant QueryStrategy_USE_SYS (line 84) | QueryStrategy_USE_SYS QueryStrategy = 3
  type NameServer (line 130) | type NameServer struct
    method Reset (line 153) | func (x *NameServer) Reset() {
    method String (line 160) | func (x *NameServer) String() string {
    method ProtoMessage (line 164) | func (*NameServer) ProtoMessage() {}
    method ProtoReflect (line 166) | func (x *NameServer) ProtoReflect() protoreflect.Message {
    method Descriptor (line 179) | func (*NameServer) Descriptor() ([]byte, []int) {
    method GetAddress (line 183) | func (x *NameServer) GetAddress() *net.Endpoint {
    method GetClientIp (line 190) | func (x *NameServer) GetClientIp() []byte {
    method GetSkipFallback (line 197) | func (x *NameServer) GetSkipFallback() bool {
    method GetPrioritizedDomain (line 204) | func (x *NameServer) GetPrioritizedDomain() []*NameServer_PriorityDoma...
    method GetExpectedGeoip (line 211) | func (x *NameServer) GetExpectedGeoip() []*router.GeoIP {
    method GetOriginalRules (line 218) | func (x *NameServer) GetOriginalRules() []*NameServer_OriginalRule {
    method GetQueryStrategy (line 225) | func (x *NameServer) GetQueryStrategy() QueryStrategy {
    method GetActPrior (line 232) | func (x *NameServer) GetActPrior() bool {
    method GetTag (line 239) | func (x *NameServer) GetTag() string {
    method GetTimeoutMs (line 246) | func (x *NameServer) GetTimeoutMs() uint64 {
    method GetDisableCache (line 253) | func (x *NameServer) GetDisableCache() bool {
    method GetServeStale (line 260) | func (x *NameServer) GetServeStale() bool {
    method GetServeExpiredTTL (line 267) | func (x *NameServer) GetServeExpiredTTL() uint32 {
    method GetFinalQuery (line 274) | func (x *NameServer) GetFinalQuery() bool {
    method GetUnexpectedGeoip (line 281) | func (x *NameServer) GetUnexpectedGeoip() []*router.GeoIP {
    method GetActUnprior (line 288) | func (x *NameServer) GetActUnprior() bool {
    method GetPolicyID (line 295) | func (x *NameServer) GetPolicyID() uint32 {
  type Config (line 302) | type Config struct
    method Reset (line 325) | func (x *Config) Reset() {
    method String (line 332) | func (x *Config) String() string {
    method ProtoMessage (line 336) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 338) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 351) | func (*Config) Descriptor() ([]byte, []int) {
    method GetNameServer (line 355) | func (x *Config) GetNameServer() []*NameServer {
    method GetClientIp (line 362) | func (x *Config) GetClientIp() []byte {
    method GetStaticHosts (line 369) | func (x *Config) GetStaticHosts() []*Config_HostMapping {
    method GetTag (line 376) | func (x *Config) GetTag() string {
    method GetDisableCache (line 383) | func (x *Config) GetDisableCache() bool {
    method GetServeStale (line 390) | func (x *Config) GetServeStale() bool {
    method GetServeExpiredTTL (line 397) | func (x *Config) GetServeExpiredTTL() uint32 {
    method GetQueryStrategy (line 404) | func (x *Config) GetQueryStrategy() QueryStrategy {
    method GetDisableFallback (line 411) | func (x *Config) GetDisableFallback() bool {
    method GetDisableFallbackIfMatch (line 418) | func (x *Config) GetDisableFallbackIfMatch() bool {
    method GetEnableParallelQuery (line 425) | func (x *Config) GetEnableParallelQuery() bool {
  type NameServer_PriorityDomain (line 432) | type NameServer_PriorityDomain struct
    method Reset (line 440) | func (x *NameServer_PriorityDomain) Reset() {
    method String (line 447) | func (x *NameServer_PriorityDomain) String() string {
    method ProtoMessage (line 451) | func (*NameServer_PriorityDomain) ProtoMessage() {}
    method ProtoReflect (line 453) | func (x *NameServer_PriorityDomain) ProtoReflect() protoreflect.Message {
    method Descriptor (line 466) | func (*NameServer_PriorityDomain) Descriptor() ([]byte, []int) {
    method GetType (line 470) | func (x *NameServer_PriorityDomain) GetType() DomainMatchingType {
    method GetDomain (line 477) | func (x *NameServer_PriorityDomain) GetDomain() string {
  type NameServer_OriginalRule (line 484) | type NameServer_OriginalRule struct
    method Reset (line 492) | func (x *NameServer_OriginalRule) Reset() {
    method String (line 499) | func (x *NameServer_OriginalRule) String() string {
    method ProtoMessage (line 503) | func (*NameServer_OriginalRule) ProtoMessage() {}
    method ProtoReflect (line 505) | func (x *NameServer_OriginalRule) ProtoReflect() protoreflect.Message {
    method Descriptor (line 518) | func (*NameServer_OriginalRule) Descriptor() ([]byte, []int) {
    method GetRule (line 522) | func (x *NameServer_OriginalRule) GetRule() string {
    method GetSize (line 529) | func (x *NameServer_OriginalRule) GetSize() uint32 {
  type Config_HostMapping (line 536) | type Config_HostMapping struct
    method Reset (line 548) | func (x *Config_HostMapping) Reset() {
    method String (line 555) | func (x *Config_HostMapping) String() string {
    method ProtoMessage (line 559) | func (*Config_HostMapping) ProtoMessage() {}
    method ProtoReflect (line 561) | func (x *Config_HostMapping) ProtoReflect() protoreflect.Message {
    method Descriptor (line 574) | func (*Config_HostMapping) Descriptor() ([]byte, []int) {
    method GetType (line 578) | func (x *Config_HostMapping) GetType() DomainMatchingType {
    method GetDomain (line 585) | func (x *Config_HostMapping) GetDomain() string {
    method GetIp (line 592) | func (x *Config_HostMapping) GetIp() [][]byte {
    method GetProxiedDomain (line 599) | func (x *Config_HostMapping) GetProxiedDomain() string {
  constant file_app_dns_config_proto_rawDesc (line 608) | file_app_dns_config_proto_rawDesc = "" +
  function file_app_dns_config_proto_rawDescGZIP (line 685) | func file_app_dns_config_proto_rawDescGZIP() []byte {
  function init (line 724) | func init() { file_app_dns_config_proto_init() }
  function file_app_dns_config_proto_init (line 725) | func file_app_dns_config_proto_init() {

FILE: app/dns/dns.go
  type DNS (line 26) | type DNS struct
    method Type (line 198) | func (*DNS) Type() interface{} {
    method Start (line 203) | func (s *DNS) Start() error {
    method Close (line 208) | func (s *DNS) Close() error {
    method IsOwnLink (line 213) | func (s *DNS) IsOwnLink(ctx context.Context) bool {
    method LookupIP (line 227) | func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, ...
    method sortClients (line 278) | func (s *DNS) sortClients(domain string) []*Client {
    method serialQuery (line 366) | func (s *DNS) serialQuery(domain string, option dns.IPOption) ([]net.I...
    method parallelQuery (line 389) | func (s *DNS) parallelQuery(domain string, option dns.IPOption) ([]net...
  type DomainMatcherInfo (line 41) | type DomainMatcherInfo struct
  function New (line 47) | func New(ctx context.Context, config *Config) (*DNS, error) {
  function mergeQueryErrors (line 342) | func mergeQueryErrors(domain string, errs []error) error {
  type queryResult (line 443) | type queryResult struct
  function asyncQueryAll (line 450) | func asyncQueryAll(domain string, option dns.IPOption, clients []*Client...
  type group (line 479) | type group struct
  function makeGroups (line 482) | func makeGroups( /*ctx context.Context,*/ clients []*Client) ([]group, [...
  function init (line 538) | func init() {
  function probeRoutes (line 544) | func probeRoutes() (ipv4 bool, ipv6 bool) {
  function checkRoutes (line 563) | func checkRoutes() (bool, bool) {
  function detectGUIPlatform (line 593) | func detectGUIPlatform() bool {

FILE: app/dns/dns_test.go
  type staticHandler (line 25) | type staticHandler struct
    method ServeDNS (line 27) | func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
  function TestUDPServerSubnet (line 114) | func TestUDPServerSubnet(t *testing.T) {
  function TestUDPServer (line 174) | func TestUDPServer(t *testing.T) {
  function TestPrioritizedDomain (line 296) | func TestPrioritizedDomain(t *testing.T) {
  function TestUDPServerIPv6 (line 382) | func TestUDPServerIPv6(t *testing.T) {
  function TestStaticHostDomain (line 443) | func TestStaticHostDomain(t *testing.T) {
  function TestIPMatch (line 514) | func TestIPMatch(t *testing.T) {
  function TestLocalDomain (line 628) | func TestLocalDomain(t *testing.T) {
  function TestMultiMatchPrioritizedDomain (line 856) | func TestMultiMatchPrioritizedDomain(t *testing.T) {

FILE: app/dns/dnscommon.go
  function Fqdn (line 23) | func Fqdn(domain string) string {
  type record (line 30) | type record struct
  type IPRecord (line 36) | type IPRecord struct
    method getIPs (line 44) | func (r *IPRecord) getIPs() ([]net.IP, int32, error) {
  type dnsRequest (line 64) | type dnsRequest struct
  function genEDNS0Options (line 72) | func genEDNS0Options(clientIP net.IP, padding int) *dnsmessage.Resource {
  function buildReqMsgs (line 130) | func buildReqMsgs(domain string, option dns_feature.IPOption, reqIDGen f...
  function parseResponse (line 182) | func parseResponse(payload []byte) (*IPRecord, error) {
  function toDnsContext (line 250) | func toDnsContext(ctx context.Context, addr string) context.Context {

FILE: app/dns/dnscommon_test.go
  function Test_parseResponse (line 16) | func Test_parseResponse(t *testing.T) {
  function Test_buildReqMsgs (line 100) | func Test_buildReqMsgs(t *testing.T) {
  function Test_genEDNS0Options (line 144) | func Test_genEDNS0Options(t *testing.T) {
  function TestFqdn (line 166) | func TestFqdn(t *testing.T) {

FILE: app/dns/fakedns/fake.go
  type Holder (line 17) | type Holder struct
    method IsIPInIPPool (line 25) | func (fkdns *Holder) IsIPInIPPool(ip net.Address) bool {
    method GetFakeIPForDomain3 (line 32) | func (fkdns *Holder) GetFakeIPForDomain3(domain string, ipv4, ipv6 boo...
    method Type (line 40) | func (*Holder) Type() interface{} {
    method Start (line 44) | func (fkdns *Holder) Start() error {
    method Close (line 51) | func (fkdns *Holder) Close() error {
    method initializeFromConfig (line 76) | func (fkdns *Holder) initializeFromConfig() error {
    method initialize (line 80) | func (fkdns *Holder) initialize(ipPoolCidr string, lruSize int) error {
    method GetFakeIPForDomain (line 100) | func (fkdns *Holder) GetFakeIPForDomain(domain string) []net.Address {
    method GetDomainFromFakeDNS (line 133) | func (fkdns *Holder) GetDomainFromFakeDNS(ip net.Address) string {
  function NewFakeDNSHolder (line 58) | func NewFakeDNSHolder() (*Holder, error) {
  function NewFakeDNSHolderConfigOnly (line 72) | func NewFakeDNSHolderConfigOnly(conf *FakeDnsPool) (*Holder, error) {
  type HolderMulti (line 144) | type HolderMulti struct
    method IsIPInIPPool (line 150) | func (h *HolderMulti) IsIPInIPPool(ip net.Address) bool {
    method GetFakeIPForDomain3 (line 162) | func (h *HolderMulti) GetFakeIPForDomain3(domain string, ipv4, ipv6 bo...
    method GetFakeIPForDomain (line 170) | func (h *HolderMulti) GetFakeIPForDomain(domain string) []net.Address {
    method GetDomainFromFakeDNS (line 178) | func (h *HolderMulti) GetDomainFromFakeDNS(ip net.Address) string {
    method Type (line 187) | func (h *HolderMulti) Type() interface{} {
    method Start (line 191) | func (h *HolderMulti) Start() error {
    method Close (line 204) | func (h *HolderMulti) Close() error {
    method createHolderGroups (line 213) | func (h *HolderMulti) createHolderGroups() error {
  function NewFakeDNSHolderMulti (line 224) | func NewFakeDNSHolderMulti(conf *FakeDnsPoolMulti) (*HolderMulti, error) {
  function init (line 232) | func init() {

FILE: app/dns/fakedns/fakedns.pb.go
  constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type FakeDnsPool (line 24) | type FakeDnsPool struct
    method Reset (line 32) | func (x *FakeDnsPool) Reset() {
    method String (line 39) | func (x *FakeDnsPool) String() string {
    method ProtoMessage (line 43) | func (*FakeDnsPool) ProtoMessage() {}
    method ProtoReflect (line 45) | func (x *FakeDnsPool) ProtoReflect() protoreflect.Message {
    method Descriptor (line 58) | func (*FakeDnsPool) Descriptor() ([]byte, []int) {
    method GetIpPool (line 62) | func (x *FakeDnsPool) GetIpPool() string {
    method GetLruSize (line 69) | func (x *FakeDnsPool) GetLruSize() int64 {
  type FakeDnsPoolMulti (line 76) | type FakeDnsPoolMulti struct
    method Reset (line 83) | func (x *FakeDnsPoolMulti) Reset() {
    method String (line 90) | func (x *FakeDnsPoolMulti) String() string {
    method ProtoMessage (line 94) | func (*FakeDnsPoolMulti) ProtoMessage() {}
    method ProtoReflect (line 96) | func (x *FakeDnsPoolMulti) ProtoReflect() protoreflect.Message {
    method Descriptor (line 109) | func (*FakeDnsPoolMulti) Descriptor() ([]byte, []int) {
    method GetPools (line 113) | func (x *FakeDnsPoolMulti) GetPools() []*FakeDnsPool {
  constant file_app_dns_fakedns_fakedns_proto_rawDesc (line 122) | file_app_dns_fakedns_fakedns_proto_rawDesc = "" +
  function file_app_dns_fakedns_fakedns_proto_rawDescGZIP (line 137) | func file_app_dns_fakedns_fakedns_proto_rawDescGZIP() []byte {
  function init (line 158) | func init() { file_app_dns_fakedns_fakedns_proto_init() }
  function file_app_dns_fakedns_fakedns_proto_init (line 159) | func file_app_dns_fakedns_fakedns_proto_init() {

FILE: app/dns/fakedns/fakedns_test.go
  function TestNewFakeDnsHolder (line 17) | func TestNewFakeDnsHolder(_ *testing.T) {
  function TestFakeDnsHolderCreateMapping (line 22) | func TestFakeDnsHolderCreateMapping(t *testing.T) {
  function TestFakeDnsHolderCreateMappingMany (line 30) | func TestFakeDnsHolderCreateMappingMany(t *testing.T) {
  function TestFakeDnsHolderCreateMappingManyAndResolve (line 42) | func TestFakeDnsHolderCreateMappingManyAndResolve(t *testing.T) {
  function TestFakeDnsHolderCreateMappingManySingleDomain (line 60) | func TestFakeDnsHolderCreateMappingManySingleDomain(t *testing.T) {
  function TestGetFakeIPForDomainConcurrently (line 69) | func TestGetFakeIPForDomainConcurrently(t *testing.T) {
  function testGetFakeIP (line 87) | func testGetFakeIP(index int, addr [][]net.Address, fkdns *Holder) func(...
  function TestFakeDnsHolderCreateMappingAndRollOver (line 94) | func TestFakeDnsHolderCreateMappingAndRollOver(t *testing.T) {
  function TestFakeDNSMulti (line 131) | func TestFakeDNSMulti(t *testing.T) {

FILE: app/dns/hosts.go
  type StaticHosts (line 15) | type StaticHosts struct
    method lookupInternal (line 79) | func (h *StaticHosts) lookupInternal(domain string) ([]net.Address, er...
    method lookup (line 100) | func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDe...
    method Lookup (line 124) | func (h *StaticHosts) Lookup(domain string, option dns.IPOption) ([]ne...
  function NewStaticHosts (line 21) | func NewStaticHosts(hosts []*Config_HostMapping) (*StaticHosts, error) {
  function filterIP (line 69) | func filterIP(ips []net.Address, option dns.IPOption) []net.Address {
  function NewStaticHostsFromCache (line 127) | func NewStaticHostsFromCache(matcher strmatcher.IndexMatcher, hostIPs ma...
  function parseIPs (line 162) | func parseIPs(raw []string) []net.Address {

FILE: app/dns/hosts_test.go
  function TestStaticHosts (line 15) | func TestStaticHosts(t *testing.T) {
  function TestStaticHostsFromCache (line 135) | func TestStaticHostsFromCache(t *testing.T) {

FILE: app/dns/nameserver.go
  type mphMatcherWrapper (line 22) | type mphMatcherWrapper struct
    method Match (line 26) | func (w *mphMatcherWrapper) Match(s string) bool {
    method String (line 30) | func (w *mphMatcherWrapper) String() string {
  type Server (line 35) | type Server interface
  type Client (line 46) | type Client struct
    method Name (line 254) | func (c *Client) Name() string {
    method QueryIP (line 259) | func (c *Client) QueryIP(ctx context.Context, domain string, option dn...
  function NewServer (line 63) | func NewServer(ctx context.Context, dest net.Destination, dispatcher rou...
  function NewClient (line 107) | func NewClient(
  function ResolveIpOptionOverride (line 321) | func ResolveIpOptionOverride(queryStrategy QueryStrategy, ipOption dns.I...

FILE: app/dns/nameserver_cached.go
  type CachedNameserver (line 15) | type CachedNameserver interface
  function queryIP (line 22) | func queryIP(ctx context.Context, s CachedNameserver, domain string, opt...
  function pull (line 50) | func pull(ctx context.Context, s CachedNameserver, fqdn string, option d...
  function fetch (line 57) | func fetch(ctx context.Context, s CachedNameserver, fqdn string, option ...
  type result (line 76) | type result struct
  function doFetch (line 82) | func doFetch(ctx context.Context, s CachedNameserver, fqdn string, optio...
  function merge (line 130) | func merge(option dns.IPOption, rec4 *IPRecord, rec6 *IPRecord, errs ......

FILE: app/dns/nameserver_doh.go
  type DoHNameServer (line 32) | type DoHNameServer struct
    method Name (line 115) | func (s *DoHNameServer) Name() string {
    method IsDisableCache (line 120) | func (s *DoHNameServer) IsDisableCache() bool {
    method newReqID (line 124) | func (s *DoHNameServer) newReqID() uint16 {
    method getCacheController (line 129) | func (s *DoHNameServer) getCacheController() *CacheController {
    method sendQuery (line 134) | func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh...
    method dohHTTPSContext (line 208) | func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte)...
    method QueryIP (line 237) | func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, op...
  function NewDoHNameServer (line 40) | func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, h2c b...

FILE: app/dns/nameserver_doh_test.go
  function TestDOHNameServer (line 16) | func TestDOHNameServer(t *testing.T) {
  function TestDOHNameServerWithCache (line 33) | func TestDOHNameServerWithCache(t *testing.T) {
  function TestDOHNameServerWithIPv4Override (line 61) | func TestDOHNameServerWithIPv4Override(t *testing.T) {
  function TestDOHNameServerWithIPv6Override (line 84) | func TestDOHNameServerWithIPv6Override(t *testing.T) {

FILE: app/dns/nameserver_fakedns.go
  type FakeDNSServer (line 11) | type FakeDNSServer struct
    method Name (line 19) | func (FakeDNSServer) Name() string {
    method IsDisableCache (line 24) | func (s *FakeDNSServer) IsDisableCache() bool {
    method QueryIP (line 28) | func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, op...
  function NewFakeDNSServer (line 15) | func NewFakeDNSServer(fd dns.FakeDNSEngine) *FakeDNSServer {

FILE: app/dns/nameserver_local.go
  type LocalNameServer (line 15) | type LocalNameServer struct
    method QueryIP (line 20) | func (s *LocalNameServer) QueryIP(ctx context.Context, domain string, ...
    method Name (line 34) | func (s *LocalNameServer) Name() string {
    method IsDisableCache (line 39) | func (s *LocalNameServer) IsDisableCache() bool {
  function NewLocalNameServer (line 44) | func NewLocalNameServer() *LocalNameServer {
  function NewLocalDNSClient (line 52) | func NewLocalDNSClient(ipOption dns.IPOption) *Client {

FILE: app/dns/nameserver_local_test.go
  function TestLocalNameServer (line 13) | func TestLocalNameServer(t *testing.T) {

FILE: app/dns/nameserver_quic.go
  constant NextProtoDQ (line 25) | NextProtoDQ = "doq"
  constant handshakeTimeout (line 27) | handshakeTimeout = time.Second * 8
  type QUICNameServer (line 30) | type QUICNameServer struct
    method Name (line 61) | func (s *QUICNameServer) Name() string {
    method IsDisableCache (line 66) | func (s *QUICNameServer) IsDisableCache() bool {
    method newReqID (line 70) | func (s *QUICNameServer) newReqID() uint16 {
    method getCacheController (line 75) | func (s *QUICNameServer) getCacheController() *CacheController { retur...
    method sendQuery (line 78) | func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrC...
    method QueryIP (line 201) | func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, o...
    method getConnection (line 214) | func (s *QUICNameServer) getConnection() (*quic.Conn, error) {
    method openConnection (line 248) | func (s *QUICNameServer) openConnection() (*quic.Conn, error) {
    method openStream (line 268) | func (s *QUICNameServer) openStream(ctx context.Context) (*quic.Stream...
  function NewQUICNameServer (line 39) | func NewQUICNameServer(url *url.URL, disableCache bool, serveStale bool,...
  function isActive (line 205) | func isActive(s *quic.Conn) bool {

FILE: app/dns/nameserver_quic_test.go
  function TestQUICNameServer (line 16) | func TestQUICNameServer(t *testing.T) {
  function TestQUICNameServerWithIPv4Override (line 43) | func TestQUICNameServerWithIPv4Override(t *testing.T) {
  function TestQUICNameServerWithIPv6Override (line 66) | func TestQUICNameServerWithIPv6Override(t *testing.T) {

FILE: app/dns/nameserver_tcp.go
  type TCPNameServer (line 23) | type TCPNameServer struct
    method Name (line 94) | func (s *TCPNameServer) Name() string {
    method IsDisableCache (line 99) | func (s *TCPNameServer) IsDisableCache() bool {
    method newReqID (line 103) | func (s *TCPNameServer) newReqID() uint16 {
    method getCacheController (line 108) | func (s *TCPNameServer) getCacheController() *CacheController {
    method sendQuery (line 113) | func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh...
    method QueryIP (line 233) | func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, op...
  function NewTCPNameServer (line 32) | func NewTCPNameServer(
  function NewTCPLocalNameServer (line 60) | func NewTCPLocalNameServer(url *url.URL, disableCache bool, serveStale b...
  function baseTCPNameServer (line 74) | func baseTCPNameServer(url *url.URL, prefix string, disableCache bool, s...

FILE: app/dns/nameserver_tcp_test.go
  function TestTCPLocalNameServer (line 16) | func TestTCPLocalNameServer(t *testing.T) {
  function TestTCPLocalNameServerWithCache (line 33) | func TestTCPLocalNameServerWithCache(t *testing.T) {
  function TestTCPLocalNameServerWithIPv4Override (line 61) | func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
  function TestTCPLocalNameServerWithIPv6Override (line 85) | func TestTCPLocalNameServerWithIPv6Override(t *testing.T) {

FILE: app/dns/nameserver_udp.go
  type ClassicNameServer (line 23) | type ClassicNameServer struct
    method Name (line 63) | func (s *ClassicNameServer) Name() string {
    method IsDisableCache (line 68) | func (s *ClassicNameServer) IsDisableCache() bool {
    method RequestsCleanup (line 73) | func (s *ClassicNameServer) RequestsCleanup() error {
    method HandleResponse (line 96) | func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet...
    method newReqID (line 144) | func (s *ClassicNameServer) newReqID() uint16 {
    method addPendingRequest (line 148) | func (s *ClassicNameServer) addPendingRequest(req *udpDnsRequest) {
    method getCacheController (line 158) | func (s *ClassicNameServer) getCacheController() *CacheController {
    method sendQuery (line 163) | func (s *ClassicNameServer) sendQuery(ctx context.Context, noResponseE...
    method QueryIP (line 189) | func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string...
  type udpDnsRequest (line 34) | type udpDnsRequest struct
  function NewClassicNameServer (line 40) | func NewClassicNameServer(address net.Destination, dispatcher routing.Di...

FILE: app/log/command/command.go
  type LoggerServer (line 13) | type LoggerServer struct
    method RestartLogger (line 18) | func (s *LoggerServer) RestartLogger(ctx context.Context, request *Res...
    method mustEmbedUnimplementedLoggerServiceServer (line 32) | func (s *LoggerServer) mustEmbedUnimplementedLoggerServiceServer() {}
  type service (line 34) | type service struct
    method Register (line 38) | func (s *service) Register(server *grpc.Server) {
  function init (line 50) | func init() {

FILE: app/log/command/command_test.go
  function TestLoggerRestart (line 18) | func TestLoggerRestart(t *testing.T) {

FILE: app/log/command/config.pb.go
  constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type Config (line 24) | type Config struct
    method Reset (line 30) | func (x *Config) Reset() {
    method String (line 37) | func (x *Config) String() string {
    method ProtoMessage (line 41) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 43) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 56) | func (*Config) Descriptor() ([]byte, []int) {
  type RestartLoggerRequest (line 60) | type RestartLoggerRequest struct
    method Reset (line 66) | func (x *RestartLoggerRequest) Reset() {
    method String (line 73) | func (x *RestartLoggerRequest) String() string {
    method ProtoMessage (line 77) | func (*RestartLoggerRequest) ProtoMessage() {}
    method ProtoReflect (line 79) | func (x *RestartLoggerRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 92) | func (*RestartLoggerRequest) Descriptor() ([]byte, []int) {
  type RestartLoggerResponse (line 96) | type RestartLoggerResponse struct
    method Reset (line 102) | func (x *RestartLoggerResponse) Reset() {
    method String (line 109) | func (x *RestartLoggerResponse) String() string {
    method ProtoMessage (line 113) | func (*RestartLoggerResponse) ProtoMessage() {}
    method ProtoReflect (line 115) | func (x *RestartLoggerResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 128) | func (*RestartLoggerResponse) Descriptor() ([]byte, []int) {
  constant file_app_log_command_config_proto_rawDesc (line 134) | file_app_log_command_config_proto_rawDesc = "" +
  function file_app_log_command_config_proto_rawDescGZIP (line 149) | func file_app_log_command_config_proto_rawDescGZIP() []byte {
  function init (line 172) | func init() { file_app_log_command_config_proto_init() }
  function file_app_log_command_config_proto_init (line 173) | func file_app_log_command_config_proto_init() {

FILE: app/log/command/config_grpc.pb.go
  constant _ (line 19) | _ = grpc.SupportPackageIsVersion9
  constant LoggerService_RestartLogger_FullMethodName (line 22) | LoggerService_RestartLogger_FullMethodName = "/xray.app.log.command.Logg...
  type LoggerServiceClient (line 28) | type LoggerServiceClient interface
  type loggerServiceClient (line 32) | type loggerServiceClient struct
    method RestartLogger (line 40) | func (c *loggerServiceClient) RestartLogger(ctx context.Context, in *R...
  function NewLoggerServiceClient (line 36) | func NewLoggerServiceClient(cc grpc.ClientConnInterface) LoggerServiceCl...
  type LoggerServiceServer (line 53) | type LoggerServiceServer interface
  type UnimplementedLoggerServiceServer (line 63) | type UnimplementedLoggerServiceServer struct
    method RestartLogger (line 65) | func (UnimplementedLoggerServiceServer) RestartLogger(context.Context,...
    method mustEmbedUnimplementedLoggerServiceServer (line 68) | func (UnimplementedLoggerServiceServer) mustEmbedUnimplementedLoggerSe...
    method testEmbeddedByValue (line 69) | func (UnimplementedLoggerServiceServer) testEmbeddedByValue()         ...
  type UnsafeLoggerServiceServer (line 74) | type UnsafeLoggerServiceServer interface
  function RegisterLoggerServiceServer (line 78) | func RegisterLoggerServiceServer(s grpc.ServiceRegistrar, srv LoggerServ...
  function _LoggerService_RestartLogger_Handler (line 89) | func _LoggerService_RestartLogger_Handler(srv interface{}, ctx context.C...

FILE: app/log/config.pb.go
  constant _ (line 20) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 22) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type LogType (line 25) | type LogType
    method Enum (line 50) | func (x LogType) Enum() *LogType {
    method String (line 56) | func (x LogType) String() string {
    method Descriptor (line 60) | func (LogType) Descriptor() protoreflect.EnumDescriptor {
    method Type (line 64) | func (LogType) Type() protoreflect.EnumType {
    method Number (line 68) | func (x LogType) Number() protoreflect.EnumNumber {
    method EnumDescriptor (line 73) | func (LogType) EnumDescriptor() ([]byte, []int) {
  constant LogType_None (line 28) | LogType_None    LogType = 0
  constant LogType_Console (line 29) | LogType_Console LogType = 1
  constant LogType_File (line 30) | LogType_File    LogType = 2
  constant LogType_Event (line 31) | LogType_Event   LogType = 3
  type Config (line 77) | type Config struct
    method Reset (line 90) | func (x *Config) Reset() {
    method String (line 97) | func (x *Config) String() string {
    method ProtoMessage (line 101) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 103) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 116) | func (*Config) Descriptor() ([]byte, []int) {
    method GetErrorLogType (line 120) | func (x *Config) GetErrorLogType() LogType {
    method GetErrorLogLevel (line 127) | func (x *Config) GetErrorLogLevel() log.Severity {
    method GetErrorLogPath (line 134) | func (x *Config) GetErrorLogPath() string {
    method GetAccessLogType (line 141) | func (x *Config) GetAccessLogType() LogType {
    method GetAccessLogPath (line 148) | func (x *Config) GetAccessLogPath() string {
    method GetEnableDnsLog (line 155) | func (x *Config) GetEnableDnsLog() bool {
    method GetMaskAddress (line 162) | func (x *Config) GetMaskAddress() string {
  constant file_app_log_config_proto_rawDesc (line 171) | file_app_log_config_proto_rawDesc = "" +
  function file_app_log_config_proto_rawDescGZIP (line 194) | func file_app_log_config_proto_rawDescGZIP() []byte {
  function init (line 219) | func init() { file_app_log_config_proto_init() }
  function file_app_log_config_proto_init (line 220) | func file_app_log_config_proto_init() {

FILE: app/log/log.go
  type Instance (line 17) | type Instance struct
    method initAccessLogger (line 54) | func (g *Instance) initAccessLogger() error {
    method initErrorLogger (line 65) | func (g *Instance) initErrorLogger() error {
    method Type (line 77) | func (*Instance) Type() interface{} {
    method startInternal (line 81) | func (g *Instance) startInternal() error {
    method Start (line 102) | func (g *Instance) Start() error {
    method Handle (line 107) | func (g *Instance) Handle(msg log.Message) {
    method Close (line 145) | func (g *Instance) Close() error {
  function New (line 29) | func New(ctx context.Context, config *Config) (*Instance, error) {
  function ParseMaskAddress (line 166) | func ParseMaskAddress(c string) (int, int, error) {
  type MaskedMsgWrapper (line 204) | type MaskedMsgWrapper struct
    method String (line 215) | func (m *MaskedMsgWrapper) String() string {
  function init (line 252) | func init() {

FILE: app/log/log_creator.go
  type HandlerCreatorOptions (line 11) | type HandlerCreatorOptions struct
  type HandlerCreator (line 15) | type HandlerCreator
  function RegisterHandlerCreator (line 21) | func RegisterHandlerCreator(logType LogType, f HandlerCreator) error {
  function createHandler (line 33) | func createHandler(logType LogType, options HandlerCreatorOptions) (log....
  function init (line 44) | func init() {

FILE: app/log/log_test.go
  function TestCustomLogHandler (line 15) | func TestCustomLogHandler(t *testing.T) {
  function TestMaskAddress (line 55) | func TestMaskAddress(t *testing.T) {

FILE: app/metrics/config.pb.go
  constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type Config (line 25) | type Config struct
    method Reset (line 34) | func (x *Config) Reset() {
    method String (line 41) | func (x *Config) String() string {
    method ProtoMessage (line 45) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 47) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 60) | func (*Config) Descriptor() ([]byte, []int) {
    method GetTag (line 64) | func (x *Config) GetTag() string {
    method GetListen (line 71) | func (x *Config) GetListen() string {
  constant file_app_metrics_config_proto_rawDesc (line 80) | file_app_metrics_config_proto_rawDesc = "" +
  function file_app_metrics_config_proto_rawDescGZIP (line 93) | func file_app_metrics_config_proto_rawDescGZIP() []byte {
  function init (line 112) | func init() { file_app_metrics_config_proto_init() }
  function file_app_metrics_config_proto_init (line 113) | func file_app_metrics_config_proto_init() {

FILE: app/metrics/metrics.go
  type MetricsHandler (line 22) | type MetricsHandler struct
    method Type (line 88) | func (p *MetricsHandler) Type() interface{} {
    method Start (line 92) | func (p *MetricsHandler) Start() error {
    method Close (line 131) | func (p *MetricsHandler) Close() error {
  function NewMetricsHandler (line 32) | func NewMetricsHandler(ctx context.Context, config *Config) (*MetricsHan...
  function init (line 135) | func init() {

FILE: app/metrics/outbound.go
  type OutboundListener (line 17) | type OutboundListener struct
    method add (line 22) | func (l *OutboundListener) add(conn net.Conn) {
    method Accept (line 33) | func (l *OutboundListener) Accept() (net.Conn, error) {
    method Close (line 43) | func (l *OutboundListener) Close() error {
    method Addr (line 58) | func (l *OutboundListener) Addr() net.Addr {
  type Outbound (line 66) | type Outbound struct
    method Dispatch (line 74) | func (co *Outbound) Dispatch(ctx context.Context, link *transport.Link) {
    method Tag (line 92) | func (co *Outbound) Tag() string {
    method Start (line 97) | func (co *Outbound) Start() error {
    method Close (line 105) | func (co *Outbound) Close() error {
    method SenderSettings (line 114) | func (co *Outbound) SenderSettings() *serial.TypedMessage {
    method ProxySettings (line 119) | func (co *Outbound) ProxySettings() *serial.TypedMessage {

FILE: app/observatory/burst/burst.go
  constant rttFailed (line 9) | rttFailed = time.Duration(math.MaxInt64 - iota)
  constant rttUntested (line 10) | rttUntested
  constant rttUnqualified (line 11) | rttUnqualified

FILE: app/observatory/burst/burstobserver.go
  type Observer (line 19) | type Observer struct
    method GetObservation (line 31) | func (o *Observer) GetObservation(ctx context.Context) (proto.Message,...
    method createResult (line 35) | func (o *Observer) createResult() []*observatory.OutboundStatus {
    method Type (line 61) | func (o *Observer) Type() interface{} {
    method Start (line 65) | func (o *Observer) Start() error {
    method Close (line 82) | func (o *Observer) Close() error {
  function New (line 90) | func New(ctx context.Context, config *Config) (*Observer, error) {
  function init (line 109) | func init() {

FILE: app/observatory/burst/config.pb.go
  constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type Config (line 24) | type Config struct
    method Reset (line 33) | func (x *Config) Reset() {
    method String (line 40) | func (x *Config) String() string {
    method ProtoMessage (line 44) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 46) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 59) | func (*Config) Descriptor() ([]byte, []int) {
    method GetSubjectSelector (line 63) | func (x *Config) GetSubjectSelector() []string {
    method GetPingConfig (line 70) | func (x *Config) GetPingConfig() *HealthPingConfig {
  type HealthPingConfig (line 77) | type HealthPingConfig struct
    method Reset (line 96) | func (x *HealthPingConfig) Reset() {
    method String (line 103) | func (x *HealthPingConfig) String() string {
    method ProtoMessage (line 107) | func (*HealthPingConfig) ProtoMessage() {}
    method ProtoReflect (line 109) | func (x *HealthPingConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 122) | func (*HealthPingConfig) Descriptor() ([]byte, []int) {
    method GetDestination (line 126) | func (x *HealthPingConfig) GetDestination() string {
    method GetConnectivity (line 133) | func (x *HealthPingConfig) GetConnectivity() string {
    method GetInterval (line 140) | func (x *HealthPingConfig) GetInterval() int64 {
    method GetSamplingCount (line 147) | func (x *HealthPingConfig) GetSamplingCount() int32 {
    method GetTimeout (line 154) | func (x *HealthPingConfig) GetTimeout() int64 {
    method GetHttpMethod (line 161) | func (x *HealthPingConfig) GetHttpMethod() string {
  constant file_app_observatory_burst_config_proto_rawDesc (line 170) | file_app_observatory_burst_config_proto_rawDesc = "" +
  function file_app_observatory_burst_config_proto_rawDescGZIP (line 193) | func file_app_observatory_burst_config_proto_rawDescGZIP() []byte {
  function init (line 214) | func init() { file_app_observatory_burst_config_proto_init() }
  function file_app_observatory_burst_config_proto_init (line 215) | func file_app_observatory_burst_config_proto_init() {

FILE: app/observatory/burst/healthping.go
  type HealthPingSettings (line 16) | type HealthPingSettings struct
  type HealthPing (line 26) | type HealthPing struct
    method StartScheduler (line 87) | func (h *HealthPing) StartScheduler(selector func() ([]string, error)) {
    method StopScheduler (line 127) | func (h *HealthPing) StopScheduler() {
    method Check (line 138) | func (h *HealthPing) Check(tags []string) error {
    method doCheck (line 154) | func (h *HealthPing) doCheck(tags []string, duration time.Duration, ro...
    method PutResult (line 216) | func (h *HealthPing) PutResult(tag string, rtt time.Duration) {
    method Cleanup (line 237) | func (h *HealthPing) Cleanup(tags []string) {
    method checkConnectivity (line 256) | func (h *HealthPing) checkConnectivity() bool {
  function NewHealthPing (line 38) | func NewHealthPing(ctx context.Context, dispatcher routing.Dispatcher, c...
  type rtt (line 147) | type rtt struct

FILE: app/observatory/burst/healthping_result.go
  type HealthPingStats (line 9) | type HealthPingStats struct
  type HealthPingRTTS (line 19) | type HealthPingRTTS struct
    method Get (line 40) | func (h *HealthPingRTTS) Get() *HealthPingStats {
    method GetWithCache (line 47) | func (h *HealthPingRTTS) GetWithCache() *HealthPingStats {
    method Put (line 58) | func (h *HealthPingRTTS) Put(d time.Duration) {
    method calcIndex (line 72) | func (h *HealthPingRTTS) calcIndex(step int) int {
    method getStatistics (line 81) | func (h *HealthPingRTTS) getStatistics() *HealthPingStats {
    method findOutdated (line 130) | func (h *HealthPingRTTS) findOutdated(now time.Time) int {
  type pingRTT (line 29) | type pingRTT struct
  function NewHealthPingResult (line 35) | func NewHealthPingResult(cap int, validity time.Duration) *HealthPingRTTS {

FILE: app/observatory/burst/healthping_result_test.go
  function TestHealthPingResults (line 12) | func TestHealthPingResults(t *testing.T) {
  function TestHealthPingResultsIgnoreOutdated (line 54) | func TestHealthPingResultsIgnoreOutdated(t *testing.T) {

FILE: app/observatory/burst/ping.go
  type pingClient (line 15) | type pingClient struct
    method MeasureDelay (line 56) | func (s *pingClient) MeasureDelay(httpMethod string) (time.Duration, e...
  function newPingClient (line 20) | func newPingClient(ctx context.Context, dispatcher routing.Dispatcher, d...
  function newDirectPingClient (line 27) | func newDirectPingClient(destination string, timeout time.Duration) *pin...
  function newHTTPClient (line 34) | func newHTTPClient(ctxv context.Context, dispatcher routing.Dispatcher, ...

FILE: app/observatory/command/command.go
  type service (line 13) | type service struct
    method GetOutboundStatus (line 20) | func (s *service) GetOutboundStatus(ctx context.Context, request *GetO...
    method Register (line 31) | func (s *service) Register(server *grpc.Server) {
  function init (line 35) | func init() {

FILE: app/observatory/command/command.pb.go
  constant _ (line 20) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 22) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type GetOutboundStatusRequest (line 25) | type GetOutboundStatusRequest struct
    method Reset (line 31) | func (x *GetOutboundStatusRequest) Reset() {
    method String (line 38) | func (x *GetOutboundStatusRequest) String() string {
    method ProtoMessage (line 42) | func (*GetOutboundStatusRequest) ProtoMessage() {}
    method ProtoReflect (line 44) | func (x *GetOutboundStatusRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 57) | func (*GetOutboundStatusRequest) Descriptor() ([]byte, []int) {
  type GetOutboundStatusResponse (line 61) | type GetOutboundStatusResponse struct
    method Reset (line 68) | func (x *GetOutboundStatusResponse) Reset() {
    method String (line 75) | func (x *GetOutboundStatusResponse) String() string {
    method ProtoMessage (line 79) | func (*GetOutboundStatusResponse) ProtoMessage() {}
    method ProtoReflect (line 81) | func (x *GetOutboundStatusResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 94) | func (*GetOutboundStatusResponse) Descriptor() ([]byte, []int) {
    method GetStatus (line 98) | func (x *GetOutboundStatusResponse) GetStatus() *observatory.Observati...
  type Config (line 105) | type Config struct
    method Reset (line 111) | func (x *Config) Reset() {
    method String (line 118) | func (x *Config) String() string {
    method ProtoMessage (line 122) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 124) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 137) | func (*Config) Descriptor() ([]byte, []int) {
  constant file_app_observatory_command_command_proto_rawDesc (line 143) | file_app_observatory_command_command_proto_rawDesc = "" +
  function file_app_observatory_command_command_proto_rawDescGZIP (line 159) | func file_app_observatory_command_command_proto_rawDescGZIP() []byte {
  function init (line 184) | func init() { file_app_observatory_command_command_proto_init() }
  function file_app_observatory_command_command_proto_init (line 185) | func file_app_observatory_command_command_proto_init() {

FILE: app/observatory/command/command_grpc.pb.go
  constant _ (line 19) | _ = grpc.SupportPackageIsVersion9
  constant ObservatoryService_GetOutboundStatus_FullMethodName (line 22) | ObservatoryService_GetOutboundStatus_FullMethodName = "/xray.core.app.ob...
  type ObservatoryServiceClient (line 28) | type ObservatoryServiceClient interface
  type observatoryServiceClient (line 32) | type observatoryServiceClient struct
    method GetOutboundStatus (line 40) | func (c *observatoryServiceClient) GetOutboundStatus(ctx context.Conte...
  function NewObservatoryServiceClient (line 36) | func NewObservatoryServiceClient(cc grpc.ClientConnInterface) Observator...
  type ObservatoryServiceServer (line 53) | type ObservatoryServiceServer interface
  type UnimplementedObservatoryServiceServer (line 63) | type UnimplementedObservatoryServiceServer struct
    method GetOutboundStatus (line 65) | func (UnimplementedObservatoryServiceServer) GetOutboundStatus(context...
    method mustEmbedUnimplementedObservatoryServiceServer (line 68) | func (UnimplementedObservatoryServiceServer) mustEmbedUnimplementedObs...
    method testEmbeddedByValue (line 69) | func (UnimplementedObservatoryServiceServer) testEmbeddedByValue()    ...
  type UnsafeObservatoryServiceServer (line 74) | type UnsafeObservatoryServiceServer interface
  function RegisterObservatoryServiceServer (line 78) | func RegisterObservatoryServiceServer(s grpc.ServiceRegistrar, srv Obser...
  function _ObservatoryService_GetOutboundStatus_Handler (line 89) | func _ObservatoryService_GetOutboundStatus_Handler(srv interface{}, ctx ...

FILE: app/observatory/config.pb.go
  constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type ObservationResult (line 24) | type ObservationResult struct
    method Reset (line 31) | func (x *ObservationResult) Reset() {
    method String (line 38) | func (x *ObservationResult) String() string {
    method ProtoMessage (line 42) | func (*ObservationResult) ProtoMessage() {}
    method ProtoReflect (line 44) | func (x *ObservationResult) ProtoReflect() protoreflect.Message {
    method Descriptor (line 57) | func (*ObservationResult) Descriptor() ([]byte, []int) {
    method GetStatus (line 61) | func (x *ObservationResult) GetStatus() []*OutboundStatus {
  type HealthPingMeasurementResult (line 68) | type HealthPingMeasurementResult struct
    method Reset (line 80) | func (x *HealthPingMeasurementResult) Reset() {
    method String (line 87) | func (x *HealthPingMeasurementResult) String() string {
    method ProtoMessage (line 91) | func (*HealthPingMeasurementResult) ProtoMessage() {}
    method ProtoReflect (line 93) | func (x *HealthPingMeasurementResult) ProtoReflect() protoreflect.Mess...
    method Descriptor (line 106) | func (*HealthPingMeasurementResult) Descriptor() ([]byte, []int) {
    method GetAll (line 110) | func (x *HealthPingMeasurementResult) GetAll() int64 {
    method GetFail (line 117) | func (x *HealthPingMeasurementResult) GetFail() int64 {
    method GetDeviation (line 124) | func (x *HealthPingMeasurementResult) GetDeviation() int64 {
    method GetAverage (line 131) | func (x *HealthPingMeasurementResult) GetAverage() int64 {
    method GetMax (line 138) | func (x *HealthPingMeasurementResult) GetMax() int64 {
    method GetMin (line 145) | func (x *HealthPingMeasurementResult) GetMin() int64 {
  type OutboundStatus (line 152) | type OutboundStatus struct
    method Reset (line 178) | func (x *OutboundStatus) Reset() {
    method String (line 185) | func (x *OutboundStatus) String() string {
    method ProtoMessage (line 189) | func (*OutboundStatus) ProtoMessage() {}
    method ProtoReflect (line 191) | func (x *OutboundStatus) ProtoReflect() protoreflect.Message {
    method Descriptor (line 204) | func (*OutboundStatus) Descriptor() ([]byte, []int) {
    method GetAlive (line 208) | func (x *OutboundStatus) GetAlive() bool {
    method GetDelay (line 215) | func (x *OutboundStatus) GetDelay() int64 {
    method GetLastErrorReason (line 222) | func (x *OutboundStatus) GetLastErrorReason() string {
    method GetOutboundTag (line 229) | func (x *OutboundStatus) GetOutboundTag() string {
    method GetLastSeenTime (line 236) | func (x *OutboundStatus) GetLastSeenTime() int64 {
    method GetLastTryTime (line 243) | func (x *OutboundStatus) GetLastTryTime() int64 {
    method GetHealthPing (line 250) | func (x *OutboundStatus) GetHealthPing() *HealthPingMeasurementResult {
  type ProbeResult (line 257) | type ProbeResult struct
    method Reset (line 273) | func (x *ProbeResult) Reset() {
    method String (line 280) | func (x *ProbeResult) String() string {
    method ProtoMessage (line 284) | func (*ProbeResult) ProtoMessage() {}
    method ProtoReflect (line 286) | func (x *ProbeResult) ProtoReflect() protoreflect.Message {
    method Descriptor (line 299) | func (*ProbeResult) Descriptor() ([]byte, []int) {
    method GetAlive (line 303) | func (x *ProbeResult) GetAlive() bool {
    method GetDelay (line 310) | func (x *ProbeResult) GetDelay() int64 {
    method GetLastErrorReason (line 317) | func (x *ProbeResult) GetLastErrorReason() string {
  type Intensity (line 324) | type Intensity struct
    method Reset (line 333) | func (x *Intensity) Reset() {
    method String (line 340) | func (x *Intensity) String() string {
    method ProtoMessage (line 344) | func (*Intensity) ProtoMessage() {}
    method ProtoReflect (line 346) | func (x *Intensity) ProtoReflect() protoreflect.Message {
    method Descriptor (line 359) | func (*Intensity) Descriptor() ([]byte, []int) {
    method GetProbeInterval (line 363) | func (x *Intensity) GetProbeInterval() uint32 {
  type Config (line 370) | type Config struct
    method Reset (line 381) | func (x *Config) Reset() {
    method String (line 388) | func (x *Config) String() string {
    method ProtoMessage (line 392) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 394) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 407) | func (*Config) Descriptor() ([]byte, []int) {
    method GetSubjectSelector (line 411) | func (x *Config) GetSubjectSelector() []string {
    method GetProbeUrl (line 418) | func (x *Config) GetProbeUrl() string {
    method GetProbeInterval (line 425) | func (x *Config) GetProbeInterval() int64 {
    method GetEnableConcurrency (line 432) | func (x *Config) GetEnableConcurrency() bool {
  constant file_app_observatory_config_proto_rawDesc (line 441) | file_app_observatory_config_proto_rawDesc = "" +
  function file_app_observatory_config_proto_rawDescGZIP (line 480) | func file_app_observatory_config_proto_rawDescGZIP() []byte {
  function init (line 506) | func init() { file_app_observatory_config_proto_init() }
  function file_app_observatory_config_proto_init (line 507) | func file_app_observatory_config_proto_init() {

FILE: app/observatory/explainErrors.go
  type errorCollector (line 5) | type errorCollector struct
    method SubmitError (line 9) | func (e *errorCollector) SubmitError(err error) {
    method UnderlyingError (line 21) | func (e *errorCollector) UnderlyingError() error {
  function newErrorCollector (line 17) | func newErrorCollector() *errorCollector {

FILE: app/observatory/observer.go
  type Observer (line 27) | type Observer struct
    method GetObservation (line 40) | func (o *Observer) GetObservation(ctx context.Context) (proto.Message,...
    method Type (line 44) | func (o *Observer) Type() interface{} {
    method Start (line 48) | func (o *Observer) Start() error {
    method Close (line 56) | func (o *Observer) Close() error {
    method background (line 63) | func (o *Observer) background() {
    method updateStatus (line 114) | func (o *Observer) updateStatus(outbounds []string) {
    method probe (line 121) | func (o *Observer) probe(outbound string) ProbeResult {
    method updateStatusForResult (line 188) | func (o *Observer) updateStatusForResult(outbound string, result *Prob...
    method findStatusLocationLockHolderOnly (line 212) | func (o *Observer) findStatusLocationLockHolderOnly(outbound string) i...
  function New (line 221) | func New(ctx context.Context, config *Config) (*Observer, error) {
  function init (line 239) | func init() {

FILE: app/policy/config.go
  method Duration (line 10) | func (s *Second) Duration() time.Duration {
  function defaultPolicy (line 17) | func defaultPolicy() *Policy {
  method overrideWith (line 33) | func (p *Policy_Timeout) overrideWith(another *Policy_Timeout) {
  method overrideWith (line 48) | func (p *Policy) overrideWith(another *Policy) {
  method ToCorePolicy (line 64) | func (p *Policy) ToCorePolicy() policy.Session {
  method ToCorePolicy (line 85) | func (p *SystemPolicy) ToCorePolicy() policy.System {

FILE: app/policy/config.pb.go
  constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type Second (line 24) | type Second struct
    method Reset (line 31) | func (x *Second) Reset() {
    method String (line 38) | func (x *Second) String() string {
    method ProtoMessage (line 42) | func (*Second) ProtoMessage() {}
    method ProtoReflect (line 44) | func (x *Second) ProtoReflect() protoreflect.Message {
    method Descriptor (line 57) | func (*Second) Descriptor() ([]byte, []int) {
    method GetValue (line 61) | func (x *Second) GetValue() uint32 {
  type Policy (line 68) | type Policy struct
    method Reset (line 77) | func (x *Policy) Reset() {
    method String (line 84) | func (x *Policy) String() string {
    method ProtoMessage (line 88) | func (*Policy) ProtoMessage() {}
    method ProtoReflect (line 90) | func (x *Policy) ProtoReflect() protoreflect.Message {
    method Descriptor (line 103) | func (*Policy) Descriptor() ([]byte, []int) {
    method GetTimeout (line 107) | func (x *Policy) GetTimeout() *Policy_Timeout {
    method GetStats (line 114) | func (x *Policy) GetStats() *Policy_Stats {
    method GetBuffer (line 121) | func (x *Policy) GetBuffer() *Policy_Buffer {
  type SystemPolicy (line 128) | type SystemPolicy struct
    method Reset (line 135) | func (x *SystemPolicy) Reset() {
    method String (line 142) | func (x *SystemPolicy) String() string {
    method ProtoMessage (line 146) | func (*SystemPolicy) ProtoMessage() {}
    method ProtoReflect (line 148) | func (x *SystemPolicy) ProtoReflect() protoreflect.Message {
    method Descriptor (line 161) | func (*SystemPolicy) Descriptor() ([]byte, []int) {
    method GetStats (line 165) | func (x *SystemPolicy) GetStats() *SystemPolicy_Stats {
  type Config (line 172) | type Config struct
    method Reset (line 180) | func (x *Config) Reset() {
    method String (line 187) | func (x *Config) String() string {
    method ProtoMessage (line 191) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 193) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 206) | func (*Config) Descriptor() ([]byte, []int) {
    method GetLevel (line 210) | func (x *Config) GetLevel() map[uint32]*Policy {
    method GetSystem (line 217) | func (x *Config) GetSystem() *SystemPolicy {
  type Policy_Timeout (line 225) | type Policy_Timeout struct
    method Reset (line 235) | func (x *Policy_Timeout) Reset() {
    method String (line 242) | func (x *Policy_Timeout) String() string {
    method ProtoMessage (line 246) | func (*Policy_Timeout) ProtoMessage() {}
    method ProtoReflect (line 248) | func (x *Policy_Timeout) ProtoReflect() protoreflect.Message {
    method Descriptor (line 261) | func (*Policy_Timeout) Descriptor() ([]byte, []int) {
    method GetHandshake (line 265) | func (x *Policy_Timeout) GetHandshake() *Second {
    method GetConnectionIdle (line 272) | func (x *Policy_Timeout) GetConnectionIdle() *Second {
    method GetUplinkOnly (line 279) | func (x *Policy_Timeout) GetUplinkOnly() *Second {
    method GetDownlinkOnly (line 286) | func (x *Policy_Timeout) GetDownlinkOnly() *Second {
  type Policy_Stats (line 293) | type Policy_Stats struct
    method Reset (line 302) | func (x *Policy_Stats) Reset() {
    method String (line 309) | func (x *Policy_Stats) String() string {
    method ProtoMessage (line 313) | func (*Policy_Stats) ProtoMessage() {}
    method ProtoReflect (line 315) | func (x *Policy_Stats) ProtoReflect() protoreflect.Message {
    method Descriptor (line 328) | func (*Policy_Stats) Descriptor() ([]byte, []int) {
    method GetUserUplink (line 332) | func (x *Policy_Stats) GetUserUplink() bool {
    method GetUserDownlink (line 339) | func (x *Policy_Stats) GetUserDownlink() bool {
    method GetUserOnline (line 346) | func (x *Policy_Stats) GetUserOnline() bool {
  type Policy_Buffer (line 353) | type Policy_Buffer struct
    method Reset (line 361) | func (x *Policy_Buffer) Reset() {
    method String (line 368) | func (x *Policy_Buffer) String() string {
    method ProtoMessage (line 372) | func (*Policy_Buffer) ProtoMessage() {}
    method ProtoReflect (line 374) | func (x *Policy_Buffer) ProtoReflect() protoreflect.Message {
    method Descriptor (line 387) | func (*Policy_Buffer) Descriptor() ([]byte, []int) {
    method GetConnection (line 391) | func (x *Policy_Buffer) GetConnection() int32 {
  type SystemPolicy_Stats (line 398) | type SystemPolicy_Stats struct
    method Reset (line 408) | func (x *SystemPolicy_Stats) Reset() {
    method String (line 415) | func (x *SystemPolicy_Stats) String() string {
    method ProtoMessage (line 419) | func (*SystemPolicy_Stats) ProtoMessage() {}
    method ProtoReflect (line 421) | func (x *SystemPolicy_Stats) ProtoReflect() protoreflect.Message {
    method Descriptor (line 434) | func (*SystemPolicy_Stats) Descriptor() ([]byte, []int) {
    method GetInboundUplink (line 438) | func (x *SystemPolicy_Stats) GetInboundUplink() bool {
    method GetInboundDownlink (line 445) | func (x *SystemPolicy_Stats) GetInboundDownlink() bool {
    method GetOutboundUplink (line 452) | func (x *SystemPolicy_Stats) GetOutboundUplink() bool {
    method GetOutboundDownlink (line 459) | func (x *SystemPolicy_Stats) GetOutboundDownlink() bool {
  constant file_app_policy_config_proto_rawDesc (line 468) | file_app_policy_config_proto_rawDesc = "" +
  function file_app_policy_config_proto_rawDescGZIP (line 514) | func file_app_policy_config_proto_rawDescGZIP() []byte {
  function init (line 552) | func init() { file_app_policy_config_proto_init() }
  function file_app_policy_config_proto_init (line 553) | func file_app_policy_config_proto_init() {

FILE: app/policy/manager.go
  type Instance (line 11) | type Instance struct
    method Type (line 34) | func (*Instance) Type() interface{} {
    method ForLevel (line 39) | func (m *Instance) ForLevel(level uint32) policy.Session {
    method ForSystem (line 47) | func (m *Instance) ForSystem() policy.System {
    method Start (line 55) | func (m *Instance) Start() error {
    method Close (line 60) | func (m *Instance) Close() error {
  function New (line 17) | func New(ctx context.Context, config *Config) (*Instance, error) {
  function init (line 64) | func init() {

FILE: app/policy/manager_test.go
  function TestPolicy (line 13) | func TestPolicy(t *testing.T) {

FILE: app/proxyman/command/command.go
  type InboundOperation (line 18) | type InboundOperation interface
  type OutboundOperation (line 24) | type OutboundOperation interface
  function getInbound (line 29) | func getInbound(handler inbound.Handler) (proxy.Inbound, error) {
  method ApplyInbound (line 38) | func (op *AddUserOperation) ApplyInbound(ctx context.Context, handler in...
  method ApplyInbound (line 55) | func (op *RemoveUserOperation) ApplyInbound(ctx context.Context, handler...
  type handlerServer (line 67) | type handlerServer struct
    method AddInbound (line 73) | func (s *handlerServer) AddInbound(ctx context.Context, request *AddIn...
    method RemoveInbound (line 81) | func (s *handlerServer) RemoveInbound(ctx context.Context, request *Re...
    method AlterInbound (line 85) | func (s *handlerServer) AlterInbound(ctx context.Context, request *Alt...
    method ListInbounds (line 103) | func (s *handlerServer) ListInbounds(ctx context.Context, request *Lis...
    method GetInboundUsers (line 125) | func (s *handlerServer) GetInboundUsers(ctx context.Context, request *...
    method GetInboundUsersCount (line 149) | func (s *handlerServer) GetInboundUsersCount(ctx context.Context, requ...
    method AddOutbound (line 165) | func (s *handlerServer) AddOutbound(ctx context.Context, request *AddO...
    method RemoveOutbound (line 172) | func (s *handlerServer) RemoveOutbound(ctx context.Context, request *R...
    method AlterOutbound (line 176) | func (s *handlerServer) AlterOutbound(ctx context.Context, request *Al...
    method ListOutbounds (line 190) | func (s *handlerServer) ListOutbounds(ctx context.Context, request *Li...
    method mustEmbedUnimplementedHandlerServiceServer (line 207) | func (s *handlerServer) mustEmbedUnimplementedHandlerServiceServer() {}
  type service (line 209) | type service struct
    method Register (line 213) | func (s *service) Register(server *grpc.Server) {
  function init (line 229) | func init() {

FILE: app/proxyman/command/command.pb.go
  constant _ (line 22) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 24) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type AddUserOperation (line 27) | type AddUserOperation struct
    method Reset (line 34) | func (x *AddUserOperation) Reset() {
    method String (line 41) | func (x *AddUserOperation) String() string {
    method ProtoMessage (line 45) | func (*AddUserOperation) ProtoMessage() {}
    method ProtoReflect (line 47) | func (x *AddUserOperation) ProtoReflect() protoreflect.Message {
    method Descriptor (line 60) | func (*AddUserOperation) Descriptor() ([]byte, []int) {
    method GetUser (line 64) | func (x *AddUserOperation) GetUser() *protocol.User {
  type RemoveUserOperation (line 71) | type RemoveUserOperation struct
    method Reset (line 78) | func (x *RemoveUserOperation) Reset() {
    method String (line 85) | func (x *RemoveUserOperation) String() string {
    method ProtoMessage (line 89) | func (*RemoveUserOperation) ProtoMessage() {}
    method ProtoReflect (line 91) | func (x *RemoveUserOperation) ProtoReflect() protoreflect.Message {
    method Descriptor (line 104) | func (*RemoveUserOperation) Descriptor() ([]byte, []int) {
    method GetEmail (line 108) | func (x *RemoveUserOperation) GetEmail() string {
  type AddInboundRequest (line 115) | type AddInboundRequest struct
    method Reset (line 122) | func (x *AddInboundRequest) Reset() {
    method String (line 129) | func (x *AddInboundRequest) String() string {
    method ProtoMessage (line 133) | func (*AddInboundRequest) ProtoMessage() {}
    method ProtoReflect (line 135) | func (x *AddInboundRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 148) | func (*AddInboundRequest) Descriptor() ([]byte, []int) {
    method GetInbound (line 152) | func (x *AddInboundRequest) GetInbound() *core.InboundHandlerConfig {
  type AddInboundResponse (line 159) | type AddInboundResponse struct
    method Reset (line 165) | func (x *AddInboundResponse) Reset() {
    method String (line 172) | func (x *AddInboundResponse) String() string {
    method ProtoMessage (line 176) | func (*AddInboundResponse) ProtoMessage() {}
    method ProtoReflect (line 178) | func (x *AddInboundResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 191) | func (*AddInboundResponse) Descriptor() ([]byte, []int) {
  type RemoveInboundRequest (line 195) | type RemoveInboundRequest struct
    method Reset (line 202) | func (x *RemoveInboundRequest) Reset() {
    method String (line 209) | func (x *RemoveInboundRequest) String() string {
    method ProtoMessage (line 213) | func (*RemoveInboundRequest) ProtoMessage() {}
    method ProtoReflect (line 215) | func (x *RemoveInboundRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 228) | func (*RemoveInboundRequest) Descriptor() ([]byte, []int) {
    method GetTag (line 232) | func (x *RemoveInboundRequest) GetTag() string {
  type RemoveInboundResponse (line 239) | type RemoveInboundResponse struct
    method Reset (line 245) | func (x *RemoveInboundResponse) Reset() {
    method String (line 252) | func (x *RemoveInboundResponse) String() string {
    method ProtoMessage (line 256) | func (*RemoveInboundResponse) ProtoMessage() {}
    method ProtoReflect (line 258) | func (x *RemoveInboundResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 271) | func (*RemoveInboundResponse) Descriptor() ([]byte, []int) {
  type AlterInboundRequest (line 275) | type AlterInboundRequest struct
    method Reset (line 283) | func (x *AlterInboundRequest) Reset() {
    method String (line 290) | func (x *AlterInboundRequest) String() string {
    method ProtoMessage (line 294) | func (*AlterInboundRequest) ProtoMessage() {}
    method ProtoReflect (line 296) | func (x *AlterInboundRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 309) | func (*AlterInboundRequest) Descriptor() ([]byte, []int) {
    method GetTag (line 313) | func (x *AlterInboundRequest) GetTag() string {
    method GetOperation (line 320) | func (x *AlterInboundRequest) GetOperation() *serial.TypedMessage {
  type AlterInboundResponse (line 327) | type AlterInboundResponse struct
    method Reset (line 333) | func (x *AlterInboundResponse) Reset() {
    method String (line 340) | func (x *AlterInboundResponse) String() string {
    method ProtoMessage (line 344) | func (*AlterInboundResponse) ProtoMessage() {}
    method ProtoReflect (line 346) | func (x *AlterInboundResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 359) | func (*AlterInboundResponse) Descriptor() ([]byte, []int) {
  type ListInboundsRequest (line 363) | type ListInboundsRequest struct
    method Reset (line 370) | func (x *ListInboundsRequest) Reset() {
    method String (line 377) | func (x *ListInboundsRequest) String() string {
    method ProtoMessage (line 381) | func (*ListInboundsRequest) ProtoMessage() {}
    method ProtoReflect (line 383) | func (x *ListInboundsRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 396) | func (*ListInboundsRequest) Descriptor() ([]byte, []int) {
    method GetIsOnlyTags (line 400) | func (x *ListInboundsRequest) GetIsOnlyTags() bool {
  type ListInboundsResponse (line 407) | type ListInboundsResponse struct
    method Reset (line 414) | func (x *ListInboundsResponse) Reset() {
    method String (line 421) | func (x *ListInboundsResponse) String() string {
    method ProtoMessage (line 425) | func (*ListInboundsResponse) ProtoMessage() {}
    method ProtoReflect (line 427) | func (x *ListInboundsResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 440) | func (*ListInboundsResponse) Descriptor() ([]byte, []int) {
    method GetInbounds (line 444) | func (x *ListInboundsResponse) GetInbounds() []*core.InboundHandlerCon...
  type GetInboundUserRequest (line 451) | type GetInboundUserRequest struct
    method Reset (line 459) | func (x *GetInboundUserRequest) Reset() {
    method String (line 466) | func (x *GetInboundUserRequest) String() string {
    method ProtoMessage (line 470) | func (*GetInboundUserRequest) ProtoMessage() {}
    method ProtoReflect (line 472) | func (x *GetInboundUserRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 485) | func (*GetInboundUserRequest) Descriptor() ([]byte, []int) {
    method GetTag (line 489) | func (x *GetInboundUserRequest) GetTag() string {
    method GetEmail (line 496) | func (x *GetInboundUserRequest) GetEmail() string {
  type GetInboundUserResponse (line 503) | type GetInboundUserResponse struct
    method Reset (line 510) | func (x *GetInboundUserResponse) Reset() {
    method String (line 517) | func (x *GetInboundUserResponse) String() string {
    method ProtoMessage (line 521) | func (*GetInboundUserResponse) ProtoMessage() {}
    method ProtoReflect (line 523) | func (x *GetInboundUserResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 536) | func (*GetInboundUserResponse) Descriptor() ([]byte, []int) {
    method GetUsers (line 540) | func (x *GetInboundUserResponse) GetUsers() []*protocol.User {
  type GetInboundUsersCountResponse (line 547) | type GetInboundUsersCountResponse struct
    method Reset (line 554) | func (x *GetInboundUsersCountResponse) Reset() {
    method String (line 561) | func (x *GetInboundUsersCountResponse) String() string {
    method ProtoMessage (line 565) | func (*GetInboundUsersCountResponse) ProtoMessage() {}
    method ProtoReflect (line 567) | func (x *GetInboundUsersCountResponse) ProtoReflect() protoreflect.Mes...
    method Descriptor (line 580) | func (*GetInboundUsersCountResponse) Descriptor() ([]byte, []int) {
    method GetCount (line 584) | func (x *GetInboundUsersCountResponse) GetCount() int64 {
  type AddOutboundRequest (line 591) | type AddOutboundRequest struct
    method Reset (line 598) | func (x *AddOutboundRequest) Reset() {
    method String (line 605) | func (x *AddOutboundRequest) String() string {
    method ProtoMessage (line 609) | func (*AddOutboundRequest) ProtoMessage() {}
    method ProtoReflect (line 611) | func (x *AddOutboundRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 624) | func (*AddOutboundRequest) Descriptor() ([]byte, []int) {
    method GetOutbound (line 628) | func (x *AddOutboundRequest) GetOutbound() *core.OutboundHandlerConfig {
  type AddOutboundResponse (line 635) | type AddOutboundResponse struct
    method Reset (line 641) | func (x *AddOutboundResponse) Reset() {
    method String (line 648) | func (x *AddOutboundResponse) String() string {
    method ProtoMessage (line 652) | func (*AddOutboundResponse) ProtoMessage() {}
    method ProtoReflect (line 654) | func (x *AddOutboundResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 667) | func (*AddOutboundResponse) Descriptor() ([]byte, []int) {
  type RemoveOutboundRequest (line 671) | type RemoveOutboundRequest struct
    method Reset (line 678) | func (x *RemoveOutboundRequest) Reset() {
    method String (line 685) | func (x *RemoveOutboundRequest) String() string {
    method ProtoMessage (line 689) | func (*RemoveOutboundRequest) ProtoMessage() {}
    method ProtoReflect (line 691) | func (x *RemoveOutboundRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 704) | func (*RemoveOutboundRequest) Descriptor() ([]byte, []int) {
    method GetTag (line 708) | func (x *RemoveOutboundRequest) GetTag() string {
  type RemoveOutboundResponse (line 715) | type RemoveOutboundResponse struct
    method Reset (line 721) | func (x *RemoveOutboundResponse) Reset() {
    method String (line 728) | func (x *RemoveOutboundResponse) String() string {
    method ProtoMessage (line 732) | func (*RemoveOutboundResponse) ProtoMessage() {}
    method ProtoReflect (line 734) | func (x *RemoveOutboundResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 747) | func (*RemoveOutboundResponse) Descriptor() ([]byte, []int) {
  type AlterOutboundRequest (line 751) | type AlterOutboundRequest struct
    method Reset (line 759) | func (x *AlterOutboundRequest) Reset() {
    method String (line 766) | func (x *AlterOutboundRequest) String() string {
    method ProtoMessage (line 770) | func (*AlterOutboundRequest) ProtoMessage() {}
    method ProtoReflect (line 772) | func (x *AlterOutboundRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 785) | func (*AlterOutboundRequest) Descriptor() ([]byte, []int) {
    method GetTag (line 789) | func (x *AlterOutboundRequest) GetTag() string {
    method GetOperation (line 796) | func (x *AlterOutboundRequest) GetOperation() *serial.TypedMessage {
  type AlterOutboundResponse (line 803) | type AlterOutboundResponse struct
    method Reset (line 809) | func (x *AlterOutboundResponse) Reset() {
    method String (line 816) | func (x *AlterOutboundResponse) String() string {
    method ProtoMessage (line 820) | func (*AlterOutboundResponse) ProtoMessage() {}
    method ProtoReflect (line 822) | func (x *AlterOutboundResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 835) | func (*AlterOutboundResponse) Descriptor() ([]byte, []int) {
  type ListOutboundsRequest (line 839) | type ListOutboundsRequest struct
    method Reset (line 845) | func (x *ListOutboundsRequest) Reset() {
    method String (line 852) | func (x *ListOutboundsRequest) String() string {
    method ProtoMessage (line 856) | func (*ListOutboundsRequest) ProtoMessage() {}
    method ProtoReflect (line 858) | func (x *ListOutboundsRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 871) | func (*ListOutboundsRequest) Descriptor() ([]byte, []int) {
  type ListOutboundsResponse (line 875) | type ListOutboundsResponse struct
    method Reset (line 882) | func (x *ListOutboundsResponse) Reset() {
    method String (line 889) | func (x *ListOutboundsResponse) String() string {
    method ProtoMessage (line 893) | func (*ListOutboundsResponse) ProtoMessage() {}
    method ProtoReflect (line 895) | func (x *ListOutboundsResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 908) | func (*ListOutboundsResponse) Descriptor() ([]byte, []int) {
    method GetOutbounds (line 912) | func (x *ListOutboundsResponse) GetOutbounds() []*core.OutboundHandler...
  type Config (line 919) | type Config struct
    method Reset (line 925) | func (x *Config) Reset() {
    method String (line 932) | func (x *Config) String() string {
    method ProtoMessage (line 936) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 938) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 951) | func (*Config) Descriptor() ([]byte, []int) {
  constant file_app_proxyman_command_command_proto_rawDesc (line 957) | file_app_proxyman_command_command_proto_rawDesc = "" +
  function file_app_proxyman_command_command_proto_rawDescGZIP (line 1020) | func file_app_proxyman_command_command_proto_rawDescGZIP() []byte {
  function init (line 1092) | func init() { file_app_proxyman_command_command_proto_init() }
  function file_app_proxyman_command_command_proto_init (line 1093) | func file_app_proxyman_command_command_proto_init() {

FILE: app/proxyman/command/command_grpc.pb.go
  constant _ (line 19) | _ = grpc.SupportPackageIsVersion9
  constant HandlerService_AddInbound_FullMethodName (line 22) | HandlerService_AddInbound_FullMethodName           = "/xray.app.proxyman...
  constant HandlerService_RemoveInbound_FullMethodName (line 23) | HandlerService_RemoveInbound_FullMethodName        = "/xray.app.proxyman...
  constant HandlerService_AlterInbound_FullMethodName (line 24) | HandlerService_AlterInbound_FullMethodName         = "/xray.app.proxyman...
  constant HandlerService_ListInbounds_FullMethodName (line 25) | HandlerService_ListInbounds_FullMethodName         = "/xray.app.proxyman...
  constant HandlerService_GetInboundUsers_FullMethodName (line 26) | HandlerService_GetInboundUsers_FullMethodName      = "/xray.app.proxyman...
  constant HandlerService_GetInboundUsersCount_FullMethodName (line 27) | HandlerService_GetInboundUsersCount_FullMethodName = "/xray.app.proxyman...
  constant HandlerService_AddOutbound_FullMethodName (line 28) | HandlerService_AddOutbound_FullMethodName          = "/xray.app.proxyman...
  constant HandlerService_RemoveOutbound_FullMethodName (line 29) | HandlerService_RemoveOutbound_FullMethodName       = "/xray.app.proxyman...
  constant HandlerService_AlterOutbound_FullMethodName (line 30) | HandlerService_AlterOutbound_FullMethodName        = "/xray.app.proxyman...
  constant HandlerService_ListOutbounds_FullMethodName (line 31) | HandlerService_ListOutbounds_FullMethodName        = "/xray.app.proxyman...
  type HandlerServiceClient (line 37) | type HandlerServiceClient interface
  type handlerServiceClient (line 50) | type handlerServiceClient struct
    method AddInbound (line 58) | func (c *handlerServiceClient) AddInbound(ctx context.Context, in *Add...
    method RemoveInbound (line 68) | func (c *handlerServiceClient) RemoveInbound(ctx context.Context, in *...
    method AlterInbound (line 78) | func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *A...
    method ListInbounds (line 88) | func (c *handlerServiceClient) ListInbounds(ctx context.Context, in *L...
    method GetInboundUsers (line 98) | func (c *handlerServiceClient) GetInboundUsers(ctx context.Context, in...
    method GetInboundUsersCount (line 108) | func (c *handlerServiceClient) GetInboundUsersCount(ctx context.Contex...
    method AddOutbound (line 118) | func (c *handlerServiceClient) AddOutbound(ctx context.Context, in *Ad...
    method RemoveOutbound (line 128) | func (c *handlerServiceClient) RemoveOutbound(ctx context.Context, in ...
    method AlterOutbound (line 138) | func (c *handlerServiceClient) AlterOutbound(ctx context.Context, in *...
    method ListOutbounds (line 148) | func (c *handlerServiceClient) ListOutbounds(ctx context.Context, in *...
  function NewHandlerServiceClient (line 54) | func NewHandlerServiceClient(cc grpc.ClientConnInterface) HandlerService...
  type HandlerServiceServer (line 161) | type HandlerServiceServer interface
  type UnimplementedHandlerServiceServer (line 180) | type UnimplementedHandlerServiceServer struct
    method AddInbound (line 182) | func (UnimplementedHandlerServiceServer) AddInbound(context.Context, *...
    method RemoveInbound (line 185) | func (UnimplementedHandlerServiceServer) RemoveInbound(context.Context...
    method AlterInbound (line 188) | func (UnimplementedHandlerServiceServer) AlterInbound(context.Context,...
    method ListInbounds (line 191) | func (UnimplementedHandlerServiceServer) ListInbounds(context.Context,...
    method GetInboundUsers (line 194) | func (UnimplementedHandlerServiceServer) GetInboundUsers(context.Conte...
    method GetInboundUsersCount (line 197) | func (UnimplementedHandlerServiceServer) GetInboundUsersCount(context....
    method AddOutbound (line 200) | func (UnimplementedHandlerServiceServer) AddOutbound(context.Context, ...
    method RemoveOutbound (line 203) | func (UnimplementedHandlerServiceServer) RemoveOutbound(context.Contex...
    method AlterOutbound (line 206) | func (UnimplementedHandlerServiceServer) AlterOutbound(context.Context...
    method ListOutbounds (line 209) | func (UnimplementedHandlerServiceServer) ListOutbounds(context.Context...
    method mustEmbedUnimplementedHandlerServiceServer (line 212) | func (UnimplementedHandlerServiceServer) mustEmbedUnimplementedHandler...
    method testEmbeddedByValue (line 213) | func (UnimplementedHandlerServiceServer) testEmbeddedByValue()        ...
  type UnsafeHandlerServiceServer (line 218) | type UnsafeHandlerServiceServer interface
  function RegisterHandlerServiceServer (line 222) | func RegisterHandlerServiceServer(s grpc.ServiceRegistrar, srv HandlerSe...
  function _HandlerService_AddInbound_Handler (line 233) | func _HandlerService_AddInbound_Handler(srv interface{}, ctx context.Con...
  function _HandlerService_RemoveInbound_Handler (line 251) | func _HandlerService_RemoveInbound_Handler(srv interface{}, ctx context....
  function _HandlerService_AlterInbound_Handler (line 269) | func _HandlerService_AlterInbound_Handler(srv interface{}, ctx context.C...
  function _HandlerService_ListInbounds_Handler (line 287) | func _HandlerService_ListInbounds_Handler(srv interface{}, ctx context.C...
  function _HandlerService_GetInboundUsers_Handler (line 305) | func _HandlerService_GetInboundUsers_Handler(srv interface{}, ctx contex...
  function _HandlerService_GetInboundUsersCount_Handler (line 323) | func _HandlerService_GetInboundUsersCount_Handler(srv interface{}, ctx c...
  function _HandlerService_AddOutbound_Handler (line 341) | func _HandlerService_AddOutbound_Handler(srv interface{}, ctx context.Co...
  function _HandlerService_RemoveOutbound_Handler (line 359) | func _HandlerService_RemoveOutbound_Handler(srv interface{}, ctx context...
  function _HandlerService_AlterOutbound_Handler (line 377) | func _HandlerService_AlterOutbound_Handler(srv interface{}, ctx context....
  function _HandlerService_ListOutbounds_Handler (line 395) | func _HandlerService_ListOutbounds_Handler(srv interface{}, ctx context....

FILE: app/proxyman/config.pb.go
  constant _ (line 22) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 24) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type InboundConfig (line 27) | type InboundConfig struct
    method Reset (line 33) | func (x *InboundConfig) Reset() {
    method String (line 40) | func (x *InboundConfig) String() string {
    method ProtoMessage (line 44) | func (*InboundConfig) ProtoMessage() {}
    method ProtoReflect (line 46) | func (x *InboundConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 59) | func (*InboundConfig) Descriptor() ([]byte, []int) {
  type SniffingConfig (line 63) | type SniffingConfig struct
    method Reset (line 80) | func (x *SniffingConfig) Reset() {
    method String (line 87) | func (x *SniffingConfig) String() string {
    method ProtoMessage (line 91) | func (*SniffingConfig) ProtoMessage() {}
    method ProtoReflect (line 93) | func (x *SniffingConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 106) | func (*SniffingConfig) Descriptor() ([]byte, []int) {
    method GetEnabled (line 110) | func (x *SniffingConfig) GetEnabled() bool {
    method GetDestinationOverride (line 117) | func (x *SniffingConfig) GetDestinationOverride() []string {
    method GetDomainsExcluded (line 124) | func (x *SniffingConfig) GetDomainsExcluded() []string {
    method GetMetadataOnly (line 131) | func (x *SniffingConfig) GetMetadataOnly() bool {
    method GetRouteOnly (line 138) | func (x *SniffingConfig) GetRouteOnly() bool {
  type ReceiverConfig (line 145) | type ReceiverConfig struct
    method Reset (line 158) | func (x *ReceiverConfig) Reset() {
    method String (line 165) | func (x *ReceiverConfig) String() string {
    method ProtoMessage (line 169) | func (*ReceiverConfig) ProtoMessage() {}
    method ProtoReflect (line 171) | func (x *ReceiverConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 184) | func (*ReceiverConfig) Descriptor() ([]byte, []int) {
    method GetPortList (line 188) | func (x *ReceiverConfig) GetPortList() *net.PortList {
    method GetListen (line 195) | func (x *ReceiverConfig) GetListen() *net.IPOrDomain {
    method GetStreamSettings (line 202) | func (x *ReceiverConfig) GetStreamSettings() *internet.StreamConfig {
    method GetReceiveOriginalDestination (line 209) | func (x *ReceiverConfig) GetReceiveOriginalDestination() bool {
    method GetSniffingSettings (line 216) | func (x *ReceiverConfig) GetSniffingSettings() *SniffingConfig {
  type InboundHandlerConfig (line 223) | type InboundHandlerConfig struct
    method Reset (line 232) | func (x *InboundHandlerConfig) Reset() {
    method String (line 239) | func (x *InboundHandlerConfig) String() string {
    method ProtoMessage (line 243) | func (*InboundHandlerConfig) ProtoMessage() {}
    method ProtoReflect (line 245) | func (x *InboundHandlerConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 258) | func (*InboundHandlerConfig) Descriptor() ([]byte, []int) {
    method GetTag (line 262) | func (x *InboundHandlerConfig) GetTag() string {
    method GetReceiverSettings (line 269) | func (x *InboundHandlerConfig) GetReceiverSettings() *serial.TypedMess...
    method GetProxySettings (line 276) | func (x *InboundHandlerConfig) GetProxySettings() *serial.TypedMessage {
  type OutboundConfig (line 283) | type OutboundConfig struct
    method Reset (line 289) | func (x *OutboundConfig) Reset() {
    method String (line 296) | func (x *OutboundConfig) String() string {
    method ProtoMessage (line 300) | func (*OutboundConfig) ProtoMessage() {}
    method ProtoReflect (line 302) | func (x *OutboundConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 315) | func (*OutboundConfig) Descriptor() ([]byte, []int) {
  type SenderConfig (line 319) | type SenderConfig struct
    method Reset (line 332) | func (x *SenderConfig) Reset() {
    method String (line 339) | func (x *SenderConfig) String() string {
    method ProtoMessage (line 343) | func (*SenderConfig) ProtoMessage() {}
    method ProtoReflect (line 345) | func (x *SenderConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 358) | func (*SenderConfig) Descriptor() ([]byte, []int) {
    method GetVia (line 362) | func (x *SenderConfig) GetVia() *net.IPOrDomain {
    method GetStreamSettings (line 369) | func (x *SenderConfig) GetStreamSettings() *internet.StreamConfig {
    method GetProxySettings (line 376) | func (x *SenderConfig) GetProxySettings() *internet.ProxyConfig {
    method GetMultiplexSettings (line 383) | func (x *SenderConfig) GetMultiplexSettings() *MultiplexingConfig {
    method GetViaCidr (line 390) | func (x *SenderConfig) GetViaCidr() string {
    method GetTargetStrategy (line 397) | func (x *SenderConfig) GetTargetStrategy() internet.DomainStrategy {
  type MultiplexingConfig (line 404) | type MultiplexingConfig struct
    method Reset (line 418) | func (x *MultiplexingConfig) Reset() {
    method String (line 425) | func (x *MultiplexingConfig) String() string {
    method ProtoMessage (line 429) | func (*MultiplexingConfig) ProtoMessage() {}
    method ProtoReflect (line 431) | func (x *MultiplexingConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 444) | func (*MultiplexingConfig) Descriptor() ([]byte, []int) {
    method GetEnabled (line 448) | func (x *MultiplexingConfig) GetEnabled() bool {
    method GetConcurrency (line 455) | func (x *MultiplexingConfig) GetConcurrency() int32 {
    method GetXudpConcurrency (line 462) | func (x *MultiplexingConfig) GetXudpConcurrency() int32 {
    method GetXudpProxyUDP443 (line 469) | func (x *MultiplexingConfig) GetXudpProxyUDP443() string {
  constant file_app_proxyman_config_proto_rawDesc (line 478) | file_app_proxyman_config_proto_rawDesc = "" +
  function file_app_proxyman_config_proto_rawDescGZIP (line 519) | func file_app_proxyman_config_proto_rawDescGZIP() []byte {
  function init (line 561) | func init() { file_app_proxyman_config_proto_init() }
  function file_app_proxyman_config_proto_init (line 562) | func file_app_proxyman_config_proto_init() {

FILE: app/proxyman/inbound/always.go
  function getStatCounter (line 21) | func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats....
  type AlwaysOnInboundHandler (line 46) | type AlwaysOnInboundHandler struct
    method Start (line 173) | func (h *AlwaysOnInboundHandler) Start() error {
    method Close (line 183) | func (h *AlwaysOnInboundHandler) Close() error {
    method Tag (line 195) | func (h *AlwaysOnInboundHandler) Tag() string {
    method GetInbound (line 199) | func (h *AlwaysOnInboundHandler) GetInbound() proxy.Inbound {
    method ReceiverSettings (line 204) | func (h *AlwaysOnInboundHandler) ReceiverSettings() *serial.TypedMessa...
    method ProxySettings (line 209) | func (h *AlwaysOnInboundHandler) ProxySettings() *serial.TypedMessage {
  function NewAlwaysOnInboundHandler (line 55) | func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiver...

FILE: app/proxyman/inbound/inbound.go
  type Manager (line 18) | type Manager struct
    method Type (line 34) | func (*Manager) Type() interface{} {
    method AddHandler (line 39) | func (m *Manager) AddHandler(ctx context.Context, handler inbound.Hand...
    method GetHandler (line 61) | func (m *Manager) GetHandler(ctx context.Context, tag string) (inbound...
    method RemoveHandler (line 73) | func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
    method ListHandlers (line 93) | func (m *Manager) ListHandlers(ctx context.Context) []inbound.Handler {
    method Start (line 108) | func (m *Manager) Start() error {
    method Close (line 129) | func (m *Manager) Close() error {
  function New (line 26) | func New(ctx context.Context, config *proxyman.InboundConfig) (*Manager,...
  function NewHandler (line 155) | func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) ...
  function init (line 184) | func init() {

FILE: app/proxyman/inbound/worker.go
  type worker (line 31) | type worker interface
  type tcpWorker (line 38) | type tcpWorker struct
    method callback (line 62) | func (w *tcpWorker) callback(conn stat.Connection) {
    method Proxy (line 137) | func (w *tcpWorker) Proxy() proxy.Inbound {
    method Start (line 141) | func (w *tcpWorker) Start() error {
    method Close (line 160) | func (w *tcpWorker) Close() error {
    method Port (line 177) | func (w *tcpWorker) Port() net.Port {
  function getTProxyType (line 55) | func getTProxyType(s *internet.MemoryStreamConfig) internet.SocketConfig...
  type udpConn (line 181) | type udpConn struct
    method setInactive (line 195) | func (c *udpConn) setInactive() {
    method updateActivity (line 199) | func (c *udpConn) updateActivity() {
    method ReadMultiBuffer (line 204) | func (c *udpConn) ReadMultiBuffer() (buf.MultiBuffer, error) {
    method Read (line 218) | func (c *udpConn) Read(buf []byte) (int, error) {
    method Write (line 223) | func (c *udpConn) Write(buf []byte) (int, error) {
    method Close (line 234) | func (c *udpConn) Close() error {
    method RemoteAddr (line 243) | func (c *udpConn) RemoteAddr() net.Addr {
    method LocalAddr (line 247) | func (c *udpConn) LocalAddr() net.Addr {
    method SetDeadline (line 251) | func (*udpConn) SetDeadline(time.Time) error {
    method SetReadDeadline (line 255) | func (*udpConn) SetReadDeadline(time.Time) error {
    method SetWriteDeadline (line 259) | func (*udpConn) SetWriteDeadline(time.Time) error {
  type connID (line 263) | type connID struct
  type udpWorker (line 268) | type udpWorker struct
    method getConnection (line 289) | func (w *udpWorker) getConnection(id connID) (*udpConn, bool) {
    method callback (line 323) | func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, or...
    method removeConn (line 389) | func (w *udpWorker) removeConn(id connID) {
    method handlePackets (line 395) | func (w *udpWorker) handlePackets() {
    method clean (line 402) | func (w *udpWorker) clean() error {
    method Start (line 428) | func (w *udpWorker) Start() error {
    method Close (line 448) | func (w *udpWorker) Close() error {
    method Port (line 476) | func (w *udpWorker) Port() net.Port {
    method Proxy (line 480) | func (w *udpWorker) Proxy() proxy.Inbound {
  type dsWorker (line 484) | type dsWorker struct
    method callback (line 499) | func (w *dsWorker) callback(conn stat.Connection) {
    method Proxy (line 538) | func (w *dsWorker) Proxy() proxy.Inbound {
    method Port (line 542) | func (w *dsWorker) Port() net.Port {
    method Start (line 546) | func (w *dsWorker) Start() error {
    method Close (line 558) | func (w *dsWorker) Close() error {
  function IsLocal (line 575) | func IsLocal(ip net.IP) bool {

FILE: app/proxyman/outbound/handler.go
  function getStatCounter (line 35) | func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats....
  type Handler (line 61) | type Handler struct
    method Tag (line 175) | func (h *Handler) Tag() string {
    method Dispatch (line 180) | func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
    method DestIpAddress (line 266) | func (h *Handler) DestIpAddress() net.IP {
    method Dial (line 271) | func (h *Handler) Dial(ctx context.Context, dest net.Destination) (sta...
    method SetOutboundGateway (line 328) | func (h *Handler) SetOutboundGateway(ctx context.Context, ob *session....
    method getStatCouterConnection (line 360) | func (h *Handler) getStatCouterConnection(conn stat.Connection) stat.C...
    method GetOutbound (line 372) | func (h *Handler) GetOutbound() proxy.Outbound {
    method Start (line 377) | func (h *Handler) Start() error {
    method Close (line 382) | func (h *Handler) Close() error {
    method SenderSettings (line 389) | func (h *Handler) SenderSettings() *serial.TypedMessage {
    method ProxySettings (line 394) | func (h *Handler) ProxySettings() *serial.TypedMessage {
  function NewHandler (line 76) | func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig)...
  function ParseRandomIP (line 398) | func ParseRandomIP(addr net.Address, prefix string) net.Address {

FILE: app/proxyman/outbound/handler_test.go
  function TestInterfaces (line 24) | func TestInterfaces(t *testing.T) {
  constant xrayKey (line 29) | xrayKey core.XrayKey = 1
  function TestOutboundWithoutStatCounter (line 31) | func TestOutboundWithoutStatCounter(t *testing.T) {
  function TestOutboundWithStatCounter (line 60) | func TestOutboundWithStatCounter(t *testing.T) {
  function TestTagsCache (line 90) | func TestTagsCache(t *testing.T) {

FILE: app/proxyman/outbound/outbound.go
  type Manager (line 17) | type Manager struct
    method Type (line 36) | func (m *Manager) Type() interface{} {
    method Start (line 41) | func (m *Manager) Start() error {
    method Close (line 63) | func (m *Manager) Close() error {
    method GetDefaultHandler (line 82) | func (m *Manager) GetDefaultHandler() outbound.Handler {
    method GetHandler (line 93) | func (m *Manager) GetHandler(tag string) outbound.Handler {
    method AddHandler (line 103) | func (m *Manager) AddHandler(ctx context.Context, handler outbound.Han...
    method RemoveHandler (line 131) | func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
    method ListHandlers (line 149) | func (m *Manager) ListHandlers(ctx context.Context) []outbound.Handler {
    method Select (line 164) | func (m *Manager) Select(selectors []string) []string {
  function New (line 27) | func New(ctx context.Context, config *proxyman.OutboundConfig) (*Manager...
  function init (line 191) | func init() {

FILE: app/proxyman/outbound/uot.go
  method getUoTConnection (line 14) | func (h *Handler) getUoTConnection(ctx context.Context, dest net.Destina...

FILE: app/reverse/bridge.go
  type Bridge (line 20) | type Bridge struct
    method cleanup (line 49) | func (b *Bridge) cleanup() {
    method monitor (line 68) | func (b *Bridge) monitor() error {
    method Start (line 93) | func (b *Bridge) Start() error {
    method Close (line 97) | func (b *Bridge) Close() error {
  function NewBridge (line 29) | func NewBridge(config *BridgeConfig, dispatcher routing.Dispatcher) (*Br...
  type BridgeWorker (line 101) | type BridgeWorker struct
    method Type (line 141) | func (w *BridgeWorker) Type() interface{} {
    method Start (line 145) | func (w *BridgeWorker) Start() error {
    method Close (line 149) | func (w *BridgeWorker) Close() error {
    method IsActive (line 153) | func (w *BridgeWorker) IsActive() bool {
    method Closed (line 157) | func (w *BridgeWorker) Closed() bool {
    method Connections (line 161) | func (w *BridgeWorker) Connections() uint32 {
    method handleInternalConn (line 165) | func (w *BridgeWorker) handleInternalConn(link *transport.Link) {
    method Dispatch (line 198) | func (w *BridgeWorker) Dispatch(ctx context.Context, dest net.Destinat...
    method DispatchLink (line 223) | func (w *BridgeWorker) DispatchLink(ctx context.Context, dest net.Dest...
  function NewBridgeWorker (line 109) | func NewBridgeWorker(domain string, tag string, d routing.Dispatcher) (*...

FILE: app/reverse/config.go
  method FillInRandom (line 10) | func (c *Control) FillInRandom() {

FILE: app/reverse/config.pb.go
  constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type Control_State (line 24) | type Control_State
    method Enum (line 43) | func (x Control_State) Enum() *Control_State {
    method String (line 49) | func (x Control_State) String() string {
    method Descriptor (line 53) | func (Control_State) Descriptor() protoreflect.EnumDescriptor {
    method Type (line 57) | func (Control_State) Type() protoreflect.EnumType {
    method Number (line 61) | func (x Control_State) Number() protoreflect.EnumNumber {
    method EnumDescriptor (line 66) | func (Control_State) EnumDescriptor() ([]byte, []int) {
  constant Control_ACTIVE (line 27) | Control_ACTIVE Control_State = 0
  constant Control_DRAIN (line 28) | Control_DRAIN  Control_State = 1
  type Control (line 70) | type Control struct
    method Reset (line 78) | func (x *Control) Reset() {
    method String (line 85) | func (x *Control) String() string {
    method ProtoMessage (line 89) | func (*Control) ProtoMessage() {}
    method ProtoReflect (line 91) | func (x *Control) ProtoReflect() protoreflect.Message {
    method Descriptor (line 104) | func (*Control) Descriptor() ([]byte, []int) {
    method GetState (line 108) | func (x *Control) GetState() Control_State {
    method GetRandom (line 115) | func (x *Control) GetRandom() []byte {
  type BridgeConfig (line 122) | type BridgeConfig struct
    method Reset (line 130) | func (x *BridgeConfig) Reset() {
    method String (line 137) | func (x *BridgeConfig) String() string {
    method ProtoMessage (line 141) | func (*BridgeConfig) ProtoMessage() {}
    method ProtoReflect (line 143) | func (x *BridgeConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 156) | func (*BridgeConfig) Descriptor() ([]byte, []int) {
    method GetTag (line 160) | func (x *BridgeConfig) GetTag() string {
    method GetDomain (line 167) | func (x *BridgeConfig) GetDomain() string {
  type PortalConfig (line 174) | type PortalConfig struct
    method Reset (line 182) | func (x *PortalConfig) Reset() {
    method String (line 189) | func (x *PortalConfig) String() string {
    method ProtoMessage (line 193) | func (*PortalConfig) ProtoMessage() {}
    method ProtoReflect (line 195) | func (x *PortalConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 208) | func (*PortalConfig) Descriptor() ([]byte, []int) {
    method GetTag (line 212) | func (x *PortalConfig) GetTag() string {
    method GetDomain (line 219) | func (x *PortalConfig) GetDomain() string {
  type Config (line 226) | type Config struct
    method Reset (line 234) | func (x *Config) Reset() {
    method String (line 241) | func (x *Config) String() string {
    method ProtoMessage (line 245) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 247) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 260) | func (*Config) Descriptor() ([]byte, []int) {
    method GetBridgeConfig (line 264) | func (x *Config) GetBridgeConfig() []*BridgeConfig {
    method GetPortalConfig (line 271) | func (x *Config) GetPortalConfig() []*PortalConfig {
  constant file_app_reverse_config_proto_rawDesc (line 280) | file_app_reverse_config_proto_rawDesc = "" +
  function file_app_reverse_config_proto_rawDescGZIP (line 306) | func file_app_reverse_config_proto_rawDescGZIP() []byte {
  function init (line 333) | func init() { file_app_reverse_config_proto_init() }
  function file_app_reverse_config_proto_init (line 334) | func file_app_reverse_config_proto_init() {

FILE: app/reverse/portal.go
  type Portal (line 23) | type Portal struct
    method Start (line 56) | func (p *Portal) Start() error {
    method Close (line 63) | func (p *Portal) Close() error {
    method HandleConnection (line 67) | func (p *Portal) HandleConnection(ctx context.Context, link *transport...
  function NewPortal (line 31) | func NewPortal(config *PortalConfig, ohm outbound.Manager) (*Portal, err...
  type Outbound (line 104) | type Outbound struct
    method Tag (line 109) | func (o *Outbound) Tag() string {
    method Dispatch (line 113) | func (o *Outbound) Dispatch(ctx context.Context, link *transport.Link) {
    method Start (line 121) | func (o *Outbound) Start() error {
    method Close (line 125) | func (o *Outbound) Close() error {
    method SenderSettings (line 130) | func (o *Outbound) SenderSettings() *serial.TypedMessage {
    method ProxySettings (line 135) | func (o *Outbound) ProxySettings() *serial.TypedMessage {
  type StaticMuxPicker (line 139) | type StaticMuxPicker struct
    method cleanup (line 155) | func (p *StaticMuxPicker) cleanup() error {
    method PickAvailable (line 175) | func (p *StaticMuxPicker) PickAvailable() (*mux.ClientWorker, error) {
    method AddWorker (line 217) | func (p *StaticMuxPicker) AddWorker(worker *PortalWorker) {
  function NewStaticMuxPicker (line 145) | func NewStaticMuxPicker() (*StaticMuxPicker, error) {
  type PortalWorker (line 224) | type PortalWorker struct
    method heartbeat (line 268) | func (w *PortalWorker) heartbeat() error {
    method IsFull (line 302) | func (w *PortalWorker) IsFull() bool {
    method Closed (line 306) | func (w *PortalWorker) Closed() bool {
  function NewPortalWorker (line 234) | func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) {

FILE: app/reverse/portal_test.go
  function TestStaticPickerEmpty (line 10) | func TestStaticPickerEmpty(t *testing.T) {

FILE: app/reverse/reverse.go
  constant internalDomain (line 15) | internalDomain = "reverse"
  function isDomain (line 18) | func isDomain(dest net.Destination, domain string) bool {
  function isInternalDomain (line 22) | func isInternalDomain(dest net.Destination) bool {
  function init (line 26) | func init() {
  type Reverse (line 38) | type Reverse struct
    method Init (line 43) | func (r *Reverse) Init(config *Config, d routing.Dispatcher, ohm outbo...
    method Type (line 63) | func (r *Reverse) Type() interface{} {
    method Start (line 67) | func (r *Reverse) Start() error {
    method Close (line 83) | func (r *Reverse) Close() error {

FILE: app/router/balancing.go
  type BalancingStrategy (line 15) | type BalancingStrategy interface
  type BalancingPrincipleTarget (line 19) | type BalancingPrincipleTarget interface
  type RoundRobinStrategy (line 23) | type RoundRobinStrategy struct
    method InjectContext (line 32) | func (s *RoundRobinStrategy) InjectContext(ctx context.Context) {
    method GetPrincipleTarget (line 42) | func (s *RoundRobinStrategy) GetPrincipleTarget(strings []string) []st...
    method PickOutbound (line 46) | func (s *RoundRobinStrategy) PickOutbound(tags []string) string {
  type Balancer (line 85) | type Balancer struct
    method PickOutbound (line 95) | func (b *Balancer) PickOutbound() (string, error) {
    method InjectContext (line 121) | func (b *Balancer) InjectContext(ctx context.Context) {
    method SelectOutbounds (line 128) | func (b *Balancer) SelectOutbounds() ([]string, error) {
  method GetPrincipleTarget (line 138) | func (r *Router) GetPrincipleTarget(tag string) ([]string, error) {
  method SetOverrideTarget (line 153) | func (r *Router) SetOverrideTarget(tag, target string) error {
  method GetOverrideTarget (line 162) | func (r *Router) GetOverrideTarget(tag string) (string, error) {

FILE: app/router/balancing_override.go
  method OverrideBalancer (line 9) | func (r *Router) OverrideBalancer(balancer string, target string) error {
  type overrideSettings (line 24) | type overrideSettings struct
  type override (line 28) | type override struct
    method Get (line 34) | func (o *override) Get() string {
    method Put (line 41) | func (o *override) Put(target string) {
    method Clear (line 48) | func (o *override) Clear() {

FILE: app/router/command/command.go
  type routingServer (line 16) | type routingServer struct
    method GetBalancerInfo (line 21) | func (s *routingServer) GetBalancerInfo(ctx context.Context, request *...
    method OverrideBalancerTarget (line 49) | func (s *routingServer) OverrideBalancerTarget(ctx context.Context, re...
    method AddRule (line 56) | func (s *routingServer) AddRule(ctx context.Context, request *AddRuleR...
    method RemoveRule (line 64) | func (s *routingServer) RemoveRule(ctx context.Context, request *Remov...
    method ListRule (line 71) | func (s *routingServer) ListRule(ctx context.Context, request *ListRul...
    method TestRoute (line 93) | func (s *routingServer) TestRoute(ctx context.Context, request *TestRo...
    method SubscribeRoutingStats (line 108) | func (s *routingServer) SubscribeRoutingStats(request *SubscribeRoutin...
    method mustEmbedUnimplementedRoutingServiceServer (line 138) | func (s *routingServer) mustEmbedUnimplementedRoutingServiceServer() {}
  function NewRoutingServer (line 86) | func NewRoutingServer(router routing.Router, routingStats stats.Channel)...
  type service (line 140) | type service struct
    method Register (line 144) | func (s *service) Register(server *grpc.Server) {
  function init (line 156) | func init() {

FILE: app/router/command/command.pb.go
  constant _ (line 21) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 23) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type RoutingContext (line 29) | type RoutingContext struct
    method Reset (line 50) | func (x *RoutingContext) Reset() {
    method String (line 57) | func (x *RoutingContext) String() string {
    method ProtoMessage (line 61) | func (*RoutingContext) ProtoMessage() {}
    method ProtoReflect (line 63) | func (x *RoutingContext) ProtoReflect() protoreflect.Message {
    method Descriptor (line 76) | func (*RoutingContext) Descriptor() ([]byte, []int) {
    method GetInboundTag (line 80) | func (x *RoutingContext) GetInboundTag() string {
    method GetNetwork (line 87) | func (x *RoutingContext) GetNetwork() net.Network {
    method GetSourceIPs (line 94) | func (x *RoutingContext) GetSourceIPs() [][]byte {
    method GetTargetIPs (line 101) | func (x *RoutingContext) GetTargetIPs() [][]byte {
    method GetSourcePort (line 108) | func (x *RoutingContext) GetSourcePort() uint32 {
    method GetTargetPort (line 115) | func (x *RoutingContext) GetTargetPort() uint32 {
    method GetTargetDomain (line 122) | func (x *RoutingContext) GetTargetDomain() string {
    method GetProtocol (line 129) | func (x *RoutingContext) GetProtocol() string {
    method GetUser (line 136) | func (x *RoutingContext) GetUser() string {
    method GetAttributes (line 143) | func (x *RoutingContext) GetAttributes() map[string]string {
    method GetOutboundGroupTags (line 150) | func (x *RoutingContext) GetOutboundGroupTags() []string {
    method GetOutboundTag (line 157) | func (x *RoutingContext) GetOutboundTag() string {
    method GetLocalIPs (line 164) | func (x *RoutingContext) GetLocalIPs() [][]byte {
    method GetLocalPort (line 171) | func (x *RoutingContext) GetLocalPort() uint32 {
    method GetVlessRoute (line 178) | func (x *RoutingContext) GetVlessRoute() uint32 {
  type SubscribeRoutingStatsRequest (line 203) | type SubscribeRoutingStatsRequest struct
    method Reset (line 210) | func (x *SubscribeRoutingStatsRequest) Reset() {
    method String (line 217) | func (x *SubscribeRoutingStatsRequest) String() string {
    method ProtoMessage (line 221) | func (*SubscribeRoutingStatsRequest) ProtoMessage() {}
    method ProtoReflect (line 223) | func (x *SubscribeRoutingStatsRequest) ProtoReflect() protoreflect.Mes...
    method Descriptor (line 236) | func (*SubscribeRoutingStatsRequest) Descriptor() ([]byte, []int) {
    method GetFieldSelectors (line 240) | func (x *SubscribeRoutingStatsRequest) GetFieldSelectors() []string {
  type TestRouteRequest (line 254) | type TestRouteRequest struct
    method Reset (line 263) | func (x *TestRouteRequest) Reset() {
    method String (line 270) | func (x *TestRouteRequest) String() string {
    method ProtoMessage (line 274) | func (*TestRouteRequest) ProtoMessage() {}
    method ProtoReflect (line 276) | func (x *TestRouteRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 289) | func (*TestRouteRequest) Descriptor() ([]byte, []int) {
    method GetRoutingContext (line 293) | func (x *TestRouteRequest) GetRoutingContext() *RoutingContext {
    method GetFieldSelectors (line 300) | func (x *TestRouteRequest) GetFieldSelectors() []string {
    method GetPublishResult (line 307) | func (x *TestRouteRequest) GetPublishResult() bool {
  type PrincipleTargetInfo (line 314) | type PrincipleTargetInfo struct
    method Reset (line 321) | func (x *PrincipleTargetInfo) Reset() {
    method String (line 328) | func (x *PrincipleTargetInfo) String() string {
    method ProtoMessage (line 332) | func (*PrincipleTargetInfo) ProtoMessage() {}
    method ProtoReflect (line 334) | func (x *PrincipleTargetInfo) ProtoReflect() protoreflect.Message {
    method Descriptor (line 347) | func (*PrincipleTargetInfo) Descriptor() ([]byte, []int) {
    method GetTag (line 351) | func (x *PrincipleTargetInfo) GetTag() []string {
  type OverrideInfo (line 358) | type OverrideInfo struct
    method Reset (line 365) | func (x *OverrideInfo) Reset() {
    method String (line 372) | func (x *OverrideInfo) String() string {
    method ProtoMessage (line 376) | func (*OverrideInfo) ProtoMessage() {}
    method ProtoReflect (line 378) | func (x *OverrideInfo) ProtoReflect() protoreflect.Message {
    method Descriptor (line 391) | func (*OverrideInfo) Descriptor() ([]byte, []int) {
    method GetTarget (line 395) | func (x *OverrideInfo) GetTarget() string {
  type BalancerMsg (line 402) | type BalancerMsg struct
    method Reset (line 410) | func (x *BalancerMsg) Reset() {
    method String (line 417) | func (x *BalancerMsg) String() string {
    method ProtoMessage (line 421) | func (*BalancerMsg) ProtoMessage() {}
    method ProtoReflect (line 423) | func (x *BalancerMsg) ProtoReflect() protoreflect.Message {
    method Descriptor (line 436) | func (*BalancerMsg) Descriptor() ([]byte, []int) {
    method GetOverride (line 440) | func (x *BalancerMsg) GetOverride() *OverrideInfo {
    method GetPrincipleTarget (line 447) | func (x *BalancerMsg) GetPrincipleTarget() *PrincipleTargetInfo {
  type GetBalancerInfoRequest (line 454) | type GetBalancerInfoRequest struct
    method Reset (line 461) | func (x *GetBalancerInfoRequest) Reset() {
    method String (line 468) | func (x *GetBalancerInfoRequest) String() string {
    method ProtoMessage (line 472) | func (*GetBalancerInfoRequest) ProtoMessage() {}
    method ProtoReflect (line 474) | func (x *GetBalancerInfoRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 487) | func (*GetBalancerInfoRequest) Descriptor() ([]byte, []int) {
    method GetTag (line 491) | func (x *GetBalancerInfoRequest) GetTag() string {
  type GetBalancerInfoResponse (line 498) | type GetBalancerInfoResponse struct
    method Reset (line 505) | func (x *GetBalancerInfoResponse) Reset() {
    method String (line 512) | func (x *GetBalancerInfoResponse) String() string {
    method ProtoMessage (line 516) | func (*GetBalancerInfoResponse) ProtoMessage() {}
    method ProtoReflect (line 518) | func (x *GetBalancerInfoResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 531) | func (*GetBalancerInfoResponse) Descriptor() ([]byte, []int) {
    method GetBalancer (line 535) | func (x *GetBalancerInfoResponse) GetBalancer() *BalancerMsg {
  type OverrideBalancerTargetRequest (line 542) | type OverrideBalancerTargetRequest struct
    method Reset (line 550) | func (x *OverrideBalancerTargetRequest) Reset() {
    method String (line 557) | func (x *OverrideBalancerTargetRequest) String() string {
    method ProtoMessage (line 561) | func (*OverrideBalancerTargetRequest) ProtoMessage() {}
    method ProtoReflect (line 563) | func (x *OverrideBalancerTargetRequest) ProtoReflect() protoreflect.Me...
    method Descriptor (line 576) | func (*OverrideBalancerTargetRequest) Descriptor() ([]byte, []int) {
    method GetBalancerTag (line 580) | func (x *OverrideBalancerTargetRequest) GetBalancerTag() string {
    method GetTarget (line 587) | func (x *OverrideBalancerTargetRequest) GetTarget() string {
  type OverrideBalancerTargetResponse (line 594) | type OverrideBalancerTargetResponse struct
    method Reset (line 600) | func (x *OverrideBalancerTargetResponse) Reset() {
    method String (line 607) | func (x *OverrideBalancerTargetResponse) String() string {
    method ProtoMessage (line 611) | func (*OverrideBalancerTargetResponse) ProtoMessage() {}
    method ProtoReflect (line 613) | func (x *OverrideBalancerTargetResponse) ProtoReflect() protoreflect.M...
    method Descriptor (line 626) | func (*OverrideBalancerTargetResponse) Descriptor() ([]byte, []int) {
  type AddRuleRequest (line 630) | type AddRuleRequest struct
    method Reset (line 638) | func (x *AddRuleRequest) Reset() {
    method String (line 645) | func (x *AddRuleRequest) String() string {
    method ProtoMessage (line 649) | func (*AddRuleRequest) ProtoMessage() {}
    method ProtoReflect (line 651) | func (x *AddRuleRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 664) | func (*AddRuleRequest) Descriptor() ([]byte, []int) {
    method GetConfig (line 668) | func (x *AddRuleRequest) GetConfig() *serial.TypedMessage {
    method GetShouldAppend (line 675) | func (x *AddRuleRequest) GetShouldAppend() bool {
  type AddRuleResponse (line 682) | type AddRuleResponse struct
    method Reset (line 688) | func (x *AddRuleResponse) Reset() {
    method String (line 695) | func (x *AddRuleResponse) String() string {
    method ProtoMessage (line 699) | func (*AddRuleResponse) ProtoMessage() {}
    method ProtoReflect (line 701) | func (x *AddRuleResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 714) | func (*AddRuleResponse) Descriptor() ([]byte, []int) {
  type RemoveRuleRequest (line 718) | type RemoveRuleRequest struct
    method Reset (line 725) | func (x *RemoveRuleRequest) Reset() {
    method String (line 732) | func (x *RemoveRuleRequest) String() string {
    method ProtoMessage (line 736) | func (*RemoveRuleRequest) ProtoMessage() {}
    method ProtoReflect (line 738) | func (x *RemoveRuleRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 751) | func (*RemoveRuleRequest) Descriptor() ([]byte, []int) {
    method GetRuleTag (line 755) | func (x *RemoveRuleRequest) GetRuleTag() string {
  type RemoveRuleResponse (line 762) | type RemoveRuleResponse struct
    method Reset (line 768) | func (x *RemoveRuleResponse) Reset() {
    method String (line 775) | func (x *RemoveRuleResponse) String() string {
    method ProtoMessage (line 779) | func (*RemoveRuleResponse) ProtoMessage() {}
    method ProtoReflect (line 781) | func (x *RemoveRuleResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 794) | func (*RemoveRuleResponse) Descriptor() ([]byte, []int) {
  type ListRuleRequest (line 798) | type ListRuleRequest struct
    method Reset (line 804) | func (x *ListRuleRequest) Reset() {
    method String (line 811) | func (x *ListRuleRequest) String() string {
    method ProtoMessage (line 815) | func (*ListRuleRequest) ProtoMessage() {}
    method ProtoReflect (line 817) | func (x *ListRuleRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 830) | func (*ListRuleRequest) Descriptor() ([]byte, []int) {
  type ListRuleItem (line 834) | type ListRuleItem struct
    method Reset (line 842) | func (x *ListRuleItem) Reset() {
    method String (line 849) | func (x *ListRuleItem) String() string {
    method ProtoMessage (line 853) | func (*ListRuleItem) ProtoMessage() {}
    method ProtoReflect (line 855) | func (x *ListRuleItem) ProtoReflect() protoreflect.Message {
    method Descriptor (line 868) | func (*ListRuleItem) Descriptor() ([]byte, []int) {
    method GetTag (line 872) | func (x *ListRuleItem) GetTag() string {
    method GetRuleTag (line 879) | func (x *ListRuleItem) GetRuleTag() string {
  type ListRuleResponse (line 886) | type ListRuleResponse struct
    method Reset (line 893) | func (x *ListRuleResponse) Reset() {
    method String (line 900) | func (x *ListRuleResponse) String() string {
    method ProtoMessage (line 904) | func (*ListRuleResponse) ProtoMessage() {}
    method ProtoReflect (line 906) | func (x *ListRuleResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 919) | func (*ListRuleResponse) Descriptor() ([]byte, []int) {
    method GetRules (line 923) | func (x *ListRuleResponse) GetRules() []*ListRuleItem {
  type Config (line 930) | type Config struct
    method Reset (line 936) | func (x *Config) Reset() {
    method String (line 943) | func (x *Config) String() string {
    method ProtoMessage (line 947) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 949) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 962) | func (*Config) Descriptor() ([]byte, []int) {
  constant file_app_router_command_command_proto_rawDesc (line 968) | file_app_router_command_command_proto_rawDesc = "" +
  function file_app_router_command_command_proto_rawDescGZIP (line 1052) | func file_app_router_command_command_proto_rawDescGZIP() []byte {
  function init (line 1113) | func init() { file_app_router_command_command_proto_init() }
  function file_app_router_command_command_proto_init (line 1114) | func file_app_router_command_command_proto_init() {

FILE: app/router/command/command_grpc.pb.go
  constant _ (line 19) | _ = grpc.SupportPackageIsVersion9
  constant RoutingService_SubscribeRoutingStats_FullMethodName (line 22) | RoutingService_SubscribeRoutingStats_FullMethodName  = "/xray.app.router...
  constant RoutingService_TestRoute_FullMethodName (line 23) | RoutingService_TestRoute_FullMethodName              = "/xray.app.router...
  constant RoutingService_GetBalancerInfo_FullMethodName (line 24) | RoutingService_GetBalancerInfo_FullMethodName        = "/xray.app.router...
  constant RoutingService_OverrideBalancerTarget_FullMethodName (line 25) | RoutingService_OverrideBalancerTarget_FullMethodName = "/xray.app.router...
  constant RoutingService_AddRule_FullMethodName (line 26) | RoutingService_AddRule_FullMethodName                = "/xray.app.router...
  constant RoutingService_RemoveRule_FullMethodName (line 27) | RoutingService_RemoveRule_FullMethodName             = "/xray.app.router...
  constant RoutingService_ListRule_FullMethodName (line 28) | RoutingService_ListRule_FullMethodName               = "/xray.app.router...
  type RoutingServiceClient (line 34) | type RoutingServiceClient interface
  type routingServiceClient (line 44) | type routingServiceClient struct
    method SubscribeRoutingStats (line 52) | func (c *routingServiceClient) SubscribeRoutingStats(ctx context.Conte...
    method TestRoute (line 71) | func (c *routingServiceClient) TestRoute(ctx context.Context, in *Test...
    method GetBalancerInfo (line 81) | func (c *routingServiceClient) GetBalancerInfo(ctx context.Context, in...
    method OverrideBalancerTarget (line 91) | func (c *routingServiceClient) OverrideBalancerTarget(ctx context.Cont...
    method AddRule (line 101) | func (c *routingServiceClient) AddRule(ctx context.Context, in *AddRul...
    method RemoveRule (line 111) | func (c *routingServiceClient) RemoveRule(ctx context.Context, in *Rem...
    method ListRule (line 121) | func (c *routingServiceClient) ListRule(ctx context.Context, in *ListR...
  function NewRoutingServiceClient (line 48) | func NewRoutingServiceClient(cc grpc.ClientConnInterface) RoutingService...
  type RoutingServiceServer (line 134) | type RoutingServiceServer interface
  type UnimplementedRoutingServiceServer (line 150) | type UnimplementedRoutingServiceServer struct
    method SubscribeRoutingStats (line 152) | func (UnimplementedRoutingServiceServer) SubscribeRoutingStats(*Subscr...
    method TestRoute (line 155) | func (UnimplementedRoutingServiceServer) TestRoute(context.Context, *T...
    method GetBalancerInfo (line 158) | func (UnimplementedRoutingServiceServer) GetBalancerInfo(context.Conte...
    method OverrideBalancerTarget (line 161) | func (UnimplementedRoutingServiceServer) OverrideBalancerTarget(contex...
    method AddRule (line 164) | func (UnimplementedRoutingServiceServer) AddRule(context.Context, *Add...
    method RemoveRule (line 167) | func (UnimplementedRoutingServiceServer) RemoveRule(context.Context, *...
    method ListRule (line 170) | func (UnimplementedRoutingServiceServer) ListRule(context.Context, *Li...
    method mustEmbedUnimplementedRoutingServiceServer (line 173) | func (UnimplementedRoutingServiceServer) mustEmbedUnimplementedRouting...
    method testEmbeddedByValue (line 174) | func (UnimplementedRoutingServiceServer) testEmbeddedByValue()        ...
  type UnsafeRoutingServiceServer (line 179) | type UnsafeRoutingServiceServer interface
  function RegisterRoutingServiceServer (line 183) | func RegisterRoutingServiceServer(s grpc.ServiceRegistrar, srv RoutingSe...
  function _RoutingService_SubscribeRoutingStats_Handler (line 194) | func _RoutingService_SubscribeRoutingStats_Handler(srv interface{}, stre...
  function _RoutingService_TestRoute_Handler (line 205) | func _RoutingService_TestRoute_Handler(srv interface{}, ctx context.Cont...
  function _RoutingService_GetBalancerInfo_Handler (line 223) | func _RoutingService_GetBalancerInfo_Handler(srv interface{}, ctx contex...
  function _RoutingService_OverrideBalancerTarget_Handler (line 241) | func _RoutingService_OverrideBalancerTarget_Handler(srv interface{}, ctx...
  function _RoutingService_AddRule_Handler (line 259) | func _RoutingService_AddRule_Handler(srv interface{}, ctx context.Contex...
  function _RoutingService_RemoveRule_Handler (line 277) | func _RoutingService_RemoveRule_Handler(srv interface{}, ctx context.Con...
  function _RoutingService_ListRule_Handler (line 295) | func _RoutingService_ListRule_Handler(srv interface{}, ctx context.Conte...

FILE: app/router/command/command_test.go
  function TestServiceSubscribeRoutingStats (line 23) | func TestServiceSubscribeRoutingStats(t *testing.T) {
  function TestServiceSubscribeSubsetOfFields (line 157) | func TestServiceSubscribeSubsetOfFields(t *testing.T) {
  function TestServiceTestRoute (line 275) | func TestServiceTestRoute(t *testing.T) {

FILE: app/router/command/config.go
  type routingContext (line 11) | type routingContext struct
    method GetSourceIPs (line 15) | func (c routingContext) GetSourceIPs() []net.IP {
    method GetSourcePort (line 19) | func (c routingContext) GetSourcePort() net.Port {
    method GetTargetIPs (line 23) | func (c routingContext) GetTargetIPs() []net.IP {
    method GetTargetPort (line 27) | func (c routingContext) GetTargetPort() net.Port {
    method GetLocalIPs (line 31) | func (c routingContext) GetLocalIPs() []net.IP {
    method GetLocalPort (line 35) | func (c routingContext) GetLocalPort() net.Port {
    method GetVlessRoute (line 39) | func (c routingContext) GetVlessRoute() net.Port {
    method GetRuleTag (line 43) | func (c routingContext) GetRuleTag() string {
    method GetSkipDNSResolve (line 50) | func (c routingContext) GetSkipDNSResolve() bool {
  function AsRoutingContext (line 55) | func AsRoutingContext(r *RoutingContext) routing.Context {
  function AsRoutingRoute (line 60) | func AsRoutingRoute(r *RoutingContext) routing.Route {
  function AsProtobufMessage (line 82) | func AsProtobufMessage(fieldSelectors []string) func(routing.Route) *Rou...
  function mapBytesToIPs (line 105) | func mapBytesToIPs(bytes [][]byte) []net.IP {
  function mapIPsToBytes (line 113) | func mapIPsToBytes(ips []net.IP) [][]byte {

FILE: app/router/condition.go
  type Condition (line 18) | type Condition interface
  type ConditionChan (line 22) | type ConditionChan
    method Add (line 29) | func (v *ConditionChan) Add(cond Condition) *ConditionChan {
    method Apply (line 35) | func (v *ConditionChan) Apply(ctx routing.Context) bool {
    method Len (line 44) | func (v *ConditionChan) Len() int {
  function NewConditionChan (line 24) | func NewConditionChan() *ConditionChan {
  type DomainMatcher (line 55) | type DomainMatcher struct
    method ApplyDomain (line 107) | func (m *DomainMatcher) ApplyDomain(domain string) bool {
    method Apply (line 112) | func (m *DomainMatcher) Apply(ctx routing.Context) bool {
  function SerializeDomainMatcher (line 59) | func SerializeDomainMatcher(domains []*Domain, w io.Writer) error {
  function NewDomainMatcherFromBuffer (line 78) | func NewDomainMatcherFromBuffer(data []byte) (*strmatcher.MphMatcherGrou...
  function NewMphMatcherGroup (line 86) | func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) {
  type MatcherAsType (line 120) | type MatcherAsType
  constant MatcherAsType_Local (line 123) | MatcherAsType_Local MatcherAsType = iota
  constant MatcherAsType_Source (line 124) | MatcherAsType_Source
  constant MatcherAsType_Target (line 125) | MatcherAsType_Target
  constant MatcherAsType_VlessRoute (line 126) | MatcherAsType_VlessRoute
  type IPMatcher (line 129) | type IPMatcher struct
    method Apply (line 143) | func (m *IPMatcher) Apply(ctx routing.Context) bool {
  function NewIPMatcher (line 134) | func NewIPMatcher(geoips []*GeoIP, asType MatcherAsType) (*IPMatcher, er...
  type PortMatcher (line 160) | type PortMatcher struct
    method Apply (line 174) | func (v *PortMatcher) Apply(ctx routing.Context) bool {
  function NewPortMatcher (line 166) | func NewPortMatcher(list *net.PortList, asType MatcherAsType) *PortMatch...
  type NetworkMatcher (line 189) | type NetworkMatcher struct
    method Apply (line 202) | func (v NetworkMatcher) Apply(ctx routing.Context) bool {
  function NewNetworkMatcher (line 193) | func NewNetworkMatcher(network []net.Network) NetworkMatcher {
  type UserMatcher (line 206) | type UserMatcher struct
    method Apply (line 233) | func (v *UserMatcher) Apply(ctx routing.Context) bool {
  function NewUserMatcher (line 211) | func NewUserMatcher(users []string) *UserMatcher {
  type InboundTagMatcher (line 251) | type InboundTagMatcher struct
    method Apply (line 268) | func (v *InboundTagMatcher) Apply(ctx routing.Context) bool {
  function NewInboundTagMatcher (line 255) | func NewInboundTagMatcher(tags []string) *InboundTagMatcher {
  type ProtocolMatcher (line 281) | type ProtocolMatcher struct
    method Apply (line 300) | func (m *ProtocolMatcher) Apply(ctx routing.Context) bool {
  function NewProtocolMatcher (line 285) | func NewProtocolMatcher(protocols []string) *ProtocolMatcher {
  type AttributeMatcher (line 313) | type AttributeMatcher struct
    method Match (line 318) | func (m *AttributeMatcher) Match(attrs map[string]string) bool {
    method Apply (line 333) | func (m *AttributeMatcher) Apply(ctx routing.Context) bool {
  type ProcessNameMatcher (line 341) | type ProcessNameMatcher struct
    method Apply (line 389) | func (m *ProcessNameMatcher) Apply(ctx routing.Context) bool {
  function NewProcessNameMatcher (line 348) | func NewProcessNameMatcher(names []string) *ProcessNameMatcher {

FILE: app/router/condition_geoip.go
  type GeoIPMatcher (line 16) | type GeoIPMatcher interface
  type GeoIPSet (line 36) | type GeoIPSet struct
  type HeuristicGeoIPMatcher (line 41) | type HeuristicGeoIPMatcher struct
    method Match (line 52) | func (m *HeuristicGeoIPMatcher) Match(ip net.IP) bool {
    method matchAddr (line 60) | func (m *HeuristicGeoIPMatcher) matchAddr(ipx netip.Addr) bool {
    method AnyMatch (line 71) | func (m *HeuristicGeoIPMatcher) AnyMatch(ips []net.IP) bool {
    method Matches (line 121) | func (m *HeuristicGeoIPMatcher) Matches(ips []net.IP) bool {
    method FilterIPs (line 209) | func (m *HeuristicGeoIPMatcher) FilterIPs(ips []net.IP) (matched []net...
    method ToggleReverse (line 299) | func (m *HeuristicGeoIPMatcher) ToggleReverse() {
    method SetReverse (line 304) | func (m *HeuristicGeoIPMatcher) SetReverse(reverse bool) {
  type ipBucket (line 46) | type ipBucket struct
  function prefixKeyFromIP (line 185) | func prefixKeyFromIP(ip net.IP) (key [9]byte, ok bool) {
  type GeneralMultiGeoIPMatcher (line 308) | type GeneralMultiGeoIPMatcher struct
    method Match (line 313) | func (mm *GeneralMultiGeoIPMatcher) Match(ip net.IP) bool {
    method AnyMatch (line 323) | func (mm *GeneralMultiGeoIPMatcher) AnyMatch(ips []net.IP) bool {
    method Matches (line 333) | func (mm *GeneralMultiGeoIPMatcher) Matches(ips []net.IP) bool {
    method FilterIPs (line 343) | func (mm *GeneralMultiGeoIPMatcher) FilterIPs(ips []net.IP) (matched [...
    method ToggleReverse (line 360) | func (mm *GeneralMultiGeoIPMatcher) ToggleReverse() {
    method SetReverse (line 367) | func (mm *GeneralMultiGeoIPMatcher) SetReverse(reverse bool) {
  type HeuristicMultiGeoIPMatcher (line 373) | type HeuristicMultiGeoIPMatcher struct
    method Match (line 378) | func (mm *HeuristicMultiGeoIPMatcher) Match(ip net.IP) bool {
    method AnyMatch (line 393) | func (mm *HeuristicMultiGeoIPMatcher) AnyMatch(ips []net.IP) bool {
    method Matches (line 443) | func (mm *HeuristicMultiGeoIPMatcher) Matches(ips []net.IP) bool {
    method FilterIPs (line 585) | func (mm *HeuristicMultiGeoIPMatcher) FilterIPs(ips []net.IP) (matched...
    method ToggleReverse (line 786) | func (mm *HeuristicMultiGeoIPMatcher) ToggleReverse() {
    method SetReverse (line 793) | func (mm *HeuristicMultiGeoIPMatcher) SetReverse(reverse bool) {
  type ipViews (line 501) | type ipViews struct
    method ensureForMatcher (line 506) | func (v *ipViews) ensureForMatcher(m *HeuristicGeoIPMatcher, ips []net...
  type ipBucketViews (line 692) | type ipBucketViews struct
    method ensureForMatcher (line 697) | func (v *ipBucketViews) ensureForMatcher(m *HeuristicGeoIPMatcher, ips...
  type GeoIPSetFactory (line 799) | type GeoIPSetFactory struct
    method GetOrCreate (line 806) | func (f *GeoIPSetFactory) GetOrCreate(key string, cidrGroups [][]*CIDR...
    method Create (line 821) | func (f *GeoIPSetFactory) Create(cidrGroups ...[]*CIDR) (*GeoIPSet, er...
  function BuildOptimizedGeoIPMatcher (line 882) | func BuildOptimizedGeoIPMatcher(geoips ...*GeoIP) (GeoIPMatcher, error) {

FILE: app/router/condition_geoip_test.go
  function getAssetPath (line 17) | func getAssetPath(file string) (string, error) {
  function TestGeoIPMatcher (line 38) | func TestGeoIPMatcher(t *testing.T) {
  function TestGeoIPMatcherRegression (line 112) | func TestGeoIPMatcherRegression(t *testing.T) {
  function TestGeoIPReverseMatcher (line 146) | func TestGeoIPReverseMatcher(t *testing.T) {
  function TestGeoIPMatcher4CN (line 184) | func TestGeoIPMatcher4CN(t *testing.T) {
  function TestGeoIPMatcher6US (line 198) | func TestGeoIPMatcher6US(t *testing.T) {
  function loadGeoIP (line 212) | func loadGeoIP(country string) ([]*router.CIDR, error) {
  function BenchmarkGeoIPMatcher4CN (line 236) | func BenchmarkGeoIPMatcher4CN(b *testing.B) {
  function BenchmarkGeoIPMatcher6US (line 252) | func BenchmarkGeoIPMatcher6US(b *testing.B) {

FILE: app/router/condition_serialize_test.go
  function TestDomainMatcherSerialization (line 14) | func TestDomainMatcherSerialization(t *testing.T) {
  function TestGeoSiteSerialization (line 54) | func TestGeoSiteSerialization(t *testing.T) {
  function TestGeoSiteSerializationWithDeps (line 132) | func TestGeoSiteSerializationWithDeps(t *testing.T) {

FILE: app/router/condition_test.go
  function withBackground (line 20) | func withBackground() routing.Context {
  function withOutbound (line 24) | func withOutbound(outbound *session.Outbound) routing.Context {
  function withInbound (line 28) | func withInbound(inbound *session.Inbound) routing.Context {
  function withContent (line 32) | func withContent(content *session.Content) routing.Context {
  function TestRoutingRule (line 36) | func TestRoutingRule(t *testing.T) {
  function loadGeoSite (line 303) | func loadGeoSite(country string) ([]*Domain, error) {
  function TestChinaSites (line 327) | func TestChinaSites(t *testing.T) {
  function BenchmarkMphDomainMatcher (line 369) | func BenchmarkMphDomainMatcher(b *testing.B) {
  function BenchmarkMultiGeoIPMatcher (line 411) | func BenchmarkMultiGeoIPMatcher(b *testing.B) {

FILE: app/router/config.go
  type Rule (line 16) | type Rule struct
    method GetTag (line 24) | func (r *Rule) GetTag() (string, error) {
    method Apply (line 32) | func (r *Rule) Apply(ctx routing.Context) bool {
  method BuildCondition (line 36) | func (rr *RoutingRule) BuildCondition() (Condition, error) {
  method Build (line 147) | func (br *BalancingRule) Build(ohm outbound.Manager, dispatcher routing....
  function GetDomainMatcherWithRuleTag (line 193) | func GetDomainMatcherWithRuleTag(domainMatcherPath string, ruleTag strin...

FILE: app/router/config.pb.go
  constant _ (line 21) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 23) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type Domain_Type (line 27) | type Domain_Type
    method Enum (line 56) | func (x Domain_Type) Enum() *Domain_Type {
    method String (line 62) | func (x Domain_Type) String() string {
    method Descriptor (line 66) | func (Domain_Type) Descriptor() protoreflect.EnumDescriptor {
    method Type (line 70) | func (Domain_Type) Type() protoreflect.EnumType {
    method Number (line 74) | func (x Domain_Type) Number() protoreflect.EnumNumber {
    method EnumDescriptor (line 79) | func (Domain_Type) EnumDescriptor() ([]byte, []int) {
  constant Domain_Plain (line 31) | Domain_Plain Domain_Type = 0
  constant Domain_Regex (line 33) | Domain_Regex Domain_Type = 1
  constant Domain_Domain (line 35) | Domain_Domain Domain_Type = 2
  constant Domain_Full (line 37) | Domain_Full Domain_Type = 3
  type Config_DomainStrategy (line 83) | type Config_DomainStrategy
    method Enum (line 108) | func (x Config_DomainStrategy) Enum() *Config_DomainStrategy {
    method String (line 114) | func (x Config_DomainStrategy) String() string {
    method Descriptor (line 118) | func (Config_DomainStrategy) Descriptor() protoreflect.EnumDescriptor {
    method Type (line 122) | func (Config_DomainStrategy) Type() protoreflect.EnumType {
    method Number (line 126) | func (x Config_DomainStrategy) Number() protoreflect.EnumNumber {
    method EnumDescriptor (line 131) | func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) {
  constant Config_AsIs (line 87) | Config_AsIs Config_DomainStrategy = 0
  constant Config_IpIfNonMatch (line 89) | Config_IpIfNonMatch Config_DomainStrategy = 2
  constant Config_IpOnDemand (line 91) | Config_IpOnDemand Config_DomainStrategy = 3
  type Domain (line 136) | type Domain struct
    method Reset (line 148) | func (x *Domain) Reset() {
    method String (line 155) | func (x *Domain) String() string {
    method ProtoMessage (line 159) | func (*Domain) ProtoMessage() {}
    method ProtoReflect (line 161) | func (x *Domain) ProtoReflect() protoreflect.Message {
    method Descriptor (line 174) | func (*Domain) Descriptor() ([]byte, []int) {
    method GetType (line 178) | func (x *Domain) GetType() Domain_Type {
    method GetValue (line 185) | func (x *Domain) GetValue() string {
    method GetAttribute (line 192) | func (x *Domain) GetAttribute() []*Domain_Attribute {
  type CIDR (line 200) | type CIDR struct
    method Reset (line 210) | func (x *CIDR) Reset() {
    method String (line 217) | func (x *CIDR) String() string {
    method ProtoMessage (line 221) | func (*CIDR) ProtoMessage() {}
    method ProtoReflect (line 223) | func (x *CIDR) ProtoReflect() protoreflect.Message {
    method Descriptor (line 236) | func (*CIDR) Descriptor() ([]byte, []int) {
    method GetIp (line 240) | func (x *CIDR) GetIp() []byte {
    method GetPrefix (line 247) | func (x *CIDR) GetPrefix() uint32 {
  type GeoIP (line 254) | type GeoIP struct
    method Reset (line 263) | func (x *GeoIP) Reset() {
    method String (line 270) | func (x *GeoIP) String() string {
    method ProtoMessage (line 274) | func (*GeoIP) ProtoMessage() {}
    method ProtoReflect (line 276) | func (x *GeoIP) ProtoReflect() protoreflect.Message {
    method Descriptor (line 289) | func (*GeoIP) Descriptor() ([]byte, []int) {
    method GetCountryCode (line 293) | func (x *GeoIP) GetCountryCode() string {
    method GetCidr (line 300) | func (x *GeoIP) GetCidr() []*CIDR {
    method GetReverseMatch (line 307) | func (x *GeoIP) GetReverseMatch() bool {
  type GeoIPList (line 314) | type GeoIPList struct
    method Reset (line 321) | func (x *GeoIPList) Reset() {
    method String (line 328) | func (x *GeoIPList) String() string {
    method ProtoMessage (line 332) | func (*GeoIPList) ProtoMessage() {}
    method ProtoReflect (line 334) | func (x *GeoIPList) ProtoReflect() protoreflect.Message {
    method Descriptor (line 347) | func (*GeoIPList) Descriptor() ([]byte, []int) {
    method GetEntry (line 351) | func (x *GeoIPList) GetEntry() []*GeoIP {
  type GeoSite (line 358) | type GeoSite struct
    method Reset (line 366) | func (x *GeoSite) Reset() {
    method String (line 373) | func (x *GeoSite) String() string {
    method ProtoMessage (line 377) | func (*GeoSite) ProtoMessage() {}
    method ProtoReflect (line 379) | func (x *GeoSite) ProtoReflect() protoreflect.Message {
    method Descriptor (line 392) | func (*GeoSite) Descriptor() ([]byte, []int) {
    method GetCountryCode (line 396) | func (x *GeoSite) GetCountryCode() string {
    method GetDomain (line 403) | func (x *GeoSite) GetDomain() []*Domain {
  type GeoSiteList (line 410) | type GeoSiteList struct
    method Reset (line 417) | func (x *GeoSiteList) Reset() {
    method String (line 424) | func (x *GeoSiteList) String() string {
    method ProtoMessage (line 428) | func (*GeoSiteList) ProtoMessage() {}
    method ProtoReflect (line 430) | func (x *GeoSiteList) ProtoReflect() protoreflect.Message {
    method Descriptor (line 443) | func (*GeoSiteList) Descriptor() ([]byte, []int) {
    method GetEntry (line 447) | func (x *GeoSiteList) GetEntry() []*GeoSite {
  type RoutingRule (line 454) | type RoutingRule struct
    method Reset (line 491) | func (x *RoutingRule) Reset() {
    method String (line 498) | func (x *RoutingRule) String() string {
    method ProtoMessage (line 502) | func (*RoutingRule) ProtoMessage() {}
    method ProtoReflect (line 504) | func (x *RoutingRule) ProtoReflect() protoreflect.Message {
    method Descriptor (line 517) | func (*RoutingRule) Descriptor() ([]byte, []int) {
    method GetTargetTag (line 521) | func (x *RoutingRule) GetTargetTag() isRoutingRule_TargetTag {
    method GetTag (line 528) | func (x *RoutingRule) GetTag() string {
    method GetBalancingTag (line 537) | func (x *RoutingRule) GetBalancingTag() string {
    method GetRuleTag (line 546) | func (x *RoutingRule) GetRuleTag() string {
    method GetDomain (line 553) | func (x *RoutingRule) GetDomain() []*Domain {
    method GetGeoip (line 560) | func (x *RoutingRule) GetGeoip() []*GeoIP {
    method GetPortList (line 567) | func (x *RoutingRule) GetPortList() *net.PortList {
    method GetNetworks (line 574) | func (x *RoutingRule) GetNetworks() []net.Network {
    method GetSourceGeoip (line 581) | func (x *RoutingRule) GetSourceGeoip() []*GeoIP {
    method GetSourcePortList (line 588) | func (x *RoutingRule) GetSourcePortList() *net.PortList {
    method GetUserEmail (line 595) | func (x *RoutingRule) GetUserEmail() []string {
    method GetInboundTag (line 602) | func (x *RoutingRule) GetInboundTag() []string {
    method GetProtocol (line 609) | func (x *RoutingRule) GetProtocol() []string {
    method GetAttributes (line 616) | func (x *RoutingRule) GetAttributes() map[string]string {
    method GetLocalGeoip (line 623) | func (x *RoutingRule) GetLocalGeoip() []*GeoIP {
    method GetLocalPortList (line 630) | func (x *RoutingRule) GetLocalPortList() *net.PortList {
    method GetVlessRouteList (line 637) | func (x *RoutingRule) GetVlessRouteList() *net.PortList {
    method GetProcess (line 644) | func (x *RoutingRule) GetProcess() []string {
    method GetWebhook (line 651) | func (x *RoutingRule) GetWebhook() *WebhookConfig {
  type isRoutingRule_TargetTag (line 658) | type isRoutingRule_TargetTag interface
  type RoutingRule_Tag (line 662) | type RoutingRule_Tag struct
    method isRoutingRule_TargetTag (line 672) | func (*RoutingRule_Tag) isRoutingRule_TargetTag() {}
  type RoutingRule_BalancingTag (line 667) | type RoutingRule_BalancingTag struct
    method isRoutingRule_TargetTag (line 674) | func (*RoutingRule_BalancingTag) isRoutingRule_TargetTag() {}
  type WebhookConfig (line 676) | type WebhookConfig struct
    method Reset (line 685) | func (x *WebhookConfig) Reset() {
    method String (line 692) | func (x *WebhookConfig) String() string {
    method ProtoMessage (line 696) | func (*WebhookConfig) ProtoMessage() {}
    method ProtoReflect (line 698) | func (x *WebhookConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 711) | func (*WebhookConfig) Descriptor() ([]byte, []int) {
    method GetUrl (line 715) | func (x *WebhookConfig) GetUrl() string {
    method GetDeduplication (line 722) | func (x *WebhookConfig) GetDeduplication() uint32 {
    method GetHeaders (line 729) | func (x *WebhookConfig) GetHeaders() map[string]string {
  type BalancingRule (line 736) | type BalancingRule struct
    method Reset (line 747) | func (x *BalancingRule) Reset() {
    method String (line 754) | func (x *BalancingRule) String() string {
    method ProtoMessage (line 758) | func (*BalancingRule) ProtoMessage() {}
    method ProtoReflect (line 760) | func (x *BalancingRule) ProtoReflect() protoreflect.Message {
    method Descriptor (line 773) | func (*BalancingRule) Descriptor() ([]byte, []int) {
    method GetTag (line 777) | func (x *BalancingRule) GetTag() string {
    method GetOutboundSelector (line 784) | func (x *BalancingRule) GetOutboundSelector() []string {
    method GetStrategy (line 791) | func (x *BalancingRule) GetStrategy() string {
    method GetStrategySettings (line 798) | func (x *BalancingRule) GetStrategySettings() *serial.TypedMessage {
    method GetFallbackTag (line 805) | func (x *BalancingRule) GetFallbackTag() string {
  type StrategyWeight (line 812) | type StrategyWeight struct
    method Reset (line 821) | func (x *StrategyWeight) Reset() {
    method String (line 828) | func (x *StrategyWeight) String() string {
    method ProtoMessage (line 832) | func (*StrategyWeight) ProtoMessage() {}
    method ProtoReflect (line 834) | func (x *StrategyWeight) ProtoReflect() protoreflect.Message {
    method Descriptor (line 847) | func (*StrategyWeight) Descriptor() ([]byte, []int) {
    method GetRegexp (line 851) | func (x *StrategyWeight) GetRegexp() bool {
    method GetMatch (line 858) | func (x *StrategyWeight) GetMatch() string {
    method GetValue (line 865) | func (x *StrategyWeight) GetValue() float32 {
  type StrategyLeastLoadConfig (line 872) | type StrategyLeastLoadConfig struct
    method Reset (line 888) | func (x *StrategyLeastLoadConfig) Reset() {
    method String (line 895) | func (x *StrategyLeastLoadConfig) String() string {
    method ProtoMessage (line 899) | func (*StrategyLeastLoadConfig) ProtoMessage() {}
    method ProtoReflect (line 901) | func (x *StrategyLeastLoadConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 914) | func (*StrategyLeastLoadConfig) Descriptor() ([]byte, []int) {
    method GetCosts (line 918) | func (x *StrategyLeastLoadConfig) GetCosts() []*StrategyWeight {
    method GetBaselines (line 925) | func (x *StrategyLeastLoadConfig) GetBaselines() []int64 {
    method GetExpected (line 932) | func (x *StrategyLeastLoadConfig) GetExpected() int32 {
    method GetMaxRTT (line 939) | func (x *StrategyLeastLoadConfig) GetMaxRTT() int64 {
    method GetTolerance (line 946) | func (x *StrategyLeastLoadConfig) GetTolerance() float32 {
  type Config (line 953) | type Config struct
    method Reset (line 962) | func (x *Config) Reset() {
    method String (line 969) | func (x *Config) String() string {
    method ProtoMessage (line 973) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 975) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 988) | func (*Config) Descriptor() ([]byte, []int) {
    method GetDomainStrategy (line 992) | func (x *Config) GetDomainStrategy() Config_DomainStrategy {
    method GetRule (line 999) | func (x *Config) GetRule() []*RoutingRule {
    method GetBalancingRule (line 1006) | func (x *Config) GetBalancingRule() []*BalancingRule {
  type Domain_Attribute (line 1013) | type Domain_Attribute struct
    method Reset (line 1025) | func (x *Domain_Attribute) Reset() {
    method String (line 1032) | func (x *Domain_Attribute) String() string {
    method ProtoMessage (line 1036) | func (*Domain_Attribute) ProtoMessage() {}
    method ProtoReflect (line 1038) | func (x *Domain_Attribute) ProtoReflect() protoreflect.Message {
    method Descriptor (line 1051) | func (*Domain_Attribute) Descriptor() ([]byte, []int) {
    method GetKey (line 1055) | func (x *Domain_Attribute) GetKey() string {
    method GetTypedValue (line 1062) | func (x *Domain_Attribute) GetTypedValue() isDomain_Attribute_TypedVal...
    method GetBoolValue (line 1069) | func (x *Domain_Attribute) GetBoolValue() bool {
    method GetIntValue (line 1078) | func (x *Domain_Attribute) GetIntValue() int64 {
  type isDomain_Attribute_TypedValue (line 1087) | type isDomain_Attribute_TypedValue interface
  type Domain_Attribute_BoolValue (line 1091) | type Domain_Attribute_BoolValue struct
    method isDomain_Attribute_TypedValue (line 1099) | func (*Domain_Attribute_BoolValue) isDomain_Attribute_TypedValue() {}
  type Domain_Attribute_IntValue (line 1095) | type Domain_Attribute_IntValue struct
    method isDomain_Attribute_TypedValue (line 1101) | func (*Domain_Attribute_IntValue) isDomain_Attribute_TypedValue() {}
  constant file_app_router_config_proto_rawDesc (line 1105) | file_app_router_config_proto_rawDesc = "" +
  function file_app_router_config_proto_rawDescGZIP (line 1207) | func file_app_router_config_proto_rawDescGZIP() []byte {
  function init (line 1269) | func init() { file_app_router_config_proto_init() }
  function file_app_router_config_proto_init (line 1270) | func file_app_router_config_proto_init() {

FILE: app/router/geosite_compact.go
  type geoSiteListGob (line 12) | type geoSiteListGob struct
  function SerializeGeoSiteList (line 18) | func SerializeGeoSiteList(sites []*GeoSite, deps map[string][]string, ho...
  type bytesWriter (line 39) | type bytesWriter struct
    method Write (line 43) | func (w *bytesWriter) Write(p []byte) (n int, err error) {
    method Bytes (line 48) | func (w *bytesWriter) Bytes() []byte {
  function LoadGeoSiteMatcher (line 52) | func LoadGeoSiteMatcher(r io.Reader, countryCode string) (strmatcher.Ind...
  function loadWithDeps (line 61) | func loadWithDeps(data *geoSiteListGob, code string, visited map[string]...
  function LoadGeoSiteHosts (line 94) | func LoadGeoSiteHosts(r io.Reader) (map[string][]string, error) {

FILE: app/router/router.go
  type Router (line 18) | type Router struct
    method Init (line 39) | func (r *Router) Init(ctx context.Context, config *Config, d dns.Clien...
    method PickRoute (line 95) | func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) {
    method AddRule (line 112) | func (r *Router) AddRule(config *serial.TypedMessage, shouldAppend boo...
    method ReloadRules (line 124) | func (r *Router) ReloadRules(config *Config, shouldAppend bool) error {
    method RuleExists (line 201) | func (r *Router) RuleExists(tag string) bool {
    method RemoveRule (line 213) | func (r *Router) RemoveRule(tag string) error {
    method ListRule (line 234) | func (r *Router) ListRule() []routing.Route {
    method pickRouteInternal (line 247) | func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routin...
    method Start (line 280) | func (r *Router) Start() error {
    method closeWebhooks (line 285) | func (r *Router) closeWebhooks() {
    method Close (line 294) | func (r *Router) Close() error {
    method Type (line 302) | func (*Router) Type() interface{} {
  type Route (line 31) | type Route struct
    method GetOutboundGroupTags (line 307) | func (r *Route) GetOutboundGroupTags() []string {
    method GetOutboundTag (line 312) | func (r *Route) GetOutboundTag() string {
    method GetRuleTag (line 316) | func (r *Route) GetRuleTag() string {
  function init (line 320) | func init() {

FILE: app/router/router_test.go
  type mockOutboundManager (line 18) | type mockOutboundManager struct
  function TestSimpleRouter (line 23) | func TestSimpleRouter(t *testing.T) {
  function TestSimpleBalancer (line 58) | func TestSimpleBalancer(t *testing.T) {
  function TestIPOnDemand (line 150) | func TestIPOnDemand(t *testing.T) {
  function TestIPIfNonMatchDomain (line 195) | func TestIPIfNonMatchDomain(t *testing.T) {
  function TestIPIfNonMatchIP (line 240) | func TestIPIfNonMatchIP(t *testing.T) {

FILE: app/router/strategy_leastload.go
  type LeastLoadStrategy (line 18) | type LeastLoadStrategy struct
    method GetPrincipleTarget (line 27) | func (l *LeastLoadStrategy) GetPrincipleTarget(strings []string) []str...
    method InjectContext (line 61) | func (s *LeastLoadStrategy) InjectContext(ctx context.Context) {
    method PickOutbound (line 69) | func (s *LeastLoadStrategy) PickOutbound(candidates []string) string {
    method pickOutbounds (line 79) | func (s *LeastLoadStrategy) pickOutbounds(candidates []string) []*node {
    method selectLeastLoad (line 101) | func (s *LeastLoadStrategy) selectLeastLoad(nodes []*node) []*node {
    method getNodes (line 141) | func (s *LeastLoadStrategy) getNodes(candidates []string, maxRTT time....
  function NewLeastLoadStrategy (line 37) | func NewLeastLoadStrategy(settings *StrategyLeastLoadConfig) *LeastLoadS...
  type node (line 52) | type node struct
  function leastloadSort (line 185) | func leastloadSort(nodes []*node) {

FILE: app/router/strategy_leastload_test.go
  function TestSelectLeastExpected (line 69) | func TestSelectLeastExpected(t *testing.T) {
  function TestSelectLeastExpected2 (line 88) | func TestSelectLeastExpected2(t *testing.T) {
  function TestSelectLeastExpectedAndBaselines (line 105) | func TestSelectLeastExpectedAndBaselines(t *testing.T) {
  function TestSelectLeastExpectedAndBaselines2 (line 125) | func TestSelectLeastExpectedAndBaselines2(t *testing.T) {
  function TestSelectLeastLoadBaselines (line 145) | func TestSelectLeastLoadBaselines(t *testing.T) {
  function TestSelectLeastLoadBaselinesNoQualified (line 163) | func TestSelectLeastLoadBaselinesNoQualified(t *testing.T) {

FILE: app/router/strategy_leastping.go
  type LeastPingStrategy (line 13) | type LeastPingStrategy struct
    method GetPrincipleTarget (line 18) | func (l *LeastPingStrategy) GetPrincipleTarget(strings []string) []str...
    method InjectContext (line 22) | func (l *LeastPingStrategy) InjectContext(ctx context.Context) {
    method PickOutbound (line 30) | func (l *LeastPingStrategy) PickOutbound(strings []string) string {
  type outboundList (line 58) | type outboundList
    method contains (line 60) | func (o outboundList) contains(name string) bool {

FILE: app/router/strategy_random.go
  type RandomStrategy (line 14) | type RandomStrategy struct
    method InjectContext (line 21) | func (s *RandomStrategy) InjectContext(ctx context.Context) {
    method GetPrincipleTarget (line 31) | func (s *RandomStrategy) GetPrincipleTarget(strings []string) []string {
    method PickOutbound (line 35) | func (s *RandomStrategy) PickOutbound(candidates []string) string {

FILE: app/router/webhook.go
  function parseURL (line 32) | func parseURL(raw string) (httpURL, socketPath string) {
  function resolveSocketPath (line 50) | func resolveSocketPath(path string) string {
  function ptr (line 65) | func ptr[T any](v T) *T { return &v }
  type event (line 67) | type event struct
  type WebhookNotifier (line 83) | type WebhookNotifier struct
    method Fire (line 134) | func (h *WebhookNotifier) Fire(ctx routing.Context, outboundTag string) {
    method post (line 212) | func (h *WebhookNotifier) post(ev *event) {
    method isDuplicate (line 244) | func (h *WebhookNotifier) isDuplicate(email string) bool {
    method cleanupLoop (line 259) | func (h *WebhookNotifier) cleanupLoop() {
    method Close (line 280) | func (h *WebhookNotifier) Close() error {
  function NewWebhookNotifier (line 94) | func NewWebhookNotifier(cfg *WebhookConfig) (*WebhookNotifier, error) {
  function buildEvent (line 158) | func buildEvent(ctx routing.Context, outboundTag string) *event {
  function enrichFromSession (line 195) | func enrichFromSession(ev *event, sctx *routing_session.Context) {

FILE: app/router/weight.go
  type weightScaler (line 13) | type weightScaler
  function NewWeightManager (line 18) | func NewWeightManager(s []*StrategyWeight, defaultWeight float64, scaler...
  type WeightManager (line 28) | type WeightManager struct
    method Get (line 37) | func (s *WeightManager) Get(tag string) float64 {
    method Apply (line 50) | func (s *WeightManager) Apply(tag string, value float64) float64 {
    method findValue (line 54) | func (s *WeightManager) findValue(tag string) float64 {
    method getMatch (line 78) | func (s *WeightManager) getMatch(tag, find string, isRegexp bool) stri...

FILE: app/router/weight_test.go
  function TestWeight (line 10) | func TestWeight(t *testing.T) {

FILE: app/stats/channel.go
  type Channel (line 12) | type Channel struct
    method Subscribers (line 37) | func (c *Channel) Subscribers() []chan interface{} {
    method Subscribe (line 44) | func (c *Channel) Subscribe() (chan interface{}, error) {
    method Unsubscribe (line 56) | func (c *Channel) Unsubscribe(subscriber chan interface{}) error {
    method Publish (line 72) | func (c *Channel) Publish(ctx context.Context, msg interface{}) {
    method Running (line 87) | func (c *Channel) Running() bool {
    method Start (line 99) | func (c *Channel) Start() error {
    method Close (line 129) | func (c *Channel) Close() error {
  function NewChannel (line 27) | func NewChannel(config *ChannelConfig) *Channel {
  type channelMessage (line 140) | type channelMessage struct
    method publish (line 145) | func (c channelMessage) publish(publisher chan channelMessage) {
    method publishNonBlocking (line 152) | func (c channelMessage) publishNonBlocking(publisher chan channelMessa...
    method broadcast (line 160) | func (c channelMessage) broadcast(subscriber chan interface{}) {
    method broadcastNonBlocking (line 167) | func (c channelMessage) broadcastNonBlocking(subscriber chan interface...

FILE: app/stats/channel_test.go
  function TestStatsChannel (line 14) | func TestStatsChannel(t *testing.T) {
  function TestStatsChannelUnsubscribe (line 98) | func TestStatsChannelUnsubscribe(t *testing.T) {
  function TestStatsChannelBlocking (line 188) | func TestStatsChannelBlocking(t *testing.T) {
  function TestStatsChannelNonBlocking (line 262) | func TestStatsChannelNonBlocking(t *testing.T) {
  function TestStatsChannelConcurrency (line 338) | func TestStatsChannelConcurrency(t *testing.T) {

FILE: app/stats/command/command.go
  type statsServer (line 20) | type statsServer struct
    method GetStats (line 32) | func (s *statsServer) GetStats(ctx context.Context, request *GetStatsR...
    method GetStatsOnline (line 51) | func (s *statsServer) GetStatsOnline(ctx context.Context, request *Get...
    method GetStatsOnlineIpList (line 65) | func (s *statsServer) GetStatsOnlineIpList(ctx context.Context, reques...
    method GetAllOnlineUsers (line 83) | func (s *statsServer) GetAllOnlineUsers(ctx context.Context, request *...
    method QueryStats (line 89) | func (s *statsServer) QueryStats(ctx context.Context, request *QuerySt...
    method GetSysStats (line 121) | func (s *statsServer) GetSysStats(ctx context.Context, request *SysSta...
    method mustEmbedUnimplementedStatsServiceServer (line 143) | func (s *statsServer) mustEmbedUnimplementedStatsServiceServer() {}
  function NewStatsServer (line 25) | func NewStatsServer(manager feature_stats.Manager) StatsServiceServer {
  type service (line 145) | type service struct
    method Register (line 149) | func (s *service) Register(server *grpc.Server) {
  function init (line 159) | func init() {

FILE: app/stats/command/command.pb.go
  constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type GetStatsRequest (line 24) | type GetStatsRequest struct
    method Reset (line 34) | func (x *GetStatsRequest) Reset() {
    method String (line 41) | func (x *GetStatsRequest) String() string {
    method ProtoMessage (line 45) | func (*GetStatsRequest) ProtoMessage() {}
    method ProtoReflect (line 47) | func (x *GetStatsRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 60) | func (*GetStatsRequest) Descriptor() ([]byte, []int) {
    method GetName (line 64) | func (x *GetStatsRequest) GetName() string {
    method GetReset_ (line 71) | func (x *GetStatsRequest) GetReset_() bool {
  type Stat (line 78) | type Stat struct
    method Reset (line 86) | func (x *Stat) Reset() {
    method String (line 93) | func (x *Stat) String() string {
    method ProtoMessage (line 97) | func (*Stat) ProtoMessage() {}
    method ProtoReflect (line 99) | func (x *Stat) ProtoReflect() protoreflect.Message {
    method Descriptor (line 112) | func (*Stat) Descriptor() ([]byte, []int) {
    method GetName (line 116) | func (x *Stat) GetName() string {
    method GetValue (line 123) | func (x *Stat) GetValue() int64 {
  type GetStatsResponse (line 130) | type GetStatsResponse struct
    method Reset (line 137) | func (x *GetStatsResponse) Reset() {
    method String (line 144) | func (x *GetStatsResponse) String() string {
    method ProtoMessage (line 148) | func (*GetStatsResponse) ProtoMessage() {}
    method ProtoReflect (line 150) | func (x *GetStatsResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 163) | func (*GetStatsResponse) Descriptor() ([]byte, []int) {
    method GetStat (line 167) | func (x *GetStatsResponse) GetStat() *Stat {
  type QueryStatsRequest (line 174) | type QueryStatsRequest struct
    method Reset (line 182) | func (x *QueryStatsRequest) Reset() {
    method String (line 189) | func (x *QueryStatsRequest) String() string {
    method ProtoMessage (line 193) | func (*QueryStatsRequest) ProtoMessage() {}
    method ProtoReflect (line 195) | func (x *QueryStatsRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 208) | func (*QueryStatsRequest) Descriptor() ([]byte, []int) {
    method GetPattern (line 212) | func (x *QueryStatsRequest) GetPattern() string {
    method GetReset_ (line 219) | func (x *QueryStatsRequest) GetReset_() bool {
  type QueryStatsResponse (line 226) | type QueryStatsResponse struct
    method Reset (line 233) | func (x *QueryStatsResponse) Reset() {
    method String (line 240) | func (x *QueryStatsResponse) String() string {
    method ProtoMessage (line 244) | func (*QueryStatsResponse) ProtoMessage() {}
    method ProtoReflect (line 246) | func (x *QueryStatsResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 259) | func (*QueryStatsResponse) Descriptor() ([]byte, []int) {
    method GetStat (line 263) | func (x *QueryStatsResponse) GetStat() []*Stat {
  type SysStatsRequest (line 270) | type SysStatsRequest struct
    method Reset (line 276) | func (x *SysStatsRequest) Reset() {
    method String (line 283) | func (x *SysStatsRequest) String() string {
    method ProtoMessage (line 287) | func (*SysStatsRequest) ProtoMessage() {}
    method ProtoReflect (line 289) | func (x *SysStatsRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 302) | func (*SysStatsRequest) Descriptor() ([]byte, []int) {
  type SysStatsResponse (line 306) | type SysStatsResponse struct
    method Reset (line 322) | func (x *SysStatsResponse) Reset() {
    method String (line 329) | func (x *SysStatsResponse) String() string {
    method ProtoMessage (line 333) | func (*SysStatsResponse) ProtoMessage() {}
    method ProtoReflect (line 335) | func (x *SysStatsResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 348) | func (*SysStatsResponse) Descriptor() ([]byte, []int) {
    method GetNumGoroutine (line 352) | func (x *SysStatsResponse) GetNumGoroutine() uint32 {
    method GetNumGC (line 359) | func (x *SysStatsResponse) GetNumGC() uint32 {
    method GetAlloc (line 366) | func (x *SysStatsResponse) GetAlloc() uint64 {
    method GetTotalAlloc (line 373) | func (x *SysStatsResponse) GetTotalAlloc() uint64 {
    method GetSys (line 380) | func (x *SysStatsResponse) GetSys() uint64 {
    method GetMallocs (line 387) | func (x *SysStatsResponse) GetMallocs() uint64 {
    method GetFrees (line 394) | func (x *SysStatsResponse) GetFrees() uint64 {
    method GetLiveObjects (line 401) | func (x *SysStatsResponse) GetLiveObjects() uint64 {
    method GetPauseTotalNs (line 408) | func (x *SysStatsResponse) GetPauseTotalNs() uint64 {
    method GetUptime (line 415) | func (x *SysStatsResponse) GetUptime() uint32 {
  type GetStatsOnlineIpListResponse (line 422) | type GetStatsOnlineIpListResponse struct
    method Reset (line 430) | func (x *GetStatsOnlineIpListResponse) Reset() {
    method String (line 437) | func (x *GetStatsOnlineIpListResponse) String() string {
    method ProtoMessage (line 441) | func (*GetStatsOnlineIpListResponse) ProtoMessage() {}
    method ProtoReflect (line 443) | func (x *GetStatsOnlineIpListResponse) ProtoReflect() protoreflect.Mes...
    method Descriptor (line 456) | func (*GetStatsOnlineIpListResponse) Descriptor() ([]byte, []int) {
    method GetName (line 460) | func (x *GetStatsOnlineIpListResponse) GetName() string {
    method GetIps (line 467) | func (x *GetStatsOnlineIpListResponse) GetIps() map[string]int64 {
  type GetAllOnlineUsersRequest (line 474) | type GetAllOnlineUsersRequest struct
    method Reset (line 480) | func (x *GetAllOnlineUsersRequest) Reset() {
    method String (line 487) | func (x *GetAllOnlineUsersRequest) String() string {
    method ProtoMessage (line 491) | func (*GetAllOnlineUsersRequest) ProtoMessage() {}
    method ProtoReflect (line 493) | func (x *GetAllOnlineUsersRequest) ProtoReflect() protoreflect.Message {
    method Descriptor (line 506) | func (*GetAllOnlineUsersRequest) Descriptor() ([]byte, []int) {
  type GetAllOnlineUsersResponse (line 510) | type GetAllOnlineUsersResponse struct
    method Reset (line 517) | func (x *GetAllOnlineUsersResponse) Reset() {
    method String (line 524) | func (x *GetAllOnlineUsersResponse) String() string {
    method ProtoMessage (line 528) | func (*GetAllOnlineUsersResponse) ProtoMessage() {}
    method ProtoReflect (line 530) | func (x *GetAllOnlineUsersResponse) ProtoReflect() protoreflect.Message {
    method Descriptor (line 543) | func (*GetAllOnlineUsersResponse) Descriptor() ([]byte, []int) {
    method GetUsers (line 547) | func (x *GetAllOnlineUsersResponse) GetUsers() []string {
  type Config (line 554) | type Config struct
    method Reset (line 560) | func (x *Config) Reset() {
    method String (line 567) | func (x *Config) String() string {
    method ProtoMessage (line 571) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 573) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 586) | func (*Config) Descriptor() ([]byte, []int) {
  constant file_app_stats_command_command_proto_rawDesc (line 592) | file_app_stats_command_command_proto_rawDesc = "" +
  function file_app_stats_command_command_proto_rawDescGZIP (line 648) | func file_app_stats_command_command_proto_rawDescGZIP() []byte {
  function init (line 693) | func init() { file_app_stats_command_command_proto_init() }
  function file_app_stats_command_command_proto_init (line 694) | func file_app_stats_command_command_proto_init() {

FILE: app/stats/command/command_grpc.pb.go
  constant _ (line 19) | _ = grpc.SupportPackageIsVersion9
  constant StatsService_GetStats_FullMethodName (line 22) | StatsService_GetStats_FullMethodName             = "/xray.app.stats.comm...
  constant StatsService_GetStatsOnline_FullMethodName (line 23) | StatsService_GetStatsOnline_FullMethodName       = "/xray.app.stats.comm...
  constant StatsService_QueryStats_FullMethodName (line 24) | StatsService_QueryStats_FullMethodName           = "/xray.app.stats.comm...
  constant StatsService_GetSysStats_FullMethodName (line 25) | StatsService_GetSysStats_FullMethodName          = "/xray.app.stats.comm...
  constant StatsService_GetStatsOnlineIpList_FullMethodName (line 26) | StatsService_GetStatsOnlineIpList_FullMethodName = "/xray.app.stats.comm...
  constant StatsService_GetAllOnlineUsers_FullMethodName (line 27) | StatsService_GetAllOnlineUsers_FullMethodName    = "/xray.app.stats.comm...
  type StatsServiceClient (line 33) | type StatsServiceClient interface
  type statsServiceClient (line 42) | type statsServiceClient struct
    method GetStats (line 50) | func (c *statsServiceClient) GetStats(ctx context.Context, in *GetStat...
    method GetStatsOnline (line 60) | func (c *statsServiceClient) GetStatsOnline(ctx context.Context, in *G...
    method QueryStats (line 70) | func (c *statsServiceClient) QueryStats(ctx context.Context, in *Query...
    method GetSysStats (line 80) | func (c *statsServiceClient) GetSysStats(ctx context.Context, in *SysS...
    method GetStatsOnlineIpList (line 90) | func (c *statsServiceClient) GetStatsOnlineIpList(ctx context.Context,...
    method GetAllOnlineUsers (line 100) | func (c *statsServiceClient) GetAllOnlineUsers(ctx context.Context, in...
  function NewStatsServiceClient (line 46) | func NewStatsServiceClient(cc grpc.ClientConnInterface) StatsServiceClie...
  type StatsServiceServer (line 113) | type StatsServiceServer interface
  type UnimplementedStatsServiceServer (line 128) | type UnimplementedStatsServiceServer struct
    method GetStats (line 130) | func (UnimplementedStatsServiceServer) GetStats(context.Context, *GetS...
    method GetStatsOnline (line 133) | func (UnimplementedStatsServiceServer) GetStatsOnline(context.Context,...
    method QueryStats (line 136) | func (UnimplementedStatsServiceServer) QueryStats(context.Context, *Qu...
    method GetSysStats (line 139) | func (UnimplementedStatsServiceServer) GetSysStats(context.Context, *S...
    method GetStatsOnlineIpList (line 142) | func (UnimplementedStatsServiceServer) GetStatsOnlineIpList(context.Co...
    method GetAllOnlineUsers (line 145) | func (UnimplementedStatsServiceServer) GetAllOnlineUsers(context.Conte...
    method mustEmbedUnimplementedStatsServiceServer (line 148) | func (UnimplementedStatsServiceServer) mustEmbedUnimplementedStatsServ...
    method testEmbeddedByValue (line 149) | func (UnimplementedStatsServiceServer) testEmbeddedByValue()          ...
  type UnsafeStatsServiceServer (line 154) | type UnsafeStatsServiceServer interface
  function RegisterStatsServiceServer (line 158) | func RegisterStatsServiceServer(s grpc.ServiceRegistrar, srv StatsServic...
  function _StatsService_GetStats_Handler (line 169) | func _StatsService_GetStats_Handler(srv interface{}, ctx context.Context...
  function _StatsService_GetStatsOnline_Handler (line 187) | func _StatsService_GetStatsOnline_Handler(srv interface{}, ctx context.C...
  function _StatsService_QueryStats_Handler (line 205) | func _StatsService_QueryStats_Handler(srv interface{}, ctx context.Conte...
  function _StatsService_GetSysStats_Handler (line 223) | func _StatsService_GetSysStats_Handler(srv interface{}, ctx context.Cont...
  function _StatsService_GetStatsOnlineIpList_Handler (line 241) | func _StatsService_GetStatsOnlineIpList_Handler(srv interface{}, ctx con...
  function _StatsService_GetAllOnlineUsers_Handler (line 259) | func _StatsService_GetAllOnlineUsers_Handler(srv interface{}, ctx contex...

FILE: app/stats/command/command_test.go
  function TestGetStats (line 14) | func TestGetStats(t *testing.T) {
  function TestQueryStats (line 63) | func TestQueryStats(t *testing.T) {

FILE: app/stats/config.pb.go
  constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type Config (line 24) | type Config struct
    method Reset (line 30) | func (x *Config) Reset() {
    method String (line 37) | func (x *Config) String() string {
    method ProtoMessage (line 41) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 43) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 56) | func (*Config) Descriptor() ([]byte, []int) {
  type ChannelConfig (line 60) | type ChannelConfig struct
    method Reset (line 69) | func (x *ChannelConfig) Reset() {
    method String (line 76) | func (x *ChannelConfig) String() string {
    method ProtoMessage (line 80) | func (*ChannelConfig) ProtoMessage() {}
    method ProtoReflect (line 82) | func (x *ChannelConfig) ProtoReflect() protoreflect.Message {
    method Descriptor (line 95) | func (*ChannelConfig) Descriptor() ([]byte, []int) {
    method GetBlocking (line 99) | func (x *ChannelConfig) GetBlocking() bool {
    method GetSubscriberLimit (line 106) | func (x *ChannelConfig) GetSubscriberLimit() int32 {
    method GetBufferSize (line 113) | func (x *ChannelConfig) GetBufferSize() int32 {
  constant file_app_stats_config_proto_rawDesc (line 122) | file_app_stats_config_proto_rawDesc = "" +
  function file_app_stats_config_proto_rawDescGZIP (line 139) | func file_app_stats_config_proto_rawDescGZIP() []byte {
  function init (line 159) | func init() { file_app_stats_config_proto_init() }
  function file_app_stats_config_proto_init (line 160) | func file_app_stats_config_proto_init() {

FILE: app/stats/counter.go
  type Counter (line 6) | type Counter struct
    method Value (line 11) | func (c *Counter) Value() int64 {
    method Set (line 16) | func (c *Counter) Set(newValue int64) int64 {
    method Add (line 21) | func (c *Counter) Add(delta int64) int64 {

FILE: app/stats/counter_test.go
  function TestStatsCounter (line 12) | func TestStatsCounter(t *testing.T) {

FILE: app/stats/online_map.go
  constant localhostIPv4 (line 10) | localhostIPv4 = "127.0.0.1"
  constant localhostIPv6 (line 11) | localhostIPv6 = "[::1]"
  type ipEntry (line 14) | type ipEntry struct
  type OnlineMap (line 22) | type OnlineMap struct
    method AddIP (line 36) | func (om *OnlineMap) AddIP(ip string) {
    method RemoveIP (line 57) | func (om *OnlineMap) RemoveIP(ip string) {
    method Count (line 73) | func (om *OnlineMap) Count() int {
    method List (line 78) | func (om *OnlineMap) List() []string {
    method IPTimeMap (line 90) | func (om *OnlineMap) IPTimeMap() map[string]time.Time {
  function NewOnlineMap (line 29) | func NewOnlineMap() *OnlineMap {

FILE: app/stats/stats.go
  type Manager (line 13) | type Manager struct
    method Type (line 33) | func (*Manager) Type() interface{} {
    method RegisterCounter (line 38) | func (m *Manager) RegisterCounter(name string) (stats.Counter, error) {
    method UnregisterCounter (line 52) | func (m *Manager) UnregisterCounter(name string) error {
    method GetCounter (line 64) | func (m *Manager) GetCounter(name string) stats.Counter {
    method VisitCounters (line 75) | func (m *Manager) VisitCounters(visitor func(string, stats.Counter) bo...
    method RegisterOnlineMap (line 87) | func (m *Manager) RegisterOnlineMap(name string) (stats.OnlineMap, err...
    method UnregisterOnlineMap (line 101) | func (m *Manager) UnregisterOnlineMap(name string) error {
    method GetOnlineMap (line 113) | func (m *Manager) GetOnlineMap(name string) stats.OnlineMap {
    method RegisterChannel (line 124) | func (m *Manager) RegisterChannel(name string) (stats.Channel, error) {
    method UnregisterChannel (line 141) | func (m *Manager) UnregisterChannel(name string) error {
    method GetChannel (line 154) | func (m *Manager) GetChannel(name string) stats.Channel {
    method GetAllOnlineUsers (line 165) | func (m *Manager) GetAllOnlineUsers() []string {
    method Start (line 180) | func (m *Manager) Start() error {
    method Close (line 197) | func (m *Manager) Close() error {
  function NewManager (line 22) | func NewManager(ctx context.Context, config *Config) (*Manager, error) {
  function init (line 215) | func init() {

FILE: app/stats/stats_test.go
  function TestInterface (line 13) | func TestInterface(t *testing.T) {
  function TestStatsChannelRunnable (line 17) | func TestStatsChannelRunnable(t *testing.T) {

FILE: app/version/config.pb.go
  constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
  constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
  type Config (line 24) | type Config struct
    method Reset (line 33) | func (x *Config) Reset() {
    method String (line 40) | func (x *Config) String() string {
    method ProtoMessage (line 44) | func (*Config) ProtoMessage() {}
    method ProtoReflect (line 46) | func (x *Config) ProtoReflect() protoreflect.Message {
    method Descriptor (line 59) | func (*Config) Descriptor() ([]byte, []int) {
    method GetCoreVersion (line 63) | func (x *Config) GetCoreVersion() string {
    method GetMinVersion (line 70) | func (x *Config) GetMinVersion() string {
    method GetMaxVersion (line 77) | func (x *Config) GetMaxVersion() string {
  constant file_app_version_config_proto_rawDesc (line 86) | file_app_version_config_proto_rawDesc = "" +
  function file_app_version_config_proto_rawDescGZIP (line 102) | func file_app_version_config_proto_rawDescGZIP() []byte {
  function init (line 121) | func init() { file_app_version_config_proto_init() }
  function file_app_version_config_proto_init (line 122) | func file_app_version_config_proto_init() {

FILE: app/version/version.go
  type Version (line 11) | type Version struct
  function New (line 16) | func New(ctx context.Context, config *Config) (*Version, error) {
  function compareVersions (line 38) | func compareVersions(v1, v2 string) (int, error) {
  function init (line 73) | func init() {

FILE: common/antireplay/antireplay_test.go
  function BenchmarkMapFilter (line 9) | func BenchmarkMapFilter(b *testing.B) {
  function TestMapFilter (line 21) | func TestMapFilter(t *testing.T) {

FILE: common/antireplay/mapfilter.go
  type ReplayFilter (line 9) | type ReplayFilter struct
  function NewMapFilter (line 18) | func NewMapFilter[T comparable](interval int64) *ReplayFilter[T] {
  method Check (line 29) | func (filter *ReplayFilter[T]) Check(sum T) bool {

FILE: common/bitmask/byte.go
  type Byte (line 4) | type Byte
    method Has (line 7) | func (b Byte) Has(bb Byte) bool {
    method Set (line 11) | func (b *Byte) Set(bb Byte) {
    method Clear (line 15) | func (b *Byte) Clear(bb Byte) {
    method Toggle (line 19) | func (b *Byte) Toggle(bb Byte) {

FILE: common/bitmask/byte_test.go
  function TestBitmaskByte (line 9) | func TestBitmaskByte(t *testing.T) {

FILE: common/buf/buffer.go
  constant Size (line 13) | Size = 8192
  type ownership (line 21) | type ownership
  constant managed (line 24) | managed ownership = iota
  constant unmanaged (line 25) | unmanaged
  constant bytespools (line 26) | bytespools
  type Buffer (line 32) | type Buffer struct
    method Release (line 104) | func (b *Buffer) Release() {
    method Clear (line 126) | func (b *Buffer) Clear() {
    method Byte (line 132) | func (b *Buffer) Byte(index int32) byte {
    method SetByte (line 137) | func (b *Buffer) SetByte(index int32, value byte) {
    method Bytes (line 142) | func (b *Buffer) Bytes() []byte {
    method Extend (line 148) | func (b *Buffer) Extend(n int32) []byte {
    method BytesRange (line 160) | func (b *Buffer) BytesRange(from, to int32) []byte {
    method BytesFrom (line 171) | func (b *Buffer) BytesFrom(from int32) []byte {
    method BytesTo (line 179) | func (b *Buffer) BytesTo(to int32) []byte {
    method Check (line 190) | func (b *Buffer) Check() {
    method Resize (line 203) | func (b *Buffer) Resize(from, to int32) {
    method Advance (line 223) | func (b *Buffer) Advance(from int32) {
    method Len (line 232) | func (b *Buffer) Len() int32 {
    method Cap (line 240) | func (b *Buffer) Cap() int32 {
    method Available (line 248) | func (b *Buffer) Available() int32 {
    method IsEmpty (line 256) | func (b *Buffer) IsEmpty() bool {
    method IsFull (line 261) | func (b *Buffer) IsFull() bool {
    method Write (line 266) | func (b *Buffer) Write(data []byte) (int, error) {
    method WriteByte (line 276) | func (b *Buffer) WriteByte(v byte) error {
    method WriteString (line 286) | func (b *Buffer) WriteString(s string) (int, error) {
    method ReadByte (line 291) | func (b *Buffer) ReadByte() (byte, error) {
    method ReadBytes (line 302) | func (b *Buffer) ReadBytes(length int32) ([]byte, error) {
    method Read (line 313) | func (b *Buffer) Read(data []byte) (int, error) {
    method ReadFrom (line 327) | func (b *Buffer) ReadFrom(reader io.Reader) (int64, error) {
    method ReadFullFrom (line 334) | func (b *Buffer) ReadFullFrom(reader io.Reader, size int32) (int64, er...
    method String (line 346) | func (b *Buffer) String() string {
  function New (line 41) | func New() *Buffer {
  function NewExisted (line 55) | func NewExisted(b []byte) *Buffer {
  function FromBytes (line 72) | func FromBytes(b []byte) *Buffer {
  function StackNew (line 82) | func StackNew() Buffer {
  function NewWithSize (line 96) | func NewWithSize(size int32) *Buffer {

FILE: common/buf/buffer_test.go
  function TestBufferClear (line 13) | func TestBufferClear(t *testing.T) {
  function TestBufferIsEmpty (line 29) | func TestBufferIsEmpty(t *testing.T) {
  function TestBufferString (line 38) | func TestBufferString(t *testing.T) {
  function TestBufferByte (line 49) | func TestBufferByte(t *testing.T) {
  function TestBufferResize (line 81) | func TestBufferResize(t *testing.T) {
  function TestBufferSlice (line 106) | func TestBufferSlice(t *testing.T) {
  function TestBufferReadFullFrom (line 135) | func TestBufferReadFullFrom(t *testing.T) {
  function BenchmarkNewBuffer (line 152) | func BenchmarkNewBuffer(b *testing.B) {
  function BenchmarkNewBufferStack (line 159) | func BenchmarkNewBufferStack(b *testing.B) {
  function BenchmarkWrite2 (line 166) | func BenchmarkWrite2(b *testing.B) {
  function BenchmarkWrite8 (line 176) | func BenchmarkWrite8(b *testing.B) {
  function BenchmarkWrite32 (line 186) | func BenchmarkWrite32(b *testing.B) {
  function BenchmarkWriteByte2 (line 198) | func BenchmarkWriteByte2(b *testing.B) {
  function BenchmarkWriteByte8 (line 209) | func BenchmarkWriteByte8(b *testing.B) {

FILE: common/buf/copy.go
  type dataHandler (line 12) | type dataHandler
  type copyHandler (line 14) | type copyHandler struct
  type SizeCounter (line 19) | type SizeCounter struct
  type CopyOption (line 24) | type CopyOption
  function UpdateActivity (line 27) | func UpdateActivity(timer signal.ActivityUpdater) CopyOption {
  function CountSize (line 36) | func CountSize(sc *SizeCounter) CopyOption {
  function AddToStatCounter (line 45) | func AddToStatCounter(sc stats.Counter) CopyOption {
  type readError (line 55) | type readError struct
    method Error (line 59) | func (e readError) Error() string {
    method Unwrap (line 63) | func (e readError) Unwrap() error {
  function IsReadError (line 68) | func IsReadError(err error) bool {
  type writeError (line 73) | type writeError struct
    method Error (line 77) | func (e writeError) Error() string {
    method Unwrap (line 81) | func (e writeError) Unwrap() error {
  function IsWriteError (line 86) | func IsWriteError(err error) bool {
  function copyInternal (line 91) | func copyInternal(reader Reader, writer Writer, handler *copyHandler) er...
  function Copy (line 111) | func Copy(reader Reader, writer Writer, options ...CopyOption) error {
  function CopyOnceTimeout (line 125) | func CopyOnceTimeout(reader Reader, writer Writer, timeout time.Duration...

FILE: common/buf/copy_test.go
  function TestReadError (line 14) | func TestReadError(t *testing.T) {
  function TestWriteError (line 35) | func TestWriteError(t *testing.T) {
  type TestReader (line 56) | type TestReader struct
    method Read (line 58) | func (TestReader) Read(b []byte) (int, error) {
  function BenchmarkCopy (line 62) | func BenchmarkCopy(b *testing.B) {

FILE: common/buf/io.go
  type Reader (line 17) | type Reader interface
  type TimeoutReader (line 26) | type TimeoutReader interface
  type TimeoutWrapperReader (line 31) | type TimeoutWrapperReader struct
    method ReadMultiBuffer (line 39) | func (r *TimeoutWrapperReader) ReadMultiBuffer() (MultiBuffer, error) {
    method ReadMultiBufferTimeout (line 55) | func (r *TimeoutWrapperReader) ReadMultiBufferTimeout(duration time.Du...
  type Writer (line 81) | type Writer interface
  function WriteAllBytes (line 87) | func WriteAllBytes(writer io.Writer, payload []byte, c stats.Counter) er...
  function isPacketReader (line 106) | func isPacketReader(reader io.Reader) bool {
  function NewReader (line 113) | func NewReader(reader io.Reader) Reader {
  function NewPacketReader (line 148) | func NewPacketReader(reader io.Reader) Reader {
  function isPacketWriter (line 158) | func isPacketWriter(writer io.Writer) bool {
  function NewWriter (line 171) | func NewWriter(writer io.Writer) Writer {

FILE: common/buf/io_test.go
  function TestWriterCreation (line 13) | func TestWriterCreation(t *testing.T) {

FILE: common/buf/multi_buffer.go
  function ReadAllToBytes (line 12) | func ReadAllToBytes(reader io.Reader) ([]byte, error) {
  type MultiBuffer (line 27) | type MultiBuffer
    method Copy (line 66) | func (mb MultiBuffer) Copy(b []byte) int {
    method Len (line 239) | func (mb MultiBuffer) Len() int32 {
    method IsEmpty (line 252) | func (mb MultiBuffer) IsEmpty() bool {
    method String (line 262) | func (mb MultiBuffer) String() string {
  function MergeMulti (line 30) | func MergeMulti(dest MultiBuffer, src MultiBuffer) (MultiBuffer, MultiBu...
  function MergeBytes (line 39) | func MergeBytes(dest MultiBuffer, src []byte) MultiBuffer {
  function ReleaseMulti (line 57) | func ReleaseMulti(mb MultiBuffer) MultiBuffer {
  function ReadFrom (line 79) | func ReadFrom(reader io.Reader) (MultiBuffer, error) {
  function SplitBytes (line 100) | func SplitBytes(mb MultiBuffer, b []byte) (MultiBuffer, int) {
  function SplitFirstBytes (line 126) | func SplitFirstBytes(mb MultiBuffer, p []byte) (MultiBuffer, int) {
  function Compact (line 137) | func Compact(mb MultiBuffer) MultiBuffer {
  function SplitFirst (line 161) | func SplitFirst(mb MultiBuffer) (MultiBuffer, *Buffer) {
  function SplitSize (line 173) | func SplitSize(mb MultiBuffer, size int32) (MultiBuffer, MultiBuffer) {
  function SplitMulti (line 207) | func SplitMulti(mb MultiBuffer, i int) (MultiBuffer, MultiBuffer) {
  function WriteMultiBuffer (line 220) | func WriteMultiBuffer(writer io.Writer, mb MultiBuffer) (MultiBuffer, er...
  type MultiBufferContainer (line 271) | type MultiBufferContainer struct
    method Read (line 276) | func (c *MultiBufferContainer) Read(b []byte) (int, error) {
    method ReadMultiBuffer (line 287) | func (c *MultiBufferContainer) ReadMultiBuffer() (MultiBuffer, error) {
    method Write (line 294) | func (c *MultiBufferContainer) Write(b []byte) (int, error) {
    method WriteMultiBuffer (line 300) | func (c *MultiBufferContainer) WriteMultiBuffer(b MultiBuffer) error {
    method Close (line 307) | func (c *MultiBufferContainer) Close() error {

FILE: common/buf/multi_buffer_test.go
  function TestMultiBufferRead (line 15) | func TestMultiBufferRead(t *testing.T) {
  function TestMultiBufferAppend (line 33) | func TestMultiBufferAppend(t *testing.T) {
  function TestMultiBufferSliceBySizeLarge (line 43) | func TestMultiBufferSliceBySizeLarge(t *testing.T) {
  function TestMultiBufferSplitFirst (line 67) | func TestMultiBufferSplitFirst(t *testing.T) {
  function TestMultiBufferReadAllToByte (line 100) | func TestMultiBufferReadAllToByte(t *testing.T) {
  function TestMultiBufferCopy (line 130) | func TestMultiBufferCopy(t *testing.T) {
  function TestSplitFirstBytes (line 146) | func TestSplitFirstBytes(t *testing.T) {
  function TestCompact (line 164) | func TestCompact(t *testing.T) {
  function TestCompactWithConsumed (line 178) | func TestCompactWithConsumed(t *testing.T) {
  function BenchmarkSplitBytes (line 201) | func BenchmarkSplitBytes(b *testing.B) {

FILE: common/buf/override.go
  type EndpointOverrideReader (line 7) | type EndpointOverrideReader struct
    method ReadMultiBuffer (line 13) | func (r *EndpointOverrideReader) ReadMultiBuffer() (MultiBuffer, error) {
  type EndpointOverrideWriter (line 25) | type EndpointOverrideWriter struct
    method WriteMultiBuffer (line 31) | func (w *EndpointOverrideWriter) WriteMultiBuffer(mb MultiBuffer) error {

FILE: common/buf/reader.go
  function readOneUDP (line 10) | func readOneUDP(r io.Reader) (*Buffer, error) {
  function ReadBuffer (line 28) | func ReadBuffer(r io.Reader) (*Buffer, error) {
  type BufferedReader (line 39) | type BufferedReader struct
    method BufferedBytes (line 49) | func (r *BufferedReader) BufferedBytes() int32 {
    method ReadByte (line 54) | func (r *BufferedReader) ReadByte() (byte, error) {
    method Read (line 61) | func (r *BufferedReader) Read(b []byte) (int, error) {
    method ReadMultiBuffer (line 89) | func (r *BufferedReader) ReadMultiBuffer() (MultiBuffer, error) {
    method ReadAtMost (line 100) | func (r *BufferedReader) ReadAtMost(size int32) (MultiBuffer, error) {
    method writeToInternal (line 117) | func (r *BufferedReader) writeToInternal(writer io.Writer) (int64, err...
    method WriteTo (line 133) | func (r *BufferedReader) WriteTo(writer io.Writer) (int64, error) {
    method Interrupt (line 142) | func (r *BufferedReader) Interrupt() {
    method Close (line 147) | func (r *BufferedReader) Close() error {
  type SingleReader (line 152) | type SingleReader struct
    method ReadMultiBuffer (line 157) | func (r *SingleReader) ReadMultiBuffer() (MultiBuffer, error) {
  type PacketReader (line 163) | type PacketReader struct
    method ReadMultiBuffer (line 168) | func (r *PacketReader) ReadMultiBuffer() (MultiBuffer, error) {

FILE: common/buf/reader_test.go
Condensed preview — 945 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,201K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "chars": 3392,
    "preview": "name: Bug report\ndescription: \"Submit Xray-core bug\"\nbody:\n  - type: checkboxes\n    attributes:\n      label: Integrity r"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report_zh.yml",
    "chars": 1963,
    "preview": "name: bug反馈\ndescription: \"提交 Xray-core bug\"\nbody:\n  - type: checkboxes\n    attributes:\n      label: 完整性要求\n      descript"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 205,
    "preview": "contact_links:\n  - name: Community Support and Questions\n    url: https://github.com/XTLS/Xray-core/discussions\n    abou"
  },
  {
    "path": ".github/build/friendly-filenames.json",
    "chars": 1733,
    "preview": "{\n  \"android-arm64\": { \"friendlyName\": \"android-arm64-v8a\" },\n  \"darwin-amd64\": { \"friendlyName\": \"macos-64\" },\n  \"darwi"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 560,
    "preview": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where "
  },
  {
    "path": ".github/docker/Dockerfile",
    "chars": 2246,
    "preview": "# syntax=docker/dockerfile:latest\nFROM --platform=$BUILDPLATFORM golang:latest AS build\n\n# Build xray-core\nWORKDIR /src\n"
  },
  {
    "path": ".github/docker/Dockerfile.usa",
    "chars": 3004,
    "preview": "# syntax=docker/dockerfile:latest\nFROM --platform=$BUILDPLATFORM golang:latest AS build\n\n# Build xray-core\nWORKDIR /src\n"
  },
  {
    "path": ".github/workflows/docker.yml",
    "chars": 4464,
    "preview": "name: Build and Push Docker Image\n\non:\n  release:\n    types:\n      - published\n      - released\n\n  workflow_dispatch:\n  "
  },
  {
    "path": ".github/workflows/release-win7.yml",
    "chars": 5967,
    "preview": "name: Build and Release for Windows 7\n\non:\n  workflow_dispatch:\n  release:\n    types: [published]\n  push:\n  pull_request"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 9881,
    "preview": "name: Build and Release\n\non:\n  workflow_dispatch:\n  release:\n    types: [published]\n  push:\n  pull_request:\n    types: ["
  },
  {
    "path": ".github/workflows/scheduled-assets-update.yml",
    "chars": 5231,
    "preview": "name: Scheduled assets update\n\n# NOTE: This Github Actions is required by other actions, for preparing other packaging a"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 2139,
    "preview": "name: Test\n\non:\n  push:\n  pull_request:\n    types: [opened, synchronize, reopened]\n\njobs:\n  check-assets:\n    runs-on: u"
  },
  {
    "path": ".gitignore",
    "chars": 804,
    "preview": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, built with `go test -c`\n*.test\n\n# Ou"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5226,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "LICENSE",
    "chars": 16725,
    "preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
  },
  {
    "path": "README.md",
    "chars": 10499,
    "preview": "# Project X\n\n[Project X](https://github.com/XTLS) originates from XTLS protocol, providing a set of network tools such a"
  },
  {
    "path": "SECURITY.md",
    "chars": 355,
    "preview": "# Security Policy\n\nIf you found an issue related to security vulnerability or protocol-identification problem, please re"
  },
  {
    "path": "app/app.go",
    "chars": 113,
    "preview": "// Package app contains feature implementations of Xray. The features may be enabled during runtime.\npackage app\n"
  },
  {
    "path": "app/commander/commander.go",
    "chars": 2745,
    "preview": "package commander\n\nimport (\n\t\"context\"\n\t\"net\"\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/c"
  },
  {
    "path": "app/commander/config.pb.go",
    "chars": 6058,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/commander/config.proto",
    "chars": 752,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.commander;\noption csharp_namespace = \"Xray.App.Commander\";\noption go_package = \"git"
  },
  {
    "path": "app/commander/outbound.go",
    "chars": 2506,
    "preview": "package commander\n\nimport (\n\t\"context\"\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/e"
  },
  {
    "path": "app/commander/service.go",
    "chars": 585,
    "preview": "package commander\n\nimport (\n\t\"context\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"google.golang.org/grpc\"\n\t\"google.golang.or"
  },
  {
    "path": "app/dispatcher/config.pb.go",
    "chars": 5187,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/dispatcher/config.proto",
    "chars": 337,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.dispatcher;\noption csharp_namespace = \"Xray.App.Dispatcher\";\noption go_package = \"g"
  },
  {
    "path": "app/dispatcher/default.go",
    "chars": 15215,
    "preview": "package dispatcher\n\nimport (\n\t\"context\"\n\t\"regexp\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"gith"
  },
  {
    "path": "app/dispatcher/dispatcher.go",
    "chars": 19,
    "preview": "package dispatcher\n"
  },
  {
    "path": "app/dispatcher/fakednssniffer.go",
    "chars": 3843,
    "preview": "package dispatcher\n\nimport (\n\t\"context\"\n\t\"strings\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/comm"
  },
  {
    "path": "app/dispatcher/sniffer.go",
    "chars": 4146,
    "preview": "package dispatcher\n\nimport (\n\t\"context\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/errors\"\n"
  },
  {
    "path": "app/dispatcher/stats.go",
    "chars": 514,
    "preview": "package dispatcher\n\nimport (\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/buf\"\n\t\"github.com/xt"
  },
  {
    "path": "app/dispatcher/stats_test.go",
    "chars": 818,
    "preview": "package dispatcher_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/xtls/xray-core/app/dispatcher\"\n\t\"github.com/xtls/xray-core/"
  },
  {
    "path": "app/dns/cache_controller.go",
    "chars": 7682,
    "preview": "package dns\n\nimport (\n\t\"context\"\n\tgo_errors \"errors\"\n\t\"runtime\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"g"
  },
  {
    "path": "app/dns/config.go",
    "chars": 2161,
    "preview": "package dns\n\nimport (\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"github.com/xtls/xray-core/common/net\"\n\t\"github.com/xt"
  },
  {
    "path": "app/dns/config.pb.go",
    "chars": 23963,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/dns/config.proto",
    "chars": 2182,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.dns;\noption csharp_namespace = \"Xray.App.Dns\";\noption go_package = \"github.com/xtls"
  },
  {
    "path": "app/dns/dns.go",
    "chars": 16330,
    "preview": "// Package dns is an implementation of core.DNS feature.\npackage dns\n\nimport (\n\t\"context\"\n\tgo_errors \"errors\"\n\t\"fmt\"\n\t\"o"
  },
  {
    "path": "app/dns/dns_test.go",
    "chars": 25090,
    "preview": "package dns_test\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/miekg/dns\"\n\t\"github.com/xtls"
  },
  {
    "path": "app/dns/dnscommon.go",
    "chars": 6309,
    "preview": "package dns\n\nimport (\n\t\"context\"\n\t\"encoding/binary\"\n\t\"math\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"gi"
  },
  {
    "path": "app/dns/dnscommon_test.go",
    "chars": 4399,
    "preview": "package dns\n\nimport (\n\t\"math/rand\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/miekg/dns\"\n\t\"github."
  },
  {
    "path": "app/dns/fakedns/fake.go",
    "chars": 6356,
    "preview": "package fakedns\n\nimport (\n\t\"context\"\n\t\"math\"\n\t\"math/big\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.c"
  },
  {
    "path": "app/dns/fakedns/fakedns.go",
    "chars": 16,
    "preview": "package fakedns\n"
  },
  {
    "path": "app/dns/fakedns/fakedns.pb.go",
    "chars": 5967,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/dns/fakedns/fakedns.proto",
    "chars": 497,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.dns.fakedns;\noption csharp_namespace = \"Xray.App.Dns.Fakedns\";\noption go_package = "
  },
  {
    "path": "app/dns/fakedns/fakedns_test.go",
    "chars": 5872,
    "preview": "package fakedns\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/xtls/xray-core/commo"
  },
  {
    "path": "app/dns/hosts.go",
    "chars": 4676,
    "preview": "package dns\n\nimport (\n\t\"context\"\n\t\"runtime\"\n\t\"strconv\"\n\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"github.com/xtls/xra"
  },
  {
    "path": "app/dns/hosts_test.go",
    "chars": 4187,
    "preview": "package dns_test\n\nimport (\n\t\"bytes\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t. \"github.com/xtls/xray-core/app/dns\"\n\t"
  },
  {
    "path": "app/dns/nameserver.go",
    "chars": 11741,
    "preview": "package dns\n\nimport (\n\t\"context\"\n\t\"net/url\"\n\t\"runtime\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/app/router\"\n\t\"git"
  },
  {
    "path": "app/dns/nameserver_cached.go",
    "chars": 4659,
    "preview": "package dns\n\nimport (\n\t\"context\"\n\tgo_errors \"errors\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"github.com/xt"
  },
  {
    "path": "app/dns/nameserver_doh.go",
    "chars": 7238,
    "preview": "package dns\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"time\"\n\n\tutls \"github.com/r"
  },
  {
    "path": "app/dns/nameserver_doh_test.go",
    "chars": 2681,
    "preview": "package dns_test\n\nimport (\n\t\"context\"\n\t\"net/url\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t. \"github.com/xtls"
  },
  {
    "path": "app/dns/nameserver_fakedns.go",
    "chars": 1243,
    "preview": "package dns\n\nimport (\n\t\"context\"\n\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"github.com/xtls/xray-core/common/net\"\n\t\"g"
  },
  {
    "path": "app/dns/nameserver_local.go",
    "chars": 1520,
    "preview": "package dns\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"github.com/xtls/xray-core/common/"
  },
  {
    "path": "app/dns/nameserver_local_test.go",
    "chars": 536,
    "preview": "package dns_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n\n\t. \"github.com/xtls/xray-core/app/dns\"\n\t\"github.com/xtls/xray-"
  },
  {
    "path": "app/dns/nameserver_quic.go",
    "chars": 7220,
    "preview": "package dns\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/binary\"\n\t\"net/url\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/apernet/quic-go\"\n\t"
  },
  {
    "path": "app/dns/nameserver_quic_test.go",
    "chars": 2184,
    "preview": "package dns_test\n\nimport (\n\t\"context\"\n\t\"net/url\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t. \"github.com/xtls"
  },
  {
    "path": "app/dns/nameserver_tcp.go",
    "chars": 6498,
    "preview": "package dns\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/binary\"\n\t\"net/url\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-c"
  },
  {
    "path": "app/dns/nameserver_tcp_test.go",
    "chars": 2715,
    "preview": "package dns_test\n\nimport (\n\t\"context\"\n\t\"net/url\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t. \"github.com/xtls"
  },
  {
    "path": "app/dns/nameserver_udp.go",
    "chars": 5419,
    "preview": "package dns\n\nimport (\n\t\"context\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github"
  },
  {
    "path": "app/log/command/command.go",
    "chars": 1437,
    "preview": "package command\n\nimport (\n\t\"context\"\n\n\t\"github.com/xtls/xray-core/app/log\"\n\t\"github.com/xtls/xray-core/common\"\n\t\"github."
  },
  {
    "path": "app/log/command/command_test.go",
    "chars": 919,
    "preview": "package command_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/xtls/xray-core/app/dispatcher\"\n\t\"github.com/xtls/xray"
  },
  {
    "path": "app/log/command/config.pb.go",
    "chars": 6438,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/log/command/config.proto",
    "chars": 440,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.log.command;\noption csharp_namespace = \"Xray.App.Log.Command\";\noption go_package = "
  },
  {
    "path": "app/log/command/config_grpc.pb.go",
    "chars": 4680,
    "preview": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n// versions:\n// - protoc-gen-go-grpc v1.6.0\n// - protoc           "
  },
  {
    "path": "app/log/config.pb.go",
    "chars": 7534,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/log/config.proto",
    "chars": 562,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.log;\noption csharp_namespace = \"Xray.App.Log\";\noption go_package = \"github.com/xtls"
  },
  {
    "path": "app/log/log.go",
    "chars": 5065,
    "preview": "package log\n\nimport (\n\t\"context\"\n\t\"net\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"g"
  },
  {
    "path": "app/log/log_creator.go",
    "chars": 1574,
    "preview": "package log\n\nimport (\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"github.c"
  },
  {
    "path": "app/log/log_test.go",
    "chars": 2305,
    "preview": "package log_test\n\nimport (\n\t\"context\"\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/golang/mock/gomock\"\n\t\"github.com/xtls/xray-core/ap"
  },
  {
    "path": "app/metrics/config.pb.go",
    "chars": 4154,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/metrics/config.proto",
    "chars": 404,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.metrics;\noption csharp_namespace = \"Xray.App.Metrics\";\noption go_package = \"github."
  },
  {
    "path": "app/metrics/metrics.go",
    "chars": 3722,
    "preview": "package metrics\n\nimport (\n\t\"context\"\n\t\"expvar\"\n\t\"net/http\"\n\t_ \"net/http/pprof\"\n\t\"strings\"\n\n\t\"github.com/xtls/xray-core/a"
  },
  {
    "path": "app/metrics/outbound.go",
    "chars": 2520,
    "preview": "package metrics\n\nimport (\n\t\"context\"\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/err"
  },
  {
    "path": "app/observatory/burst/burst.go",
    "chars": 131,
    "preview": "package burst\n\nimport (\n\t\"math\"\n\t\"time\"\n)\n\nconst (\n\trttFailed = time.Duration(math.MaxInt64 - iota)\n\trttUntested\n\trttUnq"
  },
  {
    "path": "app/observatory/burst/burstobserver.go",
    "chars": 2960,
    "preview": "package burst\n\nimport (\n\t\"context\"\n\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/app/observatory\"\n\t\"github.com/xtls/xray-core/co"
  },
  {
    "path": "app/observatory/burst/config.pb.go",
    "chars": 7866,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/observatory/burst/config.proto",
    "chars": 990,
    "preview": "syntax = \"proto3\";\n\npackage xray.core.app.observatory.burst;\noption csharp_namespace = \"Xray.App.Observatory.Burst\";\nopt"
  },
  {
    "path": "app/observatory/burst/healthping.go",
    "chars": 6832,
    "preview": "package burst\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common/dice\"\n\t\"github."
  },
  {
    "path": "app/observatory/burst/healthping_result.go",
    "chars": 3301,
    "preview": "package burst\n\nimport (\n\t\"math\"\n\t\"time\"\n)\n\n// HealthPingStats is the statistics of HealthPingRTTS\ntype HealthPingStats s"
  },
  {
    "path": "app/observatory/burst/healthping_result_test.go",
    "chars": 2485,
    "preview": "package burst_test\n\nimport (\n\t\"math\"\n\treflect \"reflect\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/app/observatory/"
  },
  {
    "path": "app/observatory/burst/ping.go",
    "chars": 2041,
    "preview": "package burst\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common/net\"\n\t\"github.com/xtls/"
  },
  {
    "path": "app/observatory/command/command.go",
    "chars": 1148,
    "preview": "package command\n\nimport (\n\t\"context\"\n\n\t\"github.com/xtls/xray-core/app/observatory\"\n\t\"github.com/xtls/xray-core/common\"\n\t"
  },
  {
    "path": "app/observatory/command/command.pb.go",
    "chars": 7741,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/observatory/command/command.proto",
    "chars": 618,
    "preview": "syntax = \"proto3\";\n\npackage xray.core.app.observatory.command;\noption csharp_namespace = \"Xray.Core.App.Observatory.Comm"
  },
  {
    "path": "app/observatory/command/command_grpc.pb.go",
    "chars": 5029,
    "preview": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n// versions:\n// - protoc-gen-go-grpc v1.6.0\n// - protoc           "
  },
  {
    "path": "app/observatory/config.pb.go",
    "chars": 16659,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/observatory/config.proto",
    "chars": 2011,
    "preview": "syntax = \"proto3\";\n\npackage xray.core.app.observatory;\noption csharp_namespace = \"Xray.App.Observatory\";\noption go_packa"
  },
  {
    "path": "app/observatory/explainErrors.go",
    "chars": 571,
    "preview": "package observatory\n\nimport \"github.com/xtls/xray-core/common/errors\"\n\ntype errorCollector struct {\n\terrors *errors.Erro"
  },
  {
    "path": "app/observatory/observatory.go",
    "chars": 20,
    "preview": "package observatory\n"
  },
  {
    "path": "app/observatory/observer.go",
    "chars": 6315,
    "preview": "package observatory\n\nimport (\n\t\"context\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"sort\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-c"
  },
  {
    "path": "app/policy/config.go",
    "chars": 2563,
    "preview": "package policy\n\nimport (\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/features/policy\"\n)\n\n// Duration converts Second to time.Du"
  },
  {
    "path": "app/policy/config.pb.go",
    "chars": 18057,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/policy/config.proto",
    "chars": 1065,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.policy;\noption csharp_namespace = \"Xray.App.Policy\";\noption go_package = \"github.co"
  },
  {
    "path": "app/policy/manager.go",
    "chars": 1433,
    "preview": "package policy\n\nimport (\n\t\"context\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/features/policy\"\n)\n"
  },
  {
    "path": "app/policy/manager_test.go",
    "chars": 995,
    "preview": "package policy_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n\n\t. \"github.com/xtls/xray-core/app/policy\"\n\t\"github.com/xtls"
  },
  {
    "path": "app/policy/policy.go",
    "chars": 81,
    "preview": "// Package policy is an implementation of policy.Manager feature.\npackage policy\n"
  },
  {
    "path": "app/proxyman/command/command.go",
    "chars": 7297,
    "preview": "package command\n\nimport (\n\t\"context\"\n\n\t\"github.com/xtls/xray-core/app/commander\"\n\t\"github.com/xtls/xray-core/common\"\n\t\"g"
  },
  {
    "path": "app/proxyman/command/command.pb.go",
    "chars": 38868,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/proxyman/command/command.proto",
    "chars": 2460,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.proxyman.command;\noption csharp_namespace = \"Xray.App.Proxyman.Command\";\noption go_"
  },
  {
    "path": "app/proxyman/command/command_grpc.pb.go",
    "chars": 20102,
    "preview": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n// versions:\n// - protoc-gen-go-grpc v1.6.0\n// - protoc           "
  },
  {
    "path": "app/proxyman/command/doc.go",
    "chars": 16,
    "preview": "package command\n"
  },
  {
    "path": "app/proxyman/config.go",
    "chars": 17,
    "preview": "package proxyman\n"
  },
  {
    "path": "app/proxyman/config.pb.go",
    "chars": 20477,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/proxyman/config.proto",
    "chars": 2275,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.proxyman;\noption csharp_namespace = \"Xray.App.Proxyman\";\noption go_package = \"githu"
  },
  {
    "path": "app/proxyman/inbound/always.go",
    "chars": 6442,
    "preview": "package inbound\n\nimport (\n\t\"context\"\n\n\t\"github.com/xtls/xray-core/app/proxyman\"\n\t\"github.com/xtls/xray-core/common\"\n\t\"gi"
  },
  {
    "path": "app/proxyman/inbound/inbound.go",
    "chars": 4801,
    "preview": "package inbound\n\nimport (\n\t\"context\"\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/app/proxyman\"\n\t\"github.com/xtls/xray-core/comm"
  },
  {
    "path": "app/proxyman/inbound/worker.go",
    "chars": 14460,
    "preview": "package inbound\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/app/proxyman\"\n\t\"github."
  },
  {
    "path": "app/proxyman/outbound/handler.go",
    "chars": 12852,
    "preview": "package outbound\n\nimport (\n\t\"context\"\n\t\"crypto/rand\"\n\tgoerrors \"errors\"\n\t\"io\"\n\t\"math/big\"\n\t\"os\"\n\n\t\"github.com/xtls/xray-"
  },
  {
    "path": "app/proxyman/outbound/handler_test.go",
    "chars": 4438,
    "preview": "package outbound_test\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core"
  },
  {
    "path": "app/proxyman/outbound/outbound.go",
    "chars": 4272,
    "preview": "package outbound\n\nimport (\n\t\"context\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/app/proxyman\"\n\t\"github.com"
  },
  {
    "path": "app/proxyman/outbound/uot.go",
    "chars": 1067,
    "preview": "package outbound\n\nimport (\n\t\"context\"\n\t\"os\"\n\n\t\"github.com/sagernet/sing/common/uot\"\n\t\"github.com/xtls/xray-core/common/e"
  },
  {
    "path": "app/reverse/bridge.go",
    "chars": 5156,
    "preview": "package reverse\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"github.com/xtls/xray-core/com"
  },
  {
    "path": "app/reverse/config.go",
    "chars": 251,
    "preview": "package reverse\n\nimport (\n\t\"crypto/rand\"\n\t\"io\"\n\n\t\"github.com/xtls/xray-core/common/dice\"\n)\n\nfunc (c *Control) FillInRand"
  },
  {
    "path": "app/reverse/config.pb.go",
    "chars": 10488,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/reverse/config.proto",
    "chars": 586,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.reverse;\noption csharp_namespace = \"Xray.Proxy.Reverse\";\noption go_package = \"githu"
  },
  {
    "path": "app/reverse/portal.go",
    "chars": 6815,
    "preview": "package reverse\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/co"
  },
  {
    "path": "app/reverse/portal_test.go",
    "chars": 396,
    "preview": "package reverse_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/xtls/xray-core/app/reverse\"\n\t\"github.com/xtls/xray-core/common\"\n"
  },
  {
    "path": "app/reverse/reverse.go",
    "chars": 1915,
    "preview": "package reverse\n\nimport (\n\t\"context\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"g"
  },
  {
    "path": "app/router/balancing.go",
    "chars": 4333,
    "preview": "package router\n\nimport (\n\t\"context\"\n\tsync \"sync\"\n\n\t\"github.com/xtls/xray-core/app/observatory\"\n\t\"github.com/xtls/xray-co"
  },
  {
    "path": "app/router/balancing_override.go",
    "chars": 928,
    "preview": "package router\n\nimport (\n\tsync \"sync\"\n\n\t\"github.com/xtls/xray-core/common/errors\"\n)\n\nfunc (r *Router) OverrideBalancer(b"
  },
  {
    "path": "app/router/command/command.go",
    "chars": 4975,
    "preview": "package command\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/err"
  },
  {
    "path": "app/router/command/command.pb.go",
    "chars": 38734,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/router/command/command.proto",
    "chars": 3857,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.router.command;\noption csharp_namespace = \"Xray.App.Router.Command\";\noption go_pack"
  },
  {
    "path": "app/router/command/command_grpc.pb.go",
    "chars": 15350,
    "preview": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n// versions:\n// - protoc-gen-go-grpc v1.6.0\n// - protoc           "
  },
  {
    "path": "app/router/command/command_test.go",
    "chars": 12438,
    "preview": "package command_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/golang/mock/gomock\"\n\t\"github.com/google/go-cm"
  },
  {
    "path": "app/router/command/config.go",
    "chars": 4271,
    "preview": "package command\n\nimport (\n\t\"strings\"\n\n\t\"github.com/xtls/xray-core/common/net\"\n\t\"github.com/xtls/xray-core/features/routi"
  },
  {
    "path": "app/router/condition.go",
    "chars": 9390,
    "preview": "package router\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"github.com/xtls/xray-"
  },
  {
    "path": "app/router/condition_geoip.go",
    "chars": 19167,
    "preview": "package router\n\nimport (\n\t\"context\"\n\t\"net/netip\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/common/errors\"\n"
  },
  {
    "path": "app/router/condition_geoip_test.go",
    "chars": 5663,
    "preview": "package router_test\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/xtls/xray-core/app/router\"\n\t\"github"
  },
  {
    "path": "app/router/condition_serialize_test.go",
    "chars": 3915,
    "preview": "package router_test\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n\t\"githu"
  },
  {
    "path": "app/router/condition_test.go",
    "chars": 10029,
    "preview": "package router_test\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n\n\t. \"github.com/xtls/xray-core/app/router\"\n\t\"github.com/xtls/xray-co"
  },
  {
    "path": "app/router/config.go",
    "chars": 5451,
    "preview": "package router\n\nimport (\n\t\"context\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strings\"\n\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"github"
  },
  {
    "path": "app/router/config.pb.go",
    "chars": 39857,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/router/config.proto",
    "chars": 4014,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.router;\noption csharp_namespace = \"Xray.App.Router\";\noption go_package = \"github.co"
  },
  {
    "path": "app/router/geosite_compact.go",
    "chars": 2174,
    "preview": "package router\n\nimport (\n\t\"encoding/gob\"\n\t\"errors\"\n\t\"io\"\n\t\"runtime\"\n\n\t\"github.com/xtls/xray-core/common/strmatcher\"\n)\n\nt"
  },
  {
    "path": "app/router/router.go",
    "chars": 7601,
    "preview": "package router\n\nimport (\n\t\"context\"\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/erro"
  },
  {
    "path": "app/router/router_test.go",
    "chars": 6951,
    "preview": "package router_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/golang/mock/gomock\"\n\t. \"github.com/xtls/xray-core/app/"
  },
  {
    "path": "app/router/strategy_leastload.go",
    "chars": 5810,
    "preview": "package router\n\nimport (\n\t\"context\"\n\t\"math\"\n\t\"sort\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/app/observatory\"\n\t\"github.com/x"
  },
  {
    "path": "app/router/strategy_leastload_test.go",
    "chars": 5209,
    "preview": "package router\n\nimport (\n\t\"testing\"\n)\n\n/*\nSplit into multiple package, need to be tested separately\n\n\tfunc TestSelectLea"
  },
  {
    "path": "app/router/strategy_leastping.go",
    "chars": 1617,
    "preview": "package router\n\nimport (\n\t\"context\"\n\n\t\"github.com/xtls/xray-core/app/observatory\"\n\t\"github.com/xtls/xray-core/common\"\n\t\""
  },
  {
    "path": "app/router/strategy_random.go",
    "chars": 1718,
    "preview": "package router\n\nimport (\n\t\"context\"\n\n\t\"github.com/xtls/xray-core/app/observatory\"\n\t\"github.com/xtls/xray-core/common\"\n\t\""
  },
  {
    "path": "app/router/webhook.go",
    "chars": 7120,
    "preview": "package router\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"str"
  },
  {
    "path": "app/router/weight.go",
    "chars": 2088,
    "preview": "package router\n\nimport (\n\t\"context\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/common/errors\"\n"
  },
  {
    "path": "app/router/weight_test.go",
    "chars": 1207,
    "preview": "package router_test\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/xtls/xray-core/app/router\"\n)\n\nfunc TestWeight(t *testi"
  },
  {
    "path": "app/stats/channel.go",
    "chars": 4264,
    "preview": "package stats\n\nimport (\n\t\"context\"\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/error"
  },
  {
    "path": "app/stats/channel_test.go",
    "chars": 9714,
    "preview": "package stats_test\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n\n\t. \"github.com/xtls/xray-core/app/stats\"\n\t\"github.com"
  },
  {
    "path": "app/stats/command/command.go",
    "chars": 4172,
    "preview": "package command\n\nimport (\n\t\"context\"\n\t\"runtime\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/app/stats\"\n\t\"github.com/xtls/xray-c"
  },
  {
    "path": "app/stats/command/command.pb.go",
    "chars": 23717,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/stats/command/command.proto",
    "chars": 1615,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.stats.command;\noption csharp_namespace = \"Xray.App.Stats.Command\";\noption go_packag"
  },
  {
    "path": "app/stats/command/command_grpc.pb.go",
    "chars": 12933,
    "preview": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n// versions:\n// - protoc-gen-go-grpc v1.6.0\n// - protoc           "
  },
  {
    "path": "app/stats/command/command_test.go",
    "chars": 1875,
    "preview": "package command_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/google/go-cmp/cmp/cmp"
  },
  {
    "path": "app/stats/config.pb.go",
    "chars": 5449,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/stats/config.proto",
    "chars": 346,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.stats;\noption csharp_namespace = \"Xray.App.Stats\";\noption go_package = \"github.com/"
  },
  {
    "path": "app/stats/counter.go",
    "chars": 478,
    "preview": "package stats\n\nimport \"sync/atomic\"\n\n// Counter is an implementation of stats.Counter.\ntype Counter struct {\n\tvalue int6"
  },
  {
    "path": "app/stats/counter_test.go",
    "chars": 665,
    "preview": "package stats_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t. \"github.com/xtls/xray-core/app/stats\"\n\t\"github.com/xtls/xray-core"
  },
  {
    "path": "app/stats/online_map.go",
    "chars": 1895,
    "preview": "package stats\n\nimport (\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n)\n\nconst (\n\tlocalhostIPv4 = \"127.0.0.1\"\n\tlocalhostIPv6 = \"[::1]\"\n"
  },
  {
    "path": "app/stats/stats.go",
    "chars": 5208,
    "preview": "package stats\n\nimport (\n\t\"context\"\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/error"
  },
  {
    "path": "app/stats/stats_test.go",
    "chars": 2004,
    "preview": "package stats_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n\n\t. \"github.com/xtls/xray-core/app/stats\"\n\t\"github.com/xtls/x"
  },
  {
    "path": "app/version/config.pb.go",
    "chars": 4482,
    "preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.36.11\n// \tprotoc        v6.33.5\n// so"
  },
  {
    "path": "app/version/config.proto",
    "chars": 334,
    "preview": "syntax = \"proto3\";\n\npackage xray.app.version;\noption csharp_namespace = \"Xray.App.Version\";\noption go_package = \"github."
  },
  {
    "path": "app/version/version.go",
    "chars": 1871,
    "preview": "package version\n\nimport (\n\t\"context\"\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"st"
  },
  {
    "path": "common/antireplay/antireplay_test.go",
    "chars": 610,
    "preview": "package antireplay\n\nimport (\n\t\"bufio\"\n\t\"crypto/rand\"\n\t\"testing\"\n)\n\nfunc BenchmarkMapFilter(b *testing.B) {\n\tfilter := Ne"
  },
  {
    "path": "common/antireplay/mapfilter.go",
    "chars": 1092,
    "preview": "package antireplay\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\n// ReplayFilter checks for replay attacks.\ntype ReplayFilter[T comparabl"
  },
  {
    "path": "common/bitmask/byte.go",
    "chars": 318,
    "preview": "package bitmask\n\n// Byte is a bitmask in byte.\ntype Byte byte\n\n// Has returns true if this bitmask contains another bitm"
  },
  {
    "path": "common/bitmask/byte_test.go",
    "chars": 703,
    "preview": "package bitmask_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/xtls/xray-core/common/bitmask\"\n)\n\nfunc TestBitmaskByte(t *test"
  },
  {
    "path": "common/buf/buf.go",
    "chars": 129,
    "preview": "// Package buf provides a light-weight memory allocation mechanism.\npackage buf // import \"github.com/xtls/xray-core/com"
  },
  {
    "path": "common/buf/buffer.go",
    "chars": 6991,
    "preview": "package buf\n\nimport (\n\t\"io\"\n\n\t\"github.com/xtls/xray-core/common/bytespool\"\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\""
  },
  {
    "path": "common/buf/buffer_test.go",
    "chars": 4488,
    "preview": "package buf_test\n\nimport (\n\t\"bytes\"\n\t\"crypto/rand\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/xtls/xray-co"
  },
  {
    "path": "common/buf/copy.go",
    "chars": 2975,
    "preview": "package buf\n\nimport (\n\t\"io\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"github.com/xtls/xray-core/common/signa"
  },
  {
    "path": "common/buf/copy_test.go",
    "chars": 1553,
    "preview": "package buf_test\n\nimport (\n\t\"crypto/rand\"\n\t\"io\"\n\t\"testing\"\n\n\t\"github.com/golang/mock/gomock\"\n\t\"github.com/xtls/xray-core"
  },
  {
    "path": "common/buf/io.go",
    "chars": 4104,
    "preview": "package buf\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"net\"\n\t\"os\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"git"
  },
  {
    "path": "common/buf/io_test.go",
    "chars": 1008,
    "preview": "package buf_test\n\nimport (\n\t\"crypto/tls\"\n\t\"io\"\n\t\"testing\"\n\n\t. \"github.com/xtls/xray-core/common/buf\"\n\t\"github.com/xtls/x"
  },
  {
    "path": "common/buf/multi_buffer.go",
    "chars": 6789,
    "preview": "package buf\n\nimport (\n\t\"io\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"github.com"
  },
  {
    "path": "common/buf/multi_buffer_test.go",
    "chars": 4229,
    "preview": "package buf_test\n\nimport (\n\t\"bytes\"\n\t\"crypto/rand\"\n\t\"io\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/"
  },
  {
    "path": "common/buf/override.go",
    "chars": 760,
    "preview": "package buf\n\nimport (\n\t\"github.com/xtls/xray-core/common/net\"\n)\n\ntype EndpointOverrideReader struct {\n\tReader\n\tDest     "
  },
  {
    "path": "common/buf/reader.go",
    "chars": 3824,
    "preview": "package buf\n\nimport (\n\t\"io\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/errors\"\n)\n\nfunc read"
  },
  {
    "path": "common/buf/reader_test.go",
    "chars": 2952,
    "preview": "package buf_test\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t. \"github.com/xtls"
  },
  {
    "path": "common/buf/readv_posix.go",
    "chars": 844,
    "preview": "//go:build !windows && !wasm && !illumos\n// +build !windows,!wasm,!illumos\n\npackage buf\n\nimport (\n\t\"syscall\"\n\t\"unsafe\"\n)"
  },
  {
    "path": "common/buf/readv_reader.go",
    "chars": 2638,
    "preview": "//go:build !wasm\n// +build !wasm\n\npackage buf\n\nimport (\n\t\"io\"\n\t\"syscall\"\n\n\t\"github.com/xtls/xray-core/common/platform\"\n\t"
  },
  {
    "path": "common/buf/readv_reader_wasm.go",
    "chars": 198,
    "preview": "//go:build wasm\n// +build wasm\n\npackage buf\n\nimport (\n\t\"io\"\n\t\"syscall\"\n)\n\nconst useReadv = false\n\nfunc NewReadVReader(re"
  },
  {
    "path": "common/buf/readv_test.go",
    "chars": 1310,
    "preview": "//go:build !wasm\n// +build !wasm\n\npackage buf_test\n\nimport (\n\t\"crypto/rand\"\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/google/go-cm"
  },
  {
    "path": "common/buf/readv_unix.go",
    "chars": 561,
    "preview": "//go:build illumos\n// +build illumos\n\npackage buf\n\nimport \"golang.org/x/sys/unix\"\n\ntype unixReader struct {\n\tiovs [][]by"
  },
  {
    "path": "common/buf/readv_windows.go",
    "chars": 733,
    "preview": "package buf\n\nimport (\n\t\"syscall\"\n)\n\ntype windowsReader struct {\n\tbufs []syscall.WSABuf\n}\n\nfunc (r *windowsReader) Init(b"
  },
  {
    "path": "common/buf/writer.go",
    "chars": 5489,
    "preview": "package buf\n\nimport (\n\t\"io\"\n\t\"net\"\n\t\"sync\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/error"
  },
  {
    "path": "common/buf/writer_test.go",
    "chars": 2349,
    "preview": "package buf_test\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"crypto/rand\"\n\t\"io\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.c"
  },
  {
    "path": "common/bytespool/pool.go",
    "chars": 1500,
    "preview": "package bytespool\n\nimport \"sync\"\n\nfunc createAllocFunc(size int32) func() interface{} {\n\treturn func() interface{} {\n\t\tr"
  },
  {
    "path": "common/cache/lru.go",
    "chars": 2301,
    "preview": "package cache\n\nimport (\n\t\"container/list\"\n\t\"sync\"\n)\n\n// Lru simple, fast lru cache implementation\ntype Lru interface {\n\t"
  },
  {
    "path": "common/cache/lru_test.go",
    "chars": 1394,
    "preview": "package cache_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/xtls/xray-core/common/cache\"\n)\n\nfunc TestLruReplaceValue(t *test"
  },
  {
    "path": "common/cmdarg/cmdarg.go",
    "chars": 298,
    "preview": "package cmdarg\n\nimport \"strings\"\n\n// Arg is used by flag to accept multiple argument.\ntype Arg []string\n\nfunc (c *Arg) S"
  },
  {
    "path": "common/common.go",
    "chars": 4714,
    "preview": "// Package common contains common utilities that are shared among other packages.\n// See each sub-package for detail.\npa"
  },
  {
    "path": "common/common_test.go",
    "chars": 798,
    "preview": "package common_test\n\nimport (\n\t\"errors\"\n\t\"testing\"\n\n\t. \"github.com/xtls/xray-core/common\"\n)\n\nfunc TestMust(t *testing.T)"
  },
  {
    "path": "common/crypto/aes.go",
    "chars": 1249,
    "preview": "package crypto\n\nimport (\n\t\"crypto/aes\"\n\t\"crypto/cipher\"\n\n\t\"github.com/xtls/xray-core/common\"\n)\n\n// NewAesDecryptionStrea"
  },
  {
    "path": "common/crypto/auth.go",
    "chars": 7951,
    "preview": "package crypto\n\nimport (\n\t\"crypto/cipher\"\n\t\"crypto/rand\"\n\t\"io\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xr"
  },
  {
    "path": "common/crypto/auth_test.go",
    "chars": 3190,
    "preview": "package crypto_test\n\nimport (\n\t\"bytes\"\n\t\"crypto/rand\"\n\t\"io\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/xtl"
  },
  {
    "path": "common/crypto/benchmark_test.go",
    "chars": 990,
    "preview": "package crypto_test\n\nimport (\n\t\"crypto/cipher\"\n\t\"testing\"\n\n\t. \"github.com/xtls/xray-core/common/crypto\"\n)\n\nconst benchSi"
  },
  {
    "path": "common/crypto/chacha20.go",
    "chars": 405,
    "preview": "package crypto\n\nimport (\n\t\"crypto/cipher\"\n\n\t\"github.com/xtls/xray-core/common/crypto/internal\"\n)\n\n// NewChaCha20Stream c"
  },
  {
    "path": "common/crypto/chacha20_test.go",
    "chars": 2345,
    "preview": "package crypto_test\n\nimport (\n\t\"crypto/rand\"\n\t\"encoding/hex\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n\t\"github.com/xt"
  },
  {
    "path": "common/crypto/chunk.go",
    "chars": 3681,
    "preview": "package crypto\n\nimport (\n\t\"encoding/binary\"\n\t\"io\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/commo"
  },
  {
    "path": "common/crypto/chunk_test.go",
    "chars": 1060,
    "preview": "package crypto_test\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"testing\"\n\n\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core"
  },
  {
    "path": "common/crypto/crypto.go",
    "chars": 379,
    "preview": "// Package crypto provides common crypto libraries for Xray.\npackage crypto // import \"github.com/xtls/xray-core/common/"
  },
  {
    "path": "common/crypto/internal/chacha.go",
    "chars": 1942,
    "preview": "package internal\n\n//go:generate go run chacha_core_gen.go\n\nimport (\n\t\"encoding/binary\"\n)\n\nconst (\n\twordSize  = 4        "
  }
]

// ... and 745 more files (download for full content)

About this extraction

This page contains the full source code of the XTLS/Xray-core GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 945 files (3.6 MB), approximately 990.8k tokens, and a symbol index with 8339 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!