Fix: update proxy config api
This commit is contained in:
parent
6c38fce2cb
commit
a0dd4ffddc
7 changed files with 109 additions and 124 deletions
|
@ -21,6 +21,22 @@ var (
|
|||
once sync.Once
|
||||
)
|
||||
|
||||
// General config
|
||||
type General struct {
|
||||
Port int
|
||||
SocksPort int
|
||||
AllowLan bool
|
||||
Mode Mode
|
||||
LogLevel C.LogLevel
|
||||
}
|
||||
|
||||
// ProxyConfig is update proxy schema
|
||||
type ProxyConfig struct {
|
||||
Port *int
|
||||
SocksPort *int
|
||||
AllowLan *bool
|
||||
}
|
||||
|
||||
// Config is clash config manager
|
||||
type Config struct {
|
||||
general *General
|
||||
|
@ -29,7 +45,7 @@ type Config struct {
|
|||
lastUpdate time.Time
|
||||
|
||||
event chan<- interface{}
|
||||
errCh chan interface{}
|
||||
reportCh chan interface{}
|
||||
observable *observable.Observable
|
||||
}
|
||||
|
||||
|
@ -45,9 +61,9 @@ func (c *Config) Subscribe() observable.Subscription {
|
|||
return sub
|
||||
}
|
||||
|
||||
// Report return a channel for collecting error message
|
||||
// Report return a channel for collecting report message
|
||||
func (c *Config) Report() chan<- interface{} {
|
||||
return c.errCh
|
||||
return c.reportCh
|
||||
}
|
||||
|
||||
func (c *Config) readConfig() (*ini.File, error) {
|
||||
|
@ -118,8 +134,8 @@ func (c *Config) UpdateRules() error {
|
|||
func (c *Config) parseGeneral(cfg *ini.File) error {
|
||||
general := cfg.Section("General")
|
||||
|
||||
port := general.Key("port").RangeInt(C.DefalutHTTPPort, 1, 65535)
|
||||
socksPort := general.Key("socks-port").RangeInt(C.DefalutSOCKSPort, 1, 65535)
|
||||
port := general.Key("port").RangeInt(0, 1, 65535)
|
||||
socksPort := general.Key("socks-port").RangeInt(0, 1, 65535)
|
||||
allowLan := general.Key("allow-lan").MustBool()
|
||||
logLevelString := general.Key("log-level").MustString(C.INFO.String())
|
||||
modeString := general.Key("mode").MustString(Rule.String())
|
||||
|
@ -135,11 +151,9 @@ func (c *Config) parseGeneral(cfg *ini.File) error {
|
|||
}
|
||||
|
||||
c.general = &General{
|
||||
Base: &Base{
|
||||
Port: &port,
|
||||
SocketPort: &socksPort,
|
||||
AllowLan: &allowLan,
|
||||
},
|
||||
Port: port,
|
||||
SocksPort: socksPort,
|
||||
AllowLan: allowLan,
|
||||
Mode: mode,
|
||||
LogLevel: logLevel,
|
||||
}
|
||||
|
@ -154,11 +168,32 @@ func (c *Config) parseGeneral(cfg *ini.File) error {
|
|||
|
||||
// UpdateGeneral dispatch update event
|
||||
func (c *Config) UpdateGeneral(general General) {
|
||||
c.event <- &Event{Type: "base", Payload: *general.Base}
|
||||
c.UpdateProxy(ProxyConfig{
|
||||
Port: &general.Port,
|
||||
SocksPort: &general.SocksPort,
|
||||
AllowLan: &general.AllowLan,
|
||||
})
|
||||
c.event <- &Event{Type: "mode", Payload: general.Mode}
|
||||
c.event <- &Event{Type: "log-level", Payload: general.LogLevel}
|
||||
}
|
||||
|
||||
// UpdateProxy dispatch update proxy event
|
||||
func (c *Config) UpdateProxy(pc ProxyConfig) {
|
||||
if pc.AllowLan != nil {
|
||||
c.general.AllowLan = *pc.AllowLan
|
||||
}
|
||||
|
||||
if (pc.AllowLan != nil || pc.Port != nil) && *pc.Port != 0 {
|
||||
c.general.Port = *pc.Port
|
||||
c.event <- &Event{Type: "http-addr", Payload: genAddr(*pc.Port, c.general.AllowLan)}
|
||||
}
|
||||
|
||||
if (pc.AllowLan != nil || pc.SocksPort != nil) && *pc.SocksPort != 0 {
|
||||
c.general.SocksPort = *pc.SocksPort
|
||||
c.event <- &Event{Type: "socks-addr", Payload: genAddr(*pc.SocksPort, c.general.AllowLan)}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) parseProxies(cfg *ini.File) error {
|
||||
proxies := make(map[string]C.Proxy)
|
||||
proxiesConfig := cfg.Section("Proxy")
|
||||
|
@ -270,18 +305,27 @@ func (c *Config) parseRules(cfg *ini.File) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) handleErrorMessage() {
|
||||
for elm := range c.errCh {
|
||||
event := elm.(Event)
|
||||
func (c *Config) handleResponseMessage() {
|
||||
for elm := range c.reportCh {
|
||||
event := elm.(*Event)
|
||||
switch event.Type {
|
||||
case "base":
|
||||
c.general.Base = event.Payload.(*Base)
|
||||
case "http-addr":
|
||||
if event.Payload.(bool) == false {
|
||||
c.general.Port = 0
|
||||
}
|
||||
break
|
||||
case "socks-addr":
|
||||
if event.Payload.(bool) == false {
|
||||
c.general.SocksPort = 0
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newConfig() *Config {
|
||||
event := make(chan interface{})
|
||||
reportCh := make(chan interface{})
|
||||
config := &Config{
|
||||
general: &General{},
|
||||
proxies: make(map[string]C.Proxy),
|
||||
|
@ -289,9 +333,10 @@ func newConfig() *Config {
|
|||
lastUpdate: time.Now(),
|
||||
|
||||
event: event,
|
||||
reportCh: reportCh,
|
||||
observable: observable.NewObservable(event),
|
||||
}
|
||||
go config.handleErrorMessage()
|
||||
go config.handleResponseMessage()
|
||||
return config
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
type General struct {
|
||||
*Base
|
||||
Mode Mode
|
||||
LogLevel C.LogLevel
|
||||
}
|
||||
|
||||
type Base struct {
|
||||
Port *int
|
||||
SocketPort *int
|
||||
AllowLan *bool
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -10,3 +11,10 @@ func trimArr(arr []string) (r []string) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
func genAddr(port int, allowLan bool) string {
|
||||
if allowLan {
|
||||
return fmt.Sprintf(":%d", port)
|
||||
}
|
||||
return fmt.Sprintf("127.0.0.1:%d", port)
|
||||
}
|
||||
|
|
|
@ -10,8 +10,6 @@ import (
|
|||
|
||||
const (
|
||||
Name = "clash"
|
||||
DefalutHTTPPort = 7890
|
||||
DefalutSOCKSPort = 7891
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
|
||||
"github.com/Dreamacro/clash/config"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/proxy"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/render"
|
||||
|
@ -21,7 +20,7 @@ func configRouter() http.Handler {
|
|||
|
||||
type configSchema struct {
|
||||
Port int `json:"port"`
|
||||
SocketPort int `json:"socket-port"`
|
||||
SocksPort int `json:"socket-port"`
|
||||
AllowLan bool `json:"allow-lan"`
|
||||
Mode string `json:"mode"`
|
||||
LogLevel string `json:"log-level"`
|
||||
|
@ -30,9 +29,9 @@ type configSchema struct {
|
|||
func getConfigs(w http.ResponseWriter, r *http.Request) {
|
||||
general := cfg.General()
|
||||
render.JSON(w, r, configSchema{
|
||||
Port: *general.Port,
|
||||
SocketPort: *general.SocketPort,
|
||||
AllowLan: *general.AllowLan,
|
||||
Port: general.Port,
|
||||
SocksPort: general.SocksPort,
|
||||
AllowLan: general.AllowLan,
|
||||
Mode: general.Mode.String(),
|
||||
LogLevel: general.LogLevel.String(),
|
||||
})
|
||||
|
@ -50,15 +49,7 @@ func updateConfigs(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// update errors
|
||||
var proxyErr, modeErr, logLevelErr error
|
||||
|
||||
// update proxy
|
||||
listener := proxy.Instance()
|
||||
proxyErr = listener.Update(&config.Base{
|
||||
AllowLan: general.AllowLan,
|
||||
Port: general.Port,
|
||||
SocketPort: general.SocksPort,
|
||||
})
|
||||
var modeErr, logLevelErr error
|
||||
|
||||
// update mode
|
||||
if general.Mode != nil {
|
||||
|
@ -81,7 +72,6 @@ func updateConfigs(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
hasError, errors := formatErrors(map[string]error{
|
||||
"proxy": proxyErr,
|
||||
"mode": modeErr,
|
||||
"log-level": logLevelErr,
|
||||
})
|
||||
|
@ -91,5 +81,13 @@ func updateConfigs(w http.ResponseWriter, r *http.Request) {
|
|||
render.JSON(w, r, errors)
|
||||
return
|
||||
}
|
||||
|
||||
// update proxy
|
||||
cfg.UpdateProxy(config.ProxyConfig{
|
||||
AllowLan: general.AllowLan,
|
||||
Port: general.Port,
|
||||
SocksPort: general.SocksPort,
|
||||
})
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ func newHub(signal chan struct{}) {
|
|||
r.Mount("/proxies", proxyRouter())
|
||||
r.Mount("/rules", ruleRouter())
|
||||
|
||||
log.Infof("RESTful API listening at: %s", addr)
|
||||
err := http.ListenAndServe(addr, r)
|
||||
if err != nil {
|
||||
log.Errorf("External controller error: %s", err.Error())
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package proxy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/Dreamacro/clash/config"
|
||||
|
@ -16,58 +15,12 @@ var (
|
|||
)
|
||||
|
||||
type Listener struct {
|
||||
httpPort int
|
||||
socksPort int
|
||||
allowLan bool
|
||||
|
||||
// signal for update
|
||||
httpSignal *C.ProxySignal
|
||||
socksSignal *C.ProxySignal
|
||||
}
|
||||
|
||||
// Info returns the proxies's current configuration
|
||||
func (l *Listener) Info() (info C.General) {
|
||||
return C.General{
|
||||
Port: &l.httpPort,
|
||||
SocksPort: &l.socksPort,
|
||||
AllowLan: &l.allowLan,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Listener) Update(base *config.Base) error {
|
||||
if base.AllowLan != nil {
|
||||
l.allowLan = *base.AllowLan
|
||||
}
|
||||
|
||||
var socksErr, httpErr error
|
||||
if base.AllowLan != nil || base.Port != nil {
|
||||
newHTTPPort := l.httpPort
|
||||
if base.Port != nil {
|
||||
newHTTPPort = *base.Port
|
||||
}
|
||||
httpErr = l.updateHTTP(newHTTPPort)
|
||||
}
|
||||
|
||||
if base.AllowLan != nil || base.SocketPort != nil {
|
||||
newSocksPort := l.socksPort
|
||||
if base.SocketPort != nil {
|
||||
newSocksPort = *base.SocketPort
|
||||
}
|
||||
socksErr = l.updateSocks(newSocksPort)
|
||||
}
|
||||
|
||||
if socksErr != nil && httpErr != nil {
|
||||
return fmt.Errorf("%s\n%s", socksErr.Error(), httpErr.Error())
|
||||
} else if socksErr != nil {
|
||||
return socksErr
|
||||
} else if httpErr != nil {
|
||||
return httpErr
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Listener) updateHTTP(port int) error {
|
||||
func (l *Listener) updateHTTP(addr string) error {
|
||||
if l.httpSignal != nil {
|
||||
signal := l.httpSignal
|
||||
signal.Done <- struct{}{}
|
||||
|
@ -75,17 +28,16 @@ func (l *Listener) updateHTTP(port int) error {
|
|||
l.httpSignal = nil
|
||||
}
|
||||
|
||||
signal, err := http.NewHttpProxy(l.genAddr(port))
|
||||
signal, err := http.NewHttpProxy(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
l.httpSignal = signal
|
||||
l.httpPort = port
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Listener) updateSocks(port int) error {
|
||||
func (l *Listener) updateSocks(addr string) error {
|
||||
if l.socksSignal != nil {
|
||||
signal := l.socksSignal
|
||||
signal.Done <- struct{}{}
|
||||
|
@ -93,32 +45,32 @@ func (l *Listener) updateSocks(port int) error {
|
|||
l.socksSignal = nil
|
||||
}
|
||||
|
||||
signal, err := socks.NewSocksProxy(l.genAddr(port))
|
||||
signal, err := socks.NewSocksProxy(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
l.socksSignal = signal
|
||||
l.socksPort = port
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Listener) genAddr(port int) string {
|
||||
host := "127.0.0.1"
|
||||
if l.allowLan {
|
||||
host = ""
|
||||
}
|
||||
return fmt.Sprintf("%s:%d", host, port)
|
||||
}
|
||||
|
||||
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)
|
||||
if event.Type == "base" {
|
||||
base := event.Payload.(config.Base)
|
||||
l.Update(&base)
|
||||
switch event.Type {
|
||||
case "http-addr":
|
||||
addr := event.Payload.(string)
|
||||
err := l.updateHTTP(addr)
|
||||
reportCH <- &config.Event{Type: "http-addr", Payload: err == nil}
|
||||
break
|
||||
case "socks-addr":
|
||||
addr := event.Payload.(string)
|
||||
err := l.updateSocks(addr)
|
||||
reportCH <- &config.Event{Type: "socks-addr", Payload: err == nil}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue