Subversion Repositories Mobile Apps.GyroMouse

Rev

Rev 1 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1 Rev 7
Line 7... Line 7...
7
//
7
//
8
 
8
 
9
import Foundation
9
import Foundation
10
import CocoaAsyncSocket
10
import CocoaAsyncSocket
11
 
11
 
12
let ServerDiscoveredServicesDidChangeNotification = Notification.Name("ServerDiscoveredServicesDidChangeNotification")
-
 
13
let ClientDidCompleteLocalConnectionNotification = Notification.Name("ClientDidCompleteLocalConnectionNotification")
-
 
14
let ClientDidFailLocalConnectionNotification = Notification.Name("ClientDidFailLocalConnectionNotification")
-
 
15
let ClientDidDisconnectNotification = Notification.Name("ClientDidDisconnectNotification")
-
 
16
 
12
 
17
class ClientHandler: NSObject, NetServiceDelegate, NetServiceBrowserDelegate, GCDAsyncSocketDelegate {
13
class ClientHandler: NSObject, NetServiceDelegate, NetServiceBrowserDelegate, GCDAsyncSocketDelegate {
18
    
14
    
19
    private var socket: GCDAsyncSocket?
15
    private var socket: GCDAsyncSocket?
20
    private var serviceBrowser: NetServiceBrowser?
16
    private var serviceBrowser: NetServiceBrowser?
Line 25... Line 21...
25
        socket?.setDelegate(nil, delegateQueue: nil)
21
        socket?.setDelegate(nil, delegateQueue: nil)
26
        socket = nil
22
        socket = nil
27
        
23
        
28
        serviceBrowser?.delegate = nil
24
        serviceBrowser?.delegate = nil
29
        serviceBrowser = nil
25
        serviceBrowser = nil
30
    }
-
 
31
    
-
 
32
    //MARK: - Privates
-
 
33
    
-
 
34
    private func sendNotificationWithName(_ name: Notification.Name, userInfo: [String : Any]?) {
-
 
35
        let center = NotificationCenter.default
-
 
36
        let notif = Notification(name: name, object: self, userInfo: userInfo)
-
 
37
        center.post(notif)
-
 
38
    }
-
 
39
    
-
 
40
    private func connectWithService(_ service: NetService) -> Bool {
-
 
41
        var isConnected = false
-
 
42
        
-
 
43
        // Copy Service Addresses
-
 
44
        let addresses = service.addresses!
-
 
45
        
-
 
46
        if socket == nil || socket?.isDisconnected ?? false {
-
 
47
            // Initialize Socket
-
 
48
            socket = GCDAsyncSocket(delegate: self, delegateQueue: DispatchQueue.main)
-
 
49
            
-
 
50
            // Connect
-
 
51
            while !isConnected && addresses.count != 0 {
-
 
52
                let address = addresses.first!
-
 
53
                
-
 
54
                do {
-
 
55
                    try socket!.connect(toAddress: address)
-
 
56
                    isConnected = true
-
 
57
                } catch {
-
 
58
                    isConnected = false
-
 
59
                    print("Unable to connect to address. Error \(error) with user info \(error.localizedDescription).", terminator: "\n")
-
 
60
                }
-
 
61
            }
-
 
62
            
-
 
63
        } else {
-
 
64
            isConnected = socket?.isConnected ?? false
-
 
65
        }
-
 
66
        
-
 
67
        return isConnected
-
 
68
    }
26
    }
69
    
27
    
70
    //MARK: - Publics
28
    //MARK: - Publics
71
    
29
    
72
    func startBrowsing() {
30
    func startBrowsing() {
Line 91... Line 49...
91
    func connectToLocalService(_ service: NetService) {
49
    func connectToLocalService(_ service: NetService) {
92
        
50
        
93
        // Resolve Service
51
        // Resolve Service
94
        service.delegate = self
52
        service.delegate = self
95
        service.resolve(withTimeout: 30)
53
        service.resolve(withTimeout: 30)
96
        
-
 
97
    }
54
    }
98
    
55
    
99
    func sendPacket(_ packet: GyroPacket) {
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) {
100
        // Encode Packet Data
-
 
101
        let packetData = NSMutableData()
-
 
102
        let archiver = NSKeyedArchiver(forWritingWith: packetData)
-
 
103
        archiver.encode(packet, forKey: "packet")
-
 
104
        archiver.finishEncoding()
-
 
105
        
-
 
106
        // Initialize Buffer
-
 
107
        let buffer = NSMutableData()
57
        let buffer = NSMutableData()
-
 
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)
108
        
67
        }
-
 
68
        else if (type == "backspace") { // backspace tapped
-
 
69
            int32var = 2; buffer.append(&int32var, length: MemoryLayout<Int32>.size) // "backspace" packet type
109
        // Fill Buffer
70
            // nothing to add
-
 
71
        }
110
        var headerLength = UInt64(packetData.length)
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)
111
        buffer.append(&headerLength, length: MemoryLayout<UInt64>.size)
96
            doublevar = moveVelocity; buffer.append(&doublevar, length: MemoryLayout<Double>.size)
-
 
97
        }
112
        buffer.append(packetData.bytes, length: packetData.length)
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
        }
113
        
102
        
114
        // Write Buffer
103
        // Write Buffer
-
 
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 ("")
115
        socket?.write(buffer as Data, withTimeout: -1, tag: 0)
111
        socket?.write(bufferData, withTimeout: -1, tag: 0)
116
    }
112
    }
117
    
113
    
118
    func endConnection() {
114
    func endConnection() {
119
        socket?.disconnect()
115
        socket?.disconnect()
120
        socket?.setDelegate(nil, delegateQueue: nil)
116
        socket?.setDelegate(nil, delegateQueue: nil)
Line 126... Line 122...
126
    func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
122
    func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
127
        // Update Services
123
        // Update Services
128
        services.append(service)
124
        services.append(service)
129
        
125
        
130
        if !moreComing {
126
        if !moreComing {
131
            sendNotificationWithName(ServerDiscoveredServicesDidChangeNotification, userInfo: nil)
127
            NotificationCenter.default.post(Notification(name: GyroMouseShouldRefreshServerListNotification, object: self, userInfo: nil))
132
        }
128
        }
133
    }
129
    }
134
    
130
    
135
    func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool) {
131
    func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool) {
136
        // Update Services
132
        // Update Services
137
        services.remove(at: services.firstIndex(of: service)!)
133
        services.remove(at: services.firstIndex(of: service)!)
138
        
134
        
139
        if !moreComing {
135
        if !moreComing {
140
            sendNotificationWithName(ServerDiscoveredServicesDidChangeNotification, userInfo: nil)
136
            NotificationCenter.default.post(Notification(name: GyroMouseShouldRefreshServerListNotification, object: self, userInfo: nil))
141
        }
137
        }
142
    }
138
    }
143
    
139
    
144
    func netServiceBrowserDidStopSearch(_ browser: NetServiceBrowser) {
140
    func netServiceBrowserDidStopSearch(_ browser: NetServiceBrowser) {
145
        stopBrowsing()
141
        stopBrowsing()
Line 155... Line 151...
155
        sender.delegate = nil
151
        sender.delegate = nil
156
    }
152
    }
157
    
153
    
158
    func netServiceDidResolveAddress(_ sender: NetService) {
154
    func netServiceDidResolveAddress(_ sender: NetService) {
159
        // Connect With Service
155
        // Connect With Service
-
 
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
  
160
        if connectWithService(sender) {
176
        if (isConnected) {
161
            print("Did Connect with Service: domain(\(sender.domain)) type(\(sender.type)) name(\(sender.name)) port(\(sender.port))", terminator: "\n")
177
            print("Did Connect with Service: domain(\(sender.domain)) type(\(sender.type)) name(\(sender.name)) port(\(sender.port))", terminator: "\n")
162
        } else {
178
        } else {
163
            print("Unable to Connect with Service: domain(\(sender.domain)) type(\(sender.type)) name(\(sender.name)) port(\(sender.port))", terminator: "\n")
179
            print("Unable to Connect with Service: domain(\(sender.domain)) type(\(sender.type)) name(\(sender.name)) port(\(sender.port))", terminator: "\n")
164
            sendNotificationWithName(ClientDidFailLocalConnectionNotification, userInfo: nil)
180
            NotificationCenter.default.post(Notification(name: GyroMouseConnectionFailedNotification, object: self, userInfo: nil))
165
        }
181
        }
166
    }
182
    }
167
    
183
    
168
    //MARK: - GCDAsyncSocketDelegate
184
    //MARK: - GCDAsyncSocketDelegate
169
    
185
    
170
    func socket(_ sock: GCDAsyncSocket, didConnectToHost host: String, port: UInt16) {
186
    func socket(_ sock: GCDAsyncSocket, didConnectToHost host: String, port: UInt16) {
171
        print("Socket Did Connect to Host: \(host) Port: \(port)", terminator: "\n")
187
        print("Socket Did Connect to Host: \(host) Port: \(port)", terminator: "\n")
172
        
-
 
173
        // Start Reading
-
 
174
        sock.readData(toLength: UInt(MemoryLayout<UInt64>.size), withTimeout: -1, tag: 0)
-
 
175
        
188
        
176
        stopBrowsing()
189
        stopBrowsing()
177
        sendNotificationWithName(ClientDidCompleteLocalConnectionNotification, userInfo: nil)
190
        NotificationCenter.default.post(Notification(name: GyroMouseConnectionSuccessNotification, object: self, userInfo: nil))
178
    }
191
    }
179
    
192
    
180
    func socketDidDisconnect(_ sock: GCDAsyncSocket, withError err: Error?) {
193
    func socketDidDisconnect(_ sock: GCDAsyncSocket, withError err: Error?) {
181
        socket?.delegate = nil
194
        socket?.delegate = nil
182
        socket = nil
195
        socket = nil
183
        
196
        
184
        startBrowsing()
197
        startBrowsing()
185
        sendNotificationWithName(ClientDidDisconnectNotification, userInfo: nil)
198
        NotificationCenter.default.post(Notification(name: GyroMouseDisconnectedNotification, object: self, userInfo: nil))
186
        
199
        
187
        if err != nil {
200
        if err != nil {
188
            print("Socket Did Disconnect with Error \(err!) with user info \(err!.localizedDescription).", terminator: "\n")
201
            print("Socket Did Disconnect with Error \(err!) with user info \(err!.localizedDescription).", terminator: "\n")
189
            sendNotificationWithName(ClientDidFailLocalConnectionNotification, userInfo: nil)
202
            //NotificationCenter.default.post(Notification(name: GyroMouseConnectionFailedNotification, object: self, userInfo: nil))
190
        } else {
203
        } else {
191
            print("Socket Did Disconnect", terminator: "\n")
204
            print("Socket Did Disconnect", terminator: "\n")
192
        }
205
        }
193
    }
206
    }
194
 
207