Browse Source

Add ConnRF to make HTTPUpgrade 0-RTT

https://github.com/XTLS/Xray-core/issues/3128#issuecomment-1991809113
RPRX 1 year ago
parent
commit
5c41292836
1 changed files with 24 additions and 12 deletions
  1. 24 12
      transport/internet/httpupgrade/dialer.go

+ 24 - 12
transport/internet/httpupgrade/dialer.go

@@ -15,6 +15,29 @@ import (
 	"github.com/xtls/xray-core/transport/internet/tls"
 )
 
+type ConnRF struct {
+	net.Conn
+	Req   *http.Request
+	First bool
+}
+
+func (c *ConnRF) Read(b []byte) (int, error) {
+	if c.First {
+		c.First = false
+		// TODO The bufio usage here is unreliable
+		resp, err := http.ReadResponse(bufio.NewReader(c.Conn), c.Req) // nolint:bodyclose
+		if err != nil {
+			return 0, err
+		}
+		if resp.Status != "101 Switching Protocols" ||
+			strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
+			strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
+			return 0, newError("unrecognized reply")
+		}
+	}
+	return c.Conn.Read(b)
+}
+
 func dialhttpUpgrade(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (net.Conn, error) {
 	transportConfiguration := streamSettings.ProtocolSettings.(*Config)
 
@@ -58,18 +81,7 @@ func dialhttpUpgrade(ctx context.Context, dest net.Destination, streamSettings *
 		return nil, err
 	}
 
-	// TODO The bufio usage here is unreliable
-	resp, err := http.ReadResponse(bufio.NewReader(conn), req) // nolint:bodyclose
-	if err != nil {
-		return nil, err
-	}
-
-	if resp.Status == "101 Switching Protocols" &&
-		strings.ToLower(resp.Header.Get("Upgrade")) == "websocket" &&
-		strings.ToLower(resp.Header.Get("Connection")) == "upgrade" {
-		return conn, nil
-	}
-	return nil, newError("unrecognized reply")
+	return &ConnRF{Conn: conn, Req: req, First: true}, nil
 }
 
 func dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) {