chore: tuic add fast-open support

This commit is contained in:
wwqgtxx 2022-11-26 21:14:56 +08:00
parent 8056b5573b
commit ae76daf393
2 changed files with 40 additions and 6 deletions

View File

@ -47,6 +47,7 @@ type TuicOption struct {
DisableSni bool `proxy:"disable_sni,omitempty"` DisableSni bool `proxy:"disable_sni,omitempty"`
MaxUdpRelayPacketSize int `proxy:"max_udp_relay_packet_size,omitempty"` MaxUdpRelayPacketSize int `proxy:"max_udp_relay_packet_size,omitempty"`
FastOpen bool `proxy:"fast-open,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"` SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"` Fingerprint string `proxy:"fingerprint,omitempty"`
CustomCA string `proxy:"ca,omitempty"` CustomCA string `proxy:"ca,omitempty"`
@ -263,6 +264,7 @@ func NewTuic(option TuicOption) (*Tuic, error) {
ReduceRtt: option.ReduceRtt, ReduceRtt: option.ReduceRtt,
RequestTimeout: option.RequestTimeout, RequestTimeout: option.RequestTimeout,
MaxUdpRelayPacketSize: option.MaxUdpRelayPacketSize, MaxUdpRelayPacketSize: option.MaxUdpRelayPacketSize,
FastOpen: option.FastOpen,
Inference: t, Inference: t,
Key: o, Key: o,
LastVisited: time.Now(), LastVisited: time.Now(),
@ -303,7 +305,7 @@ func NewTuic(option TuicOption) (*Tuic, error) {
} }
} }
} }
if time.Now().Sub(client.LastVisited) > 30*time.Minute { if client.OpenStreams.Load() == 0 && time.Now().Sub(client.LastVisited) > 30*time.Minute {
next := it.Next() next := it.Next()
clients.Remove(it) clients.Remove(it)
it = next it = next

View File

@ -38,6 +38,7 @@ type Client struct {
ReduceRtt bool ReduceRtt bool
RequestTimeout int RequestTimeout int
MaxUdpRelayPacketSize int MaxUdpRelayPacketSize int
FastOpen bool
Inference any Inference any
Key any Key any
@ -282,18 +283,49 @@ func (t *Client) DialContext(ctx context.Context, metadata *C.Metadata, dialFn f
if t.RequestTimeout > 0 { if t.RequestTimeout > 0 {
_ = stream.SetReadDeadline(time.Now().Add(time.Duration(t.RequestTimeout) * time.Millisecond)) _ = stream.SetReadDeadline(time.Now().Add(time.Duration(t.RequestTimeout) * time.Millisecond))
} }
conn := N.NewBufferedConn(stream) conn := &earlyConn{BufferedConn: N.NewBufferedConn(stream)}
if !t.FastOpen {
err = conn.Response()
if err != nil {
return nil, err
}
}
return conn, nil
}
type earlyConn struct {
*N.BufferedConn
resOnce sync.Once
resErr error
}
func (conn *earlyConn) response() error {
response, err := ReadResponse(conn) response, err := ReadResponse(conn)
if err != nil { if err != nil {
_ = conn.Close() _ = conn.Close()
return nil, err return err
} }
if response.IsFailed() { if response.IsFailed() {
_ = conn.Close() _ = conn.Close()
return nil, errors.New("connect failed") return errors.New("connect failed")
} }
_ = stream.SetReadDeadline(time.Time{}) _ = conn.SetReadDeadline(time.Time{})
return conn, nil return nil
}
func (conn *earlyConn) Response() error {
conn.resOnce.Do(func() {
conn.resErr = conn.response()
})
return conn.resErr
}
func (conn *earlyConn) Read(b []byte) (n int, err error) {
err = conn.Response()
if err != nil {
return 0, err
}
return conn.BufferedConn.Read(b)
} }
type quicStreamConn struct { type quicStreamConn struct {