Fix Darwin USB/IP availability and doorbell handling
This commit is contained in:
@@ -882,15 +882,22 @@ func (c *darwinVirtualController) handleDoorbell(doorbell uint32) {
|
||||
c.logger.Debug("process doorbell: ", err)
|
||||
return
|
||||
}
|
||||
var previousNoResponse unsafe.Pointer
|
||||
for {
|
||||
transfer := endpoint.currentTransfer()
|
||||
if transfer.ptr == nil || !transfer.message.valid() {
|
||||
return
|
||||
}
|
||||
status, length := c.handleTransfer(key, transfer.message)
|
||||
if transfer.message.noResponse() {
|
||||
return
|
||||
if transfer.ptr == previousNoResponse {
|
||||
return
|
||||
}
|
||||
previousNoResponse = transfer.ptr
|
||||
c.handleTransfer(key, transfer.message)
|
||||
continue
|
||||
}
|
||||
previousNoResponse = nil
|
||||
status, length := c.handleTransfer(key, transfer.message)
|
||||
if err := endpoint.complete(transfer, darwinUSBIPStatusToCIStatus(status), length); err != nil {
|
||||
c.logger.Debug("complete transfer: ", err)
|
||||
c.Close()
|
||||
|
||||
@@ -205,8 +205,8 @@ func TestWaitDarwinControllerClosesOnContextCancel(t *testing.T) {
|
||||
}
|
||||
|
||||
type fakeDarwinEndpointStateMachine struct {
|
||||
transfer darwinCITransfer
|
||||
currentRead bool
|
||||
transfers []darwinCITransfer
|
||||
currentRead int
|
||||
completeCalled int
|
||||
}
|
||||
|
||||
@@ -221,11 +221,12 @@ func (f *fakeDarwinEndpointStateMachine) processDoorbell(uint32) error {
|
||||
}
|
||||
|
||||
func (f *fakeDarwinEndpointStateMachine) currentTransfer() darwinCITransfer {
|
||||
if f.currentRead {
|
||||
if f.currentRead >= len(f.transfers) {
|
||||
return darwinCITransfer{}
|
||||
}
|
||||
f.currentRead = true
|
||||
return f.transfer
|
||||
transfer := f.transfers[f.currentRead]
|
||||
f.currentRead++
|
||||
return transfer
|
||||
}
|
||||
|
||||
func (f *fakeDarwinEndpointStateMachine) complete(darwinCITransfer, int, int) error {
|
||||
@@ -242,10 +243,10 @@ func TestDarwinHandleDoorbellSkipsNoResponseCompletion(t *testing.T) {
|
||||
data0: (uint32(2) << 8) | 1,
|
||||
}
|
||||
endpoint := &fakeDarwinEndpointStateMachine{
|
||||
transfer: darwinCITransfer{
|
||||
transfers: []darwinCITransfer{{
|
||||
ptr: unsafe.Pointer(&message),
|
||||
message: message,
|
||||
},
|
||||
}},
|
||||
}
|
||||
controller.endpoints[darwinEndpointKey{device: 1, endpoint: 2}] = endpoint
|
||||
|
||||
@@ -253,6 +254,37 @@ func TestDarwinHandleDoorbellSkipsNoResponseCompletion(t *testing.T) {
|
||||
require.Zero(t, endpoint.completeCalled)
|
||||
}
|
||||
|
||||
func TestDarwinHandleDoorbellContinuesAfterNoResponseTransfer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
controller := newDarwinVirtualController(context.Background(), newTestLogger(), nil, DeviceInfoTruncated{})
|
||||
noResponseMessage := darwinCIMessage{
|
||||
control: (1 << 15) | (1 << 14) | 0x3c,
|
||||
data0: (uint32(2) << 8) | 1,
|
||||
}
|
||||
responseMessage := darwinCIMessage{
|
||||
control: (1 << 15) | 0x3c,
|
||||
data0: (uint32(2) << 8) | 1,
|
||||
}
|
||||
endpoint := &fakeDarwinEndpointStateMachine{
|
||||
transfers: []darwinCITransfer{
|
||||
{
|
||||
ptr: unsafe.Pointer(&noResponseMessage),
|
||||
message: noResponseMessage,
|
||||
},
|
||||
{
|
||||
ptr: unsafe.Pointer(&responseMessage),
|
||||
message: responseMessage,
|
||||
},
|
||||
},
|
||||
}
|
||||
controller.endpoints[darwinEndpointKey{device: 1, endpoint: 2}] = endpoint
|
||||
|
||||
controller.handleDoorbell((uint32(2) << 8) | 1)
|
||||
require.Equal(t, 1, endpoint.completeCalled)
|
||||
require.Equal(t, 2, endpoint.currentRead)
|
||||
}
|
||||
|
||||
func startDarwinFakeUSBIPServer(t *testing.T) *darwinFakeUSBIPServer {
|
||||
t.Helper()
|
||||
|
||||
|
||||
@@ -384,7 +384,12 @@ func (s *ServerService) handleImport(conn net.Conn) {
|
||||
_ = WriteOpRepImport(conn, OpStatusError, nil)
|
||||
return
|
||||
}
|
||||
defer s.releaseClaim(busid)
|
||||
releaseClaim := true
|
||||
defer func() {
|
||||
if releaseClaim {
|
||||
s.releaseClaim(busid)
|
||||
}
|
||||
}()
|
||||
info := export.entry.Info
|
||||
if err := WriteOpRepImport(conn, OpStatusOK, &info); err != nil {
|
||||
s.logger.Warn("reply import ", busid, ": ", err)
|
||||
@@ -395,6 +400,8 @@ func (s *ServerService) handleImport(conn net.Conn) {
|
||||
if err := session.serve(); err != nil && s.ctx.Err() == nil {
|
||||
s.logger.Debug("data session ", busid, ": ", err)
|
||||
}
|
||||
s.releaseClaim(busid)
|
||||
releaseClaim = false
|
||||
s.broadcastChanged()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user