Chore: improve code architecture
This commit is contained in:
@ -6,31 +6,25 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/Dreamacro/clash/adapters/inbound"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
"github.com/Dreamacro/clash/tunnel"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
tun = tunnel.Instance()
|
||||
)
|
||||
|
||||
func NewHttpProxy(addr string) (*C.ProxySignal, error) {
|
||||
func NewHttpProxy(addr string) (chan<- struct{}, <-chan struct{}, error) {
|
||||
l, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
done := make(chan struct{})
|
||||
closed := make(chan struct{})
|
||||
signal := &C.ProxySignal{
|
||||
Done: done,
|
||||
Closed: closed,
|
||||
}
|
||||
|
||||
go func() {
|
||||
log.Infof("HTTP proxy listening at: %s", addr)
|
||||
log.Infoln("HTTP proxy listening at: %s", addr)
|
||||
for {
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
@ -45,12 +39,11 @@ func NewHttpProxy(addr string) (*C.ProxySignal, error) {
|
||||
|
||||
go func() {
|
||||
<-done
|
||||
close(done)
|
||||
l.Close()
|
||||
closed <- struct{}{}
|
||||
}()
|
||||
|
||||
return signal, nil
|
||||
return done, closed, nil
|
||||
}
|
||||
|
||||
func handleConn(conn net.Conn) {
|
||||
|
@ -1,116 +1,166 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/Dreamacro/clash/config"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/proxy/http"
|
||||
"github.com/Dreamacro/clash/proxy/redir"
|
||||
"github.com/Dreamacro/clash/proxy/socks"
|
||||
)
|
||||
|
||||
var (
|
||||
listener *Listener
|
||||
once sync.Once
|
||||
allowLan = false
|
||||
|
||||
socksListener *listener
|
||||
httpListener *listener
|
||||
redirListener *listener
|
||||
)
|
||||
|
||||
type Listener struct {
|
||||
// signal for update
|
||||
httpSignal *C.ProxySignal
|
||||
socksSignal *C.ProxySignal
|
||||
redirSignal *C.ProxySignal
|
||||
type listener struct {
|
||||
Address string
|
||||
Done chan<- struct{}
|
||||
Closed <-chan struct{}
|
||||
}
|
||||
|
||||
func (l *Listener) updateHTTP(addr string) error {
|
||||
if l.httpSignal != nil {
|
||||
signal := l.httpSignal
|
||||
signal.Done <- struct{}{}
|
||||
<-signal.Closed
|
||||
l.httpSignal = nil
|
||||
}
|
||||
|
||||
signal, err := http.NewHttpProxy(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
l.httpSignal = signal
|
||||
return nil
|
||||
type Ports struct {
|
||||
Port int `json:"port"`
|
||||
SocksPort int `json:"socks-port"`
|
||||
RedirPort int `json:"redir-port"`
|
||||
}
|
||||
|
||||
func (l *Listener) updateSocks(addr string) error {
|
||||
if l.socksSignal != nil {
|
||||
signal := l.socksSignal
|
||||
signal.Done <- struct{}{}
|
||||
<-signal.Closed
|
||||
l.socksSignal = nil
|
||||
}
|
||||
|
||||
signal, err := socks.NewSocksProxy(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
l.socksSignal = signal
|
||||
return nil
|
||||
func AllowLan() bool {
|
||||
return allowLan
|
||||
}
|
||||
|
||||
func (l *Listener) updateRedir(addr string) error {
|
||||
if l.redirSignal != nil {
|
||||
signal := l.redirSignal
|
||||
signal.Done <- struct{}{}
|
||||
<-signal.Closed
|
||||
l.redirSignal = nil
|
||||
}
|
||||
|
||||
signal, err := redir.NewRedirProxy(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
l.redirSignal = signal
|
||||
return nil
|
||||
func SetAllowLan(al bool) {
|
||||
allowLan = al
|
||||
}
|
||||
|
||||
func (l *Listener) process(signal chan<- struct{}) {
|
||||
sub := config.Instance().Subscribe()
|
||||
signal <- struct{}{}
|
||||
reportCH := config.Instance().Report()
|
||||
for elm := range sub {
|
||||
event := elm.(*config.Event)
|
||||
switch event.Type {
|
||||
case "http-addr":
|
||||
addr := event.Payload.(string)
|
||||
err := l.updateHTTP(addr)
|
||||
reportCH <- &config.Event{Type: "http-addr", Payload: err == nil}
|
||||
case "socks-addr":
|
||||
addr := event.Payload.(string)
|
||||
err := l.updateSocks(addr)
|
||||
reportCH <- &config.Event{Type: "socks-addr", Payload: err == nil}
|
||||
case "redir-addr":
|
||||
addr := event.Payload.(string)
|
||||
err := l.updateRedir(addr)
|
||||
reportCH <- &config.Event{Type: "redir-addr", Payload: err == nil}
|
||||
func ReCreateHTTP(port int) error {
|
||||
addr := genAddr(port, allowLan)
|
||||
|
||||
if httpListener != nil {
|
||||
if httpListener.Address == addr {
|
||||
return nil
|
||||
}
|
||||
httpListener.Done <- struct{}{}
|
||||
<-httpListener.Closed
|
||||
httpListener = nil
|
||||
}
|
||||
|
||||
if portIsZero(addr) {
|
||||
return nil
|
||||
}
|
||||
|
||||
done, closed, err := http.NewHttpProxy(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
httpListener = &listener{
|
||||
Address: addr,
|
||||
Done: done,
|
||||
Closed: closed,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run ensure config monitoring
|
||||
func (l *Listener) Run() {
|
||||
signal := make(chan struct{})
|
||||
go l.process(signal)
|
||||
<-signal
|
||||
func ReCreateSocks(port int) error {
|
||||
addr := genAddr(port, allowLan)
|
||||
|
||||
if socksListener != nil {
|
||||
if socksListener.Address == addr {
|
||||
return nil
|
||||
}
|
||||
socksListener.Done <- struct{}{}
|
||||
<-socksListener.Closed
|
||||
socksListener = nil
|
||||
}
|
||||
|
||||
if portIsZero(addr) {
|
||||
return nil
|
||||
}
|
||||
|
||||
done, closed, err := socks.NewSocksProxy(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
socksListener = &listener{
|
||||
Address: addr,
|
||||
Done: done,
|
||||
Closed: closed,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newListener() *Listener {
|
||||
return &Listener{}
|
||||
func ReCreateRedir(port int) error {
|
||||
addr := genAddr(port, allowLan)
|
||||
|
||||
if redirListener != nil {
|
||||
if redirListener.Address == addr {
|
||||
return nil
|
||||
}
|
||||
redirListener.Done <- struct{}{}
|
||||
<-redirListener.Closed
|
||||
redirListener = nil
|
||||
}
|
||||
|
||||
if portIsZero(addr) {
|
||||
return nil
|
||||
}
|
||||
|
||||
done, closed, err := redir.NewRedirProxy(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
redirListener = &listener{
|
||||
Address: addr,
|
||||
Done: done,
|
||||
Closed: closed,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Instance return singleton instance of Listener
|
||||
func Instance() *Listener {
|
||||
once.Do(func() {
|
||||
listener = newListener()
|
||||
})
|
||||
return listener
|
||||
// GetPorts return the ports of proxy servers
|
||||
func GetPorts() *Ports {
|
||||
ports := &Ports{}
|
||||
|
||||
if httpListener != nil {
|
||||
_, portStr, _ := net.SplitHostPort(httpListener.Address)
|
||||
port, _ := strconv.Atoi(portStr)
|
||||
ports.Port = port
|
||||
}
|
||||
|
||||
if socksListener != nil {
|
||||
_, portStr, _ := net.SplitHostPort(socksListener.Address)
|
||||
port, _ := strconv.Atoi(portStr)
|
||||
ports.SocksPort = port
|
||||
}
|
||||
|
||||
if redirListener != nil {
|
||||
_, portStr, _ := net.SplitHostPort(redirListener.Address)
|
||||
port, _ := strconv.Atoi(portStr)
|
||||
ports.RedirPort = port
|
||||
}
|
||||
|
||||
return ports
|
||||
}
|
||||
|
||||
func portIsZero(addr string) bool {
|
||||
_, port, err := net.SplitHostPort(addr)
|
||||
if port == "0" || port == "" || err != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func genAddr(port int, allowLan bool) string {
|
||||
if allowLan {
|
||||
return fmt.Sprintf(":%d", port)
|
||||
}
|
||||
return fmt.Sprintf("127.0.0.1:%d", port)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"net"
|
||||
|
||||
"github.com/Dreamacro/clash/adapters/inbound"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/tunnel"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
@ -14,18 +13,14 @@ var (
|
||||
tun = tunnel.Instance()
|
||||
)
|
||||
|
||||
func NewRedirProxy(addr string) (*C.ProxySignal, error) {
|
||||
func NewRedirProxy(addr string) (chan<- struct{}, <-chan struct{}, error) {
|
||||
l, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
done := make(chan struct{})
|
||||
closed := make(chan struct{})
|
||||
signal := &C.ProxySignal{
|
||||
Done: done,
|
||||
Closed: closed,
|
||||
}
|
||||
|
||||
go func() {
|
||||
log.Infof("Redir proxy listening at: %s", addr)
|
||||
@ -43,12 +38,11 @@ func NewRedirProxy(addr string) (*C.ProxySignal, error) {
|
||||
|
||||
go func() {
|
||||
<-done
|
||||
close(done)
|
||||
l.Close()
|
||||
closed <- struct{}{}
|
||||
}()
|
||||
|
||||
return signal, nil
|
||||
return done, closed, nil
|
||||
}
|
||||
|
||||
func handleRedir(conn net.Conn) {
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"net"
|
||||
|
||||
"github.com/Dreamacro/clash/adapters/inbound"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/tunnel"
|
||||
|
||||
"github.com/Dreamacro/go-shadowsocks2/socks"
|
||||
@ -15,18 +14,14 @@ var (
|
||||
tun = tunnel.Instance()
|
||||
)
|
||||
|
||||
func NewSocksProxy(addr string) (*C.ProxySignal, error) {
|
||||
func NewSocksProxy(addr string) (chan<- struct{}, <-chan struct{}, error) {
|
||||
l, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
done := make(chan struct{})
|
||||
closed := make(chan struct{})
|
||||
signal := &C.ProxySignal{
|
||||
Done: done,
|
||||
Closed: closed,
|
||||
}
|
||||
|
||||
go func() {
|
||||
log.Infof("SOCKS proxy listening at: %s", addr)
|
||||
@ -44,12 +39,11 @@ func NewSocksProxy(addr string) (*C.ProxySignal, error) {
|
||||
|
||||
go func() {
|
||||
<-done
|
||||
close(done)
|
||||
l.Close()
|
||||
closed <- struct{}{}
|
||||
}()
|
||||
|
||||
return signal, nil
|
||||
return done, closed, nil
|
||||
}
|
||||
|
||||
func handleSocks(conn net.Conn) {
|
||||
|
Reference in New Issue
Block a user