github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/infra/conf/transport_authenticators.go (about)

     1  package conf
     2  
     3  import (
     4  	"sort"
     5  
     6  	"github.com/xmplusdev/xmcore/transport/internet/headers/dns"
     7  	"github.com/xmplusdev/xmcore/transport/internet/headers/http"
     8  	"github.com/xmplusdev/xmcore/transport/internet/headers/noop"
     9  	"github.com/xmplusdev/xmcore/transport/internet/headers/srtp"
    10  	"github.com/xmplusdev/xmcore/transport/internet/headers/tls"
    11  	"github.com/xmplusdev/xmcore/transport/internet/headers/utp"
    12  	"github.com/xmplusdev/xmcore/transport/internet/headers/wechat"
    13  	"github.com/xmplusdev/xmcore/transport/internet/headers/wireguard"
    14  	"google.golang.org/protobuf/proto"
    15  )
    16  
    17  type NoOpAuthenticator struct{}
    18  
    19  func (NoOpAuthenticator) Build() (proto.Message, error) {
    20  	return new(noop.Config), nil
    21  }
    22  
    23  type NoOpConnectionAuthenticator struct{}
    24  
    25  func (NoOpConnectionAuthenticator) Build() (proto.Message, error) {
    26  	return new(noop.ConnectionConfig), nil
    27  }
    28  
    29  type SRTPAuthenticator struct{}
    30  
    31  func (SRTPAuthenticator) Build() (proto.Message, error) {
    32  	return new(srtp.Config), nil
    33  }
    34  
    35  type UTPAuthenticator struct{}
    36  
    37  func (UTPAuthenticator) Build() (proto.Message, error) {
    38  	return new(utp.Config), nil
    39  }
    40  
    41  type WechatVideoAuthenticator struct{}
    42  
    43  func (WechatVideoAuthenticator) Build() (proto.Message, error) {
    44  	return new(wechat.VideoConfig), nil
    45  }
    46  
    47  type WireguardAuthenticator struct{}
    48  
    49  func (WireguardAuthenticator) Build() (proto.Message, error) {
    50  	return new(wireguard.WireguardConfig), nil
    51  }
    52  
    53  type DNSAuthenticator struct {
    54  	Domain string `json:"domain"`
    55  }
    56  
    57  func (v *DNSAuthenticator) Build() (proto.Message, error) {
    58  	config := new(dns.Config)
    59  	config.Domain = "www.baidu.com"
    60  	if len(v.Domain) > 0 {
    61  		config.Domain = v.Domain
    62  	}
    63  	return config, nil
    64  }
    65  
    66  type DTLSAuthenticator struct{}
    67  
    68  func (DTLSAuthenticator) Build() (proto.Message, error) {
    69  	return new(tls.PacketConfig), nil
    70  }
    71  
    72  type AuthenticatorRequest struct {
    73  	Version string                 `json:"version"`
    74  	Method  string                 `json:"method"`
    75  	Path    StringList             `json:"path"`
    76  	Headers map[string]*StringList `json:"headers"`
    77  }
    78  
    79  func sortMapKeys(m map[string]*StringList) []string {
    80  	var keys []string
    81  	for key := range m {
    82  		keys = append(keys, key)
    83  	}
    84  	sort.Strings(keys)
    85  	return keys
    86  }
    87  
    88  func (v *AuthenticatorRequest) Build() (*http.RequestConfig, error) {
    89  	config := &http.RequestConfig{
    90  		Uri: []string{"/"},
    91  		Header: []*http.Header{
    92  			{
    93  				Name:  "Host",
    94  				Value: []string{"www.baidu.com", "www.bing.com"},
    95  			},
    96  			{
    97  				Name: "User-Agent",
    98  				Value: []string{
    99  					"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
   100  					"Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46",
   101  				},
   102  			},
   103  			{
   104  				Name:  "Accept-Encoding",
   105  				Value: []string{"gzip, deflate"},
   106  			},
   107  			{
   108  				Name:  "Connection",
   109  				Value: []string{"keep-alive"},
   110  			},
   111  			{
   112  				Name:  "Pragma",
   113  				Value: []string{"no-cache"},
   114  			},
   115  		},
   116  	}
   117  
   118  	if len(v.Version) > 0 {
   119  		config.Version = &http.Version{Value: v.Version}
   120  	}
   121  
   122  	if len(v.Method) > 0 {
   123  		config.Method = &http.Method{Value: v.Method}
   124  	}
   125  
   126  	if len(v.Path) > 0 {
   127  		config.Uri = append([]string(nil), (v.Path)...)
   128  	}
   129  
   130  	if len(v.Headers) > 0 {
   131  		config.Header = make([]*http.Header, 0, len(v.Headers))
   132  		headerNames := sortMapKeys(v.Headers)
   133  		for _, key := range headerNames {
   134  			value := v.Headers[key]
   135  			if value == nil {
   136  				return nil, newError("empty HTTP header value: " + key).AtError()
   137  			}
   138  			config.Header = append(config.Header, &http.Header{
   139  				Name:  key,
   140  				Value: append([]string(nil), (*value)...),
   141  			})
   142  		}
   143  	}
   144  
   145  	return config, nil
   146  }
   147  
   148  type AuthenticatorResponse struct {
   149  	Version string                 `json:"version"`
   150  	Status  string                 `json:"status"`
   151  	Reason  string                 `json:"reason"`
   152  	Headers map[string]*StringList `json:"headers"`
   153  }
   154  
   155  func (v *AuthenticatorResponse) Build() (*http.ResponseConfig, error) {
   156  	config := &http.ResponseConfig{
   157  		Header: []*http.Header{
   158  			{
   159  				Name:  "Content-Type",
   160  				Value: []string{"application/octet-stream", "video/mpeg"},
   161  			},
   162  			{
   163  				Name:  "Transfer-Encoding",
   164  				Value: []string{"chunked"},
   165  			},
   166  			{
   167  				Name:  "Connection",
   168  				Value: []string{"keep-alive"},
   169  			},
   170  			{
   171  				Name:  "Pragma",
   172  				Value: []string{"no-cache"},
   173  			},
   174  			{
   175  				Name:  "Cache-Control",
   176  				Value: []string{"private", "no-cache"},
   177  			},
   178  		},
   179  	}
   180  
   181  	if len(v.Version) > 0 {
   182  		config.Version = &http.Version{Value: v.Version}
   183  	}
   184  
   185  	if len(v.Status) > 0 || len(v.Reason) > 0 {
   186  		config.Status = &http.Status{
   187  			Code:   "200",
   188  			Reason: "OK",
   189  		}
   190  		if len(v.Status) > 0 {
   191  			config.Status.Code = v.Status
   192  		}
   193  		if len(v.Reason) > 0 {
   194  			config.Status.Reason = v.Reason
   195  		}
   196  	}
   197  
   198  	if len(v.Headers) > 0 {
   199  		config.Header = make([]*http.Header, 0, len(v.Headers))
   200  		headerNames := sortMapKeys(v.Headers)
   201  		for _, key := range headerNames {
   202  			value := v.Headers[key]
   203  			if value == nil {
   204  				return nil, newError("empty HTTP header value: " + key).AtError()
   205  			}
   206  			config.Header = append(config.Header, &http.Header{
   207  				Name:  key,
   208  				Value: append([]string(nil), (*value)...),
   209  			})
   210  		}
   211  	}
   212  
   213  	return config, nil
   214  }
   215  
   216  type Authenticator struct {
   217  	Request  AuthenticatorRequest  `json:"request"`
   218  	Response AuthenticatorResponse `json:"response"`
   219  }
   220  
   221  func (v *Authenticator) Build() (proto.Message, error) {
   222  	config := new(http.Config)
   223  	requestConfig, err := v.Request.Build()
   224  	if err != nil {
   225  		return nil, err
   226  	}
   227  	config.Request = requestConfig
   228  
   229  	responseConfig, err := v.Response.Build()
   230  	if err != nil {
   231  		return nil, err
   232  	}
   233  	config.Response = responseConfig
   234  
   235  	return config, nil
   236  }