| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- package sub
- import (
- "strings"
- "github.com/mhsanaei/3x-ui/v3/internal/database/model"
- )
- // ShareEndpoint is one render target for a subscription link: the address/port
- // to dial plus an optional set of TLS overrides. It unifies two sources behind
- // one type so the per-protocol link builders don't branch on where the override
- // came from:
- //
- // - a legacy externalProxy entry (Phase 1): the source map is carried in `ep`
- // and applied through the unchanged applyExternalProxyTLS* helpers, so the
- // emitted link is byte-identical to the pre-refactor output;
- // - a Host row (Phase 4): leaves `ep` nil and uses typed override fields.
- //
- // ForceTls is the verbatim "same"/"tls"/"none"/"" value — never pre-resolved,
- // because three behaviors branch on the raw string (keep-base, obj["tls"]
- // rewrite, none-strip).
- type ShareEndpoint struct {
- Address string
- Port int
- Remark string // extra remark slot fed to genRemark, not a rendered remark
- ForceTls string
- // ep is the source externalProxy entry. nil for host/default endpoints.
- ep map[string]any
- }
- // externalProxyToEndpoint maps one externalProxy entry to an endpoint that
- // carries the entry for delegated, provably-identical TLS application.
- func externalProxyToEndpoint(ep map[string]any) ShareEndpoint {
- e := ShareEndpoint{ep: ep}
- e.Address, _ = ep["dest"].(string)
- if p, ok := ep["port"].(float64); ok {
- e.Port = int(p)
- }
- e.Remark, _ = ep["remark"].(string)
- e.ForceTls, _ = ep["forceTls"].(string)
- return e
- }
- // inboundDefaultEndpoint is the endpoint for an inbound's own resolved
- // address/port (the no-externalProxy default). forceTls "same" keeps the base
- // security; no per-endpoint TLS override.
- func (s *SubService) inboundDefaultEndpoint(inbound *model.Inbound) ShareEndpoint {
- return ShareEndpoint{
- Address: s.resolveInboundAddress(inbound),
- Port: inbound.Port,
- ForceTls: "same",
- }
- }
- // applyEndpointTLSParams applies an endpoint's TLS overrides onto a URL-param
- // map. External-proxy endpoints delegate to the unchanged helper; host/default
- // endpoints carry no override yet (Phase 4).
- func applyEndpointTLSParams(e ShareEndpoint, params map[string]string, security string) {
- if e.ep != nil {
- applyExternalProxyTLSParams(e.ep, params, security)
- }
- }
- // applyEndpointTLSObj is applyEndpointTLSParams for the VMess base64-JSON form.
- func applyEndpointTLSObj(e ShareEndpoint, obj map[string]any, security string) {
- if e.ep != nil {
- applyExternalProxyTLSObj(e.ep, obj, security)
- }
- }
- // buildEndpointLinks renders one URL-param link per endpoint (vless/trojan/ss).
- // securityToApply mirrors the legacy externalProxy loop: "same" keeps the base
- // security, otherwise the endpoint's forceTls wins; "none" strips TLS hint
- // fields at emit time.
- func (s *SubService) buildEndpointLinks(
- eps []ShareEndpoint,
- params map[string]string,
- baseSecurity string,
- makeLink func(dest string, port int) string,
- makeRemark func(e ShareEndpoint) string,
- ) string {
- links := make([]string, 0, len(eps))
- for _, e := range eps {
- securityToApply := baseSecurity
- if e.ForceTls != "same" {
- securityToApply = e.ForceTls
- }
- nextParams := cloneStringMap(params)
- applyEndpointTLSParams(e, nextParams, securityToApply)
- applyEndpointRealityParams(e, nextParams, securityToApply)
- applyEndpointHostPath(e, nextParams)
- applyEndpointAllowInsecure(e, nextParams, securityToApply)
- links = append(links, buildLinkWithParamsAndSecurity(
- makeLink(e.Address, e.Port),
- nextParams,
- makeRemark(e),
- securityToApply,
- e.ForceTls == "none",
- ))
- }
- return strings.Join(links, "\n")
- }
- // buildEndpointVmessLinks renders one VMess base64-JSON link per endpoint.
- func (s *SubService) buildEndpointVmessLinks(eps []ShareEndpoint, baseObj map[string]any, inbound *model.Inbound, email string) string {
- var links strings.Builder
- for index, e := range eps {
- securityToApply, _ := baseObj["tls"].(string)
- if e.ForceTls != "same" {
- securityToApply = e.ForceTls
- }
- newObj := cloneVmessShareObj(baseObj, e.ForceTls)
- newObj["ps"] = s.endpointRemark(inbound, email, e.ep)
- newObj["add"] = e.Address
- newObj["port"] = e.Port
- if e.ForceTls != "same" {
- newObj["tls"] = e.ForceTls
- }
- applyEndpointTLSObj(e, newObj, securityToApply)
- applyEndpointHostPathObj(e, newObj)
- if index > 0 {
- links.WriteString("\n")
- }
- links.WriteString(buildVmessLink(newObj))
- }
- return links.String()
- }
|