mihomo/adapters/outbound/util.go

112 lines
2 KiB
Go
Raw Normal View History

2018-08-08 11:51:06 +08:00
package adapters
import (
"crypto/tls"
2018-08-08 11:51:06 +08:00
"fmt"
"net"
"net/http"
"net/url"
"sync"
2018-08-08 11:51:06 +08:00
"time"
C "github.com/Dreamacro/clash/constant"
)
2018-10-22 21:14:22 +08:00
const (
tcpTimeout = 5 * time.Second
)
var (
globalClientSessionCache tls.ClientSessionCache
once sync.Once
)
2018-08-08 11:51:06 +08:00
// DelayTest get the delay for the specified URL
func DelayTest(proxy C.Proxy, url string) (t int16, err error) {
2018-09-30 12:25:52 +08:00
addr, err := urlToMetadata(url)
2018-08-08 11:51:06 +08:00
if err != nil {
return
}
start := time.Now()
2019-03-03 11:59:07 +08:00
instance, err := proxy.Dial(&addr)
2018-08-08 11:51:06 +08:00
if err != nil {
return
}
defer instance.Close()
transport := &http.Transport{
Dial: func(string, string) (net.Conn, error) {
2018-12-22 23:56:42 +08:00
return instance, nil
2018-08-08 11:51:06 +08:00
},
// from http.DefaultTransport
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
client := http.Client{Transport: transport}
resp, err := client.Get(url)
2018-08-08 11:51:06 +08:00
if err != nil {
return
}
resp.Body.Close()
2018-08-08 11:51:06 +08:00
t = int16(time.Since(start) / time.Millisecond)
return
}
2018-09-30 12:25:52 +08:00
func urlToMetadata(rawURL string) (addr C.Metadata, err error) {
2018-08-08 11:51:06 +08:00
u, err := url.Parse(rawURL)
if err != nil {
return
}
port := u.Port()
if port == "" {
if u.Scheme == "https" {
port = "443"
} else if u.Scheme == "http" {
port = "80"
} else {
err = fmt.Errorf("%s scheme not Support", rawURL)
return
}
}
2018-09-30 12:25:52 +08:00
addr = C.Metadata{
2018-08-08 11:51:06 +08:00
AddrType: C.AtypDomainName,
Host: u.Hostname(),
IP: nil,
Port: port,
}
return
}
func selectFast(in chan interface{}) chan interface{} {
out := make(chan interface{})
go func() {
p, open := <-in
if open {
out <- p
}
close(out)
for range in {
}
}()
return out
}
func tcpKeepAlive(c net.Conn) {
if tcp, ok := c.(*net.TCPConn); ok {
tcp.SetKeepAlive(true)
2018-10-01 19:42:15 +08:00
tcp.SetKeepAlivePeriod(30 * time.Second)
}
}
func getClientSessionCache() tls.ClientSessionCache {
once.Do(func() {
globalClientSessionCache = tls.NewLRUClientSessionCache(128)
})
return globalClientSessionCache
}