11package moe.matsuri.nb4a.proxy.anytls
22
33import io.nekohasekai.sagernet.ktx.blankAsNull
4+ import io.nekohasekai.sagernet.ktx.linkBuilder
5+ import io.nekohasekai.sagernet.ktx.toLink
6+ import io.nekohasekai.sagernet.ktx.urlSafe
47import moe.matsuri.nb4a.SingBoxOptions
58import moe.matsuri.nb4a.utils.listByLineOrComma
9+ import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
610
711fun buildSingBoxOutboundAnyTLSBean (bean : AnyTLSBean ): SingBoxOptions .Outbound_AnyTLSOptions {
812 return SingBoxOptions .Outbound_AnyTLSOptions ().apply {
@@ -34,4 +38,44 @@ fun buildSingBoxOutboundAnyTLSBean(bean: AnyTLSBean): SingBoxOptions.Outbound_An
3438 }
3539 }
3640 }
37- }
41+ }
42+
43+ fun AnyTLSBean.toUri (): String {
44+ val builder = linkBuilder()
45+ .host(serverAddress)
46+ .port(serverPort)
47+ .username(password)
48+ if (! name.isNullOrBlank()) {
49+ builder.encodedFragment(name.urlSafe())
50+ }
51+ if (allowInsecure) {
52+ builder.addQueryParameter(" insecure" , " 1" )
53+ }
54+ if (! sni.isNullOrBlank()) {
55+ builder.addQueryParameter(" sni" , sni)
56+ }
57+ if (! utlsFingerprint.isNullOrBlank()) {
58+ builder.addQueryParameter(" fp" , utlsFingerprint)
59+ }
60+ return builder.toLink(" anytls" )
61+ }
62+
63+ fun parseAnytls (url : String ): AnyTLSBean {
64+ // https://github.com/anytls/anytls-go/blob/main/docs/uri_scheme.md
65+ val link = url.replace(" anytls://" , " https://" ).toHttpUrlOrNull() ? : error(
66+ " invalid anytls link $url "
67+ )
68+ return AnyTLSBean ().apply {
69+ serverAddress = link.host
70+ serverPort = link.port
71+ name = link.fragment
72+ password = link.username
73+ sni = link.queryParameter(" sni" ) ? : " "
74+ link.queryParameter(" insecure" )?.also {
75+ allowInsecure = it == " 1" || it == " true"
76+ }
77+ link.queryParameter(" fp" )?.let {
78+ utlsFingerprint = it
79+ }
80+ }
81+ }
0 commit comments