Merge branch 'master' into xcode-7.0

Conflicts:
	limelight-common-c
This commit is contained in:
Cameron Gutman 2015-07-08 23:13:55 -07:00
commit 2b0ce49646
9 changed files with 109 additions and 70 deletions

View File

@ -41,7 +41,7 @@
- (void) discoverHost:(NSString *)hostAddress withCallback:(void (^)(Host *, NSString*))callback {
HttpManager* hMan = [[HttpManager alloc] initWithHost:hostAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
ServerInfoResponse* serverInfoResponse = [[ServerInfoResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResponse withUrlRequest:[hMan newServerInfoRequest]]];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResponse withUrlRequest:[hMan newServerInfoRequest] fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
Host* host = nil;
if ([serverInfoResponse isStatusOk]) {

View File

@ -68,7 +68,8 @@ static const float POLL_RATE = 2.0f; // Poll every 2 seconds
cert:_cert];
ServerInfoResponse* response = [[ServerInfoResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:response
withUrlRequest:[hMan newServerInfoRequest]]];
withUrlRequest:[hMan newServerInfoRequest]
fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
return response;
}

View File

@ -11,7 +11,7 @@
#import "HttpResponse.h"
#import "HttpRequest.h"
@interface HttpManager : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
@interface HttpManager : NSObject <NSURLSessionDelegate>
- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId deviceName:(NSString*) deviceName cert:(NSData*) cert;
- (NSURLRequest*) newPairRequest:(NSData*)salt;
@ -22,12 +22,12 @@
- (NSURLRequest*) newPairChallenge;
- (NSURLRequest*) newAppListRequest;
- (NSURLRequest*) newServerInfoRequest;
- (NSURLRequest*) newHttpServerInfoRequest;
- (NSURLRequest*) newLaunchRequest:(NSString*)appId width:(int)width height:(int)height refreshRate:(int)refreshRate rikey:(NSString*)rikey rikeyid:(int)rikeyid;
- (NSURLRequest*) newResumeRequestWithRiKey:(NSString*)riKey riKeyId:(int)riKeyId;
- (NSURLRequest*) newQuitAppRequest;
- (NSURLRequest*) newAppAssetRequestWithAppId:(NSString*)appId;
- (void) executeRequestSynchronously:(HttpRequest*)request;
- (void) executeRequest:(HttpRequest*)request;
@end

View File

@ -15,7 +15,9 @@
#include <string.h>
@implementation HttpManager {
NSString* _baseURL;
NSURLSession* _urlSession;
NSString* _baseHTTPURL;
NSString* _baseHTTPSURL;
NSString* _host;
NSString* _uniqueId;
NSString* _deviceName;
@ -27,7 +29,8 @@
BOOL _errorOccurred;
}
static const NSString* PORT = @"47984";
static const NSString* HTTP_PORT = @"47989";
static const NSString* HTTPS_PORT = @"47984";
+ (NSData*) fixXmlVersion:(NSData*) xmlData {
NSString* dataString = [[NSString alloc] initWithData:xmlData encoding:NSUTF8StringEncoding];
@ -42,30 +45,57 @@ static const NSString* PORT = @"47984";
_uniqueId = uniqueId;
_deviceName = deviceName;
_cert = cert;
_baseURL = [NSString stringWithFormat:@"https://%@:%@", host, PORT];
_baseHTTPURL = [NSString stringWithFormat:@"http://%@:%@", host, HTTP_PORT];
_baseHTTPSURL = [NSString stringWithFormat:@"https://%@:%@", host, HTTPS_PORT];
_requestLock = dispatch_semaphore_create(0);
_respData = [[NSMutableData alloc] init];
NSURLSessionConfiguration* config = [NSURLSessionConfiguration ephemeralSessionConfiguration];
_urlSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
return self;
}
- (void) executeRequestSynchronously:(HttpRequest*)request {
Log(LOG_D, @"Making Request: %@", request);
[_respData setLength:0];
dispatch_sync(dispatch_get_main_queue(), ^{
[NSURLConnection connectionWithRequest:request.request delegate:self];
});
[[_urlSession dataTaskWithRequest:request.request completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error) {
if (error != NULL) {
Log(LOG_D, @"Connection error: %@", error);
_errorOccurred = true;
}
else {
Log(LOG_D, @"Received response: %@", response);
if (data != NULL) {
Log(LOG_D, @"\n\nReceived data: %@\n\n", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
[_respData appendData:data];
if ([[NSString alloc] initWithData:_respData encoding:NSUTF8StringEncoding] != nil) {
_requestResp = [HttpManager fixXmlVersion:_respData];
} else {
_requestResp = _respData;
}
}
}
dispatch_semaphore_signal(_requestLock);
}] resume];
dispatch_semaphore_wait(_requestLock, DISPATCH_TIME_FOREVER);
if (!_errorOccurred && request.response) {
[request.response populateWithData:_requestResp];
// If the fallback error code was detected, issue the fallback request
if (request.response.statusCode == request.fallbackError && request.fallbackRequest != NULL) {
Log(LOG_D, @"Request failed with fallback error code: %d", request.fallbackError);
request.request = request.fallbackRequest;
request.fallbackError = 0;
request.fallbackRequest = NULL;
[self executeRequestSynchronously:request];
}
}
_errorOccurred = false;
}
- (void) executeRequest:(HttpRequest*)request {
[NSURLConnection connectionWithRequest:request.request delegate:self];
}
- (NSURLRequest*) createRequestFromString:(NSString*) urlString enableTimeout:(BOOL)normalTimeout {
NSURL* url = [[NSURL alloc] initWithString:urlString];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
@ -82,67 +112,72 @@ static const NSString* PORT = @"47984";
- (NSURLRequest*) newPairRequest:(NSData*)salt {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=getservercert&salt=%@&clientcert=%@",
_baseURL, _uniqueId, _deviceName, [self bytesToHex:salt], [self bytesToHex:_cert]];
_baseHTTPSURL, _uniqueId, _deviceName, [self bytesToHex:salt], [self bytesToHex:_cert]];
// This call blocks while waiting for the user to input the PIN on the PC
return [self createRequestFromString:urlString enableTimeout:FALSE];
}
- (NSURLRequest*) newUnpairRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/unpair?uniqueid=%@", _baseURL, _uniqueId];
NSString* urlString = [NSString stringWithFormat:@"%@/unpair?uniqueid=%@", _baseHTTPSURL, _uniqueId];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest*) newChallengeRequest:(NSData*)challenge {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientchallenge=%@",
_baseURL, _uniqueId, _deviceName, [self bytesToHex:challenge]];
_baseHTTPSURL, _uniqueId, _deviceName, [self bytesToHex:challenge]];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest*) newChallengeRespRequest:(NSData*)challengeResp {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&serverchallengeresp=%@",
_baseURL, _uniqueId, _deviceName, [self bytesToHex:challengeResp]];
_baseHTTPSURL, _uniqueId, _deviceName, [self bytesToHex:challengeResp]];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest*) newClientSecretRespRequest:(NSString*)clientPairSecret {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientpairingsecret=%@", _baseURL, _uniqueId, _deviceName, clientPairSecret];
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientpairingsecret=%@", _baseHTTPSURL, _uniqueId, _deviceName, clientPairSecret];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest*) newPairChallenge {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=pairchallenge", _baseURL, _uniqueId, _deviceName];
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=pairchallenge", _baseHTTPSURL, _uniqueId, _deviceName];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest *)newAppListRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/applist?uniqueid=%@", _baseURL, _uniqueId];
NSString* urlString = [NSString stringWithFormat:@"%@/applist?uniqueid=%@", _baseHTTPSURL, _uniqueId];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest *)newServerInfoRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo?uniqueid=%@", _baseURL, _uniqueId];
NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo?uniqueid=%@", _baseHTTPSURL, _uniqueId];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest *)newHttpServerInfoRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo", _baseHTTPURL];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (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];
NSString* urlString = [NSString stringWithFormat:@"%@/launch?uniqueid=%@&appid=%@&mode=%dx%dx%d&additionalStates=1&sops=1&rikey=%@&rikeyid=%d", _baseHTTPSURL, _uniqueId, appId, width, height, refreshRate, rikey, rikeyid];
// This blocks while the app is launching
return [self createRequestFromString:urlString enableTimeout:FALSE];
}
- (NSURLRequest*) newResumeRequestWithRiKey:(NSString*)riKey riKeyId:(int)riKeyId {
NSString* urlString = [NSString stringWithFormat:@"%@/resume?uniqueid=%@&rikey=%@&rikeyid=%d", _baseURL, _uniqueId, riKey, riKeyId];
NSString* urlString = [NSString stringWithFormat:@"%@/resume?uniqueid=%@&rikey=%@&rikeyid=%d", _baseHTTPSURL, _uniqueId, riKey, riKeyId];
// This blocks while the app is resuming
return [self createRequestFromString:urlString enableTimeout:FALSE];
}
- (NSURLRequest*) newQuitAppRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/cancel?uniqueid=%@", _baseURL, _uniqueId];
NSString* urlString = [NSString stringWithFormat:@"%@/cancel?uniqueid=%@", _baseHTTPSURL, _uniqueId];
return [self createRequestFromString:urlString enableTimeout:FALSE];
}
- (NSURLRequest*) newAppAssetRequestWithAppId:(NSString *)appId {
NSString* urlString = [NSString stringWithFormat:@"%@/appasset?uniqueid=%@&appid=%@&AssetType=2&AssetIdx=0", _baseURL, _uniqueId, appId];
NSString* urlString = [NSString stringWithFormat:@"%@/appasset?uniqueid=%@&appid=%@&AssetType=2&AssetIdx=0", _baseHTTPSURL, _uniqueId, appId];
return [self createRequestFromString:urlString enableTimeout:FALSE];
}
@ -155,33 +190,6 @@ static const NSString* PORT = @"47984";
return hex;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
Log(LOG_D, @"Received response: %@", response);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
Log(LOG_D, @"\n\nReceived data: %@\n\n", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
[_respData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if ([[NSString alloc] initWithData:_respData encoding:NSUTF8StringEncoding] != nil) {
_requestResp = [HttpManager fixXmlVersion:_respData];
} else {
_requestResp = _respData;
}
dispatch_semaphore_signal(_requestLock);
}
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
SecIdentityRef identity = [self getClientCertificate];
NSArray *certArray = [self getCertificate:identity];
NSURLCredential *newCredential = [NSURLCredential credentialWithIdentity:identity certificates:certArray persistence:NSURLCredentialPersistencePermanent];
[challenge.sender useCredential:newCredential forAuthenticationChallenge:challenge];
}
// Returns an array containing the certificate
- (NSArray*)getCertificate:(SecIdentityRef) identity {
SecCertificateRef certificate = nil;
@ -217,10 +225,25 @@ static const NSString* PORT = @"47984";
return identityApp;
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
Log(LOG_D, @"connection error: %@", error);
_errorOccurred = true;
dispatch_semaphore_signal(_requestLock);
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(nonnull void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * __nullable))completionHandler {
// Allow untrusted server certificates
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
completionHandler(NSURLSessionAuthChallengeUseCredential,
[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust]);
}
// Respond to client certificate challenge with our certificate
else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate])
{
SecIdentityRef identity = [self getClientCertificate];
NSArray* certArray = [self getCertificate:identity];
NSURLCredential* newCredential = [NSURLCredential credentialWithIdentity:identity certificates:certArray persistence:NSURLCredentialPersistencePermanent];
completionHandler(NSURLSessionAuthChallengeUseCredential, newCredential);
}
else
{
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, NULL);
}
}
@end

View File

@ -13,7 +13,10 @@
@property (nonatomic) id<Response> response;
@property (nonatomic) NSURLRequest* request;
@property (nonatomic) int fallbackError;
@property (nonatomic) NSURLRequest* fallbackRequest;
+ (instancetype) requestForResponse:(id<Response>)response withUrlRequest:(NSURLRequest*)req fallbackError:(int)error fallbackRequest:(NSURLRequest*) fallbackReq;
+ (instancetype) requestForResponse:(id<Response>)response withUrlRequest:(NSURLRequest*)req;
+ (instancetype) requestWithUrlRequest:(NSURLRequest*)req;

View File

@ -25,4 +25,13 @@
return request;
}
+ (HttpRequest*) requestForResponse:(id<Response>)response withUrlRequest:(NSURLRequest*)req fallbackError:(int)error fallbackRequest:(NSURLRequest*) fallbackReq {
HttpRequest* request = [[HttpRequest alloc] init];
request.request = req;
request.response = response;
request.fallbackError = error;
request.fallbackRequest = fallbackReq;
return request;
}
@end

View File

@ -31,7 +31,8 @@
- (void) main {
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
[_httpManager executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[_httpManager newServerInfoRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[_httpManager newServerInfoRequest]
fallbackError:401 fallbackRequest:[_httpManager newHttpServerInfoRequest]]];
if (serverInfoResp == nil) {
[_callback pairFailed:@"Unable to connect to PC"];
return;
@ -60,7 +61,7 @@
}
NSInteger pairedStatus;
if (![pairResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Pairing was declined by the target."];
return;
}
@ -79,7 +80,7 @@
return;
}
if (![challengeResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Pairing stage #2 failed"];
return;
}
@ -100,7 +101,7 @@
return;
}
if (![secretResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Pairing stage #3 failed"];
return;
}
@ -110,14 +111,14 @@
NSData* serverSignature = [serverSecretResp subdataWithRange:NSMakeRange(16, 256)];
if (![cryptoMan verifySignature:serverSecret withSignature:serverSignature andCert:[Utils hexToBytes:plainCert]]) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Server certificate invalid"];
return;
}
NSData* serverChallengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:randomChallenge with:[CryptoManager getSignatureFromCert:[Utils hexToBytes:plainCert]]] with:serverSecret]];
if (![serverChallengeRespHash isEqual:serverResponse]) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Incorrect PIN"];
return;
}
@ -129,7 +130,7 @@
return;
}
if (![clientSecretResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Pairing stage #4 failed"];
return;
}
@ -140,7 +141,7 @@
return;
}
if (![clientPairChallengeResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Pairing stage #5 failed"];
return;
}
@ -149,11 +150,11 @@
- (BOOL) verifyResponseStatus:(HttpResponse*)resp {
if (resp == nil) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Network error occured."];
return false;
} else if (![resp isStatusOk]) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:resp.statusMessage];
return false;
} else {

View File

@ -45,7 +45,8 @@
cert:cert];
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest]]];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest]
fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
NSString* currentGame = [serverInfoResp getStringTag:@"currentgame"];
NSString* pairStatus = [serverInfoResp getStringTag:@"PairStatus"];
NSString* currentClient = [serverInfoResp getStringTag:@"CurrentClient"];

View File

@ -133,7 +133,8 @@ static NSArray* appList;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
HttpManager* hMan = [[HttpManager alloc] initWithHost:host.address uniqueId:_uniqueId deviceName:deviceName cert:_cert];
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest]]];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest]
fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
if (serverInfoResp == nil || ![serverInfoResp isStatusOk]) {
Log(LOG_W, @"Failed to get server info: %@", serverInfoResp.statusMessage);
[self hideLoadingFrame];
@ -160,7 +161,7 @@ static NSArray* appList;
[longClickAlert addAction:[UIAlertAction actionWithTitle:@"Unpair" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
HttpManager* hMan = [[HttpManager alloc] initWithHost:host.address uniqueId:_uniqueId deviceName:deviceName cert:_cert];
[hMan executeRequest:[HttpRequest requestWithUrlRequest:[hMan newUnpairRequest]]];
[hMan executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[hMan newUnpairRequest]]];
});
}]];
} else {