diff --git a/api/config_router.go b/api/config_router.go new file mode 100644 index 0000000..6d0c624 --- /dev/null +++ b/api/config_router.go @@ -0,0 +1,169 @@ +package api + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/go-gost/x/config" + parser "github.com/go-gost/x/config/parsing/router" + "github.com/go-gost/x/registry" +) + +// swagger:parameters createRouterRequest +type createRouterRequest struct { + // in: body + Data config.RouterConfig `json:"data"` +} + +// successful operation. +// swagger:response createRouterResponse +type createRouterResponse struct { + Data Response +} + +func createRouter(ctx *gin.Context) { + // swagger:route POST /config/routers Router createRouterRequest + // + // Create a new router, the name of the router must be unique in router list. + // + // Security: + // basicAuth: [] + // + // Responses: + // 200: createRouterResponse + + var req createRouterRequest + ctx.ShouldBindJSON(&req.Data) + + if req.Data.Name == "" { + writeError(ctx, ErrInvalid) + return + } + + v := parser.ParseRouter(&req.Data) + + if err := registry.RouterRegistry().Register(req.Data.Name, v); err != nil { + writeError(ctx, ErrDup) + return + } + + config.OnUpdate(func(c *config.Config) error { + c.Routers = append(c.Routers, &req.Data) + return nil + }) + + ctx.JSON(http.StatusOK, Response{ + Msg: "OK", + }) +} + +// swagger:parameters updateRouterRequest +type updateRouterRequest struct { + // in: path + // required: true + Router string `uri:"router" json:"router"` + // in: body + Data config.RouterConfig `json:"data"` +} + +// successful operation. +// swagger:response updateRouterResponse +type updateRouterResponse struct { + Data Response +} + +func updateRouter(ctx *gin.Context) { + // swagger:route PUT /config/routers/{router} Router updateRouterRequest + // + // Update router by name, the router must already exist. + // + // Security: + // basicAuth: [] + // + // Responses: + // 200: updateRouterResponse + + var req updateRouterRequest + ctx.ShouldBindUri(&req) + ctx.ShouldBindJSON(&req.Data) + + if !registry.RouterRegistry().IsRegistered(req.Router) { + writeError(ctx, ErrNotFound) + return + } + + req.Data.Name = req.Router + + v := parser.ParseRouter(&req.Data) + + registry.RouterRegistry().Unregister(req.Router) + + if err := registry.RouterRegistry().Register(req.Router, v); err != nil { + writeError(ctx, ErrDup) + return + } + + config.OnUpdate(func(c *config.Config) error { + for i := range c.Routers { + if c.Routers[i].Name == req.Router { + c.Routers[i] = &req.Data + break + } + } + return nil + }) + + ctx.JSON(http.StatusOK, Response{ + Msg: "OK", + }) +} + +// swagger:parameters deleteRouterRequest +type deleteRouterRequest struct { + // in: path + // required: true + Router string `uri:"router" json:"router"` +} + +// successful operation. +// swagger:response deleteRouterResponse +type deleteRouterResponse struct { + Data Response +} + +func deleteRouter(ctx *gin.Context) { + // swagger:route DELETE /config/routers/{router} Router deleteRouterRequest + // + // Delete router by name. + // + // Security: + // basicAuth: [] + // + // Responses: + // 200: deleteRouterResponse + + var req deleteRouterRequest + ctx.ShouldBindUri(&req) + + if !registry.RouterRegistry().IsRegistered(req.Router) { + writeError(ctx, ErrNotFound) + return + } + registry.RouterRegistry().Unregister(req.Router) + + config.OnUpdate(func(c *config.Config) error { + routeres := c.Routers + c.Routers = nil + for _, s := range routeres { + if s.Name == req.Router { + continue + } + c.Routers = append(c.Routers, s) + } + return nil + }) + + ctx.JSON(http.StatusOK, Response{ + Msg: "OK", + }) +} diff --git a/api/service.go b/api/service.go index 6802179..089bb10 100644 --- a/api/service.go +++ b/api/service.go @@ -138,6 +138,10 @@ func registerConfig(config *gin.RouterGroup) { config.PUT("/ingresses/:ingress", updateIngress) config.DELETE("/ingresses/:ingress", deleteIngress) + config.POST("/routers", createRouter) + config.PUT("/routers/:router", updateRouter) + config.DELETE("/routers/:router", deleteRouter) + config.POST("/limiters", createLimiter) config.PUT("/limiters/:limiter", updateLimiter) config.DELETE("/limiters/:limiter", deleteLimiter) diff --git a/go.mod b/go.mod index fd4b58e..c1ce58f 100644 --- a/go.mod +++ b/go.mod @@ -7,10 +7,10 @@ require ( github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/gin-contrib/cors v1.3.1 github.com/gin-gonic/gin v1.9.1 - github.com/go-gost/core v0.0.0-20231119062035-6b01698ea9f4 + github.com/go-gost/core v0.0.0-20231119081403-abc73f2ca2b7 github.com/go-gost/gosocks4 v0.0.1 github.com/go-gost/gosocks5 v0.4.0 - github.com/go-gost/plugin v0.0.0-20231119062132-d959ab54847f + github.com/go-gost/plugin v0.0.0-20231119081435-96a9cabbf6b6 github.com/go-gost/relay v0.4.1-0.20230916134211-828f314ddfe7 github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 github.com/go-redis/redis/v8 v8.11.5 diff --git a/go.sum b/go.sum index 76dbb1a..6606588 100644 --- a/go.sum +++ b/go.sum @@ -95,12 +95,16 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gost/core v0.0.0-20231119062035-6b01698ea9f4 h1:dWj03ofZottHxRi6+oQ17CRgOr8qw/egg0cSpSSpQsk= github.com/go-gost/core v0.0.0-20231119062035-6b01698ea9f4/go.mod h1:ndkgWVYRLwupVaFFWv8ML1Nr8tD3xhHK245PLpUDg4E= +github.com/go-gost/core v0.0.0-20231119081403-abc73f2ca2b7 h1:fxVUlZANqPApygO7lT8bYySyajiCFA62bDiNorral1w= +github.com/go-gost/core v0.0.0-20231119081403-abc73f2ca2b7/go.mod h1:ndkgWVYRLwupVaFFWv8ML1Nr8tD3xhHK245PLpUDg4E= github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s= github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc= github.com/go-gost/gosocks5 v0.4.0 h1:EIrOEkpJez4gwHrMa33frA+hHXJyevjp47thpMQsJzI= github.com/go-gost/gosocks5 v0.4.0/go.mod h1:1G6I7HP7VFVxveGkoK8mnprnJqSqJjdcASKsdUn4Pp4= github.com/go-gost/plugin v0.0.0-20231119062132-d959ab54847f h1:V5m5plmwkIt16B251Eg2cK2UOJ1IRe4fNuWdTCqn8ek= github.com/go-gost/plugin v0.0.0-20231119062132-d959ab54847f/go.mod h1:qXr2Zm9Ex2ATqnWuNUzVZqySPMnuIihvblYZt4MlZLw= +github.com/go-gost/plugin v0.0.0-20231119081435-96a9cabbf6b6 h1:nkeo0TCEZVz74eZlVBDM6xiqDjS3DGWFRBOJ6kiDudU= +github.com/go-gost/plugin v0.0.0-20231119081435-96a9cabbf6b6/go.mod h1:qXr2Zm9Ex2ATqnWuNUzVZqySPMnuIihvblYZt4MlZLw= github.com/go-gost/relay v0.4.1-0.20230916134211-828f314ddfe7 h1:qAG1OyjvdA5h221CfFSS3J359V3d2E7dJWyP29QoDSI= github.com/go-gost/relay v0.4.1-0.20230916134211-828f314ddfe7/go.mod h1:lcX+23LCQ3khIeASBo+tJ/WbwXFO32/N5YN6ucuYTG8= github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 h1:xj8gUZGYO3nb5+6Bjw9+tsFkA9sYynrOvDvvC4uDV2I= diff --git a/registry/router.go b/registry/router.go index b007106..e8b4633 100644 --- a/registry/router.go +++ b/registry/router.go @@ -38,12 +38,3 @@ func (w *routerWrapper) GetRoute(ctx context.Context, dst net.IP, opts ...router } return v.GetRoute(ctx, dst, opts...) } - -func (w *routerWrapper) SetRoute(ctx context.Context, route *router.Route, opts ...router.Option) bool { - v := w.r.get(w.name) - if v == nil { - return false - } - - return v.SetRoute(ctx, route, opts...) -} diff --git a/router/plugin.go b/router/plugin.go index f5412f4..23c1268 100644 --- a/router/plugin.go +++ b/router/plugin.go @@ -1,7 +1,6 @@ package router import ( - "bytes" "context" "encoding/json" "io" @@ -64,22 +63,6 @@ func (p *grpcPlugin) GetRoute(ctx context.Context, dst net.IP, opts ...router.Op return ParseRoute(r.Net, r.Gateway) } -func (p *grpcPlugin) SetRoute(ctx context.Context, route *router.Route, opts ...router.Option) bool { - if p.client == nil || route == nil { - return false - } - - r, _ := p.client.SetRoute(ctx, &proto.SetRouteRequest{ - Net: route.Net.String(), - Gateway: route.Gateway.String(), - }) - if r == nil { - return false - } - - return r.Ok -} - func (p *grpcPlugin) Close() error { if closer, ok := p.conn.(io.Closer); ok { return closer.Close() @@ -96,15 +79,6 @@ type httpPluginGetRouteResponse struct { Gateway string `json:"gateway"` } -type httpPluginSetRouteRequest struct { - Net string `json:"net"` - Gateway string `json:"gateway"` -} - -type httpPluginSetRouteResponse struct { - OK bool `json:"ok"` -} - type httpPlugin struct { url string client *http.Client @@ -165,43 +139,3 @@ func (p *httpPlugin) GetRoute(ctx context.Context, dst net.IP, opts ...router.Op return ParseRoute(res.Net, res.Gateway) } - -func (p *httpPlugin) SetRoute(ctx context.Context, route *router.Route, opts ...router.Option) bool { - if p.client == nil || route == nil { - return false - } - - rb := httpPluginSetRouteRequest{ - Net: route.Net.String(), - Gateway: route.Gateway.String(), - } - v, err := json.Marshal(&rb) - if err != nil { - return false - } - - req, err := http.NewRequestWithContext(ctx, http.MethodPut, p.url, bytes.NewReader(v)) - if err != nil { - return false - } - - if p.header != nil { - req.Header = p.header.Clone() - } - req.Header.Set("Content-Type", "application/json") - resp, err := p.client.Do(req) - if err != nil { - return false - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return false - } - - res := httpPluginSetRouteResponse{} - if err := json.NewDecoder(resp.Body).Decode(&res); err != nil { - return false - } - return res.OK -} diff --git a/router/router.go b/router/router.go index a491ad4..50dc125 100644 --- a/router/router.go +++ b/router/router.go @@ -214,10 +214,6 @@ func (p *localRouter) GetRoute(ctx context.Context, dst net.IP, opts ...router.O return nil } -func (*localRouter) SetRoute(ctx context.Context, route *router.Route, opts ...router.Option) bool { - return false -} - func (*localRouter) parseLine(s string) (route *router.Route) { line := strings.Replace(s, "\t", " ", -1) line = strings.TrimSpace(line)