Merge branch 'master' of github.com:limelight-stream/limelight-ios

# By Cameron Gutman
# Via Cameron Gutman
* 'master' of github.com:limelight-stream/limelight-ios:
  Add timeouts to HTTP requests
  Change StreamView's background to black
  Display a failure dialog when we fail to launch an app
This commit is contained in:
Diego Waxemberg 2014-10-21 16:18:00 -04:00
commit f0b6602b99
6 changed files with 60 additions and 25 deletions

View File

@ -102,63 +102,75 @@ static const NSString* PORT = @"47984";
[NSURLConnection connectionWithRequest:request delegate:self]; [NSURLConnection connectionWithRequest:request delegate:self];
} }
- (NSURLRequest*) createRequestFromString:(NSString*) urlString { - (NSURLRequest*) createRequestFromString:(NSString*) urlString enableTimeout:(BOOL)normalTimeout {
NSString* escapedUrl = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSString* escapedUrl = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL* url = [[NSURL alloc] initWithString:escapedUrl]; NSURL* url = [[NSURL alloc] initWithString:escapedUrl];
return [NSURLRequest requestWithURL:url]; NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
if (normalTimeout) {
// Timeout the request after 5 seconds
[request setTimeoutInterval:5];
}
else {
// Timeout the request after 60 seconds
[request setTimeoutInterval:60];
}
return request;
} }
- (NSURLRequest*) newPairRequest:(NSData*)salt { - (NSURLRequest*) newPairRequest:(NSData*)salt {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=getservercert&salt=%@&clientcert=%@", NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=getservercert&salt=%@&clientcert=%@",
_baseURL, _uniqueId, _deviceName, [self bytesToHex:salt], [self bytesToHex:_cert]]; _baseURL, _uniqueId, _deviceName, [self bytesToHex:salt], [self bytesToHex:_cert]];
return [self createRequestFromString:urlString]; // This call blocks while waiting for the user to input the PIN on the PC
return [self createRequestFromString:urlString enableTimeout:FALSE];
} }
- (NSURLRequest*) newUnpairRequest { - (NSURLRequest*) newUnpairRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/unpair?uniqueid=%@", _baseURL, _uniqueId]; NSString* urlString = [NSString stringWithFormat:@"%@/unpair?uniqueid=%@", _baseURL, _uniqueId];
return [self createRequestFromString:urlString]; return [self createRequestFromString:urlString enableTimeout:TRUE];
} }
- (NSURLRequest*) newChallengeRequest:(NSData*)challenge { - (NSURLRequest*) newChallengeRequest:(NSData*)challenge {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientchallenge=%@", NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientchallenge=%@",
_baseURL, _uniqueId, _deviceName, [self bytesToHex:challenge]]; _baseURL, _uniqueId, _deviceName, [self bytesToHex:challenge]];
return [self createRequestFromString:urlString]; return [self createRequestFromString:urlString enableTimeout:TRUE];
} }
- (NSURLRequest*) newChallengeRespRequest:(NSData*)challengeResp { - (NSURLRequest*) newChallengeRespRequest:(NSData*)challengeResp {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&serverchallengeresp=%@", NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&serverchallengeresp=%@",
_baseURL, _uniqueId, _deviceName, [self bytesToHex:challengeResp]]; _baseURL, _uniqueId, _deviceName, [self bytesToHex:challengeResp]];
return [self createRequestFromString:urlString]; return [self createRequestFromString:urlString enableTimeout:TRUE];
} }
- (NSURLRequest*) newClientSecretRespRequest:(NSString*)clientPairSecret { - (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=%@", _baseURL, _uniqueId, _deviceName, clientPairSecret];
return [self createRequestFromString:urlString]; return [self createRequestFromString:urlString enableTimeout:TRUE];
} }
- (NSURLRequest*) newPairChallenge { - (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", _baseURL, _uniqueId, _deviceName];
return [self createRequestFromString:urlString]; return [self createRequestFromString:urlString enableTimeout:TRUE];
} }
- (NSURLRequest *)newAppListRequest { - (NSURLRequest *)newAppListRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/applist?uniqueid=%@", _baseURL, _uniqueId]; NSString* urlString = [NSString stringWithFormat:@"%@/applist?uniqueid=%@", _baseURL, _uniqueId];
return [self createRequestFromString:urlString]; return [self createRequestFromString:urlString enableTimeout:TRUE];
} }
- (NSURLRequest *)newServerInfoRequest { - (NSURLRequest *)newServerInfoRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo?uniqueid=%@", _baseURL, _uniqueId]; NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo?uniqueid=%@", _baseURL, _uniqueId];
return [self createRequestFromString:urlString]; 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 { - (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", _baseURL, _uniqueId, appId, width, height, refreshRate, rikey, rikeyid];
return [self createRequestFromString:urlString]; // This blocks while the app is launching
return [self createRequestFromString:urlString enableTimeout:FALSE];
} }
- (NSURLRequest*) newResumeRequestWithRiKey:(NSString*)riKey riKeyId:(int)riKeyId { - (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", _baseURL, _uniqueId, riKey, riKeyId];
return [self createRequestFromString:urlString]; // This blocks while the app is resuming
return [self createRequestFromString:urlString enableTimeout:FALSE];
} }
- (NSString*) bytesToHex:(NSData*)data { - (NSString*) bytesToHex:(NSData*)data {

View File

@ -43,7 +43,9 @@
[_callback showPIN:PIN]; [_callback showPIN:PIN];
NSData* pairResp = [_httpManager executeRequestSynchronously:[_httpManager newPairRequest:salt]]; NSData* pairResp = [_httpManager executeRequestSynchronously:[_httpManager newPairRequest:salt]];
if ([[HttpManager getStringFromXML:pairResp tag:@"paired"] intValue] != 1) { NSString* pairedString;
pairedString = [HttpManager getStringFromXML:pairResp tag:@"paired"];
if (pairedString == NULL || ![pairedString isEqualToString:@"1"]) {
[_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]];
//TODO: better message //TODO: better message
[_callback pairFailed:@"pairResp failed"]; [_callback pairFailed:@"pairResp failed"];
@ -59,7 +61,8 @@
NSData* encryptedChallenge = [cryptoMan aesEncrypt:randomChallenge withKey:aesKey]; NSData* encryptedChallenge = [cryptoMan aesEncrypt:randomChallenge withKey:aesKey];
NSData* challengeResp = [_httpManager executeRequestSynchronously:[_httpManager newChallengeRequest:encryptedChallenge]]; NSData* challengeResp = [_httpManager executeRequestSynchronously:[_httpManager newChallengeRequest:encryptedChallenge]];
if ([[HttpManager getStringFromXML:challengeResp tag:@"paired"] intValue] != 1) { pairedString = [HttpManager getStringFromXML:challengeResp tag:@"paired"];
if (pairedString == NULL || ![pairedString isEqualToString:@"1"]) {
[_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]];
//TODO: better message //TODO: better message
[_callback pairFailed:@"challengeResp failed"]; [_callback pairFailed:@"challengeResp failed"];
@ -77,7 +80,8 @@
NSData* challengeRespEncrypted = [cryptoMan aesEncrypt:challengeRespHash withKey:aesKey]; NSData* challengeRespEncrypted = [cryptoMan aesEncrypt:challengeRespHash withKey:aesKey];
NSData* secretResp = [_httpManager executeRequestSynchronously:[_httpManager newChallengeRespRequest:challengeRespEncrypted]]; NSData* secretResp = [_httpManager executeRequestSynchronously:[_httpManager newChallengeRespRequest:challengeRespEncrypted]];
if ([[HttpManager getStringFromXML:secretResp tag:@"paired"] intValue] != 1) { pairedString = [HttpManager getStringFromXML:secretResp tag:@"paired"];
if (pairedString == NULL || ![pairedString isEqualToString:@"1"]) {
[_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]];
//TODO: better message //TODO: better message
[_callback pairFailed:@"secretResp failed"]; [_callback pairFailed:@"secretResp failed"];
@ -105,7 +109,8 @@
NSData* clientPairingSecret = [self concatData:clientSecret with:[cryptoMan signData:clientSecret withKey:[CryptoManager readKeyFromFile]]]; NSData* clientPairingSecret = [self concatData:clientSecret with:[cryptoMan signData:clientSecret withKey:[CryptoManager readKeyFromFile]]];
NSData* clientSecretResp = [_httpManager executeRequestSynchronously:[_httpManager newClientSecretRespRequest:[Utils bytesToHex:clientPairingSecret]]]; NSData* clientSecretResp = [_httpManager executeRequestSynchronously:[_httpManager newClientSecretRespRequest:[Utils bytesToHex:clientPairingSecret]]];
if (![[HttpManager getStringFromXML:clientSecretResp tag:@"paired"] isEqual:@"1"]) { pairedString = [HttpManager getStringFromXML:clientSecretResp tag:@"paired"];
if (pairedString == NULL || ![pairedString isEqualToString:@"1"]) {
[_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]];
//TODO: better message //TODO: better message
[_callback pairFailed:@"clientSecretResp failed"]; [_callback pairFailed:@"clientSecretResp failed"];
@ -113,7 +118,8 @@
} }
NSData* clientPairChallenge = [_httpManager executeRequestSynchronously:[_httpManager newPairChallenge]]; NSData* clientPairChallenge = [_httpManager executeRequestSynchronously:[_httpManager newPairChallenge]];
if (![[HttpManager getStringFromXML:clientPairChallenge tag:@"paired"] isEqual:@"1"]) { pairedString = [HttpManager getStringFromXML:clientPairChallenge tag:@"paired"];
if (pairedString == NULL || ![pairedString isEqualToString:@"1"]) {
[_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]];
//TODO: better message //TODO: better message
[_callback pairFailed:@"clientPairChallenge failed"]; [_callback pairFailed:@"clientPairChallenge failed"];

View File

@ -41,12 +41,23 @@
cert:cert]; cert:cert];
NSData* serverInfoResp = [hMan executeRequestSynchronously:[hMan newServerInfoRequest]]; NSData* serverInfoResp = [hMan executeRequestSynchronously:[hMan newServerInfoRequest]];
if (![[HttpManager getStringFromXML:serverInfoResp tag:@"currentgame"] isEqualToString:@"0"]) { NSString* currentGame = [HttpManager getStringFromXML:serverInfoResp tag:@"currentgame"];
if (currentGame == NULL) {
[_callbacks launchFailed];
return;
}
else if ([currentGame isEqualToString:@"0"]) {
// App already running, resume it // App already running, resume it
[self resumeApp:hMan]; if (![self resumeApp:hMan]) {
[_callbacks launchFailed];
return;
}
} else { } else {
// Start app // Start app
[self launchApp:hMan]; if (![self launchApp:hMan]) {
[_callbacks launchFailed];
return;
}
} }
VideoDecoderRenderer* renderer = [[VideoDecoderRenderer alloc]initWithView:_renderView]; VideoDecoderRenderer* renderer = [[VideoDecoderRenderer alloc]initWithView:_renderView];

View File

@ -81,7 +81,13 @@
} }
- (void) launchFailed { - (void) launchFailed {
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Connection Failed"
message:@"Failed to start app"
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){
[self performSegueWithIdentifier:@"returnToMainFrame" sender:self];
}]];
[self presentViewController:alert animated:YES completion:nil];
} }
- (void) displayMessage:(char*)message { - (void) displayMessage:(char*)message {

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6250" systemVersion="14A388a" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" initialViewController="wb7-af-jn8"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6250" systemVersion="14A389" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" initialViewController="wb7-af-jn8">
<dependencies> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
</dependencies> </dependencies>
@ -109,7 +109,7 @@
<view key="view" contentMode="scaleToFill" id="VPm-Ae-rc4" userLabel="RenderView" customClass="StreamView"> <view key="view" contentMode="scaleToFill" id="VPm-Ae-rc4" userLabel="RenderView" customClass="StreamView">
<rect key="frame" x="0.0" y="0.0" width="1024" height="768"/> <rect key="frame" x="0.0" y="0.0" width="1024" height="768"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
</view> </view>
<nil key="simulatedStatusBarMetrics"/> <nil key="simulatedStatusBarMetrics"/>
<nil key="simulatedTopBarMetrics"/> <nil key="simulatedTopBarMetrics"/>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6250" systemVersion="14A388a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="dgh-JZ-Q7z"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6250" systemVersion="14A389" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="dgh-JZ-Q7z">
<dependencies> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
</dependencies> </dependencies>
@ -103,7 +103,7 @@
<view key="view" contentMode="scaleToFill" id="eir-e9-IPE" customClass="StreamView"> <view key="view" contentMode="scaleToFill" id="eir-e9-IPE" customClass="StreamView">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/> <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/> <color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
</view> </view>
<nil key="simulatedStatusBarMetrics"/> <nil key="simulatedStatusBarMetrics"/>
<nil key="simulatedTopBarMetrics"/> <nil key="simulatedTopBarMetrics"/>