diff --git a/Limelight.xcodeproj/project.pbxproj b/Limelight.xcodeproj/project.pbxproj index 200fd2da..757fe744 100644 --- a/Limelight.xcodeproj/project.pbxproj +++ b/Limelight.xcodeproj/project.pbxproj @@ -37,6 +37,7 @@ FB290E7919B37D81004C83CF /* MainFrame-iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FB290E7819B37D81004C83CF /* MainFrame-iPad.storyboard */; }; FB290E7B19B38036004C83CF /* MainFrame-iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FB290E7A19B38036004C83CF /* MainFrame-iPhone.storyboard */; }; 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 */; }; FBAB29F219EDB08B00929691 /* MDNSManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FBAB29F119EDB08B00929691 /* MDNSManager.m */; }; FBAB29F619EDE0F800929691 /* Computer.m in Sources */ = {isa = PBXBuildFile; fileRef = FBAB29F519EDE0F800929691 /* Computer.m */; }; @@ -123,6 +124,8 @@ FB290E7A19B38036004C83CF /* MainFrame-iPhone.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "MainFrame-iPhone.storyboard"; sourceTree = SOURCE_ROOT; }; FB63FCF019F43EBC00227761 /* PairManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PairManager.h; sourceTree = ""; }; FB63FCF119F43EBC00227761 /* PairManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PairManager.m; sourceTree = ""; }; + 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; }; 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 = ""; }; @@ -327,6 +330,8 @@ FBC8622C19F0BEFB0087327B /* HttpManager.m */, 984C441619F48D1D0061A500 /* StreamView.h */, 984C441719F48D1D0061A500 /* StreamView.m */, + FB63FCF519F573BE00227761 /* StreamManager.h */, + FB63FCF619F573BE00227761 /* StreamManager.m */, ); path = Limelight; sourceTree = ""; @@ -682,6 +687,7 @@ buildActionMask = 2147483647; files = ( FBAB29FC19EE13AA00929691 /* CryptoManager.m in Sources */, + FB63FCF719F573BE00227761 /* StreamManager.m in Sources */, FB63FCF219F43EBC00227761 /* PairManager.m in Sources */, 98A03B5019F3598400861ACA /* VideoDecoderRenderer.m in Sources */, FBAB29F219EDB08B00929691 /* MDNSManager.m in Sources */, diff --git a/Limelight/Computer.m b/Limelight/Computer.m index 199a11dd..d6ef5e7b 100644 --- a/Limelight/Computer.m +++ b/Limelight/Computer.m @@ -26,11 +26,13 @@ - (int) resolveHost { struct hostent *hostent; - + if (inet_addr([self.hostName UTF8String]) != INADDR_NONE) { // Already an IP address - return inet_addr([self.hostName UTF8String]); + int addr = inet_addr([self.hostName UTF8String]); + NSLog(@"host address: %d", addr); + return addr; } else { @@ -39,7 +41,9 @@ { char* ipstr = inet_ntoa(*(struct in_addr*)hostent->h_addr_list[0]); NSLog(@"Resolved %@ -> %s", self.hostName, ipstr); - return inet_addr(ipstr); + int addr = inet_addr(ipstr); + NSLog(@"host address: %d", addr); + return addr; } else { diff --git a/Limelight/Connection.h b/Limelight/Connection.h index 499d8b96..50f66abb 100644 --- a/Limelight/Connection.h +++ b/Limelight/Connection.h @@ -11,7 +11,7 @@ @interface Connection : NSOperation --(id) initWithHost:(int)ipaddr width:(int)width height:(int)height renderer:(VideoDecoderRenderer*)renderer; +-(id) initWithHost:(int)ipaddr key:(NSData*)rikey keyId:(int)rikeyid width:(int)width height:(int)height refreshRate:(int)refreshRate renderer:(VideoDecoderRenderer*)myRenderer; -(void) main; @end diff --git a/Limelight/Connection.m b/Limelight/Connection.m index a4c77470..897b6e48 100644 --- a/Limelight/Connection.m +++ b/Limelight/Connection.m @@ -210,7 +210,7 @@ void ClDisplayTransientMessage(char* message) NSLog(@"DisplayTransientMessage: %s", message); } --(id) initWithHost:(int)ipaddr width:(int)width height:(int)height renderer:(VideoDecoderRenderer*)myRenderer +-(id) initWithHost:(int)ipaddr key:(NSData*)rikey keyId:(int)rikeyid width:(int)width height:(int)height refreshRate:(int)refreshRate renderer:(VideoDecoderRenderer*)myRenderer { self = [super init]; host = ipaddr; @@ -221,7 +221,11 @@ void ClDisplayTransientMessage(char* message) streamConfig.fps = 60; streamConfig.bitrate = 5000; streamConfig.packetSize = 1024; - // FIXME: RI AES members + + memcpy(streamConfig.remoteInputAesKey, [rikey bytes], [rikey length]); + memset(streamConfig.remoteInputAesIv, 0, 16); + rikeyid = htonl(rikeyid); + memcpy(streamConfig.remoteInputAesIv, &rikeyid, sizeof(rikeyid)); drCallbacks.setup = DrSetup; drCallbacks.start = DrStart; diff --git a/Limelight/CryptoManager.m b/Limelight/CryptoManager.m index b480a42b..bd039539 100644 --- a/Limelight/CryptoManager.m +++ b/Limelight/CryptoManager.m @@ -18,6 +18,9 @@ @implementation CryptoManager static const int SHA1_DIGEST_LENGTH = 20; +static NSData* key = nil; +static NSData* cert = nil; +static NSData* p12 = nil; - (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN { return [[self SHA1HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)]; @@ -142,24 +145,47 @@ static const int SHA1_DIGEST_LENGTH = 20; // TODO: these three methods are almost identical, fix the copy-pasta + (NSData*) readCertFromFile { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"]; - return [NSData dataWithContentsOfFile:certFile]; + if (cert == nil) { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + NSString *certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"]; + cert = [NSData dataWithContentsOfFile:certFile]; + } + return cert; } + (NSData*) readP12FromFile { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"]; - return [NSData dataWithContentsOfFile:p12File]; + if (p12 == nil) { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + NSString *p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"]; + p12 = [NSData dataWithContentsOfFile:p12File]; + } + return p12; } + (NSData*) readKeyFromFile { + if (key == nil) { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + NSString *keyFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"]; + key = [NSData dataWithContentsOfFile:keyFile]; + } + return key; +} + ++ (bool) keyPairExists { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *keyFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"]; - return [NSData dataWithContentsOfFile:keyFile]; + NSString *p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"]; + NSString *certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"]; + + bool keyFileExists = [[NSFileManager defaultManager] fileExistsAtPath:keyFile]; + bool p12FileExists = [[NSFileManager defaultManager] fileExistsAtPath:p12File]; + bool certFileExists = [[NSFileManager defaultManager] fileExistsAtPath:certFile]; + + return keyFileExists && p12FileExists && certFileExists; } + (NSData *)getSignatureFromCert:(NSData *)cert { @@ -177,18 +203,21 @@ static const int SHA1_DIGEST_LENGTH = 20; } + (void) generateKeyPairUsingSSl { - NSLog(@"Generating Certificate... "); - CertKeyPair certKeyPair = generateCertKeyPair(); - - NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString* documentsDirectory = [paths objectAtIndex:0]; - NSString* certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"]; - NSString* keyPairFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"]; - NSString* p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"]; - - //NSLog(@"Writing cert and key to: \n%@\n%@", certFile, keyPairFile); - saveCertKeyPair([certFile UTF8String], [p12File UTF8String], [keyPairFile UTF8String], certKeyPair); - freeCertKeyPair(certKeyPair); + if (![CryptoManager keyPairExists]) { + + NSLog(@"Generating Certificate... "); + CertKeyPair certKeyPair = generateCertKeyPair(); + + NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString* documentsDirectory = [paths objectAtIndex:0]; + NSString* certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"]; + NSString* keyPairFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"]; + NSString* p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"]; + + //NSLog(@"Writing cert and key to: \n%@\n%@", certFile, keyPairFile); + saveCertKeyPair([certFile UTF8String], [p12File UTF8String], [keyPairFile UTF8String], certKeyPair); + freeCertKeyPair(certKeyPair); + } } + (NSString*) getUniqueID { @@ -200,7 +229,7 @@ static const int SHA1_DIGEST_LENGTH = 20; // and remove the '-' to get a 16 character string NSMutableString* uniqueId = [NSMutableString stringWithString:[idString substringFromIndex:19]]; [uniqueId deleteCharactersInRange:NSMakeRange(4, 1)]; - + //NSLog(@"Unique ID: %@", uniqueId); return [NSString stringWithString:uniqueId]; } diff --git a/Limelight/HttpManager.h b/Limelight/HttpManager.h index defa3df7..c0b680e5 100644 --- a/Limelight/HttpManager.h +++ b/Limelight/HttpManager.h @@ -21,6 +21,7 @@ - (NSURLRequest*) newPairChallenge; - (NSURLRequest*) newAppListRequest; - (NSURLRequest*) newServerInfoRequest; +- (NSURLRequest*) newLaunchRequest:(NSString*)appId width:(int)width height:(int)height refreshRate:(int)refreshRate rikey:(NSString*)rikey rikeyid:(int)rikeyid; - (NSData*) executeRequestSynchronously:(NSURLRequest*)request; @end diff --git a/Limelight/HttpManager.m b/Limelight/HttpManager.m index 1df57943..b7654fbd 100644 --- a/Limelight/HttpManager.m +++ b/Limelight/HttpManager.m @@ -150,6 +150,11 @@ static const NSString* PORT = @"47984"; return [self createRequestFromString:urlString]; } +- (NSURLRequest*) newLaunchRequest:(NSString*)appId width:(int)width height:(int)height refreshRate:(int)refreshRate rikey:(NSString*)rikey rikeyid:(int)rikeyid { + NSString* urlString = [NSString stringWithFormat:@"%@/launch?uniqueid=%@&appid=%@&mode=%dx%dx%d&additionalStates=1&sops=1&rikey=%@&rikeyid=%d", _baseURL, _uniqueId, appId, width, height, refreshRate, rikey, rikeyid]; + return [self createRequestFromString:urlString]; +} + - (NSString*) bytesToHex:(NSData*)data { const unsigned char* bytes = [data bytes]; NSMutableString *hex = [[NSMutableString alloc] init]; diff --git a/Limelight/MainFrameViewController.h b/Limelight/MainFrameViewController.h index 45309e3b..760da152 100644 --- a/Limelight/MainFrameViewController.h +++ b/Limelight/MainFrameViewController.h @@ -8,8 +8,9 @@ #import #import "MDNSManager.h" +#import "PairManager.h" -@interface MainFrameViewController : UIViewController +@interface MainFrameViewController : UIViewController @property (strong, nonatomic) IBOutlet UIPickerView *HostPicker; - (IBAction)StreamButton:(UIButton *)sender; - (IBAction)PairButton:(UIButton *)sender; @@ -18,7 +19,10 @@ @property (strong, nonatomic) NSArray* streamConfigVals; @property (strong, nonatomic) NSArray* hostPickerVals; -- (int) getHostAddr; ++ (int) getResolvedHost; ++ (NSData*) getRiKey; ++ (int) getRiKeyId; + - (void) segueIntoStream; @end diff --git a/Limelight/MainFrameViewController.m b/Limelight/MainFrameViewController.m index dde7d9ee..a555ce91 100644 --- a/Limelight/MainFrameViewController.m +++ b/Limelight/MainFrameViewController.m @@ -11,18 +11,31 @@ #import "Computer.h" #import "CryptoManager.h" #import "HttpManager.h" -#import "PairManager.h" #import "Connection.h" #import "VideoDecoderRenderer.h" +#import "StreamManager.h" @implementation MainFrameViewController { NSOperationQueue* _opQueue; MDNSManager* _mDNSManager; Computer* _selectedHost; + UIAlertView* _pairAlert; + StreamManager* _streamMan; +} +static int resolvedHost; +static NSData* riKey; +static int riKeyId; + ++ (int) getResolvedHost { + return resolvedHost; } -- (int)getHostAddr { - return [_selectedHost resolveHost]; ++ (NSData*) getRiKey { + return riKey; +} + ++ (int) getRiKeyId { + return riKeyId; } - (void)PairButton:(UIButton *)sender @@ -33,18 +46,45 @@ NSData* cert = [CryptoManager readCertFromFile]; HttpManager* hMan = [[HttpManager alloc] initWithHost:_selectedHost.hostName uniqueId:uniqueId deviceName:@"roth" cert:cert]; - PairManager* pMan = [[PairManager alloc] initWithManager:hMan andCert:cert]; + PairManager* pMan = [[PairManager alloc] initWithManager:hMan andCert:cert callback:self]; [_opQueue addOperation:pMan]; } +- (void)showPIN:(NSString *)PIN { + dispatch_sync(dispatch_get_main_queue(), ^{ + _pairAlert = [[UIAlertView alloc] initWithTitle:@"Pairing" message:[NSString stringWithFormat:@"Enter the following PIN on the host machine: %@", PIN]delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil]; + [_pairAlert show]; + }); +} + +- (void)pairFailed:(NSString *)message { + dispatch_sync(dispatch_get_main_queue(), ^{ + [_pairAlert dismissWithClickedButtonIndex:0 animated:NO]; + _pairAlert = [[UIAlertView alloc] initWithTitle:@"Pairing Failed" message:message delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil]; + [_pairAlert show]; + }); +} + +- (void)pairSuccessful { + dispatch_sync(dispatch_get_main_queue(), ^{ + [_pairAlert dismissWithClickedButtonIndex:0 animated:NO]; + _pairAlert = [[UIAlertView alloc] initWithTitle:@"Pairing Succesful" message:@"Successfully paired to host" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil]; + [_pairAlert show]; + }); +} + - (void)StreamButton:(UIButton *)sender { NSLog(@"Stream Button Pressed!"); - [self segueIntoStream]; + _streamMan = [[StreamManager alloc] initWithHost:_selectedHost.hostName andViewController:self]; + [_opQueue addOperation:_streamMan]; } - (void) segueIntoStream { + resolvedHost = [_selectedHost resolveHost]; + riKey = [_streamMan getRiKey]; + riKeyId = [_streamMan getRiKeyId]; [self performSegueWithIdentifier:@"createStreamFrame" sender:self]; } diff --git a/Limelight/PairManager.h b/Limelight/PairManager.h index e7077684..ed2728d5 100644 --- a/Limelight/PairManager.h +++ b/Limelight/PairManager.h @@ -9,9 +9,21 @@ #import #import "HttpManager.h" +@protocol PairCallback + +- (void) showPIN:(NSString*)PIN; +- (void) pairSuccessful; +- (void) pairFailed:(NSString*)message; + +@end + @interface PairManager : NSOperation -- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert; +- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert callback:(id)callback; - (NSString*) generatePIN; - (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 65c57f12..8403f7be 100644 --- a/Limelight/PairManager.m +++ b/Limelight/PairManager.m @@ -14,27 +14,38 @@ @implementation PairManager { HttpManager* _httpManager; NSData* _cert; + id _callback; } -- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert { +- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert callback:(id)callback { self = [super init]; _httpManager = httpManager; _cert = cert; + _callback = callback; return self; } - (void) main { - [self initiatePair]; + NSData* serverInfo = [_httpManager executeRequestSynchronously:[_httpManager newServerInfoRequest]]; + if (![[HttpManager getStringFromXML:serverInfo tag:@"PairStatus"] isEqual:@"1"]) { + [self initiatePair]; + } else { + [_callback pairFailed:@"Already Paired"]; + } + [_httpManager executeRequestSynchronously:[_httpManager newAppListRequest]]; } - (void) initiatePair { NSString* PIN = [self generatePIN]; NSData* salt = [self saltPIN:PIN]; NSLog(@"PIN: %@, saltedPIN: %@", PIN, salt); + [_callback showPIN:PIN]; NSData* pairResp = [_httpManager executeRequestSynchronously:[_httpManager newPairRequest:salt]]; if ([[HttpManager getStringFromXML:pairResp tag:@"paired"] intValue] != 1) { [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + //TODO: better message + [_callback pairFailed:@"pairResp failed"]; return; } @@ -43,12 +54,14 @@ CryptoManager* cryptoMan = [[CryptoManager alloc] init]; NSData* aesKey = [cryptoMan createAESKeyFromSalt:salt]; - NSData* randomChallenge = [self randomBytes:16]; + NSData* randomChallenge = [PairManager randomBytes:16]; NSData* encryptedChallenge = [cryptoMan aesEncrypt:randomChallenge withKey:aesKey]; NSData* challengeResp = [_httpManager executeRequestSynchronously:[_httpManager newChallengeRequest:encryptedChallenge]]; if ([[HttpManager getStringFromXML:challengeResp tag:@"paired"] intValue] != 1) { [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + //TODO: better message + [_callback pairFailed:@"challengeResp failed"]; return; } @@ -58,13 +71,15 @@ NSData* serverResponse = [decServerChallengeResp subdataWithRange:NSMakeRange(0, 20)]; NSData* serverChallenge = [decServerChallengeResp subdataWithRange:NSMakeRange(20, 16)]; - NSData* clientSecret = [self randomBytes:16]; + NSData* clientSecret = [PairManager randomBytes:16]; NSData* challengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:serverChallenge with:[CryptoManager getSignatureFromCert:_cert]] with:clientSecret]]; NSData* challengeRespEncrypted = [cryptoMan aesEncrypt:challengeRespHash withKey:aesKey]; NSData* secretResp = [_httpManager executeRequestSynchronously:[_httpManager newChallengeRespRequest:challengeRespEncrypted]]; if ([[HttpManager getStringFromXML:secretResp tag:@"paired"] intValue] != 1) { [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + //TODO: better message + [_callback pairFailed:@"secretResp failed"]; return; } @@ -74,27 +89,36 @@ if (![cryptoMan verifySignature:serverSecret withSignature:serverSignature andCert:[self 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]]; if (![serverChallengeRespHash isEqual:serverResponse]) { [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + //TODO: better message + [_callback pairFailed:@"serverChallengeResp failed"]; return; } NSData* clientPairingSecret = [self concatData:clientSecret with:[cryptoMan signData:clientSecret withKey:[CryptoManager readKeyFromFile]]]; - NSData* clientSecretResp = [_httpManager executeRequestSynchronously:[_httpManager newClientSecretRespRequest:[self bytesToHex:clientPairingSecret]]]; + NSData* clientSecretResp = [_httpManager executeRequestSynchronously:[_httpManager newClientSecretRespRequest:[PairManager bytesToHex:clientPairingSecret]]]; if (![[HttpManager getStringFromXML:clientSecretResp tag:@"paired"] isEqual:@"1"]) { [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + //TODO: better message + [_callback pairFailed:@"clientSecretResp failed"]; return; } NSData* clientPairChallenge = [_httpManager executeRequestSynchronously:[_httpManager newPairChallenge]]; if (![[HttpManager getStringFromXML:clientPairChallenge tag:@"paired"] isEqual:@"1"]) { [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + //TODO: better message + [_callback pairFailed:@"clientPairChallenge failed"]; return; } + [_callback pairSuccessful]; } - (NSData*) concatData:(NSData*)data with:(NSData*)moreData { @@ -113,14 +137,14 @@ - (NSData*) saltPIN:(NSString*)PIN { NSMutableData* saltedPIN = [[NSMutableData alloc] initWithCapacity:20]; - [saltedPIN appendData:[self randomBytes:16]]; + [saltedPIN appendData:[PairManager randomBytes:16]]; [saltedPIN appendBytes:[PIN UTF8String] length:4]; //NSLog(@"Salted PIN: %@", [saltedPIN description]); return saltedPIN; } -- (NSData*) randomBytes:(NSInteger)length { ++ (NSData*) randomBytes:(NSInteger)length { char* bytes = malloc(length); arc4random_buf(bytes, length); NSData* randomData = [NSData dataWithBytes:bytes length:length]; @@ -146,7 +170,7 @@ return data; } -- (NSString*) bytesToHex:(NSData*)data { ++ (NSString*) bytesToHex:(NSData*)data { const unsigned char* bytes = [data bytes]; NSMutableString *hex = [[NSMutableString alloc] init]; for (int i = 0; i < [data length]; i++) { diff --git a/Limelight/StreamFrameViewController.m b/Limelight/StreamFrameViewController.m index 67b12f26..b978400b 100644 --- a/Limelight/StreamFrameViewController.m +++ b/Limelight/StreamFrameViewController.m @@ -16,28 +16,17 @@ #include #include -@interface StreamFrameViewController () - -@end - -@implementation StreamFrameViewController { - int _host; -} - -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - _host = [sender getHostAddr]; -} +@implementation StreamFrameViewController - (void)viewDidLoad { [super viewDidLoad]; - + [UIApplication sharedApplication].idleTimerDisabled = YES; VideoDecoderRenderer* renderer = [[VideoDecoderRenderer alloc]initWithView:self.view]; - Connection* conn = [[Connection alloc] initWithHost:_host width:1280 height:720 - renderer: renderer]; + Connection* conn = [[Connection alloc] initWithHost:[MainFrameViewController getResolvedHost] key:[MainFrameViewController getRiKey] keyId:[MainFrameViewController getRiKeyId] width:1280 height:720 refreshRate:60 renderer:renderer]; NSOperationQueue* opQueue = [[NSOperationQueue alloc] init]; [opQueue addOperation:conn]; diff --git a/Limelight/StreamManager.h b/Limelight/StreamManager.h new file mode 100644 index 00000000..82068ee1 --- /dev/null +++ b/Limelight/StreamManager.h @@ -0,0 +1,18 @@ +// +// StreamManager.h +// Limelight +// +// Created by Diego Waxemberg on 10/20/14. +// Copyright (c) 2014 Limelight Stream. All rights reserved. +// + +#import +#import "MainFrameViewController.h" + +@interface StreamManager : NSOperation + +- (id) initWithHost:(NSString*)host andViewController:(MainFrameViewController*)viewCont; +- (NSData*) getRiKey; +- (int) getRiKeyId; + +@end diff --git a/Limelight/StreamManager.m b/Limelight/StreamManager.m new file mode 100644 index 00000000..8ae60714 --- /dev/null +++ b/Limelight/StreamManager.m @@ -0,0 +1,50 @@ +// +// StreamManager.m +// Limelight +// +// Created by Diego Waxemberg on 10/20/14. +// Copyright (c) 2014 Limelight Stream. All rights reserved. +// + +#import "StreamManager.h" +#import "CryptoManager.h" +#import "HttpManager.h" +#import "PairManager.h" + +@implementation StreamManager { + MainFrameViewController* _viewCont; + NSString* _host; + NSData* _riKey; + int _riKeyId; +} + +- (id) initWithHost:(NSString*)host andViewController:(MainFrameViewController *)viewCont { + self = [super init]; + _host = host; + _viewCont = viewCont; + 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* launchResp = [hMan executeRequestSynchronously:[hMan newLaunchRequest:@"67339056" width:1280 height:720 refreshRate:60 rikey:[PairManager bytesToHex:_riKey] rikeyid:_riKeyId]]; + [HttpManager getStringFromXML:launchResp tag:@"gamesession"]; + [_viewCont segueIntoStream]; +} + +@end