router accepts services

This commit is contained in:
jebbs 2022-10-14 15:12:07 +08:00
parent 385475a6f6
commit 356ee6f8fa
8 changed files with 152 additions and 0 deletions

View File

@ -4,3 +4,9 @@ type Service interface {
Start() error
Close() error
}
type BoxService interface {
Service
Type() string
Tag() string
}

47
box.go
View File

@ -15,6 +15,7 @@ import (
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/outbound"
"github.com/sagernet/sing-box/route"
"github.com/sagernet/sing-box/service"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
@ -27,6 +28,7 @@ type Box struct {
router adapter.Router
inbounds []adapter.Inbound
outbounds []adapter.Outbound
services []adapter.BoxService
logFactory log.Factory
logger log.ContextLogger
logFile *os.File
@ -108,6 +110,7 @@ func New(ctx context.Context, options option.Options) (*Box, error) {
}
inbounds := make([]adapter.Inbound, 0, len(options.Inbounds))
outbounds := make([]adapter.Outbound, 0, len(options.Outbounds))
services := make([]adapter.BoxService, 0, len(options.Services))
for i, inboundOptions := range options.Inbounds {
var in adapter.Inbound
var tag string
@ -155,6 +158,34 @@ func New(ctx context.Context, options option.Options) (*Box, error) {
return nil, err
}
for i, serviceOptions := range options.Services {
var srv adapter.BoxService
var tag string
if serviceOptions.Tag != "" {
tag = serviceOptions.Tag
} else {
tag = F.ToString(i)
}
srv, err = service.New(
ctx,
router,
logFactory.NewLogger(F.ToString("service/", serviceOptions.Type, "[", tag, "]")),
serviceOptions)
if err != nil {
return nil, E.Cause(err, "parse outbound[", i, "]")
}
services = append(services, srv)
}
err = router.Initialize(inbounds, outbounds, func() adapter.Outbound {
out, oErr := outbound.New(ctx, router, logFactory.NewLogger("outbound/direct"), option.Outbound{Type: "direct", Tag: "default"})
common.Must(oErr)
outbounds = append(outbounds, out)
return out
})
if err != nil {
return nil, err
}
var clashServer adapter.ClashServer
var v2rayServer adapter.V2RayServer
if needClashAPI {
@ -175,6 +206,7 @@ func New(ctx context.Context, options option.Options) (*Box, error) {
router: router,
inbounds: inbounds,
outbounds: outbounds,
services: services,
createdAt: createdAt,
logFactory: logFactory,
logger: logFactory.Logger(),
@ -233,6 +265,18 @@ func (s *Box) start() error {
return E.Cause(err, "initialize inbound/", in.Type(), "[", tag, "]")
}
}
for i, srv := range s.services {
err = srv.Start()
if err != nil {
var tag string
if srv.Tag() == "" {
tag = F.ToString(i)
} else {
tag = srv.Tag()
}
return E.Cause(err, "initialize service/", srv.Type(), "[", tag, "]")
}
}
if s.clashServer != nil {
err = s.clashServer.Start()
if err != nil {
@ -262,6 +306,9 @@ func (s *Box) Close() error {
for _, out := range s.outbounds {
common.Close(out)
}
for _, srv := range s.services {
srv.Close()
}
return common.Close(
s.router,
s.logFactory,

5
constant/service.go Normal file
View File

@ -0,0 +1,5 @@
package constant
const (
ServiceSubscription = "subscription"
)

View File

@ -14,6 +14,7 @@ type _Options struct {
Inbounds []Inbound `json:"inbounds,omitempty"`
Outbounds []Outbound `json:"outbounds,omitempty"`
Route *RouteOptions `json:"route,omitempty"`
Services []Service `json:"services,omitempty"`
Experimental *ExperimentalOptions `json:"experimental,omitempty"`
}

45
option/service.go Normal file
View File

@ -0,0 +1,45 @@
package option
import (
"github.com/sagernet/sing-box/common/json"
C "github.com/sagernet/sing-box/constant"
E "github.com/sagernet/sing/common/exceptions"
)
type _Service struct {
Type string `json:"type"`
Tag string `json:"tag,omitempty"`
SubscriptionOptions SubscriptionServiceOptions `json:"-"`
}
type Service _Service
func (h Service) MarshalJSON() ([]byte, error) {
var v any
switch h.Type {
case C.ServiceSubscription:
v = h.SubscriptionOptions
default:
return nil, E.New("unknown service type: ", h.Type)
}
return MarshallObjects((_Service)(h), v)
}
func (h *Service) UnmarshalJSON(bytes []byte) error {
err := json.Unmarshal(bytes, (*_Service)(h))
if err != nil {
return err
}
var v any
switch h.Type {
case C.ServiceSubscription:
v = &h.SubscriptionOptions
default:
return E.New("unknown service type: ", h.Type)
}
err = UnmarshallExcluded(bytes, (*_Service)(h), v)
if err != nil {
return E.Cause(err, "service options")
}
return nil
}

14
option/subscription.go Normal file
View File

@ -0,0 +1,14 @@
package option
type SubscriptionServiceOptions struct {
Interval Duration `json:"interval,omitempty"`
Providers []SubscriptionProviderOptions `json:"providers"`
DialerOptions
}
type SubscriptionProviderOptions struct {
Tag string `json:"tag,omitempty"`
URL string `json:"url"`
Excludes []string `json:"excludes,omitempty"`
}

23
service/builder.go Normal file
View File

@ -0,0 +1,23 @@
package service
import (
"context"
"github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions"
)
func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.Service) (adapter.BoxService, error) {
if options.Type == "" {
return nil, E.New("missing service type")
}
switch options.Type {
case C.ServiceSubscription:
return NewSubscription(router, logger, options)
default:
return nil, E.New("unknown service type: ", options.Type)
}
}

11
service/subscription.go Normal file
View File

@ -0,0 +1,11 @@
package service
import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
)
func NewSubscription(router adapter.Router, logger log.ContextLogger, options option.Service) (adapter.BoxService, error) {
panic("not implemented")
}