Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 9 additions & 13 deletions devices/ios.go
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ func (d *IOSDevice) PressButton(key string) error {
return d.deviceKitClient.PressButton(key)
}

func deviceWithRsdProvider(device goios.DeviceEntry, udid string, address string, rsdPort int) (goios.DeviceEntry, error) {
func deviceWithRsdProvider(device goios.DeviceEntry, address string, rsdPort int) (goios.DeviceEntry, error) {
rsdService, err := goios.NewWithAddrPortDevice(address, rsdPort, device)
if err != nil {
return goios.DeviceEntry{}, fmt.Errorf("could not connect to RSD: %w", err)
Expand All @@ -704,23 +704,19 @@ func deviceWithRsdProvider(device goios.DeviceEntry, udid string, address string
return goios.DeviceEntry{}, fmt.Errorf("RSD handshake failed: %w", err)
}

device1, err := goios.GetDeviceWithAddress(udid, address, rsdProvider)
if err != nil {
return goios.DeviceEntry{}, fmt.Errorf("error getting device with address: %w", err)
}
// keep the entry the caller picked (USB first); looking the UDID up again
// could hand back the Wi-Fi entry
device.Address = address
device.Rsd = rsdProvider

device1.UserspaceTUN = device.UserspaceTUN
device1.UserspaceTUNHost = device.UserspaceTUNHost
device1.UserspaceTUNPort = device.UserspaceTUNPort

return device1, nil
return device, nil
}

// getEnhancedDevice gets device info enhanced with tunnel/RSD information for iOS 17+
func (d *IOSDevice) getEnhancedDevice() (goios.DeviceEntry, error) {
const userspaceTunnelHost = "localhost"

device, err := goios.GetDevice(d.Udid)
device, err := ios.GetDevice(d.Udid)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
if err != nil {
return goios.DeviceEntry{}, fmt.Errorf("device not found: %s: %w", d.Udid, err)
}
Expand All @@ -733,7 +729,7 @@ func (d *IOSDevice) getEnhancedDevice() (goios.DeviceEntry, error) {
device.UserspaceTUNPort = tunnelInfo.UserspaceTUNPort
device.UserspaceTUNHost = userspaceTunnelHost
device.UserspaceTUN = tunnelInfo.UserspaceTUN
device, err = deviceWithRsdProvider(device, d.Udid, tunnelInfo.Address, tunnelInfo.RsdPort)
device, err = deviceWithRsdProvider(device, tunnelInfo.Address, tunnelInfo.RsdPort)
if err != nil {
utils.Verbose("failed to get device with RSD provider: %v", err)
}
Expand All @@ -745,7 +741,7 @@ func (d *IOSDevice) getEnhancedDevice() (goios.DeviceEntry, error) {
device.UserspaceTUNPort = info.UserspaceTUNPort
device.UserspaceTUNHost = userspaceTunnelHost
device.UserspaceTUN = info.UserspaceTUN
device, err = deviceWithRsdProvider(device, d.Udid, info.Address, info.RsdPort)
device, err = deviceWithRsdProvider(device, info.Address, info.RsdPort)
if err != nil {
utils.Verbose("failed to get device with RSD provider: %v", err)
}
Expand Down
44 changes: 44 additions & 0 deletions devices/ios/device.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package ios

import (
"fmt"

goios "github.com/danielpaulus/go-ios/ios"
)

const usbConnectionType = "USB"

// GetDevice looks up a device by UDID, preferring its USB entry. usbmuxd lists a device that is
// also paired over Wi-Fi twice, and go-ios returns whichever entry comes first. Service connections
// through the network entry can fail (usbmuxd error code 2), which breaks port forwarding to the
// on-device agent while the device is plugged in.
func GetDevice(udid string) (goios.DeviceEntry, error) {
list, err := goios.ListDevices()
if err != nil {
return goios.DeviceEntry{}, err
}

device, ok := pickDeviceEntry(list.DeviceList, udid)
if !ok {
return goios.DeviceEntry{}, fmt.Errorf("device '%s' not found, is it attached to the machine?", udid)
}
return device, nil
}

// pickDeviceEntry returns the entry for udid, taking the USB entry over a network one.
func pickDeviceEntry(entries []goios.DeviceEntry, udid string) (goios.DeviceEntry, bool) {
var found goios.DeviceEntry
ok := false
for _, entry := range entries {
if entry.Properties.SerialNumber != udid {
continue
}
if entry.Properties.ConnectionType == usbConnectionType {
return entry, true
}
if !ok {
found, ok = entry, true
}
}
return found, ok
}
45 changes: 45 additions & 0 deletions devices/ios/device_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ios

import (
"testing"

goios "github.com/danielpaulus/go-ios/ios"
)

func entry(id int, udid, connection string) goios.DeviceEntry {
return goios.DeviceEntry{
DeviceID: id,
Properties: goios.DeviceProperties{SerialNumber: udid, ConnectionType: connection},
}
}

func TestPickDeviceEntryPrefersUSB(t *testing.T) {
entries := []goios.DeviceEntry{
entry(8, "udid-1", "Network"),
entry(7, "udid-1", "USB"),
entry(2, "udid-2", "Network"),
}

got, ok := pickDeviceEntry(entries, "udid-1")
if !ok || got.DeviceID != 7 {
t.Fatalf("expected USB entry 7, got %d (found=%v)", got.DeviceID, ok)
}
}

func TestPickDeviceEntryFallsBackToNetwork(t *testing.T) {
entries := []goios.DeviceEntry{
entry(8, "udid-1", "USB"),
entry(2, "udid-2", "Network"),
}

got, ok := pickDeviceEntry(entries, "udid-2")
if !ok || got.DeviceID != 2 {
t.Fatalf("expected network entry 2, got %d (found=%v)", got.DeviceID, ok)
}
}

func TestPickDeviceEntryNotFound(t *testing.T) {
if _, ok := pickDeviceEntry([]goios.DeviceEntry{entry(1, "udid-1", "USB")}, "missing"); ok {
t.Fatal("expected no entry for unknown udid")
}
}
3 changes: 1 addition & 2 deletions devices/ios/port-forwarding.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"sync"

goios "github.com/danielpaulus/go-ios/ios"
"github.com/danielpaulus/go-ios/ios/forward"
"github.com/mobile-next/mobilecli/utils"
)
Expand Down Expand Up @@ -42,7 +41,7 @@ func (pf *PortForwarder) Forward(srcPort, dstPort int) error {
pf.srcPort = srcPort
pf.dstPort = dstPort

device, err := goios.GetDevice(pf.udid)
device, err := GetDevice(pf.udid)
if err != nil {
return fmt.Errorf("failed to get device %s: %w", pf.udid, err)
}
Expand Down
3 changes: 2 additions & 1 deletion devices/ios_webinspector.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"time"

goios "github.com/danielpaulus/go-ios/ios"
iosutil "github.com/mobile-next/mobilecli/devices/ios"
)

// Safari cannot take the injected agent: it is not a debuggable build. A device
Expand Down Expand Up @@ -58,7 +59,7 @@ type webInspectorDialer func() (io.ReadWriteCloser, error)

// dialDeviceWebInspector connects to the web inspector service of a real device.
func dialDeviceWebInspector(udid string) (io.ReadWriteCloser, error) {
device, err := goios.GetDevice(udid)
device, err := iosutil.GetDevice(udid)
if err != nil {
return nil, fmt.Errorf("device not found: %s: %w", udid, err)
}
Expand Down