Rev 5 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5 | Rev 7 | ||
---|---|---|---|
Line 11... | Line 11... | ||
11 | 11 | ||
12 | let ServerDidConnectNotification = Notification.Name("ServerDidConnectNotification") |
12 | let ServerDidConnectNotification = Notification.Name("ServerDidConnectNotification") |
13 | let ServerDidDisconnectNotification = Notification.Name("ServerDidDisconnectNotification") |
13 | let ServerDidDisconnectNotification = Notification.Name("ServerDidDisconnectNotification") |
14 | 14 | ||
15 | protocol ServerHandlerDelegate: AnyObject { |
15 | protocol ServerHandlerDelegate: AnyObject { |
- | 16 | func computePointerMovement(grav: (X: Double, Y: Double, Z: Double), rotat: (X: Double, Z: Double), acc: (X: Double, Y: Double, Z: Double), moveVelocity: Double) |
|
- | 17 | func scrollWithRoll(roll: Double, velocity: Double) |
|
- | 18 | func clickButton(isRightButton: Bool, isButtonDown: Bool) |
|
- | 19 | func resetPointerPosition(moveMouse: Bool) |
|
16 | func |
20 | func runAppleScript(_ scriptText: String) |
17 | } |
21 | } |
18 | 22 | ||
19 | class ServerHandler: NSObject, NetServiceDelegate, GCDAsyncSocketDelegate { |
23 | class ServerHandler: NSObject, NetServiceDelegate, GCDAsyncSocketDelegate { |
20 | 24 | ||
21 | weak var delegate: ServerHandlerDelegate? |
25 | weak var delegate: ServerHandlerDelegate? |
22 | 26 | ||
23 | private var service: NetService? |
27 | private var service: NetService? |
24 | private var socket: GCDAsyncSocket? |
28 | private var socket: GCDAsyncSocket? |
25 | - | ||
26 | private let buildNumber: Int = { |
- | |
27 | let infoDictionary = Bundle.main.infoDictionary! |
- | |
28 | let build = infoDictionary[String(kCFBundleVersionKey)] as! String |
- | |
29 | return Int(build)! |
- | |
30 | }() |
- | |
31 | 29 | ||
32 | deinit { |
30 | deinit { |
33 | delegate = nil |
31 | delegate = nil |
34 | 32 | ||
35 | socket?.setDelegate(nil, delegateQueue: nil) |
33 | socket?.setDelegate(nil, delegateQueue: nil) |
Line 44... | Line 42... | ||
44 | private func sendNotificationWithName(_ name: Notification.Name, userInfo: [String : Any]?) { |
42 | private func sendNotificationWithName(_ name: Notification.Name, userInfo: [String : Any]?) { |
45 | let center = NotificationCenter.default |
43 | let center = NotificationCenter.default |
46 | let notif = Notification(name: name, object: self, userInfo: userInfo) |
44 | let notif = Notification(name: name, object: self, userInfo: userInfo) |
47 | center.post(notif) |
45 | center.post(notif) |
48 | } |
46 | } |
49 | 47 | ||
50 | private func parseHeader(_ data: Data) -> UInt64 { |
- | |
51 | var headerLength: UInt64 = 0 |
- | |
52 | memcpy(&headerLength, (data as NSData).bytes, MemoryLayout<UInt64>.size) |
- | |
53 | return headerLength |
- | |
54 | } |
- | |
55 | - | ||
56 | private func parseBody(_ data: Data) { |
- | |
57 | let unarchiver = NSKeyedUnarchiver(forReadingWith: data) |
- | |
58 | let packet = unarchiver.decodeObject(forKey: "packet") as! GyroPacket |
- | |
59 | unarchiver.finishDecoding() |
- | |
60 | - | ||
61 | if packet.minimumVersion <= buildNumber { |
- | |
62 | delegate?.serverDidReceivePacket(packet) |
- | |
63 | } else { |
- | |
64 | endConnection() |
- | |
65 | let alert = NSAlert() |
- | |
66 | alert.addButton(withTitle: "OK") |
- | |
67 | alert.messageText = "vers_incomp".localized |
- | |
68 | alert.informativeText = "incomp_message".localized |
- | |
69 | alert.alertStyle = .warning |
- | |
70 | alert.runModal() |
- | |
71 | } |
- | |
72 | } |
- | |
73 | - | ||
74 | //MARK: - Publics |
48 | //MARK: - Publics |
75 | 49 | ||
76 | func endConnection() { |
50 | func endConnection() { |
77 | socket?.disconnect() |
51 | socket?.disconnect() |
78 | } |
52 | } |
Line 115... | Line 89... | ||
115 | func socket(_ sock: GCDAsyncSocket, didAcceptNewSocket newSocket: GCDAsyncSocket) { |
89 | func socket(_ sock: GCDAsyncSocket, didAcceptNewSocket newSocket: GCDAsyncSocket) { |
116 | print("Accepted New Socket from \(newSocket.connectedHost as Optional):\(newSocket.connectedPort as Optional)", terminator: "\n") |
90 | print("Accepted New Socket from \(newSocket.connectedHost as Optional):\(newSocket.connectedPort as Optional)", terminator: "\n") |
117 | 91 | ||
118 | socket = newSocket |
92 | socket = newSocket |
119 | 93 | ||
120 | // |
94 | // read first packet header from socket |
121 | newSocket.readData(toLength: UInt(MemoryLayout< |
95 | newSocket.readData(toLength: UInt(2 * MemoryLayout<Int32>.size), withTimeout: -1, tag: 0) |
122 | 96 | ||
123 | let notif = NSUserNotification() |
97 | let notif = NSUserNotification() |
124 | notif.title = "connected".localized |
98 | notif.title = "connected".localized |
125 | notif.informativeText = "connect_with".localized + ":\(socket!.connectedHost as Optional) " + "completed".localized |
99 | notif.informativeText = "connect_with".localized + ":\(socket!.connectedHost as Optional) " + "completed".localized |
126 | notif.deliveryDate = Date() |
100 | notif.deliveryDate = Date() |
Line 149... | Line 123... | ||
149 | 123 | ||
150 | } |
124 | } |
151 | } |
125 | } |
152 | 126 | ||
153 | func socket(_ sock: GCDAsyncSocket, didRead data: Data, withTag tag: Int) { |
127 | func socket(_ sock: GCDAsyncSocket, didRead data: Data, withTag tag: Int) { |
- | 128 | var expectedByteCount = -1 |
|
- | 129 | var expectedNextTag = -1 |
|
- | 130 | ||
- | 131 | if (tag == 0) { // read packet header |
|
- | 132 | let protocolVersion = Int(data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 0 * MemoryLayout<Int32>.size, as: Int32.self) }) |
|
- | 133 | if (protocolVersion == 1) { |
|
- | 134 | expectedNextTag = Int(data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 1 * MemoryLayout<Int32>.size, as: Int32.self) }) |
|
- | 135 | if (expectedNextTag == 1) { expectedByteCount = 1 * MemoryLayout<UInt32>.size } // "key" packet type requires 1 uint32 |
|
- | 136 | else if (expectedNextTag == 2) { expectedByteCount = 0 } // "backspace" packet type has no payload |
|
- | 137 | else if (expectedNextTag == 3) { expectedByteCount = 0 }// "enter" packet type has no payload |
|
- | 138 | else if (expectedNextTag == 4) { expectedByteCount = 2 * MemoryLayout<Bool>.size } // "click" packet type requires 2 booleans |
|
- | 139 | else if (expectedNextTag == 5) { expectedByteCount = 2 * MemoryLayout<Double>.size } // "scroll" packet type requires 2 doubles |
|
- | 140 | else if (expectedNextTag == 6) { expectedByteCount = 9 * MemoryLayout<Double>.size } // "move" packet type requires 9 doubles |
|
- | 141 | else if (expectedNextTag == 7) { expectedByteCount = 0 } // "reset" packet type has no payload |
|
154 |
|
142 | } |
- | 143 | } |
|
- | 144 | else if (tag == 1) { // read "key" packet payload |
|
- | 145 | var key: String = "" |
|
- | 146 | let unicodeScalarValue: UInt32 = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 0 * MemoryLayout<UInt32>.size, as: UInt32.self) } |
|
- | 147 | let unicodeScalar = UnicodeScalar(unicodeScalarValue) |
|
- | 148 | if (unicodeScalar != nil) { |
|
155 |
|
149 | key.append(Character(unicodeScalar!)) |
- | 150 | delegate?.runAppleScript("tell app \"System Events\" to keystroke \"" + key + "\"") |
|
- | 151 | } |
|
- | 152 | expectedNextTag = 0 // prepare to read the next packet header |
|
- | 153 | expectedByteCount = 2 * MemoryLayout<Int32>.size |
|
- | 154 | } |
|
- | 155 | else if (tag == 2) { // read "backspace" packet payload |
|
156 |
|
156 | delegate?.runAppleScript("tell app \"System Events\" to key code 51") |
- | 157 | expectedNextTag = 0 // prepare to read the next packet header |
|
- | 158 | expectedByteCount = 2 * MemoryLayout<Int32>.size |
|
- | 159 | } |
|
- | 160 | else if (tag == 3) { // read "enter" packet payload |
|
- | 161 | delegate?.runAppleScript("tell app \"System Events\" to keystroke return") |
|
- | 162 | expectedNextTag = 0 // prepare to read the next packet header |
|
- | 163 | expectedByteCount = 2 * MemoryLayout<Int32>.size |
|
- | 164 | } |
|
- | 165 | else if (tag == 4) { // read "click" packet payload |
|
- | 166 | let isRightButton = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 0 * MemoryLayout<Bool>.size, as: Bool.self) } |
|
- | 167 | let isButtonDown = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 1 * MemoryLayout<Bool>.size, as: Bool.self) } |
|
- | 168 | delegate?.clickButton(isRightButton: isRightButton, isButtonDown: isButtonDown) |
|
- | 169 | expectedNextTag = 0 // prepare to read the next packet header |
|
- | 170 | expectedByteCount = 2 * MemoryLayout<Int32>.size |
|
- | 171 | } |
|
- | 172 | else if (tag == 5) { // read "scroll" packet payload |
|
- | 173 | let roll = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 0 * MemoryLayout<Double>.size, as: Double.self) } |
|
- | 174 | let scrollVelocity = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 1 * MemoryLayout<Double>.size, as: Double.self) } |
|
- | 175 | delegate?.scrollWithRoll(roll: roll, velocity: scrollVelocity) |
|
- | 176 | expectedNextTag = 0 // prepare to read the next packet header |
|
- | 177 | expectedByteCount = 2 * MemoryLayout<Int32>.size |
|
- | 178 | } |
|
- | 179 | else if (tag == 6) { // read "move" packet payload |
|
- | 180 | let gravX = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 0 * MemoryLayout<Double>.size, as: Double.self) } |
|
- | 181 | let gravY = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 1 * MemoryLayout<Double>.size, as: Double.self) } |
|
- | 182 | let gravZ = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 2 * MemoryLayout<Double>.size, as: Double.self) } |
|
- | 183 | let rotatX = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 3 * MemoryLayout<Double>.size, as: Double.self) } |
|
- | 184 | let rotatZ = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 4 * MemoryLayout<Double>.size, as: Double.self) } |
|
- | 185 | let accX = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 5 * MemoryLayout<Double>.size, as: Double.self) } |
|
- | 186 | let accY = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 6 * MemoryLayout<Double>.size, as: Double.self) } |
|
- | 187 | let accZ = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 7 * MemoryLayout<Double>.size, as: Double.self) } |
|
- | 188 | let moveVelocity = data.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: 8 * MemoryLayout<Double>.size, as: Double.self) } |
|
- | 189 | delegate?.computePointerMovement(grav: (X: gravX, Y: gravY, Z: gravZ), rotat: (X: rotatX, Z: rotatZ), acc: (X: accX, Y: accY, Z: accZ), moveVelocity: moveVelocity) |
|
- | 190 | expectedNextTag = 0 // prepare to read the next packet header |
|
- | 191 | expectedByteCount = 2 * MemoryLayout<Int32>.size |
|
- | 192 | } |
|
- | 193 | else if (tag == 7) { // read "reset" packet payload |
|
- | 194 | delegate?.resetPointerPosition(moveMouse: true) |
|
- | 195 | expectedNextTag = 0 // prepare to read the next packet header |
|
- | 196 | expectedByteCount = 2 * MemoryLayout<Int32>.size |
|
- | 197 | } |
|
- | 198 | ||
- | 199 | // do we know what to read next ? |
|
157 |
|
200 | if (expectedByteCount == -1) { |
- | 201 | endConnection() |
|
- | 202 | let alert = NSAlert() |
|
- | 203 | alert.addButton(withTitle: "OK") |
|
- | 204 | alert.messageText = "vers_incomp".localized |
|
- | 205 | alert.informativeText = "incomp_message".localized |
|
- | 206 | alert.alertStyle = .warning |
|
158 |
|
207 | alert.runModal() |
- | 208 | } |
|
- | 209 | else if (expectedByteCount == 0) { |
|
- | 210 | socket(sock, didRead: Data(), withTag: expectedNextTag) // no payload, so chain-call ourselves to process the packet directly |
|
- | 211 | } |
|
- | 212 | else { |
|
159 |
|
213 | sock.readData(toLength: UInt(expectedByteCount), withTimeout: -1, tag: expectedNextTag) // read some bytes |
160 | } |
214 | } |
161 | } |
215 | } |
162 | - | ||
163 | } |
216 | } |