Rev 1 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | // |
2 | // ClientHandler.swift |
||
3 | // GyroMouse |
||
4 | // |
||
5 | // Created by Matteo Riva on 28/08/15. |
||
6 | // Copyright © 2015 Matteo Riva. All rights reserved. |
||
7 | // |
||
8 | |||
9 | import Foundation |
||
10 | import CocoaAsyncSocket |
||
11 | |||
12 | |||
13 | class ClientHandler: NSObject, NetServiceDelegate, NetServiceBrowserDelegate, GCDAsyncSocketDelegate { |
||
14 | |||
15 | private var socket: GCDAsyncSocket? |
||
16 | private var serviceBrowser: NetServiceBrowser? |
||
17 | |||
18 | private(set) var services = [NetService]() |
||
19 | |||
20 | deinit { |
||
21 | socket?.setDelegate(nil, delegateQueue: nil) |
||
22 | socket = nil |
||
23 | |||
24 | serviceBrowser?.delegate = nil |
||
25 | serviceBrowser = nil |
||
26 | } |
||
27 | |||
28 | //MARK: - Publics |
||
29 | |||
30 | func startBrowsing() { |
||
31 | |||
32 | services = [] |
||
33 | |||
34 | // Initialize Service Browser |
||
35 | serviceBrowser = NetServiceBrowser() |
||
36 | |||
37 | // Configure Service Browser |
||
38 | serviceBrowser!.delegate = self |
||
39 | serviceBrowser!.searchForServices(ofType: "_gyroserver._tcp.", inDomain:"local.") |
||
40 | } |
||
41 | |||
42 | func stopBrowsing() { |
||
43 | serviceBrowser?.stop() |
||
44 | serviceBrowser?.delegate = nil |
||
45 | serviceBrowser = nil |
||
46 | services.removeAll() |
||
47 | } |
||
48 | |||
49 | func connectToLocalService(_ service: NetService) { |
||
50 | |||
51 | // Resolve Service |
||
52 | service.delegate = self |
||
53 | service.resolve(withTimeout: 30) |
||
54 | } |
||
55 | |||
7 | pmbaty | 56 | func sendPacket(_ type: String, keyTapped: String, isButtonDown: Bool, isRightButton: Bool, roll: Double, scrollVelocity: Double, grav: (X: Double, Y: Double, Z: Double), rotat: (X: Double, Z: Double), acc: (X: Double, Y: Double, Z: Double), moveVelocity: Double) { |
1 | pmbaty | 57 | let buffer = NSMutableData() |
7 | pmbaty | 58 | var int32var: Int32 |
59 | var uint32var: UInt32 |
||
60 | var boolvar: Bool |
||
61 | var doublevar: Double |
||
62 | int32var = 1; buffer.append(&int32var, length: MemoryLayout<Int32>.size) // protocol version |
||
63 | if (type == "key") { // key tapped |
||
64 | if (keyTapped.isEmpty) { return } // consistency check: happens when we hit a backspace |
||
65 | int32var = 1; buffer.append(&int32var, length: MemoryLayout<Int32>.size) // "key" packet type |
||
66 | uint32var = keyTapped.unicodeScalars.first!.value; buffer.append(&uint32var, length: MemoryLayout<UInt32>.size) |
||
67 | } |
||
68 | else if (type == "backspace") { // backspace tapped |
||
69 | int32var = 2; buffer.append(&int32var, length: MemoryLayout<Int32>.size) // "backspace" packet type |
||
70 | // nothing to add |
||
71 | } |
||
72 | else if (type == "enter") { // enter tapped |
||
73 | int32var = 3; buffer.append(&int32var, length: MemoryLayout<Int32>.size) // "enter" packet type |
||
74 | // nothing to add |
||
75 | } |
||
76 | else if (type == "click") { // click |
||
77 | int32var = 4; buffer.append(&int32var, length: MemoryLayout<Int32>.size) // "click" packet type |
||
78 | boolvar = isRightButton; buffer.append(&boolvar, length: MemoryLayout<Bool>.size) |
||
79 | boolvar = isButtonDown; buffer.append(&boolvar, length: MemoryLayout<Bool>.size) |
||
80 | } |
||
81 | else if (type == "scroll") { // page scroll |
||
82 | int32var = 5; buffer.append(&int32var, length: MemoryLayout<Int32>.size) // "scroll" packet type |
||
83 | doublevar = roll; buffer.append(&doublevar, length: MemoryLayout<Double>.size) |
||
84 | doublevar = scrollVelocity; buffer.append(&doublevar, length: MemoryLayout<Double>.size) |
||
85 | } |
||
86 | else if (type == "move") { // movement |
||
87 | int32var = 6; buffer.append(&int32var, length: MemoryLayout<Int32>.size) // "move" packet type |
||
88 | doublevar = grav.X; buffer.append(&doublevar, length: MemoryLayout<Double>.size) |
||
89 | doublevar = grav.Y; buffer.append(&doublevar, length: MemoryLayout<Double>.size) |
||
90 | doublevar = grav.Z; buffer.append(&doublevar, length: MemoryLayout<Double>.size) |
||
91 | doublevar = rotat.X; buffer.append(&doublevar, length: MemoryLayout<Double>.size) |
||
92 | doublevar = rotat.Z; buffer.append(&doublevar, length: MemoryLayout<Double>.size) |
||
93 | doublevar = acc.X; buffer.append(&doublevar, length: MemoryLayout<Double>.size) |
||
94 | doublevar = acc.Y; buffer.append(&doublevar, length: MemoryLayout<Double>.size) |
||
95 | doublevar = acc.Z; buffer.append(&doublevar, length: MemoryLayout<Double>.size) |
||
96 | doublevar = moveVelocity; buffer.append(&doublevar, length: MemoryLayout<Double>.size) |
||
97 | } |
||
98 | else if (type == "reset") { // reset pointer |
||
99 | int32var = 7; buffer.append(&int32var, length: MemoryLayout<Int32>.size) // "click" packet type |
||
100 | // nothing to add |
||
101 | } |
||
1 | pmbaty | 102 | |
103 | // Write Buffer |
||
7 | pmbaty | 104 | let bufferData = buffer as Data |
105 | print ("Sending \(bufferData.count) bytes packet:", terminator: "") |
||
106 | for i in 0...(bufferData.count - 1) { |
||
107 | let byte: UInt8 = bufferData.withUnsafeBytes { rawBuffer in rawBuffer.load(fromByteOffset: i * MemoryLayout<UInt8>.size, as: UInt8.self) } |
||
108 | print (" " + String(format: "%02X", byte), terminator: "") |
||
109 | } |
||
110 | print ("") |
||
111 | socket?.write(bufferData, withTimeout: -1, tag: 0) |
||
1 | pmbaty | 112 | } |
113 | |||
114 | func endConnection() { |
||
115 | socket?.disconnect() |
||
116 | socket?.setDelegate(nil, delegateQueue: nil) |
||
117 | socket = nil |
||
118 | } |
||
119 | |||
120 | //MARK: - NSNetServiceBrowserDelegate |
||
121 | |||
122 | func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) { |
||
123 | // Update Services |
||
124 | services.append(service) |
||
125 | |||
126 | if !moreComing { |
||
7 | pmbaty | 127 | NotificationCenter.default.post(Notification(name: GyroMouseShouldRefreshServerListNotification, object: self, userInfo: nil)) |
1 | pmbaty | 128 | } |
129 | } |
||
130 | |||
131 | func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool) { |
||
132 | // Update Services |
||
133 | services.remove(at: services.firstIndex(of: service)!) |
||
134 | |||
135 | if !moreComing { |
||
7 | pmbaty | 136 | NotificationCenter.default.post(Notification(name: GyroMouseShouldRefreshServerListNotification, object: self, userInfo: nil)) |
1 | pmbaty | 137 | } |
138 | } |
||
139 | |||
140 | func netServiceBrowserDidStopSearch(_ browser: NetServiceBrowser) { |
||
141 | stopBrowsing() |
||
142 | } |
||
143 | |||
144 | func netServiceBrowser(_ browser: NetServiceBrowser, didNotSearch errorDict: [String : NSNumber]) { |
||
145 | stopBrowsing() |
||
146 | } |
||
147 | |||
148 | //MARK: - NSNetServiceDelegate |
||
149 | |||
150 | func netService(_ sender: NetService, didNotResolve errorDict: [String : NSNumber]) { |
||
151 | sender.delegate = nil |
||
152 | } |
||
153 | |||
154 | func netServiceDidResolveAddress(_ sender: NetService) { |
||
155 | // Connect With Service |
||
7 | pmbaty | 156 | var isConnected = false |
157 | |||
158 | if ((socket == nil) || (socket?.isDisconnected ?? false)) { |
||
159 | // Initialize Socket |
||
160 | socket = GCDAsyncSocket(delegate: self, delegateQueue: DispatchQueue.main) |
||
161 | |||
162 | // Connect |
||
163 | while (!isConnected && (sender.addresses!.count != 0)) { |
||
164 | do { |
||
165 | try socket!.connect(toAddress: sender.addresses!.first!) |
||
166 | isConnected = true |
||
167 | } catch { |
||
168 | isConnected = false |
||
169 | print("Unable to connect to address. Error \(error) with user info \(error.localizedDescription).", terminator: "\n") |
||
170 | } |
||
171 | } |
||
172 | } else { |
||
173 | isConnected = socket?.isConnected ?? false |
||
174 | } |
||
175 | |||
176 | if (isConnected) { |
||
1 | pmbaty | 177 | print("Did Connect with Service: domain(\(sender.domain)) type(\(sender.type)) name(\(sender.name)) port(\(sender.port))", terminator: "\n") |
178 | } else { |
||
179 | print("Unable to Connect with Service: domain(\(sender.domain)) type(\(sender.type)) name(\(sender.name)) port(\(sender.port))", terminator: "\n") |
||
7 | pmbaty | 180 | NotificationCenter.default.post(Notification(name: GyroMouseConnectionFailedNotification, object: self, userInfo: nil)) |
1 | pmbaty | 181 | } |
182 | } |
||
183 | |||
184 | //MARK: - GCDAsyncSocketDelegate |
||
185 | |||
186 | func socket(_ sock: GCDAsyncSocket, didConnectToHost host: String, port: UInt16) { |
||
187 | print("Socket Did Connect to Host: \(host) Port: \(port)", terminator: "\n") |
||
188 | |||
189 | stopBrowsing() |
||
7 | pmbaty | 190 | NotificationCenter.default.post(Notification(name: GyroMouseConnectionSuccessNotification, object: self, userInfo: nil)) |
1 | pmbaty | 191 | } |
192 | |||
193 | func socketDidDisconnect(_ sock: GCDAsyncSocket, withError err: Error?) { |
||
194 | socket?.delegate = nil |
||
195 | socket = nil |
||
196 | |||
197 | startBrowsing() |
||
7 | pmbaty | 198 | NotificationCenter.default.post(Notification(name: GyroMouseDisconnectedNotification, object: self, userInfo: nil)) |
1 | pmbaty | 199 | |
200 | if err != nil { |
||
201 | print("Socket Did Disconnect with Error \(err!) with user info \(err!.localizedDescription).", terminator: "\n") |
||
7 | pmbaty | 202 | //NotificationCenter.default.post(Notification(name: GyroMouseConnectionFailedNotification, object: self, userInfo: nil)) |
1 | pmbaty | 203 | } else { |
204 | print("Socket Did Disconnect", terminator: "\n") |
||
205 | } |
||
206 | } |
||
207 | |||
208 | } |