mirror of
https://github.com/wyx2685/V2bX.git
synced 2026-02-04 04:30:08 +00:00
add singbox core(just started)
This commit is contained in:
263
core/sing/sing.go
Normal file
263
core/sing/sing.go
Normal file
@@ -0,0 +1,263 @@
|
||||
package sing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"github.com/Yuzuki616/V2bX/conf"
|
||||
vCore "github.com/Yuzuki616/V2bX/core"
|
||||
|
||||
"github.com/inazumav/sing-box/adapter"
|
||||
"github.com/inazumav/sing-box/inbound"
|
||||
"github.com/inazumav/sing-box/log"
|
||||
"github.com/inazumav/sing-box/option"
|
||||
"github.com/inazumav/sing-box/outbound"
|
||||
"github.com/inazumav/sing-box/route"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
)
|
||||
|
||||
var _ adapter.Service = (*Box)(nil)
|
||||
|
||||
type Box struct {
|
||||
createdAt time.Time
|
||||
router adapter.Router
|
||||
inbounds map[string]adapter.Inbound
|
||||
outbounds []adapter.Outbound
|
||||
logFactory log.Factory
|
||||
logger log.ContextLogger
|
||||
hookServer *HookServer
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
vCore.RegisterCore("sing", New)
|
||||
}
|
||||
|
||||
func New(_ *conf.CoreConfig) (vCore.Core, error) {
|
||||
options := option.Options{}
|
||||
ctx := context.Background()
|
||||
createdAt := time.Now()
|
||||
experimentalOptions := common.PtrValueOrDefault(options.Experimental)
|
||||
applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug))
|
||||
var defaultLogWriter io.Writer
|
||||
logFactory, err := log.New(log.Options{
|
||||
Context: ctx,
|
||||
Options: common.PtrValueOrDefault(options.Log),
|
||||
DefaultWriter: defaultLogWriter,
|
||||
BaseTime: createdAt,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create log factory")
|
||||
}
|
||||
router, err := route.NewRouter(
|
||||
ctx,
|
||||
logFactory,
|
||||
common.PtrValueOrDefault(options.Route),
|
||||
common.PtrValueOrDefault(options.DNS),
|
||||
common.PtrValueOrDefault(options.NTP),
|
||||
options.Inbounds,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse route options")
|
||||
}
|
||||
inbounds := make([]adapter.Inbound, len(options.Inbounds))
|
||||
inMap := make(map[string]adapter.Inbound, len(inbounds))
|
||||
outbounds := make([]adapter.Outbound, 0, len(options.Outbounds))
|
||||
for i, inboundOptions := range options.Inbounds {
|
||||
var in adapter.Inbound
|
||||
var tag string
|
||||
if inboundOptions.Tag != "" {
|
||||
tag = inboundOptions.Tag
|
||||
} else {
|
||||
tag = F.ToString(i)
|
||||
}
|
||||
in, err = inbound.New(
|
||||
ctx,
|
||||
router,
|
||||
logFactory.NewLogger(F.ToString("inbound/", inboundOptions.Type, "[", tag, "]")),
|
||||
inboundOptions,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse inbound[", i, "]")
|
||||
}
|
||||
inbounds[i] = in
|
||||
inMap[inboundOptions.Tag] = in
|
||||
}
|
||||
for i, outboundOptions := range options.Outbounds {
|
||||
var out adapter.Outbound
|
||||
var tag string
|
||||
if outboundOptions.Tag != "" {
|
||||
tag = outboundOptions.Tag
|
||||
} else {
|
||||
tag = F.ToString(i)
|
||||
}
|
||||
out, err = outbound.New(
|
||||
ctx,
|
||||
router,
|
||||
logFactory.NewLogger(F.ToString("outbound/", outboundOptions.Type, "[", tag, "]")),
|
||||
tag,
|
||||
outboundOptions)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse outbound[", i, "]")
|
||||
}
|
||||
outbounds = append(outbounds, out)
|
||||
}
|
||||
err = router.Initialize(inbounds, outbounds, func() adapter.Outbound {
|
||||
out, oErr := outbound.New(ctx, router, logFactory.NewLogger("outbound/direct"), "direct", option.Outbound{Type: "direct", Tag: "default"})
|
||||
common.Must(oErr)
|
||||
outbounds = append(outbounds, out)
|
||||
return out
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
server := NewHookServer(logFactory.NewLogger("Hook-Server"))
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create v2ray api server")
|
||||
}
|
||||
router.SetV2RayServer(server)
|
||||
return &Box{
|
||||
router: router,
|
||||
inbounds: inMap,
|
||||
outbounds: outbounds,
|
||||
createdAt: createdAt,
|
||||
logFactory: logFactory,
|
||||
logger: logFactory.Logger(),
|
||||
hookServer: server,
|
||||
done: make(chan struct{}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *Box) PreStart() error {
|
||||
err := b.preStart()
|
||||
if err != nil {
|
||||
// TODO: remove catch error
|
||||
defer func() {
|
||||
v := recover()
|
||||
if v != nil {
|
||||
log.Error(E.Cause(err, "origin error"))
|
||||
debug.PrintStack()
|
||||
panic("panic on early close: " + fmt.Sprint(v))
|
||||
}
|
||||
}()
|
||||
b.Close()
|
||||
return err
|
||||
}
|
||||
b.logger.Info("sing-box pre-started (", F.Seconds(time.Since(b.createdAt).Seconds()), "s)")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Box) Start() error {
|
||||
err := b.start()
|
||||
if err != nil {
|
||||
// TODO: remove catch error
|
||||
defer func() {
|
||||
v := recover()
|
||||
if v != nil {
|
||||
log.Error(E.Cause(err, "origin error"))
|
||||
debug.PrintStack()
|
||||
panic("panic on early close: " + fmt.Sprint(v))
|
||||
}
|
||||
}()
|
||||
b.Close()
|
||||
return err
|
||||
}
|
||||
b.logger.Info("sing-box started (", F.Seconds(time.Since(b.createdAt).Seconds()), "s)")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Box) preStart() error {
|
||||
err := b.startOutbounds()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.router.Start()
|
||||
}
|
||||
|
||||
func (b *Box) start() error {
|
||||
err := b.preStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i, in := range b.inbounds {
|
||||
var tag string
|
||||
if in.Tag() == "" {
|
||||
tag = F.ToString(i)
|
||||
} else {
|
||||
tag = in.Tag()
|
||||
}
|
||||
b.logger.Trace("initializing inbound/", in.Type(), "[", tag, "]")
|
||||
err = in.Start()
|
||||
if err != nil {
|
||||
return E.Cause(err, "initialize inbound/", in.Type(), "[", tag, "]")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Box) postStart() error {
|
||||
for serviceName, service := range b.outbounds {
|
||||
if lateService, isLateService := service.(adapter.PostStarter); isLateService {
|
||||
b.logger.Trace("post-starting ", service)
|
||||
err := lateService.PostStart()
|
||||
if err != nil {
|
||||
return E.Cause(err, "post-start ", serviceName)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Box) Close() error {
|
||||
select {
|
||||
case <-b.done:
|
||||
return os.ErrClosed
|
||||
default:
|
||||
close(b.done)
|
||||
}
|
||||
var errors error
|
||||
for i, in := range b.inbounds {
|
||||
b.logger.Trace("closing inbound/", in.Type(), "[", i, "]")
|
||||
errors = E.Append(errors, in.Close(), func(err error) error {
|
||||
return E.Cause(err, "close inbound/", in.Type(), "[", i, "]")
|
||||
})
|
||||
}
|
||||
for i, out := range b.outbounds {
|
||||
b.logger.Trace("closing outbound/", out.Type(), "[", i, "]")
|
||||
errors = E.Append(errors, common.Close(out), func(err error) error {
|
||||
return E.Cause(err, "close outbound/", out.Type(), "[", i, "]")
|
||||
})
|
||||
}
|
||||
b.logger.Trace("closing router")
|
||||
if err := common.Close(b.router); err != nil {
|
||||
errors = E.Append(errors, err, func(err error) error {
|
||||
return E.Cause(err, "close router")
|
||||
})
|
||||
}
|
||||
b.logger.Trace("closing log factory")
|
||||
if err := common.Close(b.logFactory); err != nil {
|
||||
errors = E.Append(errors, err, func(err error) error {
|
||||
return E.Cause(err, "close log factory")
|
||||
})
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
func (b *Box) Router() adapter.Router {
|
||||
return b.router
|
||||
}
|
||||
|
||||
func (b *Box) Protocols() []string {
|
||||
return []string{
|
||||
"v2ray",
|
||||
"shadowsocks",
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user