github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/transport/internet/httpupgrade/dialer.go (about) 1 package httpupgrade 2 3 import ( 4 "bufio" 5 "context" 6 "net/http" 7 "strings" 8 9 "github.com/v2fly/v2ray-core/v5/common" 10 "github.com/v2fly/v2ray-core/v5/common/net" 11 "github.com/v2fly/v2ray-core/v5/common/session" 12 "github.com/v2fly/v2ray-core/v5/transport/internet" 13 "github.com/v2fly/v2ray-core/v5/transport/internet/transportcommon" 14 ) 15 16 func dialhttpUpgrade(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (net.Conn, error) { 17 transportConfiguration := streamSettings.ProtocolSettings.(*Config) 18 19 conn, err := transportcommon.DialWithSecuritySettings(ctx, dest, streamSettings) 20 if err != nil { 21 return nil, newError("failed to dial request to ", dest).Base(err) 22 } 23 req, err := http.NewRequest("GET", transportConfiguration.GetNormalizedPath(), nil) 24 if err != nil { 25 return nil, err 26 } 27 28 req.Header.Set("Connection", "upgrade") 29 req.Header.Set("Upgrade", "websocket") 30 req.Host = transportConfiguration.Host 31 32 err = req.Write(conn) 33 if err != nil { 34 return nil, err 35 } 36 37 // TODO The bufio usage here is unreliable 38 resp, err := http.ReadResponse(bufio.NewReader(conn), req) // nolint:bodyclose 39 if err != nil { 40 return nil, err 41 } 42 43 if resp.Status == "101 Switching Protocols" && 44 strings.ToLower(resp.Header.Get("Upgrade")) == "websocket" && 45 strings.ToLower(resp.Header.Get("Connection")) == "upgrade" { 46 return conn, nil 47 } 48 return nil, newError("unrecognized reply") 49 } 50 51 func dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) { 52 newError("creating connection to ", dest).WriteToLog(session.ExportIDToError(ctx)) 53 54 conn, err := dialhttpUpgrade(ctx, dest, streamSettings) 55 if err != nil { 56 return nil, newError("failed to dial request to ", dest).Base(err) 57 } 58 return internet.Connection(conn), nil 59 } 60 61 func init() { 62 common.Must(internet.RegisterTransportDialer(protocolName, dial)) 63 }