Moved discovery to a worker thread per host

This commit is contained in:
Diego Waxemberg 2015-01-02 23:56:28 -05:00
parent ee61dc9a59
commit 5aeedb894a
5 changed files with 166 additions and 85 deletions

View File

@ -31,6 +31,7 @@
FB4678FA1A55FFAD00377732 /* DiscoveryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB4678F91A55FFAD00377732 /* DiscoveryManager.m */; };
FB4678FF1A565DAC00377732 /* WakeOnLanManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB4678FE1A565DAC00377732 /* WakeOnLanManager.m */; };
FB4679011A57048000377732 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB4679001A57048000377732 /* CoreFoundation.framework */; };
FB6549561A57907E001C8F39 /* DiscoveryWorker.m in Sources */ = {isa = PBXBuildFile; fileRef = FB6549551A57907E001C8F39 /* DiscoveryWorker.m */; };
FB7E794419C8B71B00A15F68 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FB7E794319C8B71B00A15F68 /* libiconv.dylib */; };
FB89462819F646E200339C8A /* CryptoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB89460619F646E200339C8A /* CryptoManager.m */; };
FB89462919F646E200339C8A /* mkcert.c in Sources */ = {isa = PBXBuildFile; fileRef = FB89460719F646E200339C8A /* mkcert.c */; };
@ -117,6 +118,8 @@
FB4678FD1A565DAC00377732 /* WakeOnLanManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WakeOnLanManager.h; sourceTree = "<group>"; };
FB4678FE1A565DAC00377732 /* WakeOnLanManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WakeOnLanManager.m; sourceTree = "<group>"; };
FB4679001A57048000377732 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
FB6549541A57907E001C8F39 /* DiscoveryWorker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiscoveryWorker.h; sourceTree = "<group>"; };
FB6549551A57907E001C8F39 /* DiscoveryWorker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DiscoveryWorker.m; sourceTree = "<group>"; };
FB7E794319C8B71B00A15F68 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; };
FB89460519F646E200339C8A /* CryptoManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoManager.h; sourceTree = "<group>"; };
FB89460619F646E200339C8A /* CryptoManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CryptoManager.m; sourceTree = "<group>"; };
@ -420,10 +423,12 @@
FB89461419F646E200339C8A /* PairManager.m */,
FBD3494119FC9C04002D2A60 /* AppManager.h */,
FBD3494219FC9C04002D2A60 /* AppManager.m */,
FB4678F81A55FFAD00377732 /* DiscoveryManager.h */,
FB4678F91A55FFAD00377732 /* DiscoveryManager.m */,
FB4678FD1A565DAC00377732 /* WakeOnLanManager.h */,
FB4678FE1A565DAC00377732 /* WakeOnLanManager.m */,
FB4678F81A55FFAD00377732 /* DiscoveryManager.h */,
FB4678F91A55FFAD00377732 /* DiscoveryManager.m */,
FB6549541A57907E001C8F39 /* DiscoveryWorker.h */,
FB6549551A57907E001C8F39 /* DiscoveryWorker.m */,
);
path = Network;
sourceTree = "<group>";
@ -787,6 +792,7 @@
FB4678ED1A50C40900377732 /* OnScreenControls.m in Sources */,
FB290D0019B2C406004C83CF /* main.m in Sources */,
FBD3494319FC9C04002D2A60 /* AppManager.m in Sources */,
FB6549561A57907E001C8F39 /* DiscoveryWorker.m in Sources */,
FB89462A19F646E200339C8A /* ControllerSupport.m in Sources */,
FBD349621A0089F6002D2A60 /* DataManager.m in Sources */,
FB89463119F646E200339C8A /* StreamManager.m in Sources */,

View File

@ -16,12 +16,12 @@
@end
@interface DiscoveryManager : NSOperation <MDNSCallback>
@interface DiscoveryManager : NSObject <MDNSCallback>
- (id) initWithHosts:(NSArray*)hosts andCallback:(id<DiscoveryCallback>) callback;
- (void) startDiscovery;
- (void) stopDiscovery;
- (void) addHostToDiscovery:(Host*)host;
- (BOOL) addHostToDiscovery:(Host*)host;
- (void) removeHostFromDiscovery:(Host*)host;
- (void) discoverHost:(NSString*)hostAddress withCallback:(void (^)(Host*))callback;

View File

@ -11,6 +11,7 @@
#import "HttpManager.h"
#import "Utils.h"
#import "DataManager.h"
#import "DiscoveryWorker.h"
@implementation DiscoveryManager {
NSMutableArray* _hostQueue;
@ -27,7 +28,6 @@
self = [super init];
_hostQueue = [NSMutableArray arrayWithArray:hosts];
_callback = callback;
_discoveredHosts = [[NSMutableArray alloc] init];
_opQueue = [[NSOperationQueue alloc] init];
_mdnsMan = [[MDNSManager alloc] initWithCallback:self];
[CryptoManager generateKeyPairUsingSSl];
@ -43,111 +43,77 @@
Host* host = nil;
if ([[HttpManager getStatusStringFromXML:serverInfoData] isEqualToString:@"OK"]) {
host = [[[DataManager alloc] init] createHost];
DataManager* dataMan = [[DataManager alloc] init];
host = [dataMan createHost];
host.address = hostAddress;
[self updateHost:host withServerInfo:serverInfoData];
[self addHostToDiscovery:host];
[DiscoveryWorker updateHost:host withServerInfo:serverInfoData];
if (![self addHostToDiscovery:host]) {
[dataMan removeHost:host];
}
}
callback(host);
}
- (void) discoverHost:(Host*)host {
if (!shouldDiscover) return;
BOOL receivedResponse = NO;
if (host.localAddress != nil) {
HttpManager* hMan = [[HttpManager alloc] initWithHost:host.localAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
NSData* serverInfoData = [hMan executeRequestSynchronously:[hMan newServerInfoRequest]];
if ([[HttpManager getStatusStringFromXML:serverInfoData] isEqualToString:@"OK"]) {
[self updateHost:host withServerInfo:serverInfoData];
host.address = host.localAddress;
receivedResponse = YES;
}
}
if (shouldDiscover && !receivedResponse && host.externalAddress != nil) {
HttpManager* hMan = [[HttpManager alloc] initWithHost:host.externalAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
NSData* serverInfoData = [hMan executeRequestSynchronously:[hMan newServerInfoRequest]];
if ([[HttpManager getStatusStringFromXML:serverInfoData] isEqualToString:@"OK"]) {
[self updateHost:host withServerInfo:serverInfoData];
host.address = host.externalAddress;
receivedResponse = YES;
}
}
if (shouldDiscover && !receivedResponse && host.address != nil) {
HttpManager* hMan = [[HttpManager alloc] initWithHost:host.address uniqueId:_uniqueId deviceName:deviceName cert:_cert];
NSData* serverInfoData = [hMan executeRequestSynchronously:[hMan newServerInfoRequest]];
if ([[HttpManager getStatusStringFromXML:serverInfoData] isEqualToString:@"OK"]) {
[self updateHost:host withServerInfo:serverInfoData];
receivedResponse = YES;
}
}
host.online = receivedResponse;
if (receivedResponse) {
NSLog(@"Received response from: %@\n{\n\t address:%@ \n\t localAddress:%@ \n\t externalAddress:%@ \n\t uuid:%@ \n\t mac:%@ \n\t pairState:%d \n\t online:%d \n}", host.name, host.address, host.localAddress, host.externalAddress, host.uuid, host.mac, host.pairState, host.online);
}
// If the host has already been discovered, we update the reference
BOOL hostInList = NO;
for (int i = 0; i < _discoveredHosts.count; i++) {
Host* discoveredHost = [_discoveredHosts objectAtIndex:i];
if ([discoveredHost.uuid isEqualToString:host.uuid]) {
[_discoveredHosts removeObject:discoveredHost];
[_discoveredHosts insertObject:host atIndex:i];
hostInList = YES;
}
}
if (!hostInList) {
[_discoveredHosts addObject:host];
}
}
- (void) updateHost:(Host*)host withServerInfo:(NSData*)serverInfoData {
host.name = [HttpManager getStringFromXML:serverInfoData tag:@"hostname"];
host.externalAddress = [HttpManager getStringFromXML:serverInfoData tag:@"ExternalIP"];
host.localAddress = [HttpManager getStringFromXML:serverInfoData tag:@"LocalIP"];
host.uuid = [HttpManager getStringFromXML:serverInfoData tag:@"uniqueid"];
host.mac = [HttpManager getStringFromXML:serverInfoData tag:@"mac"];
NSString* pairState = [HttpManager getStringFromXML:serverInfoData tag:@"PairStatus"];
if ([pairState isEqualToString:@"1"]) {
host.pairState = PairStatePaired;
} else {
host.pairState = PairStateUnpaired;
}
}
- (void) startDiscovery {
NSLog(@"Starting discovery");
shouldDiscover = YES;
[_mdnsMan searchForHosts];
[_opQueue addOperation:self];
for (Host* host in _hostQueue) {
[_opQueue addOperation:[self createWorkerForHost:host]];
}
}
- (void) stopDiscovery {
NSLog(@"Stopping discovery");
shouldDiscover = NO;
[_mdnsMan stopSearching];
[_opQueue cancelAllOperations];
}
shouldDiscover = NO;
[_mdnsMan stopSearching];
}
- (void) addHostToDiscovery:(Host *)host {
[_hostQueue addObject:host];
- (BOOL) addHostToDiscovery:(Host *)host {
if (![self isHostInDiscovery:host]) {
[_hostQueue addObject:host];
if (shouldDiscover) {
[_opQueue addOperation:[self createWorkerForHost:host]];
}
return YES;
}
return NO;
}
- (void) removeHostFromDiscovery:(Host *)host {
for (DiscoveryWorker* worker in [_opQueue operations]) {
if ([worker getHost] == host) {
[worker cancel];
}
}
[_hostQueue removeObject:host];
}
- (void)updateHosts:(NSArray *)hosts {
[_hostQueue addObjectsFromArray:hosts];
}
- (void)main {
while (shouldDiscover && !self.isCancelled) {
NSLog(@"Running discovery loop");
[_discoveredHosts removeAllObjects];
for (Host* host in _hostQueue) {
[self discoverHost:host];
for (Host* host in hosts) {
if ([self addHostToDiscovery:host]) {
[_callback updateAllHosts:_hostQueue];
}
[_callback updateAllHosts:_discoveredHosts];
[NSThread sleepForTimeInterval:2.0f];
}
}
- (BOOL) isHostInDiscovery:(Host*)host {
for (int i = 0; i < _hostQueue.count; i++) {
Host* discoveredHost = [_hostQueue objectAtIndex:i];
if ([discoveredHost.uuid isEqualToString:host.uuid]) {
return YES;
}
}
return NO;
}
- (NSOperation*) createWorkerForHost:(Host*)host {
DiscoveryWorker* worker = [[DiscoveryWorker alloc] initWithHost:host uniqueId:_uniqueId cert:_cert];
return worker;
}
@end

View File

@ -0,0 +1,19 @@
//
// DiscoveryWorker.h
// Limelight
//
// Created by Diego Waxemberg on 1/2/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Host.h"
@interface DiscoveryWorker : NSOperation
- (id) initWithHost:(Host*)host uniqueId:(NSString*)uniqueId cert:(NSData*)cert;
- (Host*) getHost;
+ (void) updateHost:(Host*)host withServerInfo:(NSData*)serverInfoData;
@end

View File

@ -0,0 +1,90 @@
//
// DiscoveryWorker.m
// Limelight
//
// Created by Diego Waxemberg on 1/2/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
//
#import "DiscoveryWorker.h"
#import "Utils.h"
#import "HttpManager.h"
@implementation DiscoveryWorker {
Host* _host;
NSString* _uniqueId;
NSData* _cert;
}
static const float POLL_RATE = 2.0f; // Poll every 2 seconds
- (id) initWithHost:(Host*)host uniqueId:(NSString*)uniqueId cert:(NSData*)cert {
self = [super init];
_host = host;
_uniqueId = uniqueId;
_cert = cert;
return self;
}
- (Host*) getHost {
return _host;
}
- (void)main {
while (!self.cancelled) {
BOOL receivedResponse = NO;
if (!self.cancelled && _host.localAddress != nil) {
HttpManager* hMan = [[HttpManager alloc] initWithHost:_host.localAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
NSData* serverInfoData = [hMan executeRequestSynchronously:[hMan newServerInfoRequest]];
if ([[HttpManager getStatusStringFromXML:serverInfoData] isEqualToString:@"OK"]) {
[DiscoveryWorker updateHost:_host withServerInfo:serverInfoData];
_host.address = _host.localAddress;
receivedResponse = YES;
}
}
if (!self.cancelled && !receivedResponse && _host.externalAddress != nil) {
HttpManager* hMan = [[HttpManager alloc] initWithHost:_host.externalAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
NSData* serverInfoData = [hMan executeRequestSynchronously:[hMan newServerInfoRequest]];
if ([[HttpManager getStatusStringFromXML:serverInfoData] isEqualToString:@"OK"]) {
[DiscoveryWorker updateHost:_host withServerInfo:serverInfoData];
_host.address = _host.externalAddress;
receivedResponse = YES;
}
}
if (!self.cancelled && !receivedResponse && _host.address != nil) {
HttpManager* hMan = [[HttpManager alloc] initWithHost:_host.address uniqueId:_uniqueId deviceName:deviceName cert:_cert];
NSData* serverInfoData = [hMan executeRequestSynchronously:[hMan newServerInfoRequest]];
if ([[HttpManager getStatusStringFromXML:serverInfoData] isEqualToString:@"OK"]) {
[DiscoveryWorker updateHost:_host withServerInfo:serverInfoData];
receivedResponse = YES;
}
}
_host.online = receivedResponse;
if (receivedResponse) {
NSLog(@"Received response from: %@\n{\n\t address:%@ \n\t localAddress:%@ \n\t externalAddress:%@ \n\t uuid:%@ \n\t mac:%@ \n\t pairState:%d \n\t online:%d \n}", _host.name, _host.address, _host.localAddress, _host.externalAddress, _host.uuid, _host.mac, _host.pairState, _host.online);
} else {
// If the host is not online, we do not know the pairstate
_host.pairState = PairStateUnknown;
}
if (!self.cancelled) {
[NSThread sleepForTimeInterval:POLL_RATE];
}
}
}
+ (void) updateHost:(Host*)host withServerInfo:(NSData*)serverInfoData {
host.name = [HttpManager getStringFromXML:serverInfoData tag:@"hostname"];
host.externalAddress = [HttpManager getStringFromXML:serverInfoData tag:@"ExternalIP"];
host.localAddress = [HttpManager getStringFromXML:serverInfoData tag:@"LocalIP"];
host.uuid = [HttpManager getStringFromXML:serverInfoData tag:@"uniqueid"];
host.mac = [HttpManager getStringFromXML:serverInfoData tag:@"mac"];
NSString* pairState = [HttpManager getStringFromXML:serverInfoData tag:@"PairStatus"];
if ([pairState isEqualToString:@"1"]) {
host.pairState = PairStatePaired;
} else {
host.pairState = PairStateUnpaired;
}
}
@end