usbip: poll the devlist periodically in standard static mode
Against a plain usbipd (no control extension) the client synced the device list exactly once and then slept until shutdown: devices that changed busid on replug were never rediscovered, and in all-devices mode a worker that stopped had no path back. Refresh the devlist on an interval, re-probe the control extension every few minutes in case the server was upgraded, and warn that serial rules cannot match against servers whose listings carry no serial numbers.
This commit is contained in:
@@ -51,6 +51,17 @@ func (a *clientAssignment) Matched() bool {
|
||||
return len(a.targets) > 0
|
||||
}
|
||||
|
||||
// HasSerialTargets reports whether any match rule requires a serial
|
||||
// number. targets is immutable after construction.
|
||||
func (a *clientAssignment) HasSerialTargets() bool {
|
||||
for _, target := range a.targets {
|
||||
if target.match.Serial != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *clientAssignment) SetActive(busid string, active bool) {
|
||||
a.access.Lock()
|
||||
defer a.access.Unlock()
|
||||
|
||||
@@ -23,6 +23,13 @@ const (
|
||||
controlSessionIdleHint = "control session lost"
|
||||
controlHandshakeBackoffStart = time.Second
|
||||
controlHandshakeBackoffMax = 30 * time.Second
|
||||
|
||||
// Standard usbipd has no change notifications; poll the devlist so
|
||||
// replugged or re-enumerated devices are discovered, and re-probe
|
||||
// the control extension occasionally in case the server was
|
||||
// upgraded to sing-box.
|
||||
staticModeRefreshInterval = 15 * time.Second
|
||||
staticModeControlRetryInterval = 10 * time.Minute
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -115,12 +122,30 @@ func (c *ClientService) run() {
|
||||
}
|
||||
|
||||
func (c *ClientService) runStandardStaticMode() error {
|
||||
if c.assignment.HasSerialTargets() {
|
||||
c.logger.Warn("serial device matches cannot be evaluated against a standard usbipd server (its device list carries no serial numbers)")
|
||||
}
|
||||
err := c.syncRemoteStateContext(c.ctx)
|
||||
if err != nil {
|
||||
return E.Cause(err, "initial static devlist sync")
|
||||
}
|
||||
<-c.ctx.Done()
|
||||
return nil
|
||||
refresh := time.NewTicker(staticModeRefreshInterval)
|
||||
defer refresh.Stop()
|
||||
retryControl := time.NewTimer(staticModeControlRetryInterval)
|
||||
defer retryControl.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-c.ctx.Done():
|
||||
return nil
|
||||
case <-retryControl.C:
|
||||
return nil
|
||||
case <-refresh.C:
|
||||
err = c.syncRemoteStateContext(c.ctx)
|
||||
if err != nil && c.ctx.Err() == nil {
|
||||
c.logger.Debug("static devlist refresh: ", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ClientService) runControlSession() error {
|
||||
|
||||
Reference in New Issue
Block a user