mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2026-02-16 10:31:02 +00:00
starting steam and paring work
This commit is contained in:
@@ -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 = "<group>"; };
|
||||
FB63FCF119F43EBC00227761 /* PairManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PairManager.m; sourceTree = "<group>"; };
|
||||
FB63FCF519F573BE00227761 /* StreamManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamManager.h; sourceTree = "<group>"; };
|
||||
FB63FCF619F573BE00227761 /* StreamManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StreamManager.m; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
FBAB29F319EDB0C400929691 /* MDNSManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDNSManager.h; sourceTree = "<group>"; };
|
||||
@@ -327,6 +330,8 @@
|
||||
FBC8622C19F0BEFB0087327B /* HttpManager.m */,
|
||||
984C441619F48D1D0061A500 /* StreamView.h */,
|
||||
984C441719F48D1D0061A500 /* StreamView.m */,
|
||||
FB63FCF519F573BE00227761 /* StreamManager.h */,
|
||||
FB63FCF619F573BE00227761 /* StreamManager.m */,
|
||||
);
|
||||
path = Limelight;
|
||||
sourceTree = "<group>";
|
||||
@@ -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 */,
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
@interface Connection : NSOperation <NSStreamDelegate>
|
||||
|
||||
-(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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "MDNSManager.h"
|
||||
#import "PairManager.h"
|
||||
|
||||
@interface MainFrameViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate, MDNSCallback, NSURLConnectionDelegate>
|
||||
@interface MainFrameViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate, MDNSCallback, NSURLConnectionDelegate, PairCallback>
|
||||
@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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,21 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "HttpManager.h"
|
||||
|
||||
@protocol PairCallback <NSObject>
|
||||
|
||||
- (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<PairCallback>)callback;
|
||||
- (NSString*) generatePIN;
|
||||
- (NSData*) saltPIN:(NSString*)PIN;
|
||||
- (void) initiatePair;
|
||||
|
||||
+ (NSData*) randomBytes:(NSInteger)length;
|
||||
+ (NSString*) bytesToHex:(NSData*)data;
|
||||
|
||||
@end
|
||||
|
||||
@@ -14,27 +14,38 @@
|
||||
@implementation PairManager {
|
||||
HttpManager* _httpManager;
|
||||
NSData* _cert;
|
||||
id<PairCallback> _callback;
|
||||
}
|
||||
|
||||
- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert {
|
||||
- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert callback:(id<PairCallback>)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++) {
|
||||
|
||||
@@ -16,28 +16,17 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
@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];
|
||||
|
||||
18
Limelight/StreamManager.h
Normal file
18
Limelight/StreamManager.h
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// StreamManager.h
|
||||
// Limelight
|
||||
//
|
||||
// Created by Diego Waxemberg on 10/20/14.
|
||||
// Copyright (c) 2014 Limelight Stream. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MainFrameViewController.h"
|
||||
|
||||
@interface StreamManager : NSOperation
|
||||
|
||||
- (id) initWithHost:(NSString*)host andViewController:(MainFrameViewController*)viewCont;
|
||||
- (NSData*) getRiKey;
|
||||
- (int) getRiKeyId;
|
||||
|
||||
@end
|
||||
50
Limelight/StreamManager.m
Normal file
50
Limelight/StreamManager.m
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user