|
@@ -1,9 +1,11 @@
|
|
|
package tls
|
|
|
|
|
|
import (
|
|
|
+ "context"
|
|
|
"crypto/rand"
|
|
|
"crypto/tls"
|
|
|
"math/big"
|
|
|
+ "time"
|
|
|
|
|
|
utls "github.com/refraction-networking/utls"
|
|
|
"github.com/xtls/xray-core/common/buf"
|
|
@@ -14,7 +16,7 @@ import (
|
|
|
|
|
|
type Interface interface {
|
|
|
net.Conn
|
|
|
- Handshake() error
|
|
|
+ HandshakeContext(ctx context.Context) error
|
|
|
VerifyHostname(host string) error
|
|
|
NegotiatedProtocol() (name string, mutual bool)
|
|
|
}
|
|
@@ -25,6 +27,16 @@ type Conn struct {
|
|
|
*tls.Conn
|
|
|
}
|
|
|
|
|
|
+const tlsCloseTimeout = 250 * time.Millisecond
|
|
|
+
|
|
|
+func (c *Conn) Close() error {
|
|
|
+ timer := time.AfterFunc(tlsCloseTimeout, func() {
|
|
|
+ c.Conn.NetConn().Close()
|
|
|
+ })
|
|
|
+ defer timer.Stop()
|
|
|
+ return c.Conn.Close()
|
|
|
+}
|
|
|
+
|
|
|
func (c *Conn) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|
|
mb = buf.Compact(mb)
|
|
|
mb, err := buf.WriteMultiBuffer(c, mb)
|
|
@@ -32,8 +44,8 @@ func (c *Conn) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
-func (c *Conn) HandshakeAddress() net.Address {
|
|
|
- if err := c.Handshake(); err != nil {
|
|
|
+func (c *Conn) HandshakeAddressContext(ctx context.Context) net.Address {
|
|
|
+ if err := c.HandshakeContext(ctx); err != nil {
|
|
|
return nil
|
|
|
}
|
|
|
state := c.ConnectionState()
|
|
@@ -64,8 +76,16 @@ type UConn struct {
|
|
|
*utls.UConn
|
|
|
}
|
|
|
|
|
|
-func (c *UConn) HandshakeAddress() net.Address {
|
|
|
- if err := c.Handshake(); err != nil {
|
|
|
+func (c *UConn) Close() error {
|
|
|
+ timer := time.AfterFunc(tlsCloseTimeout, func() {
|
|
|
+ c.Conn.NetConn().Close()
|
|
|
+ })
|
|
|
+ defer timer.Stop()
|
|
|
+ return c.Conn.Close()
|
|
|
+}
|
|
|
+
|
|
|
+func (c *UConn) HandshakeAddressContext(ctx context.Context) net.Address {
|
|
|
+ if err := c.HandshakeContext(ctx); err != nil {
|
|
|
return nil
|
|
|
}
|
|
|
state := c.ConnectionState()
|
|
@@ -77,7 +97,7 @@ func (c *UConn) HandshakeAddress() net.Address {
|
|
|
|
|
|
// WebsocketHandshake basically calls UConn.Handshake inside it but it will only send
|
|
|
// http/1.1 in its ALPN.
|
|
|
-func (c *UConn) WebsocketHandshake() error {
|
|
|
+func (c *UConn) WebsocketHandshakeContext(ctx context.Context) error {
|
|
|
// Build the handshake state. This will apply every variable of the TLS of the
|
|
|
// fingerprint in the UConn
|
|
|
if err := c.BuildHandshakeState(); err != nil {
|
|
@@ -99,7 +119,7 @@ func (c *UConn) WebsocketHandshake() error {
|
|
|
if err := c.BuildHandshakeState(); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- return c.Handshake()
|
|
|
+ return c.HandshakeContext(ctx)
|
|
|
}
|
|
|
|
|
|
func (c *UConn) NegotiatedProtocol() (name string, mutual bool) {
|
|
@@ -118,7 +138,7 @@ func copyConfig(c *tls.Config) *utls.Config {
|
|
|
ServerName: c.ServerName,
|
|
|
InsecureSkipVerify: c.InsecureSkipVerify,
|
|
|
VerifyPeerCertificate: c.VerifyPeerCertificate,
|
|
|
- KeyLogWriter: c.KeyLogWriter,
|
|
|
+ KeyLogWriter: c.KeyLogWriter,
|
|
|
}
|
|
|
}
|
|
|
|