chore: separate packages

This commit is contained in:
wweir
2021-12-06 14:44:24 +08:00
parent 05a1a3249a
commit bad7ae702a
15 changed files with 51 additions and 289 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ import (
"github.com/cristalhq/aconfig/aconfigyaml"
"github.com/miekg/dns"
"github.com/pkg/errors"
"github.com/wweir/deferlog/log"
"github.com/sower-proxy/deferlog/log"
"github.com/wweir/sower/router"
)
+5 -5
View File
@@ -8,14 +8,14 @@ import (
"time"
"github.com/pkg/errors"
"github.com/wweir/deferlog/log"
"github.com/wweir/sower/pkg/teeconn"
"github.com/sower-proxy/conns/relay"
"github.com/sower-proxy/conns/teeconn"
"github.com/sower-proxy/deferlog/log"
"github.com/wweir/sower/router"
"github.com/wweir/sower/transport"
"github.com/wweir/sower/transport/socks5"
"github.com/wweir/sower/transport/sower"
"github.com/wweir/sower/transport/trojan"
"github.com/wweir/sower/util"
)
func GenProxyDial(proxyType, proxyHost, proxyPassword string) router.ProxyDialFn {
@@ -97,7 +97,7 @@ func ServeHTTP(ln net.Listener, r *router.Router) {
defer rc.Close()
teeconn.Stop().Reread()
util.Relay(teeconn, rc)
relay.Relay(teeconn, rc)
log.Debug().
Str("host", req.Host).
Dur("spend", time.Since(start)).
@@ -134,7 +134,7 @@ func ServeHTTPS(ln net.Listener, r *router.Router) {
defer rc.Close()
teeconn.Stop().Reread()
util.Relay(teeconn, rc)
relay.Relay(teeconn, rc)
log.Debug().
Str("host", domain).
Dur("spend", time.Since(start)).
+7 -7
View File
@@ -9,12 +9,12 @@ import (
"time"
"github.com/cristalhq/aconfig"
"github.com/wweir/deferlog"
"github.com/wweir/deferlog/log"
"github.com/wweir/sower/pkg/teeconn"
"github.com/sower-proxy/conns/relay"
"github.com/sower-proxy/conns/teeconn"
"github.com/sower-proxy/deferlog"
"github.com/sower-proxy/deferlog/log"
"github.com/wweir/sower/transport/sower"
"github.com/wweir/sower/transport/trojan"
"github.com/wweir/sower/util"
"golang.org/x/crypto/acme/autocert"
)
@@ -124,7 +124,7 @@ func serve443(ln net.Listener, fakeSite string, sower *sower.Sower, trojan *troj
if addr, err = sower.Unwrap(teeconn); err == nil {
teeconn.Stop()
dur, err = util.RelayTo(teeconn, addr.String())
dur, err = relay.RelayTo(teeconn, addr.String())
return
}
@@ -133,11 +133,11 @@ func serve443(ln net.Listener, fakeSite string, sower *sower.Sower, trojan *troj
if addr, err = trojan.Unwrap(teeconn); err == nil {
teeconn.Stop()
dur, err = util.RelayTo(teeconn, addr.String())
dur, err = relay.RelayTo(teeconn, addr.String())
return
}
// 3. fallback to fake site
teeconn.Stop().Reread()
dur, err = util.RelayTo(teeconn, fakeSite)
dur, err = relay.RelayTo(teeconn, fakeSite)
}
+4 -2
View File
@@ -12,8 +12,9 @@ require (
github.com/miekg/dns v1.1.43
github.com/oschwald/geoip2-golang v1.5.0
github.com/pkg/errors v0.9.1
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6
github.com/wweir/deferlog v1.0.0
github.com/sower-proxy/conns v0.0.1
github.com/sower-proxy/deferlog v1.0.1
github.com/sower-proxy/mem v0.0.1
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e
)
@@ -22,6 +23,7 @@ require (
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/oschwald/maxminddb-golang v1.8.0 // indirect
github.com/rs/zerolog v1.26.0 // indirect
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6 // indirect
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
golang.org/x/text v0.3.6 // indirect
+6 -2
View File
@@ -33,14 +33,18 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE=
github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo=
github.com/sower-proxy/conns v0.0.1 h1:8tKWQR+nEEH0UBfFSz4M7HAhFFf/o9rQZ/6I0yWjXE8=
github.com/sower-proxy/conns v0.0.1/go.mod h1:jpifOR3jj9HFTE3wXd6sKdd778ZaRC/zoLKkdtvXNB8=
github.com/sower-proxy/deferlog v1.0.1 h1:ZRMpB3BOt0tpGiRIPKzg4/1kQ9UGZWgVM3sA1kAmW+c=
github.com/sower-proxy/deferlog v1.0.1/go.mod h1:wd8Yxz45ZbCgzXEafgDCj7XLlcqYUoEoLyiP1NQOUMk=
github.com/sower-proxy/mem v0.0.1 h1:z5Mde14Bf+NNP4wbZwQ1noMf5XzEmWH7o05FhfSJEWA=
github.com/sower-proxy/mem v0.0.1/go.mod h1:/VJ8gxzVmxqKrjSX41Ye0I9ynnueamcjhFIZGwe0/tg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6 h1:TtyC78WMafNW8QFfv3TeP3yWNDG+uxNkk9vOrnDu6JA=
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6/go.mod h1:h8272+G2omSmi30fBXiZDMkmHuOgonplfKIKjQWzlfs=
github.com/wweir/deferlog v1.0.0 h1:rARp+N6FGQeGiN9Ufoty8y8lBchldeOCgmEmPjIV8Ss=
github.com/wweir/deferlog v1.0.0/go.mod h1:MnYQMIry5XfHBVK/qh1TPMDd/YY4izq3OxboMFXdHrg=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-139
View File
@@ -1,139 +0,0 @@
package mem
import (
"errors"
"reflect"
"sync"
"time"
"github.com/ulule/deepcopier"
)
// Data define the type which can speed up by mem cache
type Data interface {
Fulfill(key string) (err error)
}
// Cache is the definition of cache, be careful of the memory usage
type Cache struct {
old *sync.Map
now *sync.Map
barrier *sync.Map
rotate <-chan time.Time
rwmutex *sync.RWMutex
}
// DefaultCache is default cache for surge
var DefaultCache = New(time.Minute)
// Remember is a surge, it provides a quite simple way to use cache
func Remember(dst Data, key string) error {
return DefaultCache.Remember(dst, key)
}
// Delete is a surge, it delete a specified data in DefaultCache
func Delete(dst Data, key string) {
DefaultCache.Delete(dst, key)
}
// New create a cache entity with a custom expiration time
func New(rotateInterval time.Duration) *Cache {
return &Cache{
old: &sync.Map{},
now: &sync.Map{},
barrier: &sync.Map{},
rotate: time.NewTicker(rotateInterval).C,
rwmutex: &sync.RWMutex{},
}
}
// Remember automatically save and retrieve data from a cache entity
func (c *Cache) Remember(dst Data, key string) error {
rv := reflect.ValueOf(dst)
if rv.Kind() != reflect.Ptr {
panic("invalid not pointor type: " + reflect.TypeOf(dst).Name())
} else if rv.IsNil() {
return errors.New("invalid nil pointor")
}
c.rwmutex.RLock()
defer c.rwmutex.RUnlock()
// rotate logic, rwlock just protect fields in Cache, but not field content.
// So that, write lock just take a very short time, and simple read lock is
// just an atomic action, do not care the performance
select {
case <-c.rotate:
c.old = c.now
c.now = &sync.Map{}
c.barrier = &sync.Map{}
default:
}
// First: load from cache
if val, ok := c.now.Load(key); ok {
return deepcopier.Copy(val).To(dst)
}
// Second: load from old cache, or waitting the sigle groutine getting data
ch := make(chan struct{})
if chVal, ok := c.barrier.LoadOrStore(key, ch); ok {
close(ch) // the ch is not used
if val, ok := c.old.Load(key); ok {
return deepcopier.Copy(val).To(dst)
}
// type chan: wait the sigle groutine getting data
// type error: already failed
if ch, ok = chVal.(chan struct{}); ok {
<-ch
if val, ok := c.now.Load(key); ok {
return deepcopier.Copy(val).To(dst)
}
}
val, _ := c.barrier.Load(key)
if err, ok := val.(error); ok {
return err
}
panic("new value lost, please report a bug")
}
// Third: getting data from CacheType, maybe from db
err := dst.Fulfill(key)
if err != nil {
c.barrier.Store(key, err)
return err
}
c.now.Store(key, dst)
close(ch) // broadcast, wakeup all waiting groutine
return nil
}
// Delete immediately specified the cached content to expire
func (c *Cache) Delete(dst Data, key string) {
c.rwmutex.Lock()
defer c.rwmutex.Unlock()
c.old.Delete(key)
c.now.Delete(key)
c.barrier.Store(key, errors.New(key+" is deleted"))
}
// Rotate force refresh cached data
func (c *Cache) Rotate(reset bool) {
c.rwmutex.Lock()
defer c.rwmutex.Unlock()
if reset {
c.old = &sync.Map{}
} else {
c.old = c.now
}
c.now = &sync.Map{}
c.barrier = &sync.Map{}
}
@@ -1,4 +1,4 @@
package util
package suffixtree
import (
"runtime"
@@ -1,9 +1,9 @@
package util_test
package suffixtree_test
import (
"testing"
"github.com/wweir/sower/util"
"github.com/wweir/sower/pkg/suffixtree"
)
func TestNode_Match(t *testing.T) {
@@ -13,18 +13,18 @@ func TestNode_Match(t *testing.T) {
}
tests := []struct {
name string
node *util.Node
node *suffixtree.Node
tests []test
}{{
"simple",
util.NewNodeFromRules("a.wweir.cc", "b.wweir.cc"),
suffixtree.NewNodeFromRules("a.wweir.cc", "b.wweir.cc"),
[]test{
{"a.wweir.cc", true},
{"b.wweir.cc", true},
},
}, {
"parent",
util.NewNodeFromRules("wweir.cc", "a.wweir.cc"),
suffixtree.NewNodeFromRules("wweir.cc", "a.wweir.cc"),
[]test{
{"wweir.cc", true},
{"a.wweir.cc", true},
@@ -32,7 +32,7 @@ func TestNode_Match(t *testing.T) {
},
}, {
"fuzz1",
util.NewNodeFromRules("wweir.cc", "a.wweir.cc", "*.wweir.cc"),
suffixtree.NewNodeFromRules("wweir.cc", "a.wweir.cc", "*.wweir.cc"),
[]test{
{"wweir.cc", true},
{"a.wweir.cc", true},
@@ -41,7 +41,7 @@ func TestNode_Match(t *testing.T) {
},
}, {
"fuzz2",
util.NewNodeFromRules("a.*.cc", "c.wweir.*"),
suffixtree.NewNodeFromRules("a.*.cc", "c.wweir.*"),
[]test{
{"wweir.cc", false},
{"a.wweir.cc", true},
@@ -50,7 +50,7 @@ func TestNode_Match(t *testing.T) {
},
}, {
"fuzz3",
util.NewNodeFromRules("*.*.cc", "iamp.*.*"),
suffixtree.NewNodeFromRules("*.*.cc", "iamp.*.*"),
[]test{
{"wweir.cc", false},
{"a.wweir.cc", true},
@@ -59,7 +59,7 @@ func TestNode_Match(t *testing.T) {
},
}, {
"fuzz4",
util.NewNodeFromRules("**.cc", "a.**.com", "**.wweir.*"),
suffixtree.NewNodeFromRules("**.cc", "a.**.com", "**.wweir.*"),
[]test{
{"wweir.cc", true},
{"a.wweir.cc", true},
-56
View File
@@ -1,56 +0,0 @@
package teeconn
import (
"io"
"net"
)
type Conn struct {
net.Conn
buf []byte
offset int
stop bool // read
err error
}
func New(c net.Conn) *Conn {
return &Conn{Conn: c}
}
func (t *Conn) Reread() {
t.offset = 0
}
func (t *Conn) Reset() {
t.buf = []byte{}
t.offset = 0
}
func (t *Conn) Stop() *Conn {
t.stop = true
return t
}
func (t *Conn) Read(b []byte) (n int, err error) {
length := len(t.buf) - t.offset
if length > 0 {
n = copy(b, t.buf[t.offset:])
t.offset += n
return n, t.err
}
n, t.err = t.Conn.Read(b)
if !t.stop {
t.buf = append(t.buf, b[:n]...)
t.offset += n
}
return n, t.err
}
func (t *Conn) Write(b []byte) (n int, err error) {
if t.stop {
return t.Conn.Write(b)
}
return 0, io.ErrShortWrite
}
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"net"
"time"
"github.com/wweir/deferlog/log"
"github.com/sower-proxy/deferlog/log"
)
func (r *Router) localSite(domain string) bool {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"time"
"github.com/miekg/dns"
"github.com/wweir/deferlog/log"
"github.com/sower-proxy/deferlog/log"
)
func (r *Router) ServeDNS(w dns.ResponseWriter, req *dns.Msg) {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"sync"
"time"
"github.com/wweir/deferlog/log"
"github.com/sower-proxy/deferlog/log"
)
var pingClient = http.Client{
+13 -12
View File
@@ -8,18 +8,19 @@ import (
"github.com/miekg/dns"
geoip2 "github.com/oschwald/geoip2-golang"
"github.com/pkg/errors"
"github.com/wweir/deferlog"
"github.com/wweir/deferlog/log"
"github.com/sower-proxy/conns/relay"
"github.com/sower-proxy/deferlog"
"github.com/sower-proxy/deferlog/log"
"github.com/sower-proxy/mem"
"github.com/wweir/sower/pkg/dhcp"
"github.com/wweir/sower/pkg/mem"
"github.com/wweir/sower/util"
"github.com/wweir/sower/pkg/suffixtree"
)
type ProxyDialFn func(network, host string, port uint16) (net.Conn, error)
type Router struct {
blockRule *util.Node
directRule *util.Node
proxyRule *util.Node
blockRule *suffixtree.Node
directRule *suffixtree.Node
proxyRule *suffixtree.Node
ProxyDial ProxyDialFn
accessCache *mem.Cache
@@ -57,13 +58,13 @@ func NewRouter(serveIP, fallbackDNS, mmdbFile string, proxyDial ProxyDialFn) *Ro
}
func (r *Router) SetBlockRules(blockList []string) {
r.blockRule = util.NewNodeFromRules(blockList...)
r.blockRule = suffixtree.NewNodeFromRules(blockList...)
}
func (r *Router) SetDirectRules(directList []string) {
r.directRule = util.NewNodeFromRules(directList...)
r.directRule = suffixtree.NewNodeFromRules(directList...)
}
func (r *Router) SetProxyRules(proxyList []string) {
r.proxyRule = util.NewNodeFromRules(proxyList...)
r.proxyRule = suffixtree.NewNodeFromRules(proxyList...)
}
func (r *Router) SetCountryCIDRs(directCIDRs []string) {
r.country.cidrs = make([]*net.IPNet, 0, len(directCIDRs))
@@ -139,11 +140,11 @@ func (r *Router) ProxyHandle(conn net.Conn, domain string, port uint16) error {
}
defer rc.Close()
util.Relay(conn, rc)
relay.Relay(conn, rc)
return nil
}
func (r *Router) DirectHandle(conn net.Conn, addr string) error {
dur, err := util.RelayTo(conn, addr)
dur, err := relay.RelayTo(conn, addr)
return errors.Wrapf(err, "spend (%s)", dur)
}
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"strings"
"testing"
"github.com/wweir/deferlog/log"
"github.com/wweir/sower/pkg/teeconn"
"github.com/sower-proxy/conns/teeconn"
"github.com/sower-proxy/deferlog/log"
"github.com/wweir/sower/transport/sower"
"github.com/wweir/sower/transport/trojan"
)
-50
View File
@@ -1,50 +0,0 @@
package util
import (
"io"
"net"
"sync"
"sync/atomic"
"time"
"github.com/pkg/errors"
)
func RelayTo(conn net.Conn, addr string) (dur time.Duration, err error) {
if _, _, err := net.SplitHostPort(addr); err != nil {
addr = net.JoinHostPort(addr, "80")
}
start := time.Now()
rc, err := net.DialTimeout("tcp", addr, 5*time.Second)
if err != nil {
return time.Since(start), errors.WithStack(err)
}
defer rc.Close()
Relay(conn, rc)
return time.Since(start), nil
}
func Relay(conn1, conn2 net.Conn) {
wg := &sync.WaitGroup{}
exitFlag := new(int32)
wg.Add(2)
go redirect(conn2, conn1, wg, exitFlag)
redirect(conn1, conn2, wg, exitFlag)
wg.Wait()
}
func redirect(dst, src net.Conn, wg *sync.WaitGroup, exitFlag *int32) {
// io.Copy(dst, io.TeeReader(src, os.Stdout))
io.Copy(dst, src)
if atomic.CompareAndSwapInt32(exitFlag, 0, 1) {
// wakeup blocked goroutine
now := time.Now()
src.SetDeadline(now)
dst.SetDeadline(now)
}
wg.Done()
}