sing-box/service/usbip/server.go
2026-06-25 17:39:07 +08:00

107 lines
2.9 KiB
Go

//go:build with_usbip && (linux || (darwin && cgo) || windows)
package usbip
import (
"context"
"net"
"github.com/sagernet/sing-box/adapter"
boxService "github.com/sagernet/sing-box/adapter/service"
"github.com/sagernet/sing-box/common/listener"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-usbip"
E "github.com/sagernet/sing/common/exceptions"
N "github.com/sagernet/sing/common/network"
)
type ServerService struct {
boxService.Adapter
ctx context.Context
logger log.ContextLogger
inner *usbip.ServerService
}
type dynamicServerService struct {
ServerService
host *usbip.DynamicHost
}
var _ adapter.USBIPDynamicServer = (*dynamicServerService)(nil)
func NewServerService(ctx context.Context, logger log.ContextLogger, tag string, options option.USBIPServerServiceOptions) (adapter.Service, error) {
listenOptions := options.ListenOptions
if listenOptions.ListenPort == 0 {
listenOptions.ListenPort = usbip.DefaultPort
}
boxListener := listener.New(listener.Options{
Context: ctx,
Logger: logger,
Network: []string{N.NetworkTCP},
Listen: listenOptions,
})
serverOptions := usbip.ServerOptions{
Logger: logger,
Listen: func(context.Context) (net.Listener, error) {
return boxListener.ListenTCP()
},
}
base := ServerService{
Adapter: boxService.NewAdapter(C.TypeUSBIPServer, tag),
ctx: ctx,
logger: logger,
}
providerType := options.Provider
if providerType == "" {
providerType = option.USBIPProviderDefault
}
switch providerType {
case option.USBIPProviderDefault:
defaultOptions, isDefault := options.Options.(*option.USBIPDefaultProviderOptions)
if isDefault {
serverOptions.Devices = toDeviceMatches(defaultOptions.Devices)
}
inner, err := usbip.NewServerService(ctx, serverOptions)
if err != nil {
return nil, err
}
base.inner = inner
return &base, nil
case option.USBIPProviderDynamic:
host := usbip.NewDynamicHost(logger)
inner, err := usbip.NewDynamicServerService(ctx, serverOptions, host)
if err != nil {
return nil, err
}
base.inner = inner
return &dynamicServerService{ServerService: base, host: host}, nil
default:
return nil, E.New("unknown usbip provider type: ", providerType)
}
}
func (s *ServerService) Start(stage adapter.StartStage) error {
if stage != adapter.StartStateStart {
return nil
}
return s.inner.Start()
}
func (s *ServerService) Close() error {
return s.inner.Close()
}
func (s *dynamicServerService) AddDevice(info usbip.ProvidedDeviceInfo, transport usbip.DeviceTransport) (string, error) {
return s.host.AddDevice(info, transport)
}
func (s *dynamicServerService) RemoveDevice(busID string) {
s.host.RemoveDevice(busID)
}
func (s *dynamicServerService) SubscribeDevices(ctx context.Context, listener func([]usbip.ControlDeviceInfo)) {
s.inner.SubscribeDevices(ctx, listener)
}