From 3de42ec13a5cbf83dbb6e6ace2d47d5d02f4bf04 Mon Sep 17 00:00:00 2001
From: ZhouYixun <291028775@qq.com>
Date: Mon, 28 Nov 2022 00:00:58 +0800
Subject: [PATCH] fix: rm issue
---
device.go | 242 +++++++++++++++++++++-
device_test.go | 80 +++++++
idevice.go | 2 +
pkg/libimobiledevice/client_dtxmessage.go | 1 -
pkg/libimobiledevice/usbmux.go | 35 +++-
pkg/libimobiledevice/webinspector.go | 17 ++
usbmux.go | 4 +-
7 files changed, 371 insertions(+), 10 deletions(-)
diff --git a/device.go b/device.go
index 201a5c1..f15103b 100644
--- a/device.go
+++ b/device.go
@@ -1,10 +1,31 @@
+/*
+ * sonic-gidevice Connect to your iOS Devices.
+ * Copyright (C) 2022 SonicCloudOrg
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package giDevice
import (
"bytes"
"context"
+ "encoding/binary"
"errors"
"fmt"
+ "io"
+ "log"
+ "net"
"os"
"path"
"strings"
@@ -28,7 +49,40 @@ func newDevice(client *libimobiledevice.UsbmuxClient, properties DevicePropertie
}
}
+func NewRemoteConnect(ip string, port int) *device {
+ client, err := libimobiledevice.NewUsbmuxClient(fmt.Sprintf("%s:%d", ip, port))
+ if err != nil {
+ log.Panic(err)
+ }
+
+ clientConnectInit(client.InnerConn())
+
+ devicePropertiesPacket, err := client.ReceivePacket()
+ if err != nil {
+ log.Panic(err)
+ }
+ var properties = &DeviceProperties{}
+ err = devicePropertiesPacket.Unmarshal(properties)
+ if err != nil {
+ log.Panic(err)
+ }
+ buffer := new(bytes.Buffer)
+ data, err1 := client.InnerConn().Read(4)
+ if err1 != nil {
+ log.Panic(err1)
+ }
+ buffer.Write(data)
+ var remoteLockdownPort uint32
+ if err = binary.Read(buffer, binary.LittleEndian, &remoteLockdownPort); err != nil {
+ log.Panic(err)
+ }
+ dev := newDevice(client, *properties)
+ dev.remoteAddr = fmt.Sprintf("%s:%d", ip, remoteLockdownPort)
+ return dev
+}
+
type device struct {
+ remoteAddr string
umClient *libimobiledevice.UsbmuxClient
lockdownClient *libimobiledevice.LockdownClient
@@ -56,11 +110,16 @@ func (d *device) Properties() DeviceProperties {
}
func (d *device) NewConnect(port int, timeout ...time.Duration) (InnerConn, error) {
- newClient, err := libimobiledevice.NewUsbmuxClient(timeout...)
+
+ newClient, err := libimobiledevice.NewUsbmuxClient(d.remoteAddr, timeout...)
if err != nil {
return nil, err
}
+ if d.remoteAddr != "" {
+ clientConnectInit(newClient.InnerConn())
+ }
+
var pkt libimobiledevice.Packet
if pkt, err = newClient.NewPlistPacket(
newClient.NewConnectRequest(d.properties.DeviceID, port),
@@ -381,6 +440,105 @@ func (d *device) testmanagerdService() (testmanagerd Testmanagerd, err error) {
return
}
+func (d *device) Share(port int) error {
+
+ ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
+ if err != nil {
+ return err
+ }
+ address, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:0", "0.0.0.0"))
+ if err != nil {
+ return err
+ }
+
+ lockdownLn, err := net.ListenTCP("tcp", address)
+ if err != nil {
+ return err
+ }
+ go func() {
+ err = d.shareBaseTcpServer(ln, lockdownLn.Addr().(*net.TCPAddr).Port)
+ if err != nil {
+ log.Panic(err)
+ }
+ }()
+
+ return d.shareServer(lockdownLn)
+}
+
+func (d *device) shareBaseTcpServer(ln net.Listener, serverPort int) error {
+ defer ln.Close()
+ for {
+ conn, err := ln.Accept()
+ if err != nil {
+ return err
+ }
+ remoteAddress := conn.RemoteAddr().String()
+ if debugFlag {
+ log.Printf("Incomming base request from: %v\n", remoteAddress)
+ }
+
+ var remoteUsb = libimobiledevice.NewRemoteUsbmuxConn(conn)
+ localUsb, err := libimobiledevice.NewUsbmuxClient("", 0)
+ if err != nil {
+ log.Panic(err)
+ }
+
+ if !serverCheckInit(remoteUsb.InnerConn()) {
+ continue
+ }
+
+ propertiesPacket, err := remoteUsb.NewPlistPacket(d.properties)
+ if err != nil {
+ log.Panic(err)
+ }
+ err = remoteUsb.SendPacket(propertiesPacket)
+ if err != nil {
+ log.Panic(err)
+ }
+
+ buf := new(bytes.Buffer)
+ b := make([]byte, 4)
+ binary.LittleEndian.PutUint32(b, uint32(serverPort))
+ buf.Write(b)
+ _, err = conn.Write(buf.Bytes())
+ if err != nil {
+ log.Panic(err)
+ }
+ forwardingData(conn, localUsb.RawConn())
+ }
+}
+
+func (d *device) shareServer(ln net.Listener) error {
+ defer ln.Close()
+ for {
+ conn, err := ln.Accept()
+ if err != nil {
+ return err
+ }
+ remoteAddress := conn.RemoteAddr().String()
+
+ var remoteUsb = libimobiledevice.NewRemoteUsbmuxConn(conn)
+
+ if !serverCheckInit(remoteUsb.InnerConn()) {
+ remoteUsb.Close()
+ continue
+ }
+
+ if debugFlag {
+ log.Printf("Incomming server request from: %v\n", remoteAddress)
+ }
+
+ newClient, err := libimobiledevice.NewUsbmuxClient("", 0)
+ if err != nil {
+ log.Panic(err)
+ }
+
+ rConn := newClient.RawConn()
+ rConn.SetDeadline(time.Time{})
+ forwardingData(conn, rConn)
+ }
+}
+
func (d *device) AfcService() (afc Afc, err error) {
if d.afc != nil {
return d.afc, nil
@@ -887,7 +1045,6 @@ func (d *device) XCTest(bundleID string, opts ...XCTestOption) (out <-chan strin
return _out, cancelFunc, err
}
- // see https://github.com/SonicCloudOrg/sonic-gidevice/issues/31
// if err = d.instruments.startObserving(pid); err != nil {
// return _out, cancelFunc, err
// }
@@ -972,3 +1129,84 @@ func (d *device) _uploadXCTestConfiguration(bundleID string, sessionId uuid.UUID
return
}
+
+func serverCheckInit(conn InnerConn) bool {
+ if !checkRecvMagic(conn, true) {
+ conn.Close()
+ return false
+ }
+
+ buf := new(bytes.Buffer)
+ b := make([]byte, 4)
+ binary.LittleEndian.PutUint32(b, uint32(5))
+ buf.Write(b)
+ buf.Write(checkMagic[6:])
+
+ err := conn.Write(buf.Bytes())
+ if err != nil {
+ log.Panic(err)
+ }
+ return true
+}
+
+func clientConnectInit(conn InnerConn) {
+ buf := new(bytes.Buffer)
+ b := make([]byte, 4)
+
+ binary.LittleEndian.PutUint32(b, uint32(6))
+ buf.Write(b)
+ buf.Write(checkMagic[:6])
+
+ err := conn.Write(buf.Bytes())
+ if err != nil {
+ log.Panic(err)
+ }
+ if !checkRecvMagic(conn, false) {
+ conn.Close()
+ log.Panic("connection failed non remote sib connection")
+ }
+}
+
+func forwardingData(lConn, rConn net.Conn) {
+ go func(lConn, rConn net.Conn) {
+ if _, err := io.Copy(lConn, rConn); err != nil {
+ lConn.Close()
+ rConn.Close()
+ if debugFlag {
+ log.Println(err)
+ }
+ return
+ }
+ }(lConn, rConn)
+ go func(lConn, rConn net.Conn) {
+ if _, err := io.Copy(rConn, lConn); err != nil {
+ lConn.Close()
+ rConn.Close()
+ if debugFlag {
+ log.Println(err)
+ }
+ return
+ }
+ }(lConn, rConn)
+}
+
+// the connection is of the specified type
+var checkMagic = [11]byte{0x61, 0x4F, 0x47, 0x32, 0x77, 0x6F, 0x53, 0x45, 0x45, 0x73, 0x2F}
+
+func checkRecvMagic(conn InnerConn, isPrefix bool) bool {
+ data, err := conn.Read(4)
+ if err != nil {
+ log.Panic(err)
+ }
+ data, err = conn.Read(int(binary.LittleEndian.Uint32(data)))
+ if err != nil {
+ log.Panic(err)
+ }
+ var subMagic []byte
+ if isPrefix {
+ subMagic = checkMagic[:6]
+ } else {
+ subMagic = checkMagic[6:]
+ }
+ return bytes.Equal(subMagic, data)
+}
diff --git a/device_test.go b/device_test.go
index 00de1fc..c403550 100644
--- a/device_test.go
+++ b/device_test.go
@@ -2,6 +2,7 @@ package giDevice
import (
"fmt"
+ "log"
"os"
"os/signal"
"testing"
@@ -172,3 +173,82 @@ func Test_device_InstallationProxyBrowse(t *testing.T) {
t.Logf("%#v", l)
}
}
+
+func Test_device_share(t *testing.T) {
+ setupDevice(t)
+ SetDebug(true, true)
+ err := dev.Share(9123)
+ if err != nil {
+ log.Panic(err)
+ }
+}
+
+func Test_device_connect(t *testing.T) {
+ SetDebug(true, true)
+ remoteDev := NewRemoteConnect("127.0.0.1", 9123)
+ data, err := remoteDev.GetValue("", "ProductVersion")
+ if err != nil {
+ log.Panic(err)
+ }
+ log.Println(data)
+}
+
+func TestMockPerfdUser1(t *testing.T) {
+ //SetDebug(true, true)
+ remoteDev := NewRemoteConnect("127.0.0.1", 9123)
+ data, err := remoteDev.PerfStart(
+ WithPerfSystemCPU(true),
+ WithPerfSystemMem(true),
+ WithPerfSystemDisk(true),
+ WithPerfSystemNetwork(true),
+ WithPerfNetwork(true),
+ WithPerfFPS(true),
+ WithPerfGPU(true),
+ //WithPerfProcessAttributes("cpuUsage", "memAnon"),
+ //WithPerfBundleID("com.apple.mobilesafari"),
+ )
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ timer := time.NewTimer(time.Duration(time.Second * 20))
+ for {
+ select {
+ case <-timer.C:
+ dev.PerfStop()
+ return
+ case d := <-data:
+ fmt.Println(string(d))
+ }
+ }
+}
+
+func TestMockPerfdUser2(t *testing.T) {
+ //SetDebug(true, true)
+ remoteDev := NewRemoteConnect("127.0.0.1", 9123)
+ data, err := remoteDev.PerfStart(
+ WithPerfSystemCPU(true),
+ WithPerfSystemMem(true),
+ WithPerfSystemDisk(true),
+ WithPerfSystemNetwork(true),
+ WithPerfNetwork(true),
+ WithPerfFPS(true),
+ WithPerfGPU(true),
+ //WithPerfProcessAttributes("cpuUsage", "memAnon"),
+ //WithPerfBundleID("com.apple.mobilesafari"),
+ )
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ timer := time.NewTimer(time.Duration(time.Second * 10))
+ for {
+ select {
+ case <-timer.C:
+ dev.PerfStop()
+ return
+ case d := <-data:
+ fmt.Println(string(d))
+ }
+ }
+}
diff --git a/idevice.go b/idevice.go
index 7f83a09..3da5147 100644
--- a/idevice.go
+++ b/idevice.go
@@ -81,6 +81,8 @@ type Device interface {
PerfStop()
WebInspectorService() (webInspector WebInspector, err error)
+
+ Share(port int) error
}
type DeviceProperties = libimobiledevice.DeviceProperties
diff --git a/pkg/libimobiledevice/client_dtxmessage.go b/pkg/libimobiledevice/client_dtxmessage.go
index 7fed570..7c03e35 100644
--- a/pkg/libimobiledevice/client_dtxmessage.go
+++ b/pkg/libimobiledevice/client_dtxmessage.go
@@ -179,7 +179,6 @@ func (c *dtxMessageClient) ReceiveDTXMessage() (result *DTXMessageResult, err er
var aux, obj []byte
- // see https://github.com/SonicCloudOrg/sonic-gidevice/issues/28
if r, l := payloadSize+payload.AuxiliaryLength, len(rawPayload); int(r) <= l {
aux = rawPayload[payloadSize:r]
} else {
diff --git a/pkg/libimobiledevice/usbmux.go b/pkg/libimobiledevice/usbmux.go
index 06b32a1..2d7743c 100644
--- a/pkg/libimobiledevice/usbmux.go
+++ b/pkg/libimobiledevice/usbmux.go
@@ -1,3 +1,20 @@
+/*
+ * sonic-gidevice Connect to your iOS Devices.
+ * Copyright (C) 2022 SonicCloudOrg
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package libimobiledevice
import (
@@ -15,7 +32,7 @@ import (
var DefaultDeadlineTimeout = 30 * time.Second
const (
- BundleID = "electricbubble.libimobiledevice"
+ BundleID = "org.cloud.sonic.gidevice"
ProgramName = "libimobiledevice"
ClientVersion = "libimobiledevice-beta"
LibUSBMuxVersion = 3
@@ -112,13 +129,13 @@ type DeviceProperties struct {
NetworkAddress []byte `plist:"NetworkAddress"`
}
-func NewUsbmuxClient(timeout ...time.Duration) (c *UsbmuxClient, err error) {
+func NewUsbmuxClient(addr string, timeout ...time.Duration) (c *UsbmuxClient, err error) {
if len(timeout) == 0 {
timeout = []time.Duration{DefaultDeadlineTimeout}
}
c = &UsbmuxClient{version: ProtoVersionPlist}
var conn net.Conn
- if conn, err = rawDial(timeout[0]); err != nil {
+ if conn, err = rawDial(addr, timeout[0]); err != nil {
return nil, fmt.Errorf("usbmux connect: %w", err)
}
@@ -126,6 +143,12 @@ func NewUsbmuxClient(timeout ...time.Duration) (c *UsbmuxClient, err error) {
return
}
+func NewRemoteUsbmuxConn(conn net.Conn) (c *UsbmuxClient) {
+ c = &UsbmuxClient{version: ProtoVersionPlist}
+ c.innerConn = newInnerConn(conn, 0)
+ return
+}
+
type UsbmuxClient struct {
innerConn InnerConn
version ProtoVersion
@@ -259,11 +282,13 @@ func (c *UsbmuxClient) InnerConn() InnerConn {
return c.innerConn
}
-func rawDial(timeout time.Duration) (net.Conn, error) {
+func rawDial(addr string, timeout time.Duration) (net.Conn, error) {
dialer := net.Dialer{
Timeout: timeout,
}
-
+ if addr != "" {
+ return dialer.Dial("tcp", addr)
+ }
var network, address string
switch runtime.GOOS {
case "darwin", "android", "linux":
diff --git a/pkg/libimobiledevice/webinspector.go b/pkg/libimobiledevice/webinspector.go
index 1f7f521..6d6de5d 100644
--- a/pkg/libimobiledevice/webinspector.go
+++ b/pkg/libimobiledevice/webinspector.go
@@ -1,3 +1,20 @@
+/*
+ * sonic-gidevice Connect to your iOS Devices.
+ * Copyright (C) 2022 SonicCloudOrg
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package libimobiledevice
import (
diff --git a/usbmux.go b/usbmux.go
index c6a986f..6050536 100644
--- a/usbmux.go
+++ b/usbmux.go
@@ -9,7 +9,7 @@ import (
var _ Usbmux = (*usbmux)(nil)
func NewUsbmux() (Usbmux, error) {
- umClient, err := libimobiledevice.NewUsbmuxClient()
+ umClient, err := libimobiledevice.NewUsbmuxClient("")
if err != nil {
return nil, err
}
@@ -99,7 +99,7 @@ func (um *usbmux) Listen(devNotifier chan Device) (context.CancelFunc, error) {
if baseDev.MessageType != libimobiledevice.MessageTypeDeviceAdd {
baseDev.Properties.DeviceID = baseDev.DeviceID
}
- client, err := libimobiledevice.NewUsbmuxClient()
+ client, err := libimobiledevice.NewUsbmuxClient("")
if err != nil {
continue
}