mihomo/transport/restls/restls.go
3andne 2fef00d2a8
Support Restls-V1 in Clash.Meta (#441)
* feat: impl restls

* fix: don't break shadowtls' working

* chores: correct restls-client-go version

* feat: bump restls-client-go version

* fix: consistent naming `client-fingerprint`

* docs: update example config

* chore: adjust client-fingerprint's snippet

---------

Co-authored-by: wwqgtxx <wwqgtxx@gmail.com>
Co-authored-by: Larvan2 <78135608+Larvan2@users.noreply.github.com>
2023-03-14 13:33:24 +08:00

57 lines
1.1 KiB
Go

package restls
import (
"net"
tls "github.com/3andne/restls-client-go"
)
const (
Mode string = "restls"
)
// Restls
type Restls struct {
net.Conn
firstPacketCache []byte
firstPacket bool
}
func (r *Restls) Read(b []byte) (int, error) {
if err := r.Conn.(*tls.UConn).Handshake(); err != nil {
return 0, err
}
n, err := r.Conn.(*tls.UConn).Read(b)
return n, err
}
func (r *Restls) Write(b []byte) (int, error) {
if r.firstPacket {
r.firstPacketCache = append([]byte(nil), b...)
r.firstPacket = false
return len(b), nil
}
if len(r.firstPacketCache) != 0 {
b = append(r.firstPacketCache, b...)
r.firstPacketCache = nil
}
n, err := r.Conn.(*tls.UConn).Write(b)
return n, err
}
// NewRestls return a Restls Connection
func NewRestls(conn net.Conn, config *tls.Config) (net.Conn, error) {
if config != nil {
clientIDPtr := config.ClientID.Load()
if clientIDPtr != nil {
return &Restls{
Conn: tls.UClient(conn, config, *clientIDPtr),
firstPacket: true,
}, nil
}
}
return &Restls{
Conn: tls.UClient(conn, config, tls.HelloChrome_Auto),
firstPacket: true,
}, nil
}