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
[](https://docs.rw)
[](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)
[](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
[](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
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
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.