Skip to content

Instantly share code, notes, and snippets.

@jweinberg
Last active August 29, 2015 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jweinberg/ebc4ccdb506ae4349c1a to your computer and use it in GitHub Desktop.
Save jweinberg/ebc4ccdb506ae4349c1a to your computer and use it in GitHub Desktop.
//
// HarmonyDiscovery.swift
// XMPPFun
//
// Created by Joshua Weinberg on 4/25/15.
// Copyright (c) 2015 Joshua Weinberg. All rights reserved.
//
import Foundation
@objc public class HarmonyDiscovery : NSObject {
private let _socketQueue: dispatch_queue_t
private let _timer: dispatch_source_t
private var _socketSource: dispatch_source_t?
override init() {
_socketQueue = dispatch_queue_create("com.jweinberg.socket", DISPATCH_QUEUE_SERIAL)
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
}
private func readDeviceInformation(data: NSData) -> [String:String] {
if let string = NSString(bytes: data.bytes, length: data.length, encoding: NSUTF8StringEncoding) as? String {
var deviceInformation = [String:String]()
for source in string.componentsSeparatedByString(";") {
let pair = source.componentsSeparatedByString(":")
if pair.count > 1 {
deviceInformation[pair[0]] = pair[1]
}
}
return deviceInformation
}
return [:]
}
public func startDiscovery(callback: ([String:String]?) -> ()) {
var server = sockaddr_in()
server.sin_family = sa_family_t(AF_INET)
server.sin_addr = in_addr(s_addr: 0)
server.sin_port = CFSwapInt16HostToBig(58391)
let tcpsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
_socketSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, UInt(tcpsock), 0, _socketQueue)
setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, &server, socklen_t(sizeof(sockaddr_in)))
var saddr = unsafeBitCast(server, sockaddr.self)
bind(tcpsock, &saddr, socklen_t(sizeof(sockaddr)))
dispatch_source_set_event_handler(_socketSource!) {
let data = NSMutableData()
var buff = [UInt8](count: 1024, repeatedValue: 0)
let accepted = accept(tcpsock, nil, nil)
var count = 0;
do {
count = read(accepted, &buff, 1024)
data.appendBytes(buff, length: count)
} while count > 0
callback(self.readDeviceInformation(data))
}
dispatch_resume(_socketSource!)
listen(tcpsock, 1024)
var bPort = sockaddr_in()
bPort.sin_family = sa_family_t(AF_INET)
var bAddr = in_addr()
inet_pton(AF_INET, "192.168.2.255", &bAddr)
bPort.sin_addr = bAddr
bPort.sin_port = CFSwapInt16HostToBig(5224)
let sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)
// set socket options enable broadcast
var broadcastEnable = 1
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, socklen_t(sizeof(Int)))
dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC, NSEC_PER_SEC / 10)
dispatch_source_set_event_handler(_timer) {
let request = "_logitech-reverse-bonjour._tcp.local.\n58391";
let buf = [UInt8](request.utf8)
var bAddr = unsafeBitCast(bPort, sockaddr.self)
sendto(sock, buf, Int(count(buf)), Int32(0), &bAddr, socklen_t(sizeof(sockaddr_in)))
}
dispatch_resume(_timer)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment