github.com/kelleygo/clashcore@v1.0.2/common/net/earlyconn.go (about) 1 package net 2 3 import ( 4 "net" 5 "sync" 6 7 "github.com/kelleygo/clashcore/common/buf" 8 "github.com/kelleygo/clashcore/common/once" 9 ) 10 11 type earlyConn struct { 12 ExtendedConn // only expose standard N.ExtendedConn function to outside 13 resFunc func() error 14 resOnce sync.Once 15 resErr error 16 } 17 18 func (conn *earlyConn) Response() error { 19 conn.resOnce.Do(func() { 20 conn.resErr = conn.resFunc() 21 }) 22 return conn.resErr 23 } 24 25 func (conn *earlyConn) Read(b []byte) (n int, err error) { 26 err = conn.Response() 27 if err != nil { 28 return 0, err 29 } 30 return conn.ExtendedConn.Read(b) 31 } 32 33 func (conn *earlyConn) ReadBuffer(buffer *buf.Buffer) (err error) { 34 err = conn.Response() 35 if err != nil { 36 return err 37 } 38 return conn.ExtendedConn.ReadBuffer(buffer) 39 } 40 41 func (conn *earlyConn) Upstream() any { 42 return conn.ExtendedConn 43 } 44 45 func (conn *earlyConn) Success() bool { 46 return once.Done(&conn.resOnce) && conn.resErr == nil 47 } 48 49 func (conn *earlyConn) ReaderReplaceable() bool { 50 return conn.Success() 51 } 52 53 func (conn *earlyConn) ReaderPossiblyReplaceable() bool { 54 return !conn.Success() 55 } 56 57 func (conn *earlyConn) WriterReplaceable() bool { 58 return true 59 } 60 61 var _ ExtendedConn = (*earlyConn)(nil) 62 63 func NewEarlyConn(c net.Conn, f func() error) net.Conn { 64 return &earlyConn{ExtendedConn: NewExtendedConn(c), resFunc: f} 65 }