diff --git a/uixt/ai/wings_service.go b/uixt/ai/wings_service.go index 9c0615ee..5dea7484 100644 --- a/uixt/ai/wings_service.go +++ b/uixt/ai/wings_service.go @@ -160,6 +160,7 @@ func (w *WingsService) Assert(ctx context.Context, opts *AssertOptions) (*Assert LogID: generateWingsUUID(), }, } + log.Info().Interface("apiRequest", apiRequest).Msg("Wings API request") // Call Wings API startTime := time.Now() @@ -419,7 +420,7 @@ func (w *WingsService) callWingsAPI(ctx context.Context, request WingsActionRequ // Execute HTTP request client := &http.Client{ - Timeout: 30 * time.Second, + Timeout: 60 * time.Second, } resp, err := client.Do(httpReq) diff --git a/uixt/driver_session.go b/uixt/driver_session.go index 66b83962..43bc1491 100644 --- a/uixt/driver_session.go +++ b/uixt/driver_session.go @@ -308,6 +308,9 @@ func (s *DriverSession) Request(method string, urlStr string, rawBody []byte, op } if err = rawResp.CheckErr(); err != nil { + if resp.StatusCode == http.StatusOK { + return rawResp, nil + } return nil, err } diff --git a/uixt/ios_device.go b/uixt/ios_device.go index fbd712df..484eec18 100644 --- a/uixt/ios_device.go +++ b/uixt/ios_device.go @@ -106,7 +106,10 @@ func NewIOSDevice(opts ...option.IOSDeviceOption) (device *IOSDevice, err error) device = &IOSDevice{ DeviceEntry: *iosDevice, 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") @@ -119,8 +122,12 @@ func NewIOSDevice(opts ...option.IOSDeviceOption) (device *IOSDevice, err error) type IOSDevice struct { ios.DeviceEntry - Options *option.IOSDeviceOptions - listeners map[int]*forward.ConnListener + Options *option.IOSDeviceOptions + // 键为remotePort,值为对应的listener和localPort + listeners map[int]struct { + listener *forward.ConnListener + localPort int + } } type DeviceDetail struct { @@ -197,8 +204,10 @@ func (dev *IOSDevice) IsHealthy() (bool, error) { } func (dev *IOSDevice) Teardown() error { - for _, listener := range dev.listeners { - _ = listener.Close() + for _, forwardInfo := range dev.listeners { + if forwardInfo.listener != nil { + _ = forwardInfo.listener.Close() + } } return nil } @@ -287,18 +296,37 @@ func (dev *IOSDevice) Uninstall(bundleId string) error { return nil } -func (dev *IOSDevice) Forward(localPort, remotePort int) error { - if dev.listeners[localPort] != nil { - log.Warn().Msg(fmt.Sprintf("local port :%d is already in use", localPort)) - _ = dev.listeners[localPort].Close() +func (dev *IOSDevice) Forward(remotePort int) (int, error) { + // 检查remotePort是否已经被转发 + if forwardInfo, exists := dev.listeners[remotePort]; exists && forwardInfo.listener != nil { + 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)) if err != nil { - log.Error().Err(err).Msg(fmt.Sprintf("failed to forward %d to %d", localPort, remotePort)) - return err + log.Error().Err(err).Msg(fmt.Sprintf("failed to forward local port :%d to remote port :%d", localPort, remotePort)) + 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) { diff --git a/uixt/ios_driver_wda.go b/uixt/ios_driver_wda.go index 724b1357..2358c3bc 100644 --- a/uixt/ios_driver_wda.go +++ b/uixt/ios_driver_wda.go @@ -13,7 +13,6 @@ import ( "os/exec" "path" "path/filepath" - "strconv" "strings" "syscall" "time" @@ -60,40 +59,22 @@ type WDADriver struct { } 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 { - localPort, err = builtin.GetFreePort() - if err != nil { - 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 0, errors.Wrap(code.DeviceHTTPDriverError, + fmt.Sprintf("forward tcp port failed: %v", err)) } return localPort, nil } 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 { - localMjpegPort, err = builtin.GetFreePort() - if err != nil { - 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") + return 0, errors.Wrap(code.DeviceHTTPDriverError, + fmt.Sprintf("forward tcp port failed: %v", err)) } + log.Info().Int("WDA_LOCAL_MJPEG_PORT", localMjpegPort). + Msg("reuse WDA local mjpeg port") return localMjpegPort, nil }