github.com/yggdrasil-network/yggdrasil-go@v0.5.6/src/core/link_tls.go (about) 1 package core 2 3 import ( 4 "context" 5 "crypto/tls" 6 "fmt" 7 "net" 8 "net/url" 9 10 "github.com/Arceliar/phony" 11 ) 12 13 type linkTLS struct { 14 phony.Inbox 15 *links 16 tcp *linkTCP 17 listener *net.ListenConfig 18 config *tls.Config 19 _listeners map[*Listener]context.CancelFunc 20 } 21 22 func (l *links) newLinkTLS(tcp *linkTCP) *linkTLS { 23 lt := &linkTLS{ 24 links: l, 25 tcp: tcp, 26 listener: &net.ListenConfig{ 27 Control: tcp.tcpContext, 28 KeepAlive: -1, 29 }, 30 config: l.core.config.tls.Clone(), 31 _listeners: map[*Listener]context.CancelFunc{}, 32 } 33 return lt 34 } 35 36 func (l *linkTLS) dial(ctx context.Context, url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) { 37 dialers, err := l.tcp.dialersFor(url, info) 38 if err != nil { 39 return nil, err 40 } 41 if len(dialers) == 0 { 42 return nil, nil 43 } 44 for _, d := range dialers { 45 tlsconfig := l.config.Clone() 46 tlsconfig.ServerName = options.tlsSNI 47 tlsdialer := &tls.Dialer{ 48 NetDialer: d.dialer, 49 Config: tlsconfig, 50 } 51 var conn net.Conn 52 conn, err = tlsdialer.DialContext(ctx, "tcp", d.addr.String()) 53 if err != nil { 54 continue 55 } 56 return conn, nil 57 } 58 return nil, err 59 } 60 61 func (l *linkTLS) listen(ctx context.Context, url *url.URL, sintf string) (net.Listener, error) { 62 hostport := url.Host 63 if sintf != "" { 64 if host, port, err := net.SplitHostPort(hostport); err == nil { 65 hostport = fmt.Sprintf("[%s%%%s]:%s", host, sintf, port) 66 } 67 } 68 listener, err := l.listener.Listen(ctx, "tcp", hostport) 69 if err != nil { 70 return nil, err 71 } 72 tlslistener := tls.NewListener(listener, l.config) 73 return tlslistener, nil 74 }