Created new host discovery system

- now store host uuid and mac address
- use uuid to check for duplicate hosts
- try local and external IPs
- pair status is shown
- server status is shown
- validate host when manually adding
This commit is contained in:
Diego Waxemberg 2015-01-01 22:30:03 -05:00
parent 0e2765ad86
commit e8c8f4f8e9
17 changed files with 326 additions and 154 deletions

View File

@ -28,6 +28,7 @@
FB290E7919B37D81004C83CF /* iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FB290E7819B37D81004C83CF /* iPad.storyboard */; };
FB290E7B19B38036004C83CF /* iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FB290E7A19B38036004C83CF /* iPhone.storyboard */; };
FB4678ED1A50C40900377732 /* OnScreenControls.m in Sources */ = {isa = PBXBuildFile; fileRef = FB4678EC1A50C40900377732 /* OnScreenControls.m */; };
FB4678FA1A55FFAD00377732 /* DiscoveryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB4678F91A55FFAD00377732 /* DiscoveryManager.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 */; };
@ -40,7 +41,6 @@
FB89463019F646E200339C8A /* StreamConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = FB89461919F646E200339C8A /* StreamConfiguration.m */; };
FB89463119F646E200339C8A /* StreamManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB89461B19F646E200339C8A /* StreamManager.m */; };
FB89463219F646E200339C8A /* VideoDecoderRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = FB89461D19F646E200339C8A /* VideoDecoderRenderer.m */; };
FB89463319F646E200339C8A /* Computer.m in Sources */ = {isa = PBXBuildFile; fileRef = FB89462019F646E200339C8A /* Computer.m */; };
FB89463419F646E200339C8A /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = FB89462219F646E200339C8A /* Utils.m */; };
FB89463519F646E200339C8A /* MainFrameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FB89462519F646E200339C8A /* MainFrameViewController.m */; };
FB89463619F646E200339C8A /* StreamFrameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FB89462719F646E200339C8A /* StreamFrameViewController.m */; };
@ -110,6 +110,8 @@
FB4678EB1A50C40900377732 /* OnScreenControls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OnScreenControls.h; sourceTree = "<group>"; };
FB4678EC1A50C40900377732 /* OnScreenControls.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OnScreenControls.m; sourceTree = "<group>"; };
FB4678F21A51BDCB00377732 /* Limelight 0.3.0.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Limelight 0.3.0.xcdatamodel"; sourceTree = "<group>"; };
FB4678F81A55FFAD00377732 /* DiscoveryManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiscoveryManager.h; sourceTree = "<group>"; };
FB4678F91A55FFAD00377732 /* DiscoveryManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DiscoveryManager.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>"; };
@ -133,8 +135,6 @@
FB89461B19F646E200339C8A /* StreamManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StreamManager.m; sourceTree = "<group>"; };
FB89461C19F646E200339C8A /* VideoDecoderRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoDecoderRenderer.h; sourceTree = "<group>"; };
FB89461D19F646E200339C8A /* VideoDecoderRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VideoDecoderRenderer.m; sourceTree = "<group>"; };
FB89461F19F646E200339C8A /* Computer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Computer.h; sourceTree = "<group>"; };
FB89462019F646E200339C8A /* Computer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Computer.m; sourceTree = "<group>"; };
FB89462119F646E200339C8A /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utils.h; sourceTree = "<group>"; };
FB89462219F646E200339C8A /* Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Utils.m; sourceTree = "<group>"; };
FB89462419F646E200339C8A /* MainFrameViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainFrameViewController.h; sourceTree = "<group>"; };
@ -413,6 +413,8 @@
FB89461419F646E200339C8A /* PairManager.m */,
FBD3494119FC9C04002D2A60 /* AppManager.h */,
FBD3494219FC9C04002D2A60 /* AppManager.m */,
FB4678F81A55FFAD00377732 /* DiscoveryManager.h */,
FB4678F91A55FFAD00377732 /* DiscoveryManager.m */,
);
path = Network;
sourceTree = "<group>";
@ -435,8 +437,6 @@
FB89461E19F646E200339C8A /* Utility */ = {
isa = PBXGroup;
children = (
FB89461F19F646E200339C8A /* Computer.h */,
FB89462019F646E200339C8A /* Computer.m */,
FBDE86E719F82315001C18A8 /* App.h */,
FBDE86E819F82315001C18A8 /* App.m */,
FB89462119F646E200339C8A /* Utils.h */,
@ -758,7 +758,6 @@
FB290D0419B2C406004C83CF /* AppDelegate.m in Sources */,
FB89463419F646E200339C8A /* Utils.m in Sources */,
FBDE86E619F82297001C18A8 /* UIAppView.m in Sources */,
FB89463319F646E200339C8A /* Computer.m in Sources */,
FB89462F19F646E200339C8A /* Connection.m in Sources */,
FB89462919F646E200339C8A /* mkcert.c in Sources */,
FBDE86E019F7A837001C18A8 /* UIComputerView.m in Sources */,
@ -769,6 +768,7 @@
FB89462C19F646E200339C8A /* HttpManager.m in Sources */,
FB89462D19F646E200339C8A /* MDNSManager.m in Sources */,
FB89462B19F646E200339C8A /* StreamView.m in Sources */,
FB4678FA1A55FFAD00377732 /* DiscoveryManager.m in Sources */,
FBD3495B1A004411002D2A60 /* Host.m in Sources */,
FB89463519F646E200339C8A /* MainFrameViewController.m in Sources */,
FB89463619F646E200339C8A /* StreamFrameViewController.m in Sources */,

View File

@ -19,6 +19,6 @@
- (Settings*) retrieveSettings;
- (NSArray*) retrieveHosts;
- (void) saveHosts;
- (Host*) createHost:(NSString*)name hostname:(NSString*)address;
- (Host*) createHost;
@end

View File

@ -45,12 +45,9 @@
}
}
- (Host*) createHost:(NSString*)name hostname:(NSString*)address {
- (Host*) createHost {
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Host" inManagedObjectContext:[self.appDelegate managedObjectContext]];
Host* host = [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
host.name = name;
host.address = address;
return host;
}

View File

@ -8,11 +8,17 @@
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "Utils.h"
@interface Host : NSManagedObject
@property (nonatomic, retain) NSString * address;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * address;
@property (nonatomic, retain) NSString * localAddress;
@property (nonatomic, retain) NSString * externalAddress;
@property (nonatomic, retain) NSString * uuid;
@property (nonatomic, retain) NSString * mac;
@property (nonatomic) BOOL online;
@property (nonatomic) PairState pairState;
@end

View File

@ -11,7 +11,13 @@
@implementation Host
@dynamic address;
@dynamic name;
@dynamic address;
@dynamic localAddress;
@dynamic externalAddress;
@dynamic uuid;
@dynamic mac;
@dynamic pairState;
@synthesize online;
@end

View File

@ -2,7 +2,12 @@
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="6254" systemVersion="14C81f" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
<entity name="Host" representedClassName="Host" syncable="YES">
<attribute name="address" attributeType="String" syncable="YES"/>
<attribute name="externalAddress" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="localAddress" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="mac" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="name" attributeType="String" syncable="YES"/>
<attribute name="pairState" optional="YES" attributeType="Integer 32" defaultValueString="0" syncable="YES"/>
<attribute name="uuid" optional="YES" attributeType="String" syncable="YES"/>
</entity>
<entity name="Settings" representedClassName="Settings" syncable="YES">
<attribute name="bitrate" attributeType="Integer 32" defaultValueString="10000" syncable="YES"/>
@ -12,7 +17,7 @@
<attribute name="width" attributeType="Integer 32" defaultValueString="1280" syncable="YES"/>
</entity>
<elements>
<element name="Host" positionX="0" positionY="0" width="128" height="73"/>
<element name="Host" positionX="0" positionY="0" width="128" height="148"/>
<element name="Settings" positionX="0" positionY="0" width="128" height="118"/>
</elements>
</model>

View File

@ -0,0 +1,27 @@
//
// DiscoveryManager.h
// Limelight
//
// Created by Diego Waxemberg on 1/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MDNSManager.h"
#import "Host.h"
@protocol DiscoveryCallback <NSObject>
- (void) updateAllHosts:(NSArray*)hosts;
@end
@interface DiscoveryManager : NSOperation <MDNSCallback>
- (id) initWithHosts:(NSArray*)hosts andCallback:(id<DiscoveryCallback>) callback;
- (void) startDiscovery;
- (void) stopDiscovery;
- (void) addHostToDiscovery:(Host*)host;
- (void) discoverHost:(NSString*)hostAddress withCallback:(void (^)(Host*))callback;
@end

View File

@ -0,0 +1,149 @@
//
// DiscoveryManager.m
// Limelight
//
// Created by Diego Waxemberg on 1/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
//
#import "DiscoveryManager.h"
#import "CryptoManager.h"
#import "HttpManager.h"
#import "Utils.h"
#import "DataManager.h"
@implementation DiscoveryManager {
NSMutableArray* _hostQueue;
NSMutableArray* _discoveredHosts;
id<DiscoveryCallback> _callback;
MDNSManager* _mdnsMan;
NSOperationQueue* _opQueue;
NSString* _uniqueId;
NSData* _cert;
BOOL shouldDiscover;
}
- (id)initWithHosts:(NSArray *)hosts andCallback:(id<DiscoveryCallback>)callback {
self = [super init];
_hostQueue = [NSMutableArray arrayWithArray:hosts];
_callback = callback;
_discoveredHosts = [[NSMutableArray alloc] init];
_opQueue = [[NSOperationQueue alloc] init];
_mdnsMan = [[MDNSManager alloc] initWithCallback:self];
[CryptoManager generateKeyPairUsingSSl];
_uniqueId = [CryptoManager getUniqueID];
_cert = [CryptoManager readCertFromFile];
shouldDiscover = NO;
return self;
}
- (void) discoverHost:(NSString *)hostAddress withCallback:(void (^)(Host *))callback {
HttpManager* hMan = [[HttpManager alloc] initWithHost:hostAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
NSData* serverInfoData = [hMan executeRequestSynchronously:[hMan newServerInfoRequest]];
Host* host = nil;
if ([[HttpManager getStatusStringFromXML:serverInfoData] isEqualToString:@"OK"]) {
host = [[[DataManager alloc] init] createHost];
host.address = hostAddress;
[self updateHost:host withServerInfo:serverInfoData];
[self addHostToDiscovery: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];
}
- (void) stopDiscovery {
shouldDiscover = NO;
[_mdnsMan stopSearching];
}
- (void) addHostToDiscovery:(Host *)host {
[_hostQueue addObject: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];
}
[_callback updateAllHosts:_discoveredHosts];
[NSThread sleepForTimeInterval:3.0f];
}
}
@end

View File

@ -7,7 +7,8 @@
//
#import "MDNSManager.h"
#import "Computer.h"
#import "Host.h"
#import "DataManager.h"
@implementation MDNSManager {
NSNetServiceBrowser* mDNSBrowser;
@ -46,9 +47,12 @@ static NSString* NV_SERVICE_TYPE = @"_nvstream._tcp";
- (NSArray*) getFoundHosts {
NSMutableArray* hosts = [[NSMutableArray alloc] init];
DataManager* dataMan = [[DataManager alloc] init];
for (NSNetService* service in services) {
if (service.hostName != nil) {
[hosts addObject:[[Computer alloc] initWithHost:service]];
Host* host = [dataMan createHost];
host.address = service.hostName;
[hosts addObject:host];
}
}
return hosts;

View File

@ -7,18 +7,18 @@
//
#import <UIKit/UIKit.h>
#import "Computer.h"
#import "Host.h"
@protocol HostCallback <NSObject>
- (void) hostClicked:(Computer*)computer;
- (void) hostClicked:(Host*)host;
- (void) addHostClicked;
@end
@interface UIComputerView : UIView
- (id) initWithComputer:(Computer*)computer andCallback:(id<HostCallback>)callback;
- (id) initWithComputer:(Host*)host andCallback:(id<HostCallback>)callback;
- (id) initForAddWithCallback:(id<HostCallback>)callback;
- (NSString*) online;
@end

View File

@ -9,9 +9,11 @@
#import "UIComputerView.h"
@implementation UIComputerView {
Computer* _computer;
Host* _host;
UIButton* _hostButton;
UILabel* _hostLabel;
UILabel* _hostStatus;
UILabel* _hostPairState;
id<HostCallback> _callback;
CGSize _labelSize;
}
@ -29,27 +31,61 @@ static int LABEL_DY = 20;
_hostButton.layer.shadowOpacity = 0.7;
_hostLabel = [[UILabel alloc] init];
_hostStatus = [[UILabel alloc] init];
_hostPairState = [[UILabel alloc] init];
return self;
}
- (id) initWithComputer:(Computer*)computer andCallback:(id<HostCallback>)callback {
- (id) initWithComputer:(Host*)host andCallback:(id<HostCallback>)callback {
self = [self init];
_computer = computer;
_host = host;
_callback = callback;
[_hostLabel setText:[_computer displayName]];
[_hostLabel setText:_host.name];
[_hostLabel sizeToFit];
_hostLabel.textColor = [UIColor whiteColor];
switch (host.pairState) {
case PairStateUnknown:
[_hostPairState setText:@"Pair State Unknown"];
break;
case PairStateUnpaired:
[_hostPairState setText:@"Not Paired"];
break;
case PairStatePaired:
[_hostPairState setText:@"Paired"];
break;
}
[_hostPairState sizeToFit];
_hostPairState.textColor = [UIColor whiteColor];
if (host.online) {
_hostStatus.text = @"Online";
_hostStatus.textColor = [UIColor greenColor];
} else {
_hostStatus.text = @"Offline";
_hostStatus.textColor = [UIColor grayColor];
}
[_hostStatus sizeToFit];
[_hostButton addTarget:self action:@selector(hostClicked) forControlEvents:UIControlEventTouchUpInside];
_hostLabel.center = CGPointMake(_hostButton.frame.origin.x + (_hostButton.frame.size.width / 2), _hostButton.frame.origin.y + _hostButton.frame.size.height + LABEL_DY);
_hostPairState.center = CGPointMake(_hostLabel.center.x, _hostLabel.center.y + LABEL_DY);
_hostStatus.center = CGPointMake(_hostPairState.center.x, _hostPairState.center.y + LABEL_DY);
[self updateBounds];
[self addSubview:_hostButton];
[self addSubview:_hostLabel];
[self addSubview:_hostStatus];
[self addSubview:_hostPairState];
return self;
}
- (NSString *)online {
return _hostStatus.text;
}
- (void) updateBounds {
float x = _hostButton.frame.origin.x < _hostLabel.frame.origin.x ? _hostButton.frame.origin.x : _hostLabel.frame.origin.x;
float y = _hostButton.frame.origin.y < _hostLabel.frame.origin.y ? _hostButton.frame.origin.y : _hostLabel.frame.origin.y;
@ -83,19 +119,11 @@ static int LABEL_DY = 20;
}
- (void) hostClicked {
[_callback hostClicked:_computer];
[_callback hostClicked:_host];
}
- (void) addClicked {
[_callback addHostClicked];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
@end

View File

@ -1,19 +0,0 @@
//
// Computer.h
// Limelight
//
// Created by Diego Waxemberg on 10/14/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Computer : NSObject
@property NSString* displayName;
@property NSString* hostName;
@property BOOL paired;
- (id) initWithHost:(NSNetService*)host;
- (id) initWithIp:(NSString*)host;
@end

View File

@ -1,47 +0,0 @@
//
// Computer.m
// Limelight
//
// Created by Diego Waxemberg on 10/14/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
//
#import "Computer.h"
@implementation Computer
- (id) initWithHost:(NSNetService *)host {
self = [super init];
self.hostName = [host hostName];
self.displayName = [host name];
return self;
}
- (id) initWithIp:(NSString*)host {
self = [super init];
self.hostName = host;
self.displayName = host;
return self;
}
- (BOOL)isEqual:(id)object {
if ([object isKindOfClass:[Computer class]]) {
return [self.hostName isEqual:[object valueForKey:@"hostName"]];
} else {
return NO;
}
}
- (NSUInteger)hash {
NSUInteger prime = 31;
NSUInteger result = 1;
result = prime * result + (self.hostName == nil ? 0 : [self.hostName hash]);
return result;
}
@end

View File

@ -10,6 +10,14 @@
@interface Utils : NSObject
typedef NS_ENUM(int, PairState) {
PairStateUnknown,
PairStateUnpaired,
PairStatePaired
};
FOUNDATION_EXPORT NSString *const deviceName;
+ (NSData*) randomBytes:(NSInteger)length;
+ (NSString*) bytesToHex:(NSData*)data;
+ (NSData*) hexToBytes:(NSString*) hex;

View File

@ -13,6 +13,7 @@
#include <netdb.h>
@implementation Utils
NSString *const deviceName = @"roth";
+ (NSData*) randomBytes:(NSInteger)length {
char* bytes = malloc(length);

View File

@ -7,7 +7,7 @@
//
#import <UIKit/UIKit.h>
#import "MDNSManager.h"
#import "DiscoveryManager.h"
#import "PairManager.h"
#import "StreamConfiguration.h"
#import "UIComputerView.h"
@ -15,7 +15,7 @@
#import "AppManager.h"
#import "SWRevealViewController.h"
@interface MainFrameViewController : UICollectionViewController <MDNSCallback, PairCallback, HostCallback, AppCallback, AppAssetCallback, NSURLConnectionDelegate, SWRevealViewControllerDelegate>
@interface MainFrameViewController : UICollectionViewController <DiscoveryCallback, PairCallback, HostCallback, AppCallback, AppAssetCallback, NSURLConnectionDelegate, SWRevealViewControllerDelegate>
@property (strong, nonatomic) IBOutlet UIButton *limelightLogoButton;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *computerNameButton;

View File

@ -6,7 +6,6 @@
//
#import "MainFrameViewController.h"
#import "Computer.h"
#import "CryptoManager.h"
#import "HttpManager.h"
#import "Connection.h"
@ -22,17 +21,15 @@
@implementation MainFrameViewController {
NSOperationQueue* _opQueue;
MDNSManager* _mDNSManager;
Computer* _selectedHost;
Host* _selectedHost;
NSString* _uniqueId;
NSData* _cert;
NSString* _currentGame;
DiscoveryManager* _discMan;
UIAlertView* _pairAlert;
UIScrollView* hostScrollView;
int currentPosition;
}
static NSString* deviceName = @"roth";
static NSMutableSet* hostList;
static NSArray* appList;
static StreamConfiguration* streamConfig;
@ -66,13 +63,14 @@ static StreamConfiguration* streamConfig;
- (void)alreadyPaired {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
HttpManager* hMan = [[HttpManager alloc] initWithHost:_selectedHost.hostName uniqueId:_uniqueId deviceName:deviceName cert:_cert];
NSData* appListResp = [hMan executeRequestSynchronously:[hMan newAppListRequest]];
appList = [HttpManager getAppListFromXML:appListResp];
dispatch_async(dispatch_get_main_queue(), ^{
[self updateApps];
_computerNameButton.title = _selectedHost.displayName;
NSLog(@"Setting _computerNameButton.title: %@", _selectedHost.name);
_computerNameButton.title = _selectedHost.name;
});
HttpManager* hMan = [[HttpManager alloc] initWithHost:_selectedHost.address uniqueId:_uniqueId deviceName:deviceName cert:_cert];
NSData* appListResp = [hMan executeRequestSynchronously:[hMan newAppListRequest]];
appList = [HttpManager getAppListFromXML:appListResp];
[AppManager retrieveAppAssets:appList withManager:hMan andCallback:self];
});
@ -97,11 +95,11 @@ static StreamConfiguration* streamConfig;
[self presentViewController:alert animated:YES completion:nil];
}
- (void) hostClicked:(Computer *)computer {
NSLog(@"Clicked host: %@", computer.displayName);
_selectedHost = computer;
- (void) hostClicked:(Host *)host {
NSLog(@"Clicked host: %@", host.name);
_selectedHost = host;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
HttpManager* hMan = [[HttpManager alloc] initWithHost:computer.hostName uniqueId:_uniqueId deviceName:deviceName cert:_cert];
HttpManager* hMan = [[HttpManager alloc] initWithHost:host.address uniqueId:_uniqueId deviceName:deviceName cert:_cert];
NSData* serverInfoResp = [hMan executeRequestSynchronously:[hMan newServerInfoRequest]];
if ([[HttpManager getStringFromXML:serverInfoResp tag:@"PairStatus"] isEqualToString:@"1"]) {
NSLog(@"Already Paired");
@ -119,17 +117,24 @@ static StreamConfiguration* streamConfig;
UIAlertController* alertController = [UIAlertController alertControllerWithTitle:@"Host Address" message:@"Please enter a hostname or IP address" preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
NSString* host = ((UITextField*)[[alertController textFields] objectAtIndex:0]).text;
Computer* newHost = [[Computer alloc] initWithIp:host];
[hostList addObject:newHost];
[self updateHosts:[hostList allObjects]];
DataManager* dataMan = [[DataManager alloc] init];
[dataMan createHost:newHost.displayName hostname:newHost.hostName];
[dataMan saveHosts];
//TODO: get pair state
NSString* hostAddress = ((UITextField*)[[alertController textFields] objectAtIndex:0]).text;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[_discMan discoverHost:hostAddress withCallback:^(Host* host){
if (host != nil) {
DataManager* dataMan = [[DataManager alloc] init];
[dataMan saveHosts];
dispatch_async(dispatch_get_main_queue(), ^{
[hostList addObject:host];
[self updateHosts];
});
} else {
UIAlertController* hostNotFoundAlert = [UIAlertController alertControllerWithTitle:@"Host Not Found" message:[NSString stringWithFormat:@"Unable to connect to host: \n%@", hostAddress] preferredStyle:UIAlertControllerStyleAlert];
[hostNotFoundAlert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:nil]];
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:hostNotFoundAlert animated:YES completion:nil];
});
}
}];});
}]];
[alertController addTextFieldWithConfigurationHandler:nil];
[self presentViewController:alertController animated:YES completion:nil];
@ -138,8 +143,8 @@ static StreamConfiguration* streamConfig;
- (void) appClicked:(App *)app {
NSLog(@"Clicked app: %@", app.appName);
streamConfig = [[StreamConfiguration alloc] init];
streamConfig.host = _selectedHost.hostName;
streamConfig.hostAddr = [Utils resolveHost:_selectedHost.hostName];
streamConfig.host = _selectedHost.address;
streamConfig.hostAddr = [Utils resolveHost:_selectedHost.address];
streamConfig.appID = app.appId;
if (streamConfig.hostAddr == 0) {
[self displayDnsFailedDialog];
@ -169,7 +174,7 @@ static StreamConfiguration* streamConfig;
[alertController addAction:[UIAlertAction actionWithTitle:@"Quit App" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){
NSLog(@"Quitting application: %@", currentApp.appName);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
HttpManager* hMan = [[HttpManager alloc] initWithHost:_selectedHost.hostName uniqueId:_uniqueId deviceName:deviceName cert:_cert];
HttpManager* hMan = [[HttpManager alloc] initWithHost:_selectedHost.address uniqueId:_uniqueId deviceName:deviceName cert:_cert];
[hMan executeRequestSynchronously:[hMan newQuitAppRequest]];
// TODO: handle failure to quit app
currentApp.isRunning = NO;
@ -198,15 +203,6 @@ static StreamConfiguration* streamConfig;
return nil;
}
- (App*) findAppInAppList:(NSString*)appId {
for (App* app in appList) {
if ([app.appId isEqualToString:appId]) {
return app;
}
}
return nil;
}
- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position {
// If we moved back to the center position, we should save the settings
if (position == FrontViewPositionLeft) {
@ -253,7 +249,9 @@ static StreamConfiguration* streamConfig;
[hostScrollView setShowsHorizontalScrollIndicator:NO];
[self retrieveSavedHosts];
[self updateHosts:[hostList allObjects]];
_discMan = [[DiscoveryManager alloc] initWithHosts:[hostList allObjects] andCallback:self];
[self updateHosts];
[self.view addSubview:hostScrollView];
}
@ -267,8 +265,7 @@ static StreamConfiguration* streamConfig;
[self.navigationController.navigationBar setShadowImage:fakeImage];
[self.navigationController.navigationBar setBackgroundImage:fakeImage forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
_mDNSManager = [[MDNSManager alloc] initWithCallback:self];
[_mDNSManager searchForHosts];
[_discMan startDiscovery];
// This will refresh the applist
if (_selectedHost != nil) {
@ -279,28 +276,38 @@ static StreamConfiguration* streamConfig;
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[_mDNSManager stopSearching];
// when discovery stops, we must create a new instance because you cannot restart an NSOperation when it is finished
[_discMan stopDiscovery];
_discMan = [[DiscoveryManager alloc] initWithHosts:[hostList allObjects] andCallback:self];
// In case the host objects were updated in the background
[[[DataManager alloc] init] saveHosts];
}
- (void) retrieveSavedHosts {
//TODO: Get rid of Computer and only use Host
DataManager* dataMan = [[DataManager alloc] init];
NSArray* hosts = [dataMan retrieveHosts];
for (Host* host in hosts) {
Computer* comp = [[Computer alloc] initWithIp:host.address];
comp.displayName = host.name;
[hostList addObject:comp];
}
[hostList addObjectsFromArray:hosts];
}
- (void)updateHosts:(NSArray *)hosts {
[hostList addObjectsFromArray:hosts];
- (void) updateAllHosts:(NSArray *)hosts {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"New host list:");
for (Host* host in hosts) {
NSLog(@"Host: \n{\n\t name:%@ \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);
}
[hostList removeAllObjects];
[hostList addObjectsFromArray:hosts];
[self updateHosts];
});
}
- (void)updateHosts {
NSLog(@"Updating hosts...");
[[hostScrollView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
UIComputerView* addComp = [[UIComputerView alloc] initForAddWithCallback:self];
UIComputerView* compView;
float prevEdge = -1;
for (Computer* comp in hostList) {
for (Host* comp in hostList) {
compView = [[UIComputerView alloc] initWithComputer:comp andCallback:self];
compView.center = CGPointMake([self getCompViewX:compView addComp:addComp prevEdge:prevEdge], hostScrollView.frame.size.height / 2);
prevEdge = compView.frame.origin.x + compView.frame.size.width;