Files
httprunner/hrp/pkg/gidevice/usbmux.go
2022-10-23 22:59:34 +08:00

154 lines
3.4 KiB
Go

package gidevice
import (
"context"
"github.com/httprunner/httprunner/v4/hrp/pkg/gidevice/pkg/libimobiledevice"
)
var _ Usbmux = (*usbmux)(nil)
func NewUsbmux() (Usbmux, error) {
umClient, err := libimobiledevice.NewUsbmuxClient()
if err != nil {
return nil, err
}
return &usbmux{client: umClient}, nil
}
func newUsbmux(client *libimobiledevice.UsbmuxClient) *usbmux {
return &usbmux{client: client}
}
type usbmux struct {
client *libimobiledevice.UsbmuxClient
}
func (um *usbmux) Devices() (devices []Device, err error) {
var pkt libimobiledevice.Packet
if pkt, err = um.client.NewPlistPacket(
um.client.NewBasicRequest(libimobiledevice.MessageTypeDeviceList),
); err != nil {
return nil, err
}
if err = um.client.SendPacket(pkt); err != nil {
return nil, err
}
var respPkt libimobiledevice.Packet
if respPkt, err = um.client.ReceivePacket(); err != nil {
return nil, err
}
reply := struct {
DeviceList []libimobiledevice.BaseDevice `plist:"DeviceList"`
}{}
if err = respPkt.Unmarshal(&reply); err != nil {
return nil, err
}
devices = make([]Device, len(reply.DeviceList))
for i := range reply.DeviceList {
dev := reply.DeviceList[i]
devices[i] = newDevice(um.client, dev.Properties)
}
return
}
func (um *usbmux) ReadBUID() (buid string, err error) {
var pktReadBUID libimobiledevice.Packet
if pktReadBUID, err = um.client.NewPlistPacket(
um.client.NewBasicRequest(libimobiledevice.MessageTypeReadBUID),
); err != nil {
return "", err
}
if err = um.client.SendPacket(pktReadBUID); err != nil {
return "", err
}
respPkt, err := um.client.ReceivePacket()
if err != nil {
return "", err
}
reply := struct {
BUID string `plist:"BUID"`
}{}
if err = respPkt.Unmarshal(&reply); err != nil {
return "", err
}
buid = reply.BUID
return
}
func (um *usbmux) Listen(devNotifier chan Device) (context.CancelFunc, error) {
baseDevNotifier := make(chan libimobiledevice.BaseDevice)
ctx, cancelFunc, err := um.listen(baseDevNotifier)
go func(ctx context.Context) {
defer close(devNotifier)
for {
select {
case <-ctx.Done():
return
case baseDev := <-baseDevNotifier:
if baseDev.MessageType != libimobiledevice.MessageTypeDeviceAdd {
baseDev.Properties.DeviceID = baseDev.DeviceID
}
client, err := libimobiledevice.NewUsbmuxClient()
if err != nil {
continue
}
devNotifier <- newDevice(client, baseDev.Properties)
}
}
}(ctx)
return cancelFunc, err
}
func (um *usbmux) listen(devNotifier chan libimobiledevice.BaseDevice) (ctx context.Context, cancelFunc context.CancelFunc, err error) {
var pkt libimobiledevice.Packet
if pkt, err = um.client.NewPlistPacket(
um.client.NewBasicRequest(libimobiledevice.MessageTypeListen),
); err != nil {
return nil, nil, err
}
if err = um.client.SendPacket(pkt); err != nil {
return nil, nil, err
}
ctx, cancelFunc = context.WithCancel(context.Background())
go func(ctx context.Context) {
defer close(devNotifier)
for {
select {
case <-ctx.Done():
return
default:
var respPkt libimobiledevice.Packet
if respPkt, err = um.client.ReceivePacket(); err != nil {
break
}
var replyDevice libimobiledevice.BaseDevice
if err = respPkt.Unmarshal(&replyDevice); err != nil {
break
}
if replyDevice.MessageType == libimobiledevice.MessageTypeResult {
break
}
devNotifier <- replyDevice
}
}
}(ctx)
return ctx, cancelFunc, nil
}