Improve: config convergent and add log-level

This commit is contained in:
Dreamacro
2018-07-26 00:04:59 +08:00
parent 7357d2d0c2
commit 8389150318
31 changed files with 757 additions and 484 deletions

View File

@ -1,77 +0,0 @@
package http
import (
"io"
"net"
"net/http"
"time"
C "github.com/Dreamacro/clash/constant"
)
type HttpAdapter struct {
addr *C.Addr
r *http.Request
w http.ResponseWriter
done chan struct{}
}
func (h *HttpAdapter) Close() {
h.done <- struct{}{}
}
func (h *HttpAdapter) Addr() *C.Addr {
return h.addr
}
func (h *HttpAdapter) Connect(proxy C.ProxyAdapter) {
req := http.Transport{
Dial: func(string, string) (net.Conn, error) {
return proxy.Conn(), nil
},
// from http.DefaultTransport
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
resp, err := req.RoundTrip(h.r)
if err != nil {
return
}
defer resp.Body.Close()
header := h.w.Header()
for k, vv := range resp.Header {
for _, v := range vv {
header.Add(k, v)
}
}
h.w.WriteHeader(resp.StatusCode)
var writer io.Writer = h.w
if len(resp.TransferEncoding) > 0 && resp.TransferEncoding[0] == "chunked" {
writer = ChunkWriter{Writer: h.w}
}
io.Copy(writer, resp.Body)
}
type ChunkWriter struct {
io.Writer
}
func (cw ChunkWriter) Write(b []byte) (int, error) {
n, err := cw.Writer.Write(b)
if err == nil {
cw.Writer.(http.Flusher).Flush()
}
return n, err
}
func NewHttp(host string, w http.ResponseWriter, r *http.Request) (*HttpAdapter, chan struct{}) {
done := make(chan struct{})
return &HttpAdapter{
addr: parseHttpAddr(host),
r: r,
w: w,
done: done,
}, done
}

View File

@ -1,35 +0,0 @@
package http
import (
"bufio"
"io"
"net"
C "github.com/Dreamacro/clash/constant"
)
type HttpsAdapter struct {
addr *C.Addr
conn net.Conn
rw *bufio.ReadWriter
}
func (h *HttpsAdapter) Close() {
h.conn.Close()
}
func (h *HttpsAdapter) Addr() *C.Addr {
return h.addr
}
func (h *HttpsAdapter) Connect(proxy C.ProxyAdapter) {
go io.Copy(h.conn, proxy.ReadWriter())
io.Copy(proxy.ReadWriter(), h.conn)
}
func NewHttps(host string, conn net.Conn) *HttpsAdapter {
return &HttpsAdapter{
addr: parseHttpAddr(host),
conn: conn,
}
}

View File

@ -6,15 +6,15 @@ import (
"net/http"
"strings"
"github.com/Dreamacro/clash/adapters/local"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/tunnel"
"github.com/riobard/go-shadowsocks2/socks"
log "github.com/sirupsen/logrus"
)
var (
tun = tunnel.GetInstance()
tun = tunnel.Instance()
)
func NewHttpProxy(addr string) (*C.ProxySignal, error) {
@ -61,7 +61,7 @@ func handleHTTP(w http.ResponseWriter, r *http.Request) {
if !strings.Contains(addr, ":") {
addr += ":80"
}
req, done := NewHttp(addr, w, r)
req, done := adapters.NewHttp(addr, w, r)
tun.Add(req)
<-done
}
@ -77,33 +77,5 @@ func handleTunneling(w http.ResponseWriter, r *http.Request) {
}
// w.WriteHeader(http.StatusOK) doesn't works in Safari
conn.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
tun.Add(NewHttps(r.Host, conn))
}
func parseHttpAddr(target string) *C.Addr {
host, port, _ := net.SplitHostPort(target)
ipAddr, err := net.ResolveIPAddr("ip", host)
var resolveIP *net.IP
if err == nil {
resolveIP = &ipAddr.IP
}
var addType int
ip := net.ParseIP(host)
switch {
case ip == nil:
addType = socks.AtypDomainName
case ip.To4() == nil:
addType = socks.AtypIPv6
default:
addType = socks.AtypIPv4
}
return &C.Addr{
NetWork: C.TCP,
AddrType: addType,
Host: host,
IP: resolveIP,
Port: port,
}
tun.Add(adapters.NewHttps(r.Host, conn))
}

View File

@ -4,11 +4,10 @@ import (
"fmt"
"sync"
"github.com/Dreamacro/clash/config"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/proxy/http"
"github.com/Dreamacro/clash/proxy/socks"
log "github.com/sirupsen/logrus"
)
var (
@ -35,24 +34,24 @@ func (l *Listener) Info() (info C.General) {
}
}
func (l *Listener) Update(allowLan *bool, httpPort *int, socksPort *int) error {
if allowLan != nil {
l.allowLan = *allowLan
func (l *Listener) Update(base *config.Base) error {
if base.AllowLan != nil {
l.allowLan = *base.AllowLan
}
var socksErr, httpErr error
if allowLan != nil || httpPort != nil {
if base.AllowLan != nil || base.Port != nil {
newHTTPPort := l.httpPort
if httpPort != nil {
newHTTPPort = *httpPort
if base.Port != nil {
newHTTPPort = *base.Port
}
httpErr = l.updateHTTP(newHTTPPort)
}
if allowLan != nil || socksPort != nil {
if base.AllowLan != nil || base.SocketPort != nil {
newSocksPort := l.socksPort
if socksPort != nil {
newSocksPort = *socksPort
if base.SocketPort != nil {
newSocksPort = *base.SocketPort
}
socksErr = l.updateSocks(newSocksPort)
}
@ -112,29 +111,30 @@ func (l *Listener) genAddr(port int) string {
return fmt.Sprintf("%s:%d", host, port)
}
func (l *Listener) Run() error {
return l.Update(&l.allowLan, &l.httpPort, &l.socksPort)
func (l *Listener) process(signal chan<- struct{}) {
sub := config.Instance().Subscribe()
signal <- struct{}{}
for elm := range sub {
event := elm.(*config.Event)
if event.Type == "base" {
base := event.Payload.(config.Base)
l.Update(&base)
}
}
}
// Run ensure config monitoring
func (l *Listener) Run() {
signal := make(chan struct{})
go l.process(signal)
<-signal
}
func newListener() *Listener {
cfg, err := C.GetConfig()
if err != nil {
log.Fatalf("Read config error: %s", err.Error())
}
general := cfg.Section("General")
port := general.Key("port").RangeInt(C.DefalutHTTPPort, 1, 65535)
socksPort := general.Key("socks-port").RangeInt(C.DefalutSOCKSPort, 1, 65535)
allowLan := general.Key("allow-lan").MustBool()
return &Listener{
httpPort: port,
socksPort: socksPort,
allowLan: allowLan,
}
return &Listener{}
}
// Instance return singleton instance of Listener
func Instance() *Listener {
once.Do(func() {
listener = newListener()

View File

@ -1,10 +1,9 @@
package socks
import (
"io"
"net"
"strconv"
"github.com/Dreamacro/clash/adapters/local"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/tunnel"
@ -13,7 +12,7 @@ import (
)
var (
tun = tunnel.GetInstance()
tun = tunnel.Instance()
)
func NewSocksProxy(addr string) (*C.ProxySignal, error) {
@ -60,59 +59,5 @@ func handleSocks(conn net.Conn) {
return
}
conn.(*net.TCPConn).SetKeepAlive(true)
tun.Add(NewSocks(target, conn))
}
type SocksAdapter struct {
conn net.Conn
addr *C.Addr
}
func (s *SocksAdapter) Close() {
s.conn.Close()
}
func (s *SocksAdapter) Addr() *C.Addr {
return s.addr
}
func (s *SocksAdapter) Connect(proxy C.ProxyAdapter) {
go io.Copy(s.conn, proxy.ReadWriter())
io.Copy(proxy.ReadWriter(), s.conn)
}
func parseSocksAddr(target socks.Addr) *C.Addr {
var host, port string
var ip net.IP
switch target[0] {
case socks.AtypDomainName:
host = string(target[2 : 2+target[1]])
port = strconv.Itoa((int(target[2+target[1]]) << 8) | int(target[2+target[1]+1]))
ipAddr, err := net.ResolveIPAddr("ip", host)
if err == nil {
ip = ipAddr.IP
}
case socks.AtypIPv4:
ip = net.IP(target[1 : 1+net.IPv4len])
port = strconv.Itoa((int(target[1+net.IPv4len]) << 8) | int(target[1+net.IPv4len+1]))
case socks.AtypIPv6:
ip = net.IP(target[1 : 1+net.IPv6len])
port = strconv.Itoa((int(target[1+net.IPv6len]) << 8) | int(target[1+net.IPv6len+1]))
}
return &C.Addr{
NetWork: C.TCP,
AddrType: int(target[0]),
Host: host,
IP: &ip,
Port: port,
}
}
func NewSocks(target socks.Addr, conn net.Conn) *SocksAdapter {
return &SocksAdapter{
conn: conn,
addr: parseSocksAddr(target),
}
tun.Add(adapters.NewSocks(target, conn))
}