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