feat: 初始化 iOS 远程控制端项目

This commit is contained in:
2026-07-29 10:34:02 +08:00
parent 11173eb04c
commit 1e37aa64cc
20 changed files with 2610 additions and 0 deletions

View File

@@ -0,0 +1,179 @@
import Foundation
/// RTCDataChannel
/// control_message.proto (proto3) protobuf
/// SwiftProtobuf
/// x/y/x1/y1/x2/y2 0.0 ~ 1.0
struct ControlMessage {
enum Action: Int {
case unknown = 0
case touch = 1
case swipe = 2
case key = 3
case longPress = 4
case motionEvent = 5
case setResolution = 6 //
case reportResolution = 7 //
case setStreamMode = 8 //
case reportStreamMode = 9 //
}
var action: Action = .unknown // field 1, varint
var x: Double = 0 // field 2, fixed64
var y: Double = 0 // field 3, fixed64
var x1: Double = 0 // field 4, fixed64
var y1: Double = 0 // field 5, fixed64
var x2: Double = 0 // field 6, fixed64
var y2: Double = 0 // field 7, fixed64
var duration: Int64 = 0 // field 8, varint
var keyCode: Int32 = 0 // field 9, varint
var keyAction: Int32 = 0 // field 10, varint (0= 1=)
var motionAction: Int32 = 0 // field 11, varint (0=DOWN 1=UP 2=MOVE 3=CANCEL)
var width: Int32 = 0 // field 12, varint
var height: Int32 = 0 // field 13, varint
var fps: Int32 = 0 // field 14, varint
var streamMode: Int32 = 0 // field 15, varint (0=WebRTC 1=)
// MARK: - Encode
func serializedData() -> Data {
var w = ProtoWriter()
w.writeVarintField(1, UInt64(action.rawValue))
w.writeDoubleField(2, x)
w.writeDoubleField(3, y)
w.writeDoubleField(4, x1)
w.writeDoubleField(5, y1)
w.writeDoubleField(6, x2)
w.writeDoubleField(7, y2)
w.writeVarintField(8, UInt64(bitPattern: duration))
w.writeVarintField(9, UInt64(bitPattern: Int64(keyCode)))
w.writeVarintField(10, UInt64(bitPattern: Int64(keyAction)))
w.writeVarintField(11, UInt64(bitPattern: Int64(motionAction)))
w.writeVarintField(12, UInt64(bitPattern: Int64(width)))
w.writeVarintField(13, UInt64(bitPattern: Int64(height)))
w.writeVarintField(14, UInt64(bitPattern: Int64(fps)))
w.writeVarintField(15, UInt64(bitPattern: Int64(streamMode)))
return w.data
}
// MARK: - Decode
static func parse(from data: Data) -> ControlMessage? {
var msg = ControlMessage()
var r = ProtoReader(data: data)
while let (field, wire) = r.readTag() {
switch (field, wire) {
case (1, 0):
guard let v = r.readVarint() else { return nil }
msg.action = Action(rawValue: Int(v)) ?? .unknown
case (2, 1): guard let v = r.readDouble() else { return nil }; msg.x = v
case (3, 1): guard let v = r.readDouble() else { return nil }; msg.y = v
case (4, 1): guard let v = r.readDouble() else { return nil }; msg.x1 = v
case (5, 1): guard let v = r.readDouble() else { return nil }; msg.y1 = v
case (6, 1): guard let v = r.readDouble() else { return nil }; msg.x2 = v
case (7, 1): guard let v = r.readDouble() else { return nil }; msg.y2 = v
case (8, 0): guard let v = r.readVarint() else { return nil }; msg.duration = Int64(bitPattern: v)
case (9, 0): guard let v = r.readVarint() else { return nil }; msg.keyCode = Int32(truncatingIfNeeded: Int64(bitPattern: v))
case (10, 0): guard let v = r.readVarint() else { return nil }; msg.keyAction = Int32(truncatingIfNeeded: Int64(bitPattern: v))
case (11, 0): guard let v = r.readVarint() else { return nil }; msg.motionAction = Int32(truncatingIfNeeded: Int64(bitPattern: v))
case (12, 0): guard let v = r.readVarint() else { return nil }; msg.width = Int32(truncatingIfNeeded: Int64(bitPattern: v))
case (13, 0): guard let v = r.readVarint() else { return nil }; msg.height = Int32(truncatingIfNeeded: Int64(bitPattern: v))
case (14, 0): guard let v = r.readVarint() else { return nil }; msg.fps = Int32(truncatingIfNeeded: Int64(bitPattern: v))
case (15, 0): guard let v = r.readVarint() else { return nil }; msg.streamMode = Int32(truncatingIfNeeded: Int64(bitPattern: v))
default:
// wire type
if !r.skip(wireType: wire) { return nil }
}
}
return msg
}
}
// MARK: - protobuf
private struct ProtoWriter {
var data = Data()
mutating func writeVarint(_ value: UInt64) {
var v = value
while v >= 0x80 {
data.append(UInt8((v & 0x7F) | 0x80))
v >>= 7
}
data.append(UInt8(v))
}
/// proto3(0)
mutating func writeVarintField(_ field: Int, _ value: UInt64) {
guard value != 0 else { return }
writeVarint(UInt64(field << 3 | 0))
writeVarint(value)
}
mutating func writeDoubleField(_ field: Int, _ value: Double) {
guard value != 0 else { return }
writeVarint(UInt64(field << 3 | 1))
var bits = value.bitPattern.littleEndian
withUnsafeBytes(of: &bits) { data.append(contentsOf: $0) }
}
}
private struct ProtoReader {
let data: Data
var offset: Int
init(data: Data) {
self.data = data
self.offset = data.startIndex
}
mutating func readTag() -> (Int, Int)? {
guard offset < data.endIndex, let key = readVarint() else { return nil }
return (Int(key >> 3), Int(key & 0x7))
}
mutating func readVarint() -> UInt64? {
var result: UInt64 = 0
var shift: UInt64 = 0
while offset < data.endIndex {
let byte = data[offset]
offset += 1
result |= UInt64(byte & 0x7F) << shift
if byte & 0x80 == 0 { return result }
shift += 7
if shift >= 64 { return nil }
}
return nil
}
mutating func readDouble() -> Double? {
guard offset + 8 <= data.endIndex else { return nil }
var bits: UInt64 = 0
for i in (0..<8).reversed() {
bits = (bits << 8) | UInt64(data[offset + i])
}
offset += 8
return Double(bitPattern: bits)
}
mutating func skip(wireType: Int) -> Bool {
switch wireType {
case 0: return readVarint() != nil
case 1:
guard offset + 8 <= data.endIndex else { return false }
offset += 8
return true
case 2:
guard let len = readVarint(), offset + Int(len) <= data.endIndex else { return false }
offset += Int(len)
return true
case 5:
guard offset + 4 <= data.endIndex else { return false }
offset += 4
return true
default:
return false
}
}
}