added other dsconnect settings
This commit is contained in:
@@ -31,6 +31,7 @@ type Client struct {
|
||||
OnClientLeft func(msg *protocol.ClientLeft)
|
||||
OnRequestDevice func(targetClient, fromClient, busID, requestID string)
|
||||
OnReleaseDevice func(busID, fromClient string)
|
||||
OnForceRelease func(targetClient, fromClient, busID string)
|
||||
OnTunnelData func(tunnelID string, data []byte)
|
||||
|
||||
ctx context.Context
|
||||
@@ -255,6 +256,18 @@ func (c *Client) handleTextMessage(data []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
case protocol.MsgForceRelease:
|
||||
if c.OnForceRelease != nil {
|
||||
var msg struct {
|
||||
TargetClient string `json:"target_client"`
|
||||
FromClient string `json:"from_client"`
|
||||
BusID string `json:"bus_id"`
|
||||
}
|
||||
if json.Unmarshal(data, &msg) == nil {
|
||||
c.OnForceRelease(msg.TargetClient, msg.FromClient, msg.BusID)
|
||||
}
|
||||
}
|
||||
|
||||
case protocol.MsgReleaseDevice:
|
||||
if c.OnReleaseDevice != nil {
|
||||
var msg struct {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/duffy/usb-server/internal/config"
|
||||
"github.com/duffy/usb-server/internal/protocol"
|
||||
"github.com/duffy/usb-server/internal/usb"
|
||||
"github.com/duffy/usb-server/internal/usbip"
|
||||
@@ -16,6 +17,7 @@ import (
|
||||
// ShareManager handles sharing USB devices
|
||||
type ShareManager struct {
|
||||
client *Client
|
||||
cfg *config.Config
|
||||
mu sync.RWMutex
|
||||
devices []usb.Device
|
||||
active map[string]*activeShare // busID -> active share
|
||||
@@ -38,9 +40,10 @@ type shareTunnel struct {
|
||||
}
|
||||
|
||||
// NewShareManager creates a share manager
|
||||
func NewShareManager(client *Client) *ShareManager {
|
||||
func NewShareManager(client *Client, cfg *config.Config) *ShareManager {
|
||||
sm := &ShareManager{
|
||||
client: client,
|
||||
cfg: cfg,
|
||||
active: make(map[string]*activeShare),
|
||||
tunnels: make(map[string]*shareTunnel),
|
||||
}
|
||||
@@ -50,6 +53,7 @@ func NewShareManager(client *Client) *ShareManager {
|
||||
client.OnReleaseDevice = sm.handleReleaseDevice
|
||||
client.OnTunnelData = sm.handleTunnelData
|
||||
client.OnClientLeft = sm.handleClientLeft
|
||||
client.OnForceRelease = sm.handleForceRelease
|
||||
|
||||
return sm
|
||||
}
|
||||
@@ -129,10 +133,11 @@ func (sm *ShareManager) broadcastDeviceList() {
|
||||
}
|
||||
|
||||
msg := &protocol.DeviceList{
|
||||
Type: protocol.MsgDeviceList,
|
||||
ClientID: sm.client.ID(),
|
||||
ClientName: sm.client.Config().Name,
|
||||
Devices: protoDevices,
|
||||
Type: protocol.MsgDeviceList,
|
||||
ClientID: sm.client.ID(),
|
||||
ClientName: sm.client.Config().Name,
|
||||
Devices: protoDevices,
|
||||
AllowForceDetach: sm.cfg.AllowForceDetach,
|
||||
}
|
||||
|
||||
sm.client.SendJSON(msg)
|
||||
@@ -312,6 +317,24 @@ func (sm *ShareManager) handleReleaseDevice(busID, fromClient string) {
|
||||
sm.broadcastDeviceList()
|
||||
}
|
||||
|
||||
func (sm *ShareManager) handleForceRelease(targetClient, fromClient, busID string) {
|
||||
if !sm.cfg.AllowForceDetach {
|
||||
log.Printf("[share] force-release denied for %s (not allowed by config)", busID)
|
||||
return
|
||||
}
|
||||
|
||||
sm.mu.RLock()
|
||||
share, exists := sm.active[busID]
|
||||
sm.mu.RUnlock()
|
||||
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("[share] force-releasing %s (requested by %s, was used by %s)", busID, fromClient[:8], share.usedBy[:8])
|
||||
sm.handleReleaseDevice(busID, share.usedBy)
|
||||
}
|
||||
|
||||
func (sm *ShareManager) handleClientLeft(msg *protocol.ClientLeft) {
|
||||
sm.mu.RLock()
|
||||
var toRelease []string
|
||||
|
||||
+28
-8
@@ -33,10 +33,11 @@ type UseManager struct {
|
||||
cfg *config.Config
|
||||
cfgPath string
|
||||
mu sync.RWMutex
|
||||
available map[string][]RemoteDevice // clientID -> devices
|
||||
attached map[string]*AttachedDevice // busID@clientID -> attached info
|
||||
tunnels map[string]*useTunnel // tunnelID -> tunnel
|
||||
pending map[string]chan *protocol.DeviceGranted // requestID -> response channel
|
||||
available map[string][]RemoteDevice // clientID -> devices
|
||||
attached map[string]*AttachedDevice // busID@clientID -> attached info
|
||||
tunnels map[string]*useTunnel // tunnelID -> tunnel
|
||||
pending map[string]chan *protocol.DeviceGranted // requestID -> response channel
|
||||
forceDetachable map[string]bool // clientID -> allow_force_detach
|
||||
}
|
||||
|
||||
type useTunnel struct {
|
||||
@@ -53,10 +54,11 @@ func NewUseManager(client *Client, cfg *config.Config, cfgPath string) *UseManag
|
||||
client: client,
|
||||
cfg: cfg,
|
||||
cfgPath: cfgPath,
|
||||
available: make(map[string][]RemoteDevice),
|
||||
attached: make(map[string]*AttachedDevice),
|
||||
tunnels: make(map[string]*useTunnel),
|
||||
pending: make(map[string]chan *protocol.DeviceGranted),
|
||||
available: make(map[string][]RemoteDevice),
|
||||
attached: make(map[string]*AttachedDevice),
|
||||
tunnels: make(map[string]*useTunnel),
|
||||
pending: make(map[string]chan *protocol.DeviceGranted),
|
||||
forceDetachable: make(map[string]bool),
|
||||
}
|
||||
|
||||
client.OnDeviceList = um.handleDeviceList
|
||||
@@ -284,6 +286,7 @@ func (um *UseManager) handleDeviceList(msg *protocol.DeviceList) {
|
||||
})
|
||||
}
|
||||
um.available[msg.ClientID] = remoteDevs
|
||||
um.forceDetachable[msg.ClientID] = msg.AllowForceDetach
|
||||
|
||||
// Collect devices to auto-connect (while holding the lock to check attached map)
|
||||
var toAutoConnect []RemoteDevice
|
||||
@@ -382,6 +385,22 @@ func (um *UseManager) IsAutoConnect(vendorID, productID string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsForceDetachable checks if a share client allows force-detach
|
||||
func (um *UseManager) IsForceDetachable(clientID string) bool {
|
||||
um.mu.RLock()
|
||||
defer um.mu.RUnlock()
|
||||
return um.forceDetachable[clientID]
|
||||
}
|
||||
|
||||
// ForceDetachDevice sends a force-release request to the share client
|
||||
func (um *UseManager) ForceDetachDevice(clientID, busID string) error {
|
||||
return um.client.SendJSON(&protocol.ForceRelease{
|
||||
Type: protocol.MsgForceRelease,
|
||||
TargetClient: clientID,
|
||||
BusID: busID,
|
||||
})
|
||||
}
|
||||
|
||||
func (um *UseManager) handleDeviceGranted(msg *protocol.DeviceGranted) {
|
||||
um.mu.RLock()
|
||||
ch, exists := um.pending[msg.RequestID]
|
||||
@@ -430,6 +449,7 @@ func (um *UseManager) handleTunnelData(tunnelID string, data []byte) {
|
||||
func (um *UseManager) handleClientLeft(msg *protocol.ClientLeft) {
|
||||
um.mu.Lock()
|
||||
delete(um.available, msg.ClientID)
|
||||
delete(um.forceDetachable, msg.ClientID)
|
||||
|
||||
// Detach any devices from this client
|
||||
for key, dev := range um.attached {
|
||||
|
||||
Reference in New Issue
Block a user