package core import ( "context" "crypto/tls" "fmt" "net" "net/http" "net/url" "github.com/Arceliar/phony" "github.com/coder/websocket" ) type linkWSS struct { phony.Inbox *links tlsconfig *tls.Config } type linkWSSConn struct { net.Conn } func (l *links) newLinkWSS() *linkWSS { lwss := &linkWSS{ links: l, tlsconfig: l.core.config.tls.Clone(), } return lwss } func (l *linkWSS) dial(ctx context.Context, url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) { tlsconfig := l.tlsconfig.Clone() return l.links.findSuitableIP(url, func(hostname string, ip net.IP, port int) (net.Conn, error) { tlsconfig.ServerName = hostname u := *url u.Host = net.JoinHostPort(ip.String(), fmt.Sprintf("%d", port)) addr := &net.TCPAddr{ IP: ip, Port: port, } dialer, err := l.tcp.dialerFor(addr, info.sintf) if err != nil { return nil, err } wsconn, _, err := websocket.Dial(ctx, u.String(), &websocket.DialOptions{ HTTPClient: &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, Dial: dialer.Dial, DialContext: dialer.DialContext, TLSClientConfig: tlsconfig, }, }, Subprotocols: []string{"ygg-ws"}, Host: hostname, }) if err != nil { return nil, err } return &linkWSSConn{ Conn: websocket.NetConn(ctx, wsconn, websocket.MessageBinary), }, nil }) } func (l *linkWSS) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) { return nil, fmt.Errorf("WSS listener not supported, use WS listener behind reverse proxy instead") }