浏览代码

Fix TFO async write

世界 2 年之前
父节点
当前提交
fe8d46cce5
共有 1 个文件被更改,包括 20 次插入8 次删除
  1. 20 8
      common/dialer/tfo.go

+ 20 - 8
common/dialer/tfo.go

@@ -7,6 +7,7 @@ import (
 	"io"
 	"net"
 	"os"
+	"sync"
 	"time"
 
 	"github.com/sagernet/sing/common"
@@ -24,6 +25,7 @@ type slowOpenConn struct {
 	destination M.Socksaddr
 	conn        net.Conn
 	create      chan struct{}
+	access      sync.Mutex
 	err         error
 }
 
@@ -60,16 +62,26 @@ func (c *slowOpenConn) Read(b []byte) (n int, err error) {
 }
 
 func (c *slowOpenConn) Write(b []byte) (n int, err error) {
-	if c.conn == nil {
-		c.conn, err = c.dialer.DialContext(c.ctx, c.network, c.destination.String(), b)
-		if err != nil {
-			c.conn = nil
-			c.err = E.Cause(err, "dial tcp fast open")
+	if c.conn != nil {
+		return c.conn.Write(b)
+	}
+	c.access.Lock()
+	defer c.access.Unlock()
+	select {
+	case <-c.create:
+		if c.err != nil {
+			return 0, c.err
 		}
-		close(c.create)
-		return
+		return c.conn.Write(b)
+	default:
+	}
+	c.conn, err = c.dialer.DialContext(c.ctx, c.network, c.destination.String(), b)
+	if err != nil {
+		c.conn = nil
+		c.err = E.Cause(err, "dial tcp fast open")
 	}
-	return c.conn.Write(b)
+	close(c.create)
+	return
 }
 
 func (c *slowOpenConn) Close() error {