diff --git a/Limelight.xcodeproj/project.pbxproj b/Limelight.xcodeproj/project.pbxproj index 757fe74..3d45ea7 100644 --- a/Limelight.xcodeproj/project.pbxproj +++ b/Limelight.xcodeproj/project.pbxproj @@ -27,7 +27,6 @@ FB290D1B19B2C406004C83CF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FB290D1919B2C406004C83CF /* InfoPlist.strings */; }; FB290D1D19B2C406004C83CF /* LimelightTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FB290D1C19B2C406004C83CF /* LimelightTests.m */; }; FB290D3719B2C6E3004C83CF /* Connection.m in Sources */ = {isa = PBXBuildFile; fileRef = FB290D2719B2C6E3004C83CF /* Connection.m */; }; - FB290D3819B2C6E3004C83CF /* ConnectionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = FB290D2919B2C6E3004C83CF /* ConnectionHandler.m */; }; FB290D3919B2C6E3004C83CF /* MainFrameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FB290D2B19B2C6E3004C83CF /* MainFrameViewController.m */; }; FB290D3A19B2C6E3004C83CF /* StreamFrameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FB290D2D19B2C6E3004C83CF /* StreamFrameViewController.m */; }; FB290DB719B2C870004C83CF /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290DB619B2C870004C83CF /* libz.dylib */; }; @@ -39,6 +38,8 @@ FB63FCF219F43EBC00227761 /* PairManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB63FCF119F43EBC00227761 /* PairManager.m */; }; FB63FCF719F573BE00227761 /* StreamManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB63FCF619F573BE00227761 /* StreamManager.m */; }; FB7E794419C8B71B00A15F68 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FB7E794319C8B71B00A15F68 /* libiconv.dylib */; }; + FB8945EF19F5C3CD00339C8A /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = FB8945EE19F5C3CD00339C8A /* Utils.m */; }; + FB8945F219F5C76C00339C8A /* StreamConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = FB8945F119F5C76C00339C8A /* StreamConfiguration.m */; }; FBAB29F219EDB08B00929691 /* MDNSManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FBAB29F119EDB08B00929691 /* MDNSManager.m */; }; FBAB29F619EDE0F800929691 /* Computer.m in Sources */ = {isa = PBXBuildFile; fileRef = FBAB29F519EDE0F800929691 /* Computer.m */; }; FBAB29FC19EE13AA00929691 /* CryptoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FBAB29FB19EE13AA00929691 /* CryptoManager.m */; }; @@ -104,8 +105,6 @@ FB290D1C19B2C406004C83CF /* LimelightTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LimelightTests.m; sourceTree = ""; }; FB290D2619B2C6E3004C83CF /* Connection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Connection.h; sourceTree = ""; }; FB290D2719B2C6E3004C83CF /* Connection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Connection.m; sourceTree = ""; }; - FB290D2819B2C6E3004C83CF /* ConnectionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConnectionHandler.h; sourceTree = ""; }; - FB290D2919B2C6E3004C83CF /* ConnectionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConnectionHandler.m; sourceTree = ""; }; FB290D2A19B2C6E3004C83CF /* MainFrameViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainFrameViewController.h; sourceTree = ""; }; FB290D2B19B2C6E3004C83CF /* MainFrameViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainFrameViewController.m; sourceTree = ""; }; FB290D2C19B2C6E3004C83CF /* StreamFrameViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamFrameViewController.h; sourceTree = ""; }; @@ -127,6 +126,10 @@ FB63FCF519F573BE00227761 /* StreamManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamManager.h; sourceTree = ""; }; FB63FCF619F573BE00227761 /* StreamManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StreamManager.m; sourceTree = ""; }; FB7E794319C8B71B00A15F68 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; + FB8945ED19F5C3CD00339C8A /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utils.h; sourceTree = ""; }; + FB8945EE19F5C3CD00339C8A /* Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Utils.m; sourceTree = ""; }; + FB8945F019F5C76C00339C8A /* StreamConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamConfiguration.h; sourceTree = ""; }; + FB8945F119F5C76C00339C8A /* StreamConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StreamConfiguration.m; sourceTree = ""; }; FBAB29F119EDB08B00929691 /* MDNSManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDNSManager.m; sourceTree = ""; }; FBAB29F319EDB0C400929691 /* MDNSManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDNSManager.h; sourceTree = ""; }; FBAB29F419EDE0F800929691 /* Computer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Computer.h; sourceTree = ""; }; @@ -305,8 +308,6 @@ FB290D3019B2C6E3004C83CF /* Video */, FB290D2619B2C6E3004C83CF /* Connection.h */, FB290D2719B2C6E3004C83CF /* Connection.m */, - FB290D2819B2C6E3004C83CF /* ConnectionHandler.h */, - FB290D2919B2C6E3004C83CF /* ConnectionHandler.m */, FB290D2A19B2C6E3004C83CF /* MainFrameViewController.h */, FB290D2B19B2C6E3004C83CF /* MainFrameViewController.m */, FB290D2C19B2C6E3004C83CF /* StreamFrameViewController.h */, @@ -332,6 +333,10 @@ 984C441719F48D1D0061A500 /* StreamView.m */, FB63FCF519F573BE00227761 /* StreamManager.h */, FB63FCF619F573BE00227761 /* StreamManager.m */, + FB8945ED19F5C3CD00339C8A /* Utils.h */, + FB8945EE19F5C3CD00339C8A /* Utils.m */, + FB8945F019F5C76C00339C8A /* StreamConfiguration.h */, + FB8945F119F5C76C00339C8A /* StreamConfiguration.m */, ); path = Limelight; sourceTree = ""; @@ -609,6 +614,9 @@ LastUpgradeCheck = 0510; ORGANIZATIONNAME = "Limelight Stream"; TargetAttributes = { + FB290CED19B2C406004C83CF = { + DevelopmentTeam = DM46QST4M7; + }; FB290D0D19B2C406004C83CF = { TestTargetID = FB290CED19B2C406004C83CF; }; @@ -689,6 +697,7 @@ FBAB29FC19EE13AA00929691 /* CryptoManager.m in Sources */, FB63FCF719F573BE00227761 /* StreamManager.m in Sources */, FB63FCF219F43EBC00227761 /* PairManager.m in Sources */, + FB8945EF19F5C3CD00339C8A /* Utils.m in Sources */, 98A03B5019F3598400861ACA /* VideoDecoderRenderer.m in Sources */, FBAB29F219EDB08B00929691 /* MDNSManager.m in Sources */, FBC8622D19F0BEFB0087327B /* HttpManager.m in Sources */, @@ -697,11 +706,11 @@ FBAB29F619EDE0F800929691 /* Computer.m in Sources */, FB290D3A19B2C6E3004C83CF /* StreamFrameViewController.m in Sources */, FB290D0019B2C406004C83CF /* main.m in Sources */, + FB8945F219F5C76C00339C8A /* StreamConfiguration.m in Sources */, FB290D3919B2C6E3004C83CF /* MainFrameViewController.m in Sources */, 984C441819F48D1D0061A500 /* StreamView.m in Sources */, FB290D3719B2C6E3004C83CF /* Connection.m in Sources */, FBCC0E9D19F00659009729EB /* mkcert.c in Sources */, - FB290D3819B2C6E3004C83CF /* ConnectionHandler.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -825,6 +834,8 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Limelight/Limelight-Prefix.pch"; HEADER_SEARCH_PATHS = ( @@ -841,6 +852,7 @@ "$(PROJECT_DIR)/libs/openssl/lib", ); PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; WRAPPER_EXTENSION = app; }; name = Debug; @@ -850,6 +862,8 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Limelight/Limelight-Prefix.pch"; HEADER_SEARCH_PATHS = ( @@ -866,6 +880,7 @@ "$(PROJECT_DIR)/libs/openssl/lib", ); PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; WRAPPER_EXTENSION = app; }; name = Release; diff --git a/Limelight/AppDelegate.h b/Limelight/AppDelegate.h index 1b744af..3e323b4 100644 --- a/Limelight/AppDelegate.h +++ b/Limelight/AppDelegate.h @@ -18,6 +18,5 @@ - (void)saveContext; - (NSURL *)applicationDocumentsDirectory; -+ (NSOperationQueue*) getMainOpQueue; @end diff --git a/Limelight/AppDelegate.m b/Limelight/AppDelegate.m index d672ad8..2783fd1 100644 --- a/Limelight/AppDelegate.m +++ b/Limelight/AppDelegate.m @@ -18,15 +18,9 @@ static NSOperationQueue* mainQueue; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - mainQueue = [[NSOperationQueue alloc]init]; return YES; } -+ (NSOperationQueue*) getMainOpQueue -{ - return mainQueue; -} - - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. diff --git a/Limelight/Computer.h b/Limelight/Computer.h index 40ea8d5..17fec12 100644 --- a/Limelight/Computer.h +++ b/Limelight/Computer.h @@ -14,6 +14,5 @@ @property BOOL paired; - (id) initWithHost:(NSNetService*)host; -- (int) resolveHost; @end diff --git a/Limelight/Computer.m b/Limelight/Computer.m index d6ef5e7..2d03366 100644 --- a/Limelight/Computer.m +++ b/Limelight/Computer.m @@ -8,10 +8,6 @@ #import "Computer.h" -#include -#include -#include - @implementation Computer - (id) initWithHost:(NSNetService *)host { @@ -23,33 +19,4 @@ return self; } -- (int) resolveHost -{ - struct hostent *hostent; - - if (inet_addr([self.hostName UTF8String]) != INADDR_NONE) - { - // Already an IP address - int addr = inet_addr([self.hostName UTF8String]); - NSLog(@"host address: %d", addr); - return addr; - } - else - { - hostent = gethostbyname([self.hostName UTF8String]); - if (hostent != NULL) - { - char* ipstr = inet_ntoa(*(struct in_addr*)hostent->h_addr_list[0]); - NSLog(@"Resolved %@ -> %s", self.hostName, ipstr); - int addr = inet_addr(ipstr); - NSLog(@"host address: %d", addr); - return addr; - } - else - { - NSLog(@"Failed to resolve host: %d", h_errno); - return -1; - } - } -} @end diff --git a/Limelight/Connection.h b/Limelight/Connection.h index 50f66ab..502ce42 100644 --- a/Limelight/Connection.h +++ b/Limelight/Connection.h @@ -8,10 +8,11 @@ #import #import "VideoDecoderRenderer.h" +#import "StreamConfiguration.h" @interface Connection : NSOperation --(id) initWithHost:(int)ipaddr key:(NSData*)rikey keyId:(int)rikeyid width:(int)width height:(int)height refreshRate:(int)refreshRate renderer:(VideoDecoderRenderer*)myRenderer; +-(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer; -(void) main; @end diff --git a/Limelight/Connection.m b/Limelight/Connection.m index fa89453..37c3196 100644 --- a/Limelight/Connection.m +++ b/Limelight/Connection.m @@ -193,22 +193,22 @@ void ClDisplayTransientMessage(char* message) NSLog(@"DisplayTransientMessage: %s", message); } --(id) initWithHost:(int)ipaddr key:(NSData*)rikey keyId:(int)rikeyid width:(int)width height:(int)height refreshRate:(int)refreshRate renderer:(VideoDecoderRenderer*)myRenderer +-(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer { self = [super init]; - host = ipaddr; + host = config.host; renderer = myRenderer; - streamConfig.width = width; - streamConfig.height = height; - streamConfig.fps = 60; - streamConfig.bitrate = 5000; + streamConfig.width = config.width; + streamConfig.height = config.height; + streamConfig.fps = config.frameRate; + streamConfig.bitrate = config.bitRate; streamConfig.packetSize = 1024; - memcpy(streamConfig.remoteInputAesKey, [rikey bytes], [rikey length]); + memcpy(streamConfig.remoteInputAesKey, [config.riKey bytes], [config.riKey length]); memset(streamConfig.remoteInputAesIv, 0, 16); - rikeyid = htonl(rikeyid); - memcpy(streamConfig.remoteInputAesIv, &rikeyid, sizeof(rikeyid)); + int riKeyId = htonl(config.riKeyId); + memcpy(streamConfig.remoteInputAesIv, &riKeyId, sizeof(riKeyId)); drCallbacks.setup = DrSetup; drCallbacks.start = DrStart; diff --git a/Limelight/ConnectionHandler.h b/Limelight/ConnectionHandler.h deleted file mode 100644 index f590e35..0000000 --- a/Limelight/ConnectionHandler.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// ConnectionHandler.h -// Limelight-iOS -// -// Created by Diego Waxemberg on 1/27/14. -// Copyright (c) 2014 Diego Waxemberg. All rights reserved. -// - -#import - -@interface ConnectionHandler : NSOperation -@property NSString* hostName; -@property int mode; - -+ (void) pairWithHost:(NSString*)host; -+ (void) streamWithHost:(NSString*)host viewController:(UIViewController*)viewCont; -+ (NSString*) resolveHost:(NSString*)host; - -@end diff --git a/Limelight/ConnectionHandler.m b/Limelight/ConnectionHandler.m deleted file mode 100644 index 9ce4a35..0000000 --- a/Limelight/ConnectionHandler.m +++ /dev/null @@ -1,336 +0,0 @@ -// -// ConnectionHandler.m -// Limelight-iOS -// -// Created by Diego Waxemberg on 1/27/14. -// Copyright (c) 2014 Diego Waxemberg. All rights reserved. -// - -#import "ConnectionHandler.h" -#import "AppDelegate.h" -#import -#import "MainFrameViewController.h" - -#include -#include -#include -#include -#include - -@implementation ConnectionHandler -static const int PAIR_MODE = 0x1; -static const int STREAM_MODE = 0x2; - -static MainFrameViewController* viewCont; - -+ (void)streamWithHost:(NSString *)host viewController:(MainFrameViewController *)viewController -{ - viewCont = viewController; - ConnectionHandler* streamHandler = [[ConnectionHandler alloc] initForStream:host]; - [[AppDelegate getMainOpQueue] addOperation:streamHandler]; -} - -+ (void)pairWithHost:(NSString *)host -{ - ConnectionHandler* pairHandler = [[ConnectionHandler alloc] initForPair:host]; - [[AppDelegate getMainOpQueue]addOperation:pairHandler]; -} - -+ (NSString*) resolveHost:(NSString*)host -{ - struct hostent *hostent; - - if (inet_addr([host UTF8String]) != INADDR_NONE) - { - // Already an IP address - return host; - } - else - { - hostent = gethostbyname([host UTF8String]); - if (hostent != NULL) - { - char* ipstr = inet_ntoa(*(struct in_addr*)hostent->h_addr_list[0]); - NSLog(@"Resolved %@ -> %s", host, ipstr); - return [NSString stringWithUTF8String:ipstr]; - } - else - { - NSLog(@"Failed to resolve host: %d", h_errno); - return nil; - } - } -} - -+ (NSString*) getId -{ - // we need to generate some unique id - NSUUID* uniqueId = [ASIdentifierManager sharedManager].advertisingIdentifier; - NSString* idString = [NSString stringWithString:[uniqueId UUIDString]]; - - //use just the last 12 digits because GameStream truncates id's - return [idString substringFromIndex:24]; -} - -+ (NSString*) getName -{ - NSString* name = [UIDevice currentDevice].name; - NSLog(@"Device Name: %@", name); - - //sanitize name - name = [name stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - return name; -} - -- (id) initForStream:(NSString*)host -{ - self = [super init]; - self.hostName = host; - self.mode = STREAM_MODE; - return self; -} - -- (id) initForPair:(NSString*)host -{ - self = [super init]; - self.hostName = host; - self.mode = PAIR_MODE; - return self; -} - -- (void) main -{ - switch (self.mode) - { - case STREAM_MODE: - { - bool pairState; - int err = [self pairState:&pairState]; - if (err) { - NSLog(@"ERROR: Pair state error: %d", err); - break; - } - - if (!pairState) - { - NSLog(@"WARN: Not paired with host!"); - UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Not Paired" - message:@"This device is not paired with the host." - delegate:nil - cancelButtonTitle:@"Okay" - otherButtonTitles:nil, nil]; - [self showAlert:alert]; - return; - } - - //TODO: parse this from http request - unsigned int appId = 67339056; - - NSData* applist = [self httpRequest:[NSString stringWithFormat:@"applist?uniqueid=%@", [ConnectionHandler getId]]]; - - NSString* streamString = [NSString stringWithFormat:@"http://%@:47989/launch?uniqueid=%@&appid=%u", [ConnectionHandler resolveHost:self.hostName], [ConnectionHandler getId], appId]; - NSLog(@"host: %@", self.hostName); - - NSURL* url = [[NSURL alloc] initWithString:streamString]; - - NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url]; - [request setHTTPMethod:@"GET"]; - - NSURLResponse* response = nil; - NSData *response1 = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL]; - - - [viewCont performSelector:@selector(segueIntoStream) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO]; - break; - } - case PAIR_MODE: - { - NSLog(@"Trying to pair to %@...", self.hostName); - - bool pairState; - int err = [self pairState:&pairState]; - if (err) { - NSLog(@"ERROR: Pair state error: %d", err); - break; - } - - NSLog(@"Pair state: %i", pairState); - - if(pairState) - { - UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"Pairing" - message:[NSString stringWithFormat:@"Already paired to:\n %@", self.hostName] - delegate:nil - cancelButtonTitle:@"Okay" - otherButtonTitles:nil, nil]; - [self showAlert:alert]; - NSLog(@"Showing alertview"); - break; - } - - // this will hang until it pairs successfully or unsuccessfully - NSData* pairResponse = [self httpRequest:[NSString stringWithFormat:@"pair?uniqueid=%@&devicename=%@", [ConnectionHandler getId], [ConnectionHandler getName]]]; - - void* buffer = [self getXMLBufferFromData:pairResponse]; - if (buffer == NULL) { - NSLog(@"ERROR: Unable to allocate pair buffer."); - UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Pairing" - message:[NSString stringWithFormat:@"Failed to pair with host:\n %@", self.hostName] - delegate:nil - cancelButtonTitle:@"Okay" - otherButtonTitles:nil, nil]; - [self showAlert:alert]; - break; - } - xmlDocPtr doc = xmlParseMemory(buffer, [pairResponse length]-1); - - if (doc == NULL) { - NSLog(@"ERROR: An error occured trying to parse pair response."); - break; - } - - xmlNodePtr node = xmlDocGetRootElement(doc); - node = node->xmlChildrenNode; - while (node != NULL) { - NSLog(@"Node: %s", node->name); - if (!xmlStrcmp(node->name, (const xmlChar*)"sessionid")) - { - xmlChar* sessionid = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); - - if (xmlStrcmp(sessionid, (xmlChar*)"0")) { - UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Pairing" - message:[NSString stringWithFormat:@"Successfully paired to host:\n %@", self.hostName] - delegate:nil - cancelButtonTitle:@"Okay" - otherButtonTitles:nil, nil]; - [self showAlert:alert]; - - } else { - UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Pairing" - message:[NSString stringWithFormat:@"Pairing was declined by host:\n %@", self.hostName] - delegate:nil - cancelButtonTitle:@"Okay" - otherButtonTitles:nil, nil]; - [self showAlert:alert]; - } - - xmlFree(sessionid); - goto cleanup; - } - node = node->next; - } - - NSLog(@"ERROR: Could not find \"sessionid\" element in XML"); - - cleanup: - xmlFreeNode(node); - break; - } - default: - { - NSLog(@"Invalid connection mode specified!!!"); - } - } -} - -- (int) pairState: (bool*)paired -{ - int err; - NSData* pairData = [self httpRequest:[NSString stringWithFormat:@"pairstate?uniqueid=%@", [ConnectionHandler getId]]]; - - void* buffer = [self getXMLBufferFromData:pairData]; - - if (buffer == NULL) { - NSLog(@"ERROR: Unable to allocate pair state buffer."); - UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Pairing" - message:[NSString stringWithFormat:@"Failed to get pair state with host:\n %@", self.hostName] - delegate:nil - cancelButtonTitle:@"Okay" - otherButtonTitles:nil, nil]; - [self showAlert:alert]; - return -1; - } - - xmlDocPtr doc = xmlParseMemory(buffer, [pairData length]-1); - - if (doc == NULL) { - NSLog(@"ERROR: An error occured trying to parse pair state."); - return -1; - } - - xmlNodePtr node = xmlDocGetRootElement(doc); - while (node != NULL) { - NSLog(@"Node: %s", node->name); - if (!xmlStrcmp(node->name, (const xmlChar*)"paired")) - { - xmlChar* pairState = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); - *paired = !xmlStrcmp(pairState, (const xmlChar*)"1"); - err = 0; - - xmlFree(pairState); - goto cleanup; - } - node = node->xmlChildrenNode; - } - - NSLog(@"ERROR: Could not find \"paired\" element in XML"); - err = -2; - -cleanup: - xmlFreeNode(node); - return err; -} - -- (NSData*) httpRequest:(NSString*)args -{ - NSString* requestString = [NSString stringWithFormat:@"http://%@:47989/%@", [ConnectionHandler resolveHost:self.hostName], args]; - - NSLog(@"Making HTTP request: %@", requestString); - - NSURL* url = [[NSURL alloc] initWithString:requestString]; - - NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url]; - [request setHTTPMethod:@"GET"]; - [request setTimeoutInterval:7]; - - NSURLResponse* response = nil; - NSError* error = nil; - NSData* responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; - - if (error != nil) { - NSLog(@"An error occured making HTTP request: %@\n Caused by: %@", [error localizedDescription], [error localizedFailureReason]); - } - return responseData; -} - - -- (void*) getXMLBufferFromData:(NSData*)data -{ - if (data == nil) { - NSLog(@"ERROR: No data to get XML from!"); - return NULL; - } - char* buffer = malloc([data length] + 1); - if (buffer == NULL) { - NSLog(@"ERROR: Unable to allocate XML buffer."); - return NULL; - } - [data getBytes:buffer length:[data length]]; - buffer[[data length]] = 0; - - NSLog(@"Buffer: %s", buffer); - - //#AllTheJank - void* newBuffer = (void*)[[[NSString stringWithUTF8String:buffer]stringByReplacingOccurrencesOfString:@"UTF-16" withString:@"UTF-8" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [data length])] UTF8String]; - - NSLog(@"New Buffer: %s", newBuffer); - free(buffer); - return newBuffer; -} - -- (void) showAlert:(UIAlertView*) alert -{ - [alert performSelector:@selector(show) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO]; -} - -@end diff --git a/Limelight/Images.xcassets/AppIcon.appiconset/Contents.json b/Limelight/Images.xcassets/AppIcon.appiconset/Contents.json index 91bf9c1..b7f3352 100644 --- a/Limelight/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/Limelight/Images.xcassets/AppIcon.appiconset/Contents.json @@ -15,6 +15,11 @@ "size" : "60x60", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, { "idiom" : "ipad", "size" : "29x29", diff --git a/Limelight/MainFrameViewController.h b/Limelight/MainFrameViewController.h index 760da15..3dcb829 100644 --- a/Limelight/MainFrameViewController.h +++ b/Limelight/MainFrameViewController.h @@ -19,10 +19,8 @@ @property (strong, nonatomic) NSArray* streamConfigVals; @property (strong, nonatomic) NSArray* hostPickerVals; -+ (int) getResolvedHost; -+ (NSData*) getRiKey; -+ (int) getRiKeyId; - - (void) segueIntoStream; ++ (NSString*) getHost; + @end diff --git a/Limelight/MainFrameViewController.m b/Limelight/MainFrameViewController.m index a555ce9..726eb43 100644 --- a/Limelight/MainFrameViewController.m +++ b/Limelight/MainFrameViewController.m @@ -7,7 +7,6 @@ // #import "MainFrameViewController.h" -#import "ConnectionHandler.h" #import "Computer.h" #import "CryptoManager.h" #import "HttpManager.h" @@ -20,22 +19,11 @@ MDNSManager* _mDNSManager; Computer* _selectedHost; UIAlertView* _pairAlert; - StreamManager* _streamMan; } -static int resolvedHost; -static NSData* riKey; -static int riKeyId; +static NSString* host; -+ (int) getResolvedHost { - return resolvedHost; -} - -+ (NSData*) getRiKey { - return riKey; -} - -+ (int) getRiKeyId { - return riKeyId; ++ (NSString*) getHost { + return host; } - (void)PairButton:(UIButton *)sender @@ -77,14 +65,7 @@ static int riKeyId; - (void)StreamButton:(UIButton *)sender { NSLog(@"Stream Button Pressed!"); - _streamMan = [[StreamManager alloc] initWithHost:_selectedHost.hostName andViewController:self]; - [_opQueue addOperation:_streamMan]; -} - -- (void) segueIntoStream { - resolvedHost = [_selectedHost resolveHost]; - riKey = [_streamMan getRiKey]; - riKeyId = [_streamMan getRiKeyId]; + host = _selectedHost.hostName; [self performSegueWithIdentifier:@"createStreamFrame" sender:self]; } diff --git a/Limelight/PairManager.h b/Limelight/PairManager.h index ed2728d..12cd30e 100644 --- a/Limelight/PairManager.h +++ b/Limelight/PairManager.h @@ -23,7 +23,4 @@ - (NSData*) saltPIN:(NSString*)PIN; - (void) initiatePair; -+ (NSData*) randomBytes:(NSInteger)length; -+ (NSString*) bytesToHex:(NSData*)data; - @end diff --git a/Limelight/PairManager.m b/Limelight/PairManager.m index 8403f7b..9c77f68 100644 --- a/Limelight/PairManager.m +++ b/Limelight/PairManager.m @@ -8,6 +8,7 @@ #import "PairManager.h" #import "CryptoManager.h" +#import "Utils.h" #include @@ -54,7 +55,7 @@ CryptoManager* cryptoMan = [[CryptoManager alloc] init]; NSData* aesKey = [cryptoMan createAESKeyFromSalt:salt]; - NSData* randomChallenge = [PairManager randomBytes:16]; + NSData* randomChallenge = [Utils randomBytes:16]; NSData* encryptedChallenge = [cryptoMan aesEncrypt:randomChallenge withKey:aesKey]; NSData* challengeResp = [_httpManager executeRequestSynchronously:[_httpManager newChallengeRequest:encryptedChallenge]]; @@ -65,13 +66,13 @@ return; } - NSData* encServerChallengeResp = [self hexToBytes:[HttpManager getStringFromXML:challengeResp tag:@"challengeresponse"]]; + NSData* encServerChallengeResp = [Utils hexToBytes:[HttpManager getStringFromXML:challengeResp tag:@"challengeresponse"]]; NSData* decServerChallengeResp = [cryptoMan aesDecrypt:encServerChallengeResp withKey:aesKey]; NSData* serverResponse = [decServerChallengeResp subdataWithRange:NSMakeRange(0, 20)]; NSData* serverChallenge = [decServerChallengeResp subdataWithRange:NSMakeRange(20, 16)]; - NSData* clientSecret = [PairManager randomBytes:16]; + NSData* clientSecret = [Utils randomBytes:16]; NSData* challengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:serverChallenge with:[CryptoManager getSignatureFromCert:_cert]] with:clientSecret]]; NSData* challengeRespEncrypted = [cryptoMan aesEncrypt:challengeRespHash withKey:aesKey]; @@ -83,18 +84,18 @@ return; } - NSData* serverSecretResp = [self hexToBytes:[HttpManager getStringFromXML:secretResp tag:@"pairingsecret"]]; + NSData* serverSecretResp = [Utils hexToBytes:[HttpManager getStringFromXML:secretResp tag:@"pairingsecret"]]; NSData* serverSecret = [serverSecretResp subdataWithRange:NSMakeRange(0, 16)]; NSData* serverSignature = [serverSecretResp subdataWithRange:NSMakeRange(16, 256)]; - if (![cryptoMan verifySignature:serverSecret withSignature:serverSignature andCert:[self hexToBytes:plainCert]]) { + if (![cryptoMan verifySignature:serverSecret withSignature:serverSignature andCert:[Utils hexToBytes:plainCert]]) { [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; //TODO: better message [_callback pairFailed:@"verifySignature failed"]; return; } - NSData* serverChallengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:randomChallenge with:[CryptoManager getSignatureFromCert:[self hexToBytes:plainCert]]] with:serverSecret]]; + NSData* serverChallengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:randomChallenge with:[CryptoManager getSignatureFromCert:[Utils hexToBytes:plainCert]]] with:serverSecret]]; if (![serverChallengeRespHash isEqual:serverResponse]) { [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; //TODO: better message @@ -103,7 +104,7 @@ } NSData* clientPairingSecret = [self concatData:clientSecret with:[cryptoMan signData:clientSecret withKey:[CryptoManager readKeyFromFile]]]; - NSData* clientSecretResp = [_httpManager executeRequestSynchronously:[_httpManager newClientSecretRespRequest:[PairManager bytesToHex:clientPairingSecret]]]; + NSData* clientSecretResp = [_httpManager executeRequestSynchronously:[_httpManager newClientSecretRespRequest:[Utils bytesToHex:clientPairingSecret]]]; if (![[HttpManager getStringFromXML:clientSecretResp tag:@"paired"] isEqual:@"1"]) { [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; //TODO: better message @@ -131,52 +132,14 @@ NSString* PIN = [NSString stringWithFormat:@"%d%d%d%d", arc4random() % 10, arc4random() % 10, arc4random() % 10, arc4random() % 10]; - NSLog(@"PIN: %@", PIN); return PIN; } - (NSData*) saltPIN:(NSString*)PIN { NSMutableData* saltedPIN = [[NSMutableData alloc] initWithCapacity:20]; - [saltedPIN appendData:[PairManager randomBytes:16]]; + [saltedPIN appendData:[Utils randomBytes:16]]; [saltedPIN appendBytes:[PIN UTF8String] length:4]; - - //NSLog(@"Salted PIN: %@", [saltedPIN description]); return saltedPIN; } -+ (NSData*) randomBytes:(NSInteger)length { - char* bytes = malloc(length); - arc4random_buf(bytes, length); - NSData* randomData = [NSData dataWithBytes:bytes length:length]; - free(bytes); - return randomData; -} - -- (NSData*) hexToBytes:(NSString*) hex { - int len = [hex length]; - NSMutableData* data = [NSMutableData dataWithCapacity:len / 2]; - char byteChars[3] = {'\0','\0','\0'}; - unsigned long wholeByte; - - const char *chars = [hex UTF8String]; - int i = 0; - while (i < len) { - byteChars[0] = chars[i++]; - byteChars[1] = chars[i++]; - wholeByte = strtoul(byteChars, NULL, 16); - [data appendBytes:&wholeByte length:1]; - } - - return data; -} - -+ (NSString*) bytesToHex:(NSData*)data { - const unsigned char* bytes = [data bytes]; - NSMutableString *hex = [[NSMutableString alloc] init]; - for (int i = 0; i < [data length]; i++) { - [hex appendFormat:@"%02X" , bytes[i]]; - } - return hex; -} - @end diff --git a/Limelight/StreamConfiguration.h b/Limelight/StreamConfiguration.h new file mode 100644 index 0000000..7842358 --- /dev/null +++ b/Limelight/StreamConfiguration.h @@ -0,0 +1,21 @@ +// +// StreamConfiguration.h +// Limelight +// +// Created by Diego Waxemberg on 10/20/14. +// Copyright (c) 2014 Limelight Stream. All rights reserved. +// + +#import + +@interface StreamConfiguration : NSObject + +@property int host; +@property int width; +@property int height; +@property int frameRate; +@property int bitRate; +@property int riKeyId; +@property NSData* riKey; + +@end diff --git a/Limelight/StreamConfiguration.m b/Limelight/StreamConfiguration.m new file mode 100644 index 0000000..e31ebd1 --- /dev/null +++ b/Limelight/StreamConfiguration.m @@ -0,0 +1,13 @@ +// +// StreamConfiguration.m +// Limelight +// +// Created by Diego Waxemberg on 10/20/14. +// Copyright (c) 2014 Limelight Stream. All rights reserved. +// + +#import "StreamConfiguration.h" + +@implementation StreamConfiguration +@synthesize host, width, height, frameRate, bitRate, riKeyId, riKey; +@end diff --git a/Limelight/StreamFrameViewController.m b/Limelight/StreamFrameViewController.m index b978400..1f4d5d1 100644 --- a/Limelight/StreamFrameViewController.m +++ b/Limelight/StreamFrameViewController.m @@ -10,7 +10,7 @@ #import "MainFrameViewController.h" #import "Connection.h" #import "VideoDecoderRenderer.h" -#import "ConnectionHandler.h" +#import "StreamManager.h" #include #include @@ -24,12 +24,9 @@ [UIApplication sharedApplication].idleTimerDisabled = YES; - VideoDecoderRenderer* renderer = [[VideoDecoderRenderer alloc]initWithView:self.view]; - - Connection* conn = [[Connection alloc] initWithHost:[MainFrameViewController getResolvedHost] key:[MainFrameViewController getRiKey] keyId:[MainFrameViewController getRiKeyId] width:1280 height:720 refreshRate:60 renderer:renderer]; - + StreamManager* streamMan = [[StreamManager alloc] initWithHost:[MainFrameViewController getHost] renderView:self.view]; NSOperationQueue* opQueue = [[NSOperationQueue alloc] init]; - [opQueue addOperation:conn]; + [opQueue addOperation:streamMan]; } - (void)didReceiveMemoryWarning diff --git a/Limelight/StreamManager.h b/Limelight/StreamManager.h index 82068ee..a4973dc 100644 --- a/Limelight/StreamManager.h +++ b/Limelight/StreamManager.h @@ -7,12 +7,9 @@ // #import -#import "MainFrameViewController.h" @interface StreamManager : NSOperation -- (id) initWithHost:(NSString*)host andViewController:(MainFrameViewController*)viewCont; -- (NSData*) getRiKey; -- (int) getRiKeyId; +- (id) initWithHost:(NSString*)host renderView:(UIView*)view; @end diff --git a/Limelight/StreamManager.m b/Limelight/StreamManager.m index 8ae6071..4a9e786 100644 --- a/Limelight/StreamManager.m +++ b/Limelight/StreamManager.m @@ -9,42 +9,49 @@ #import "StreamManager.h" #import "CryptoManager.h" #import "HttpManager.h" -#import "PairManager.h" +#import "Utils.h" +#import "Connection.h" +#import "StreamConfiguration.h" @implementation StreamManager { - MainFrameViewController* _viewCont; NSString* _host; - NSData* _riKey; - int _riKeyId; + UIView* _renderView; } -- (id) initWithHost:(NSString*)host andViewController:(MainFrameViewController *)viewCont { +- (id) initWithHost:(NSString*)host renderView:(UIView*)view { self = [super init]; _host = host; - _viewCont = viewCont; + _renderView = view; return self; } -- (NSData*) getRiKey { - return _riKey; -} - -- (int) getRiKeyId { - return _riKeyId; -} - - (void)main { [CryptoManager generateKeyPairUsingSSl]; NSString* uniqueId = [CryptoManager getUniqueID]; NSData* cert = [CryptoManager readCertFromFile]; HttpManager* hMan = [[HttpManager alloc] initWithHost:_host uniqueId:uniqueId deviceName:@"roth" cert:cert]; - _riKey = [PairManager randomBytes:16]; - _riKeyId = arc4random(); + NSData* riKey = [Utils randomBytes:16]; + int riKeyId = arc4random(); - NSData* launchResp = [hMan executeRequestSynchronously:[hMan newLaunchRequest:@"67339056" width:1280 height:720 refreshRate:60 rikey:[PairManager bytesToHex:_riKey] rikeyid:_riKeyId]]; + NSData* launchResp = [hMan executeRequestSynchronously:[hMan newLaunchRequest:@"67339056" width:1920 height:1080 refreshRate:30 rikey:[Utils bytesToHex:riKey] rikeyid:riKeyId]]; [HttpManager getStringFromXML:launchResp tag:@"gamesession"]; - [_viewCont segueIntoStream]; + + VideoDecoderRenderer* renderer = [[VideoDecoderRenderer alloc]initWithView:_renderView]; + + StreamConfiguration* config = [[StreamConfiguration alloc] init]; + config.host = [Utils resolveHost:_host]; + config.width = 1920; + config.height = 1080; + config.frameRate = 30; + config.bitRate = 10000; + config.riKey = riKey; + config.riKeyId = riKeyId; + + Connection* conn = [[Connection alloc] initWithConfig:config renderer:renderer]; + + NSOperationQueue* opQueue = [[NSOperationQueue alloc] init]; + [opQueue addOperation:conn]; } @end diff --git a/Limelight/Utils.h b/Limelight/Utils.h new file mode 100644 index 0000000..b9be2d0 --- /dev/null +++ b/Limelight/Utils.h @@ -0,0 +1,18 @@ +// +// Utils.h +// Limelight +// +// Created by Diego Waxemberg on 10/20/14. +// Copyright (c) 2014 Limelight Stream. All rights reserved. +// + +#import + +@interface Utils : NSObject + ++ (NSData*) randomBytes:(NSInteger)length; ++ (NSString*) bytesToHex:(NSData*)data; ++ (NSData*) hexToBytes:(NSString*) hex; ++ (int) resolveHost:(NSString*)host; + +@end diff --git a/Limelight/Utils.m b/Limelight/Utils.m new file mode 100644 index 0000000..f030295 --- /dev/null +++ b/Limelight/Utils.m @@ -0,0 +1,76 @@ +// +// Utils.m +// Limelight +// +// Created by Diego Waxemberg on 10/20/14. +// Copyright (c) 2014 Limelight Stream. All rights reserved. +// + +#import "Utils.h" + +#include +#include +#include + +@implementation Utils + ++ (NSData*) randomBytes:(NSInteger)length { + char* bytes = malloc(length); + arc4random_buf(bytes, length); + NSData* randomData = [NSData dataWithBytes:bytes length:length]; + free(bytes); + return randomData; +} + ++ (NSData*) hexToBytes:(NSString*) hex { + unsigned long len = [hex length]; + NSMutableData* data = [NSMutableData dataWithCapacity:len / 2]; + char byteChars[3] = {'\0','\0','\0'}; + unsigned long wholeByte; + + const char *chars = [hex UTF8String]; + int i = 0; + while (i < len) { + byteChars[0] = chars[i++]; + byteChars[1] = chars[i++]; + wholeByte = strtoul(byteChars, NULL, 16); + [data appendBytes:&wholeByte length:1]; + } + + return data; +} + ++ (NSString*) bytesToHex:(NSData*)data { + const unsigned char* bytes = [data bytes]; + NSMutableString *hex = [[NSMutableString alloc] init]; + for (int i = 0; i < [data length]; i++) { + [hex appendFormat:@"%02X" , bytes[i]]; + } + return hex; +} + ++ (int) resolveHost:(NSString*)host { + struct hostent *hostent; + + if (inet_addr([host UTF8String]) != INADDR_NONE) { + // Already an IP address + int addr = inet_addr([host UTF8String]); + NSLog(@"host address: %d", addr); + return addr; + } else { + hostent = gethostbyname([host UTF8String]); + if (hostent != NULL) { + char* ipstr = inet_ntoa(*(struct in_addr*)hostent->h_addr_list[0]); + NSLog(@"Resolved %@ -> %s", host, ipstr); + int addr = inet_addr(ipstr); + NSLog(@"host address: %d", addr); + return addr; + } else { + NSLog(@"Failed to resolve host: %d", h_errno); + return -1; + } + } +} + + +@end