github.com/eagleql/xray-core@v1.4.4/infra/conf/transport_internet.go (about) 1 package conf 2 3 import ( 4 "encoding/json" 5 "math" 6 "net/url" 7 "strconv" 8 "strings" 9 10 "github.com/eagleql/xray-core/common/platform/filesystem" 11 "github.com/eagleql/xray-core/common/protocol" 12 "github.com/eagleql/xray-core/common/serial" 13 "github.com/eagleql/xray-core/transport/internet" 14 "github.com/eagleql/xray-core/transport/internet/domainsocket" 15 "github.com/eagleql/xray-core/transport/internet/http" 16 "github.com/eagleql/xray-core/transport/internet/kcp" 17 "github.com/eagleql/xray-core/transport/internet/quic" 18 "github.com/eagleql/xray-core/transport/internet/tcp" 19 "github.com/eagleql/xray-core/transport/internet/tls" 20 "github.com/eagleql/xray-core/transport/internet/websocket" 21 "github.com/eagleql/xray-core/transport/internet/xtls" 22 "github.com/golang/protobuf/proto" 23 ) 24 25 var ( 26 kcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{ 27 "none": func() interface{} { return new(NoOpAuthenticator) }, 28 "srtp": func() interface{} { return new(SRTPAuthenticator) }, 29 "utp": func() interface{} { return new(UTPAuthenticator) }, 30 "wechat-video": func() interface{} { return new(WechatVideoAuthenticator) }, 31 "dtls": func() interface{} { return new(DTLSAuthenticator) }, 32 "wireguard": func() interface{} { return new(WireguardAuthenticator) }, 33 }, "type", "") 34 35 tcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{ 36 "none": func() interface{} { return new(NoOpConnectionAuthenticator) }, 37 "http": func() interface{} { return new(Authenticator) }, 38 }, "type", "") 39 ) 40 41 type KCPConfig struct { 42 Mtu *uint32 `json:"mtu"` 43 Tti *uint32 `json:"tti"` 44 UpCap *uint32 `json:"uplinkCapacity"` 45 DownCap *uint32 `json:"downlinkCapacity"` 46 Congestion *bool `json:"congestion"` 47 ReadBufferSize *uint32 `json:"readBufferSize"` 48 WriteBufferSize *uint32 `json:"writeBufferSize"` 49 HeaderConfig json.RawMessage `json:"header"` 50 Seed *string `json:"seed"` 51 } 52 53 // Build implements Buildable. 54 func (c *KCPConfig) Build() (proto.Message, error) { 55 config := new(kcp.Config) 56 57 if c.Mtu != nil { 58 mtu := *c.Mtu 59 if mtu < 576 || mtu > 1460 { 60 return nil, newError("invalid mKCP MTU size: ", mtu).AtError() 61 } 62 config.Mtu = &kcp.MTU{Value: mtu} 63 } 64 if c.Tti != nil { 65 tti := *c.Tti 66 if tti < 10 || tti > 100 { 67 return nil, newError("invalid mKCP TTI: ", tti).AtError() 68 } 69 config.Tti = &kcp.TTI{Value: tti} 70 } 71 if c.UpCap != nil { 72 config.UplinkCapacity = &kcp.UplinkCapacity{Value: *c.UpCap} 73 } 74 if c.DownCap != nil { 75 config.DownlinkCapacity = &kcp.DownlinkCapacity{Value: *c.DownCap} 76 } 77 if c.Congestion != nil { 78 config.Congestion = *c.Congestion 79 } 80 if c.ReadBufferSize != nil { 81 size := *c.ReadBufferSize 82 if size > 0 { 83 config.ReadBuffer = &kcp.ReadBuffer{Size: size * 1024 * 1024} 84 } else { 85 config.ReadBuffer = &kcp.ReadBuffer{Size: 512 * 1024} 86 } 87 } 88 if c.WriteBufferSize != nil { 89 size := *c.WriteBufferSize 90 if size > 0 { 91 config.WriteBuffer = &kcp.WriteBuffer{Size: size * 1024 * 1024} 92 } else { 93 config.WriteBuffer = &kcp.WriteBuffer{Size: 512 * 1024} 94 } 95 } 96 if len(c.HeaderConfig) > 0 { 97 headerConfig, _, err := kcpHeaderLoader.Load(c.HeaderConfig) 98 if err != nil { 99 return nil, newError("invalid mKCP header config.").Base(err).AtError() 100 } 101 ts, err := headerConfig.(Buildable).Build() 102 if err != nil { 103 return nil, newError("invalid mKCP header config").Base(err).AtError() 104 } 105 config.HeaderConfig = serial.ToTypedMessage(ts) 106 } 107 108 if c.Seed != nil { 109 config.Seed = &kcp.EncryptionSeed{Seed: *c.Seed} 110 } 111 112 return config, nil 113 } 114 115 type TCPConfig struct { 116 HeaderConfig json.RawMessage `json:"header"` 117 AcceptProxyProtocol bool `json:"acceptProxyProtocol"` 118 } 119 120 // Build implements Buildable. 121 func (c *TCPConfig) Build() (proto.Message, error) { 122 config := new(tcp.Config) 123 if len(c.HeaderConfig) > 0 { 124 headerConfig, _, err := tcpHeaderLoader.Load(c.HeaderConfig) 125 if err != nil { 126 return nil, newError("invalid TCP header config").Base(err).AtError() 127 } 128 ts, err := headerConfig.(Buildable).Build() 129 if err != nil { 130 return nil, newError("invalid TCP header config").Base(err).AtError() 131 } 132 config.HeaderSettings = serial.ToTypedMessage(ts) 133 } 134 if c.AcceptProxyProtocol { 135 config.AcceptProxyProtocol = c.AcceptProxyProtocol 136 } 137 return config, nil 138 } 139 140 type WebSocketConfig struct { 141 Path string `json:"path"` 142 Path2 string `json:"Path"` // The key was misspelled. For backward compatibility, we have to keep track the old key. 143 Headers map[string]string `json:"headers"` 144 AcceptProxyProtocol bool `json:"acceptProxyProtocol"` 145 } 146 147 // Build implements Buildable. 148 func (c *WebSocketConfig) Build() (proto.Message, error) { 149 path := c.Path 150 if path == "" && c.Path2 != "" { 151 path = c.Path2 152 } 153 header := make([]*websocket.Header, 0, 32) 154 for key, value := range c.Headers { 155 header = append(header, &websocket.Header{ 156 Key: key, 157 Value: value, 158 }) 159 } 160 var ed uint32 161 if u, err := url.Parse(path); err == nil { 162 if q := u.Query(); q.Get("ed") != "" { 163 Ed, _ := strconv.Atoi(q.Get("ed")) 164 ed = uint32(Ed) 165 q.Del("ed") 166 u.RawQuery = q.Encode() 167 path = u.String() 168 } 169 } 170 config := &websocket.Config{ 171 Path: path, 172 Header: header, 173 Ed: ed, 174 } 175 if c.AcceptProxyProtocol { 176 config.AcceptProxyProtocol = c.AcceptProxyProtocol 177 } 178 return config, nil 179 } 180 181 type HTTPConfig struct { 182 Host *StringList `json:"host"` 183 Path string `json:"path"` 184 } 185 186 // Build implements Buildable. 187 func (c *HTTPConfig) Build() (proto.Message, error) { 188 config := &http.Config{ 189 Path: c.Path, 190 } 191 if c.Host != nil { 192 config.Host = []string(*c.Host) 193 } 194 return config, nil 195 } 196 197 type QUICConfig struct { 198 Header json.RawMessage `json:"header"` 199 Security string `json:"security"` 200 Key string `json:"key"` 201 } 202 203 // Build implements Buildable. 204 func (c *QUICConfig) Build() (proto.Message, error) { 205 config := &quic.Config{ 206 Key: c.Key, 207 } 208 209 if len(c.Header) > 0 { 210 headerConfig, _, err := kcpHeaderLoader.Load(c.Header) 211 if err != nil { 212 return nil, newError("invalid QUIC header config.").Base(err).AtError() 213 } 214 ts, err := headerConfig.(Buildable).Build() 215 if err != nil { 216 return nil, newError("invalid QUIC header config").Base(err).AtError() 217 } 218 config.Header = serial.ToTypedMessage(ts) 219 } 220 221 var st protocol.SecurityType 222 switch strings.ToLower(c.Security) { 223 case "aes-128-gcm": 224 st = protocol.SecurityType_AES128_GCM 225 case "chacha20-poly1305": 226 st = protocol.SecurityType_CHACHA20_POLY1305 227 default: 228 st = protocol.SecurityType_NONE 229 } 230 231 config.Security = &protocol.SecurityConfig{ 232 Type: st, 233 } 234 235 return config, nil 236 } 237 238 type DomainSocketConfig struct { 239 Path string `json:"path"` 240 Abstract bool `json:"abstract"` 241 Padding bool `json:"padding"` 242 } 243 244 // Build implements Buildable. 245 func (c *DomainSocketConfig) Build() (proto.Message, error) { 246 return &domainsocket.Config{ 247 Path: c.Path, 248 Abstract: c.Abstract, 249 Padding: c.Padding, 250 }, nil 251 } 252 253 func readFileOrString(f string, s []string) ([]byte, error) { 254 if len(f) > 0 { 255 return filesystem.ReadFile(f) 256 } 257 if len(s) > 0 { 258 return []byte(strings.Join(s, "\n")), nil 259 } 260 return nil, newError("both file and bytes are empty.") 261 } 262 263 type TLSCertConfig struct { 264 CertFile string `json:"certificateFile"` 265 CertStr []string `json:"certificate"` 266 KeyFile string `json:"keyFile"` 267 KeyStr []string `json:"key"` 268 Usage string `json:"usage"` 269 OcspStapling uint64 `json:"ocspStapling"` 270 OneTimeLoading bool `json:"oneTimeLoading"` 271 } 272 273 // Build implements Buildable. 274 func (c *TLSCertConfig) Build() (*tls.Certificate, error) { 275 certificate := new(tls.Certificate) 276 277 cert, err := readFileOrString(c.CertFile, c.CertStr) 278 if err != nil { 279 return nil, newError("failed to parse certificate").Base(err) 280 } 281 certificate.Certificate = cert 282 certificate.CertificatePath = c.CertFile 283 284 if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 { 285 key, err := readFileOrString(c.KeyFile, c.KeyStr) 286 if err != nil { 287 return nil, newError("failed to parse key").Base(err) 288 } 289 certificate.Key = key 290 certificate.KeyPath = c.KeyFile 291 } 292 293 switch strings.ToLower(c.Usage) { 294 case "encipherment": 295 certificate.Usage = tls.Certificate_ENCIPHERMENT 296 case "verify": 297 certificate.Usage = tls.Certificate_AUTHORITY_VERIFY 298 case "issue": 299 certificate.Usage = tls.Certificate_AUTHORITY_ISSUE 300 default: 301 certificate.Usage = tls.Certificate_ENCIPHERMENT 302 } 303 if certificate.KeyPath == "" && certificate.CertificatePath == "" { 304 certificate.OneTimeLoading = true 305 } else { 306 certificate.OneTimeLoading = c.OneTimeLoading 307 } 308 certificate.OcspStapling = c.OcspStapling 309 310 return certificate, nil 311 } 312 313 type TLSConfig struct { 314 Insecure bool `json:"allowInsecure"` 315 Certs []*TLSCertConfig `json:"certificates"` 316 ServerName string `json:"serverName"` 317 ALPN *StringList `json:"alpn"` 318 EnableSessionResumption bool `json:"enableSessionResumption"` 319 DisableSystemRoot bool `json:"disableSystemRoot"` 320 MinVersion string `json:"minVersion"` 321 MaxVersion string `json:"maxVersion"` 322 CipherSuites string `json:"cipherSuites"` 323 PreferServerCipherSuites bool `json:"preferServerCipherSuites"` 324 Fingerprint string `json:"fingerprint"` 325 } 326 327 // Build implements Buildable. 328 func (c *TLSConfig) Build() (proto.Message, error) { 329 config := new(tls.Config) 330 config.Certificate = make([]*tls.Certificate, len(c.Certs)) 331 for idx, certConf := range c.Certs { 332 cert, err := certConf.Build() 333 if err != nil { 334 return nil, err 335 } 336 config.Certificate[idx] = cert 337 } 338 serverName := c.ServerName 339 config.AllowInsecure = c.Insecure 340 if len(c.ServerName) > 0 { 341 config.ServerName = serverName 342 } 343 if c.ALPN != nil && len(*c.ALPN) > 0 { 344 config.NextProtocol = []string(*c.ALPN) 345 } 346 config.EnableSessionResumption = c.EnableSessionResumption 347 config.DisableSystemRoot = c.DisableSystemRoot 348 config.MinVersion = c.MinVersion 349 config.MaxVersion = c.MaxVersion 350 config.CipherSuites = c.CipherSuites 351 config.PreferServerCipherSuites = c.PreferServerCipherSuites 352 config.Fingerprint = strings.ToLower(c.Fingerprint) 353 return config, nil 354 } 355 356 type XTLSCertConfig struct { 357 CertFile string `json:"certificateFile"` 358 CertStr []string `json:"certificate"` 359 KeyFile string `json:"keyFile"` 360 KeyStr []string `json:"key"` 361 Usage string `json:"usage"` 362 OcspStapling uint64 `json:"ocspStapling"` 363 OneTimeLoading bool `json:"oneTimeLoading"` 364 } 365 366 // Build implements Buildable. 367 func (c *XTLSCertConfig) Build() (*xtls.Certificate, error) { 368 certificate := new(xtls.Certificate) 369 cert, err := readFileOrString(c.CertFile, c.CertStr) 370 if err != nil { 371 return nil, newError("failed to parse certificate").Base(err) 372 } 373 certificate.Certificate = cert 374 certificate.CertificatePath = c.CertFile 375 376 if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 { 377 key, err := readFileOrString(c.KeyFile, c.KeyStr) 378 if err != nil { 379 return nil, newError("failed to parse key").Base(err) 380 } 381 certificate.Key = key 382 certificate.KeyPath = c.KeyFile 383 } 384 385 switch strings.ToLower(c.Usage) { 386 case "encipherment": 387 certificate.Usage = xtls.Certificate_ENCIPHERMENT 388 case "verify": 389 certificate.Usage = xtls.Certificate_AUTHORITY_VERIFY 390 case "issue": 391 certificate.Usage = xtls.Certificate_AUTHORITY_ISSUE 392 default: 393 certificate.Usage = xtls.Certificate_ENCIPHERMENT 394 } 395 if certificate.KeyPath == "" && certificate.CertificatePath == "" { 396 certificate.OneTimeLoading = true 397 } else { 398 certificate.OneTimeLoading = c.OneTimeLoading 399 } 400 certificate.OcspStapling = c.OcspStapling 401 402 return certificate, nil 403 } 404 405 type XTLSConfig struct { 406 Insecure bool `json:"allowInsecure"` 407 Certs []*XTLSCertConfig `json:"certificates"` 408 ServerName string `json:"serverName"` 409 ALPN *StringList `json:"alpn"` 410 EnableSessionResumption bool `json:"enableSessionResumption"` 411 DisableSystemRoot bool `json:"disableSystemRoot"` 412 MinVersion string `json:"minVersion"` 413 MaxVersion string `json:"maxVersion"` 414 CipherSuites string `json:"cipherSuites"` 415 PreferServerCipherSuites bool `json:"preferServerCipherSuites"` 416 } 417 418 // Build implements Buildable. 419 func (c *XTLSConfig) Build() (proto.Message, error) { 420 config := new(xtls.Config) 421 config.Certificate = make([]*xtls.Certificate, len(c.Certs)) 422 for idx, certConf := range c.Certs { 423 cert, err := certConf.Build() 424 if err != nil { 425 return nil, err 426 } 427 config.Certificate[idx] = cert 428 } 429 serverName := c.ServerName 430 config.AllowInsecure = c.Insecure 431 if len(c.ServerName) > 0 { 432 config.ServerName = serverName 433 } 434 if c.ALPN != nil && len(*c.ALPN) > 0 { 435 config.NextProtocol = []string(*c.ALPN) 436 } 437 config.EnableSessionResumption = c.EnableSessionResumption 438 config.DisableSystemRoot = c.DisableSystemRoot 439 config.MinVersion = c.MinVersion 440 config.MaxVersion = c.MaxVersion 441 config.CipherSuites = c.CipherSuites 442 config.PreferServerCipherSuites = c.PreferServerCipherSuites 443 return config, nil 444 } 445 446 type TransportProtocol string 447 448 // Build implements Buildable. 449 func (p TransportProtocol) Build() (string, error) { 450 switch strings.ToLower(string(p)) { 451 case "tcp": 452 return "tcp", nil 453 case "kcp", "mkcp": 454 return "mkcp", nil 455 case "ws", "websocket": 456 return "websocket", nil 457 case "h2", "http": 458 return "http", nil 459 case "ds", "domainsocket": 460 return "domainsocket", nil 461 case "quic": 462 return "quic", nil 463 case "grpc", "gun": 464 return "grpc", nil 465 default: 466 return "", newError("Config: unknown transport protocol: ", p) 467 } 468 } 469 470 type SocketConfig struct { 471 Mark int32 `json:"mark"` 472 TFO interface{} `json:"tcpFastOpen"` 473 TProxy string `json:"tproxy"` 474 AcceptProxyProtocol bool `json:"acceptProxyProtocol"` 475 DomainStrategy string `json:"domainStrategy"` 476 DialerProxy string `json:"dialerProxy"` 477 } 478 479 // Build implements Buildable. 480 func (c *SocketConfig) Build() (*internet.SocketConfig, error) { 481 tfo := int32(0) // don't invoke setsockopt() for TFO 482 if c.TFO != nil { 483 switch v := c.TFO.(type) { 484 case bool: 485 if v { 486 tfo = 256 487 } else { 488 tfo = -1 // TFO need to be disabled 489 } 490 case float64: 491 tfo = int32(math.Min(v, math.MaxInt32)) 492 default: 493 return nil, newError("tcpFastOpen: only boolean and integer value is acceptable") 494 } 495 } 496 var tproxy internet.SocketConfig_TProxyMode 497 switch strings.ToLower(c.TProxy) { 498 case "tproxy": 499 tproxy = internet.SocketConfig_TProxy 500 case "redirect": 501 tproxy = internet.SocketConfig_Redirect 502 default: 503 tproxy = internet.SocketConfig_Off 504 } 505 506 var dStrategy = internet.DomainStrategy_AS_IS 507 switch strings.ToLower(c.DomainStrategy) { 508 case "useip", "use_ip": 509 dStrategy = internet.DomainStrategy_USE_IP 510 case "useip4", "useipv4", "use_ipv4", "use_ip_v4", "use_ip4": 511 dStrategy = internet.DomainStrategy_USE_IP4 512 case "useip6", "useipv6", "use_ipv6", "use_ip_v6", "use_ip6": 513 dStrategy = internet.DomainStrategy_USE_IP6 514 } 515 516 return &internet.SocketConfig{ 517 Mark: c.Mark, 518 Tfo: tfo, 519 Tproxy: tproxy, 520 DomainStrategy: dStrategy, 521 AcceptProxyProtocol: c.AcceptProxyProtocol, 522 DialerProxy: c.DialerProxy, 523 }, nil 524 } 525 526 type StreamConfig struct { 527 Network *TransportProtocol `json:"network"` 528 Security string `json:"security"` 529 TLSSettings *TLSConfig `json:"tlsSettings"` 530 XTLSSettings *XTLSConfig `json:"xtlsSettings"` 531 TCPSettings *TCPConfig `json:"tcpSettings"` 532 KCPSettings *KCPConfig `json:"kcpSettings"` 533 WSSettings *WebSocketConfig `json:"wsSettings"` 534 HTTPSettings *HTTPConfig `json:"httpSettings"` 535 DSSettings *DomainSocketConfig `json:"dsSettings"` 536 QUICSettings *QUICConfig `json:"quicSettings"` 537 SocketSettings *SocketConfig `json:"sockopt"` 538 GRPCConfig *GRPCConfig `json:"grpcSettings"` 539 GUNConfig *GRPCConfig `json:"gunSettings"` 540 } 541 542 // Build implements Buildable. 543 func (c *StreamConfig) Build() (*internet.StreamConfig, error) { 544 config := &internet.StreamConfig{ 545 ProtocolName: "tcp", 546 } 547 if c.Network != nil { 548 protocol, err := c.Network.Build() 549 if err != nil { 550 return nil, err 551 } 552 config.ProtocolName = protocol 553 } 554 if strings.EqualFold(c.Security, "tls") { 555 tlsSettings := c.TLSSettings 556 if tlsSettings == nil { 557 if c.XTLSSettings != nil { 558 return nil, newError(`TLS: Please use "tlsSettings" instead of "xtlsSettings".`) 559 } 560 tlsSettings = &TLSConfig{} 561 } 562 ts, err := tlsSettings.Build() 563 if err != nil { 564 return nil, newError("Failed to build TLS config.").Base(err) 565 } 566 tm := serial.ToTypedMessage(ts) 567 config.SecuritySettings = append(config.SecuritySettings, tm) 568 config.SecurityType = tm.Type 569 } 570 if strings.EqualFold(c.Security, "xtls") { 571 if config.ProtocolName != "tcp" && config.ProtocolName != "mkcp" && config.ProtocolName != "domainsocket" { 572 return nil, newError("XTLS only supports TCP, mKCP and DomainSocket for now.") 573 } 574 xtlsSettings := c.XTLSSettings 575 if xtlsSettings == nil { 576 if c.TLSSettings != nil { 577 return nil, newError(`XTLS: Please use "xtlsSettings" instead of "tlsSettings".`) 578 } 579 xtlsSettings = &XTLSConfig{} 580 } 581 ts, err := xtlsSettings.Build() 582 if err != nil { 583 return nil, newError("Failed to build XTLS config.").Base(err) 584 } 585 tm := serial.ToTypedMessage(ts) 586 config.SecuritySettings = append(config.SecuritySettings, tm) 587 config.SecurityType = tm.Type 588 } 589 if c.TCPSettings != nil { 590 ts, err := c.TCPSettings.Build() 591 if err != nil { 592 return nil, newError("Failed to build TCP config.").Base(err) 593 } 594 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 595 ProtocolName: "tcp", 596 Settings: serial.ToTypedMessage(ts), 597 }) 598 } 599 if c.KCPSettings != nil { 600 ts, err := c.KCPSettings.Build() 601 if err != nil { 602 return nil, newError("Failed to build mKCP config.").Base(err) 603 } 604 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 605 ProtocolName: "mkcp", 606 Settings: serial.ToTypedMessage(ts), 607 }) 608 } 609 if c.WSSettings != nil { 610 ts, err := c.WSSettings.Build() 611 if err != nil { 612 return nil, newError("Failed to build WebSocket config.").Base(err) 613 } 614 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 615 ProtocolName: "websocket", 616 Settings: serial.ToTypedMessage(ts), 617 }) 618 } 619 if c.HTTPSettings != nil { 620 ts, err := c.HTTPSettings.Build() 621 if err != nil { 622 return nil, newError("Failed to build HTTP config.").Base(err) 623 } 624 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 625 ProtocolName: "http", 626 Settings: serial.ToTypedMessage(ts), 627 }) 628 } 629 if c.DSSettings != nil { 630 ds, err := c.DSSettings.Build() 631 if err != nil { 632 return nil, newError("Failed to build DomainSocket config.").Base(err) 633 } 634 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 635 ProtocolName: "domainsocket", 636 Settings: serial.ToTypedMessage(ds), 637 }) 638 } 639 if c.QUICSettings != nil { 640 qs, err := c.QUICSettings.Build() 641 if err != nil { 642 return nil, newError("Failed to build QUIC config").Base(err) 643 } 644 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 645 ProtocolName: "quic", 646 Settings: serial.ToTypedMessage(qs), 647 }) 648 } 649 if c.GRPCConfig == nil { 650 c.GRPCConfig = c.GUNConfig 651 } 652 if c.GRPCConfig != nil { 653 gs, err := c.GRPCConfig.Build() 654 if err != nil { 655 return nil, newError("Failed to build gRPC config.").Base(err) 656 } 657 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 658 ProtocolName: "grpc", 659 Settings: serial.ToTypedMessage(gs), 660 }) 661 } 662 if c.SocketSettings != nil { 663 ss, err := c.SocketSettings.Build() 664 if err != nil { 665 return nil, newError("Failed to build sockopt").Base(err) 666 } 667 config.SocketSettings = ss 668 } 669 return config, nil 670 } 671 672 type ProxyConfig struct { 673 Tag string `json:"tag"` 674 675 // TransportLayerProxy: For compatibility. 676 TransportLayerProxy bool `json:"transportLayer"` 677 } 678 679 // Build implements Buildable. 680 func (v *ProxyConfig) Build() (*internet.ProxyConfig, error) { 681 if v.Tag == "" { 682 return nil, newError("Proxy tag is not set.") 683 } 684 return &internet.ProxyConfig{ 685 Tag: v.Tag, 686 TransportLayerProxy: v.TransportLayerProxy, 687 }, nil 688 }