feat: 优化ios forward链路

This commit is contained in:
余泓铮
2025-07-18 12:12:10 +08:00
parent d4dff22dd8
commit 984edf3f3c
2 changed files with 49 additions and 40 deletions
+41 -13
View File
@@ -106,7 +106,10 @@ func NewIOSDevice(opts ...option.IOSDeviceOption) (device *IOSDevice, err error)
device = &IOSDevice{ device = &IOSDevice{
DeviceEntry: *iosDevice, DeviceEntry: *iosDevice,
Options: deviceOptions, Options: deviceOptions,
listeners: make(map[int]*forward.ConnListener), listeners: make(map[int]struct {
listener *forward.ConnListener
localPort int
}),
} }
log.Info().Str("udid", device.Options.UDID).Msg("init ios device") log.Info().Str("udid", device.Options.UDID).Msg("init ios device")
@@ -119,8 +122,12 @@ func NewIOSDevice(opts ...option.IOSDeviceOption) (device *IOSDevice, err error)
type IOSDevice struct { type IOSDevice struct {
ios.DeviceEntry ios.DeviceEntry
Options *option.IOSDeviceOptions Options *option.IOSDeviceOptions
listeners map[int]*forward.ConnListener // 键为remotePort,值为对应的listener和localPort
listeners map[int]struct {
listener *forward.ConnListener
localPort int
}
} }
type DeviceDetail struct { type DeviceDetail struct {
@@ -197,8 +204,10 @@ func (dev *IOSDevice) IsHealthy() (bool, error) {
} }
func (dev *IOSDevice) Teardown() error { func (dev *IOSDevice) Teardown() error {
for _, listener := range dev.listeners { for _, forwardInfo := range dev.listeners {
_ = listener.Close() if forwardInfo.listener != nil {
_ = forwardInfo.listener.Close()
}
} }
return nil return nil
} }
@@ -287,18 +296,37 @@ func (dev *IOSDevice) Uninstall(bundleId string) error {
return nil return nil
} }
func (dev *IOSDevice) Forward(localPort, remotePort int) error { func (dev *IOSDevice) Forward(remotePort int) (int, error) {
if dev.listeners[localPort] != nil { // 检查remotePort是否已经被转发
log.Warn().Msg(fmt.Sprintf("local port :%d is already in use", localPort)) if forwardInfo, exists := dev.listeners[remotePort]; exists && forwardInfo.listener != nil {
_ = dev.listeners[localPort].Close() log.Info().Msg(fmt.Sprintf("remote port :%d is already forwarded to local port :%d", remotePort, forwardInfo.localPort))
return forwardInfo.localPort, nil
} }
// 获取一个空闲的本地端口
localPort, err := builtin.GetFreePort()
if err != nil {
log.Error().Err(err).Msg("failed to get free port")
return 0, err
}
listener, err := forward.Forward(dev.DeviceEntry, uint16(localPort), uint16(remotePort)) listener, err := forward.Forward(dev.DeviceEntry, uint16(localPort), uint16(remotePort))
if err != nil { if err != nil {
log.Error().Err(err).Msg(fmt.Sprintf("failed to forward %d to %d", localPort, remotePort)) log.Error().Err(err).Msg(fmt.Sprintf("failed to forward local port :%d to remote port :%d", localPort, remotePort))
return err return 0, err
} }
dev.listeners[localPort] = listener
return nil // 保存转发信息,以remotePort为键
dev.listeners[remotePort] = struct {
listener *forward.ConnListener
localPort int
}{
listener: listener,
localPort: localPort,
}
log.Info().Msg(fmt.Sprintf("forwarded local port :%d to remote port :%d", localPort, remotePort))
return localPort, nil
} }
func (dev *IOSDevice) GetDeviceInfo() (*DeviceDetail, error) { func (dev *IOSDevice) GetDeviceInfo() (*DeviceDetail, error) {
+8 -27
View File
@@ -13,7 +13,6 @@ import (
"os/exec" "os/exec"
"path" "path"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"syscall" "syscall"
"time" "time"
@@ -60,40 +59,22 @@ type WDADriver struct {
} }
func (wd *WDADriver) getLocalPort() (int, error) { func (wd *WDADriver) getLocalPort() (int, error) {
localPort, err := strconv.Atoi(os.Getenv("WDA_LOCAL_PORT")) localPort, err := wd.Device.Forward(wd.Device.Options.WDAPort)
if err != nil { if err != nil {
localPort, err = builtin.GetFreePort() return 0, errors.Wrap(code.DeviceHTTPDriverError,
if err != nil { fmt.Sprintf("forward tcp port failed: %v", err))
return 0, errors.Wrap(code.DeviceHTTPDriverError,
fmt.Sprintf("get free port failed: %v", err))
}
// forward local port to device
if err = wd.Device.Forward(localPort, wd.Device.Options.WDAPort); err != nil {
return 0, errors.Wrap(code.DeviceHTTPDriverError,
fmt.Sprintf("forward tcp port failed: %v", err))
}
} else {
log.Info().Int("WDA_LOCAL_PORT", localPort).Msg("reuse WDA local port")
} }
return localPort, nil return localPort, nil
} }
func (wd *WDADriver) getMjpegLocalPort() (int, error) { func (wd *WDADriver) getMjpegLocalPort() (int, error) {
localMjpegPort, err := strconv.Atoi(os.Getenv("WDA_LOCAL_MJPEG_PORT")) localMjpegPort, err := wd.Device.Forward(wd.Device.Options.WDAMjpegPort)
if err != nil { if err != nil {
localMjpegPort, err = builtin.GetFreePort() return 0, errors.Wrap(code.DeviceHTTPDriverError,
if err != nil { fmt.Sprintf("forward tcp port failed: %v", err))
return 0, errors.Wrap(code.DeviceHTTPDriverError,
fmt.Sprintf("get free port failed: %v", err))
}
if err = wd.Device.Forward(localMjpegPort, wd.Device.Options.WDAMjpegPort); err != nil {
return 0, errors.Wrap(code.DeviceHTTPDriverError,
fmt.Sprintf("forward tcp port failed: %v", err))
}
} else {
log.Info().Int("WDA_LOCAL_MJPEG_PORT", localMjpegPort).
Msg("reuse WDA local mjpeg port")
} }
log.Info().Int("WDA_LOCAL_MJPEG_PORT", localMjpegPort).
Msg("reuse WDA local mjpeg port")
return localMjpegPort, nil return localMjpegPort, nil
} }