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/a1cadaa975e0d0028412 to your computer and use it in GitHub Desktop.
Save jweinberg/a1cadaa975e0d0028412 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 {
static let ListenPortNumber: UInt16 = 58391
static let BroadcastPortNumber: UInt16 = 5224
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: [UInt8]) -> [String:String] {
if let string = String(bytes: data, encoding: NSUTF8StringEncoding) {
var deviceInformation = [String:String]()
for source in string.componentsSeparatedByString(";") {
if let index = find(source, ":") {
deviceInformation[source.substringToIndex(index)] = source.substringFromIndex(index)
}
}
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 = HarmonyDiscovery.ListenPortNumber.bigEndian
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)))
weak var weakSelf = self
dispatch_source_set_event_handler(_socketSource) {
var data = [UInt8]()
var buff = [UInt8](count: 1024, repeatedValue: 0)
let accepted = accept(tcpsock, nil, nil)
var count = 0;
do {
count = read(accepted, &buff, 1024)
data += buff[0...count]
} while count > 0
callback(weakSelf?.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 = HarmonyDiscovery.BroadcastPortNumber.bigEndian
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 = Array(request.utf8)
var bAddr = unsafeBitCast(bPort, sockaddr.self)
sendto(sock, buf, buf.count, 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