aboutsummaryrefslogtreecommitdiff
path: root/talk
diff options
context:
space:
mode:
authortkchin@webrtc.org <tkchin@webrtc.org>2014-11-27 00:52:38 +0000
committertkchin@webrtc.org <tkchin@webrtc.org>2014-11-27 00:52:38 +0000
commit3e9ad26112c5341aebf54ff8d43216acf7099063 (patch)
treeeaedca294713cf640c0721e868408be8b3542947 /talk
parent79b9eba3abbf02f7a569280d8a735847ce09ec25 (diff)
downloadwebrtc-3e9ad26112c5341aebf54ff8d43216acf7099063.tar.gz
Refactor iOS AppRTC parsing code.
Moved parsing code to JSON categories for the relevant objects. No longer prefer ISAC as audio codec. BUG= R=glaznev@webrtc.org Review URL: https://webrtc-codereview.appspot.com/31989005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7755 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'talk')
-rw-r--r--talk/examples/objc/AppRTCDemo/APPRTCAppClient.h8
-rw-r--r--talk/examples/objc/AppRTCDemo/APPRTCAppClient.m197
-rw-r--r--talk/examples/objc/AppRTCDemo/APPRTCConnectionManager.m119
-rw-r--r--talk/examples/objc/AppRTCDemo/ARDSignalingParams.h46
-rw-r--r--talk/examples/objc/AppRTCDemo/ARDSignalingParams.m130
-rw-r--r--talk/examples/objc/AppRTCDemo/ARDUtilities.h46
-rw-r--r--talk/examples/objc/AppRTCDemo/ARDUtilities.m72
-rw-r--r--talk/examples/objc/AppRTCDemo/RTCICECandidate+JSON.h35
-rw-r--r--talk/examples/objc/AppRTCDemo/RTCICECandidate+JSON.m56
-rw-r--r--talk/examples/objc/AppRTCDemo/RTCICEServer+JSON.h36
-rw-r--r--talk/examples/objc/AppRTCDemo/RTCICEServer+JSON.m59
-rw-r--r--talk/examples/objc/AppRTCDemo/RTCMediaConstraints+JSON.h36
-rw-r--r--talk/examples/objc/AppRTCDemo/RTCMediaConstraints+JSON.m54
-rw-r--r--talk/examples/objc/AppRTCDemo/RTCSessionDescription+JSON.h36
-rw-r--r--talk/examples/objc/AppRTCDemo/RTCSessionDescription+JSON.m50
-rwxr-xr-xtalk/libjingle_examples.gyp12
16 files changed, 734 insertions, 258 deletions
diff --git a/talk/examples/objc/AppRTCDemo/APPRTCAppClient.h b/talk/examples/objc/AppRTCDemo/APPRTCAppClient.h
index 8b21db5858..880d5f8a48 100644
--- a/talk/examples/objc/AppRTCDemo/APPRTCAppClient.h
+++ b/talk/examples/objc/AppRTCDemo/APPRTCAppClient.h
@@ -27,6 +27,7 @@
#import <Foundation/Foundation.h>
+#import "ARDSignalingParams.h"
#import "GAEChannelClient.h"
@class APPRTCAppClient;
@@ -50,14 +51,13 @@
// for the registered handler to be called with received messages.
@interface APPRTCAppClient : NSObject
-@property(nonatomic) BOOL initiator;
-@property(nonatomic, copy, readonly) RTCMediaConstraints* videoConstraints;
+@property(nonatomic, readonly) ARDSignalingParams *params;
@property(nonatomic, weak) id<APPRTCAppClientDelegate> delegate;
- (instancetype)initWithDelegate:(id<APPRTCAppClientDelegate>)delegate
messageHandler:(id<GAEMessageHandler>)handler;
-- (void)connectToRoom:(NSURL*)room;
-- (void)sendData:(NSData*)data;
+- (void)connectToRoom:(NSURL *)room;
+- (void)sendData:(NSData *)data;
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// Disallow init and don't add to documentation
diff --git a/talk/examples/objc/AppRTCDemo/APPRTCAppClient.m b/talk/examples/objc/AppRTCDemo/APPRTCAppClient.m
index 853496f81b..20e708de35 100644
--- a/talk/examples/objc/AppRTCDemo/APPRTCAppClient.m
+++ b/talk/examples/objc/AppRTCDemo/APPRTCAppClient.m
@@ -33,8 +33,11 @@
#import <dispatch/dispatch.h>
+#import "ARDSignalingParams.h"
+#import "ARDUtilities.h"
#import "GAEChannelClient.h"
#import "RTCICEServer.h"
+#import "RTCICEServer+JSON.h"
#import "RTCMediaConstraints.h"
#import "RTCPair.h"
@@ -60,14 +63,15 @@
}
- (void)connectToRoom:(NSURL*)url {
- NSString* urlString =
+ NSString *urlString =
[[url absoluteString] stringByAppendingString:@"&t=json"];
- NSURL* requestURL = [NSURL URLWithString:urlString];
- NSURLRequest* request = [NSURLRequest requestWithURL:requestURL];
- [self sendURLRequest:request
- completionHandler:^(NSError* error,
- NSHTTPURLResponse* httpResponse,
- NSData* responseData) {
+ NSURL *requestURL = [NSURL URLWithString:urlString];
+ NSURLRequest *request = [NSURLRequest requestWithURL:requestURL];
+ [NSURLConnection sendAsynchronousRequest:request
+ completionHandler:^(NSURLResponse *response,
+ NSData *data,
+ NSError *error) {
+ NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
int statusCode = [httpResponse statusCode];
[self logVerbose:[NSString stringWithFormat:
@"Response received\nURL\n%@\nStatus [%d]\nHeaders\n%@",
@@ -81,116 +85,74 @@
if (statusCode != 200) {
return;
}
- [self handleResponseData:responseData
- forRoomRequest:request];
+ [self handleResponseData:data forRoomRequest:request];
}];
}
- (void)sendData:(NSData*)data {
NSParameterAssert([data length] > 0);
- NSString* message = [NSString stringWithUTF8String:[data bytes]];
+ NSString *message = [NSString stringWithUTF8String:[data bytes]];
[self logVerbose:[NSString stringWithFormat:@"Send message:\n%@", message]];
if (!_postMessageURL) {
return;
}
- NSMutableURLRequest* request =
+ NSMutableURLRequest *request =
[NSMutableURLRequest requestWithURL:_postMessageURL];
request.HTTPMethod = @"POST";
[request setHTTPBody:data];
- [self sendURLRequest:request
- completionHandler:^(NSError* error,
- NSHTTPURLResponse* httpResponse,
- NSData* responseData) {
+ [NSURLConnection sendAsynchronousRequest:request
+ completionHandler:^(NSURLResponse *response,
+ NSData *data,
+ NSError *error) {
+ NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
int status = [httpResponse statusCode];
- NSString* response = [responseData length] > 0 ?
- [NSString stringWithUTF8String:[responseData bytes]] :
+ NSString *responseString = [data length] > 0 ?
+ [NSString stringWithUTF8String:[data bytes]] :
nil;
NSAssert(status == 200,
@"Bad response [%d] to message: %@\n\n%@",
status,
message,
- response);
+ responseString);
}];
}
#pragma mark - Private
-- (void)logVerbose:(NSString*)message {
+- (void)logVerbose:(NSString *)message {
if (_verboseLogging) {
NSLog(@"%@", message);
}
}
-- (void)handleResponseData:(NSData*)responseData
- forRoomRequest:(NSURLRequest*)request {
- NSDictionary* roomJSON = [self parseJSONData:responseData];
- [self logVerbose:[NSString stringWithFormat:@"Room JSON:\n%@", roomJSON]];
- NSParameterAssert(roomJSON);
- if (roomJSON[@"error"]) {
- NSArray* errorMessages = roomJSON[@"error_messages"];
- NSMutableString* message = [NSMutableString string];
- for (NSString* errorMessage in errorMessages) {
+- (void)handleResponseData:(NSData *)responseData
+ forRoomRequest:(NSURLRequest *)request {
+ ARDSignalingParams *params =
+ [ARDSignalingParams paramsFromJSONData:responseData];
+ if (params.errorMessages.count > 0) {
+ NSMutableString *message = [NSMutableString string];
+ for (NSString *errorMessage in params.errorMessages) {
[message appendFormat:@"%@\n", errorMessage];
}
[self.delegate appClient:self didErrorWithMessage:message];
return;
}
- NSString* pcConfig = roomJSON[@"pc_config"];
- NSData* pcConfigData = [pcConfig dataUsingEncoding:NSUTF8StringEncoding];
- NSDictionary* pcConfigJSON = [self parseJSONData:pcConfigData];
- [self logVerbose:[NSString stringWithFormat:@"PCConfig JSON:\n%@",
- pcConfigJSON]];
- NSParameterAssert(pcConfigJSON);
-
- NSArray* iceServers = [self parseICEServersForPCConfigJSON:pcConfigJSON];
- [self requestTURNServerForICEServers:iceServers
- turnServerUrl:roomJSON[@"turn_url"]];
-
- _initiator = [roomJSON[@"initiator"] boolValue];
- [self logVerbose:[NSString stringWithFormat:@"Initiator: %d", _initiator]];
- _postMessageURL = [self parsePostMessageURLForRoomJSON:roomJSON
- request:request];
- [self logVerbose:[NSString stringWithFormat:@"POST message URL:\n%@",
- _postMessageURL]];
- _videoConstraints = [self parseVideoConstraintsForRoomJSON:roomJSON];
- [self logVerbose:[NSString stringWithFormat:@"Media constraints:\n%@",
- _videoConstraints]];
- NSString* token = roomJSON[@"token"];
+ [self requestTURNServerForICEServers:params.iceServers
+ turnServerUrl:[params.turnRequestURL absoluteString]];
+ NSString *token = params.channelToken;
[self logVerbose:
[NSString stringWithFormat:@"About to open GAE with token: %@",
token]];
_gaeChannel =
[[GAEChannelClient alloc] initWithToken:token
delegate:_messageHandler];
-}
-
-- (NSDictionary*)parseJSONData:(NSData*)data {
- NSError* error = nil;
- NSDictionary* json =
- [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
- NSAssert(!error, @"Unable to parse. %@", error.localizedDescription);
- return json;
-}
-
-- (NSArray*)parseICEServersForPCConfigJSON:(NSDictionary*)pcConfigJSON {
- NSMutableArray* result = [NSMutableArray array];
- NSArray* iceServers = pcConfigJSON[@"iceServers"];
- for (NSDictionary* iceServer in iceServers) {
- NSString* url = iceServer[@"urls"];
- NSString* username = pcConfigJSON[@"username"];
- NSString* credential = iceServer[@"credential"];
- username = username ? username : @"";
- credential = credential ? credential : @"";
- [self logVerbose:[NSString stringWithFormat:@"url [%@] - credential [%@]",
- url,
- credential]];
- RTCICEServer* server =
- [[RTCICEServer alloc] initWithURI:[NSURL URLWithString:url]
- username:username
- password:credential];
- [result addObject:server];
- }
- return result;
+ _params = params;
+ // Generate URL for posting data.
+ NSDictionary *roomJSON = [NSDictionary dictionaryWithJSONData:responseData];
+ _postMessageURL = [self parsePostMessageURLForRoomJSON:roomJSON
+ request:request];
+ [self logVerbose:[NSString stringWithFormat:@"POST message URL:\n%@",
+ _postMessageURL]];
}
- (NSURL*)parsePostMessageURLForRoomJSON:(NSDictionary*)roomJSON
@@ -207,63 +169,26 @@
return [NSURL URLWithString:postMessageUrl];
}
-- (RTCMediaConstraints*)parseVideoConstraintsForRoomJSON:
- (NSDictionary*)roomJSON {
- NSString* mediaConstraints = roomJSON[@"media_constraints"];
- RTCMediaConstraints* constraints = nil;
- if ([mediaConstraints length] > 0) {
- NSData* constraintsData =
- [mediaConstraints dataUsingEncoding:NSUTF8StringEncoding];
- NSDictionary* constraintsJSON = [self parseJSONData:constraintsData];
- id video = constraintsJSON[@"video"];
- if ([video isKindOfClass:[NSDictionary class]]) {
- NSDictionary* mandatory = video[@"mandatory"];
- NSMutableArray* mandatoryContraints =
- [NSMutableArray arrayWithCapacity:[mandatory count]];
- [mandatory enumerateKeysAndObjectsUsingBlock:^(
- id key, id obj, BOOL* stop) {
- [mandatoryContraints addObject:[[RTCPair alloc] initWithKey:key
- value:obj]];
- }];
- // TODO(tkchin): figure out json formats for optional constraints.
- constraints =
- [[RTCMediaConstraints alloc]
- initWithMandatoryConstraints:mandatoryContraints
- optionalConstraints:nil];
- } else if ([video isKindOfClass:[NSNumber class]] && [video boolValue]) {
- constraints = [[RTCMediaConstraints alloc] init];
- }
- }
- return constraints;
-}
-
-- (void)requestTURNServerWithUrl:(NSString*)turnServerUrl
+- (void)requestTURNServerWithUrl:(NSString *)turnServerUrl
completionHandler:
- (void (^)(RTCICEServer* turnServer))completionHandler {
- NSURL* turnServerURL = [NSURL URLWithString:turnServerUrl];
- NSMutableURLRequest* request =
+ (void (^)(RTCICEServer *turnServer))completionHandler {
+ NSURL *turnServerURL = [NSURL URLWithString:turnServerUrl];
+ NSMutableURLRequest *request =
[NSMutableURLRequest requestWithURL:turnServerURL];
[request addValue:@"Mozilla/5.0" forHTTPHeaderField:@"user-agent"];
[request addValue:@"https://apprtc.appspot.com"
forHTTPHeaderField:@"origin"];
- [self sendURLRequest:request
- completionHandler:^(NSError* error,
- NSHTTPURLResponse* response,
- NSData* responseData) {
+ [NSURLConnection sendAsynchronousRequest:request
+ completionHandler:^(NSURLResponse *response,
+ NSData *data,
+ NSError *error) {
if (error) {
NSLog(@"Unable to get TURN server.");
completionHandler(nil);
return;
}
- NSDictionary* json = [self parseJSONData:responseData];
- NSString* username = json[@"username"];
- NSString* password = json[@"password"];
- NSArray* uris = json[@"uris"];
- NSParameterAssert([uris count] > 0);
- RTCICEServer* turnServer =
- [[RTCICEServer alloc] initWithURI:[NSURL URLWithString:uris[0]]
- username:username
- password:password];
+ NSDictionary *json = [NSDictionary dictionaryWithJSONData:data];
+ RTCICEServer *turnServer = [RTCICEServer serverFromCEODJSONDictionary:json];
completionHandler(turnServer);
}];
}
@@ -295,26 +220,4 @@
}
}
-- (void)sendURLRequest:(NSURLRequest*)request
- completionHandler:(void (^)(NSError* error,
- NSHTTPURLResponse* httpResponse,
- NSData* responseData))completionHandler {
- dispatch_async(_backgroundQueue, ^{
- NSError* error = nil;
- NSURLResponse* response = nil;
- NSData* responseData = [NSURLConnection sendSynchronousRequest:request
- returningResponse:&response
- error:&error];
- NSParameterAssert(!response ||
- [response isKindOfClass:[NSHTTPURLResponse class]]);
- if (error) {
- NSLog(@"Failed URL request for:%@\nError:%@", request, error);
- }
- dispatch_async(dispatch_get_main_queue(), ^{
- NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
- completionHandler(error, httpResponse, responseData);
- });
- });
-}
-
@end
diff --git a/talk/examples/objc/AppRTCDemo/APPRTCConnectionManager.m b/talk/examples/objc/AppRTCDemo/APPRTCConnectionManager.m
index 9a39528dff..9134e4dcb9 100644
--- a/talk/examples/objc/AppRTCDemo/APPRTCConnectionManager.m
+++ b/talk/examples/objc/AppRTCDemo/APPRTCConnectionManager.m
@@ -31,6 +31,7 @@
#import "APPRTCAppClient.h"
#import "GAEChannelClient.h"
#import "RTCICECandidate.h"
+#import "RTCICECandidate+JSON.h"
#import "RTCMediaConstraints.h"
#import "RTCMediaStream.h"
#import "RTCPair.h"
@@ -38,6 +39,7 @@
#import "RTCPeerConnectionDelegate.h"
#import "RTCPeerConnectionFactory.h"
#import "RTCSessionDescription.h"
+#import "RTCSessionDescription+JSON.h"
#import "RTCSessionDescriptionDelegate.h"
#import "RTCStatsDelegate.h"
#import "RTCVideoCapturer.h"
@@ -158,7 +160,7 @@
[RTCVideoCapturer capturerWithDeviceName:cameraID];
self.videoSource = [self.peerConnectionFactory
videoSourceWithCapturer:capturer
- constraints:self.client.videoConstraints];
+ constraints:self.client.params.mediaConstraints];
localVideoTrack =
[self.peerConnectionFactory videoTrackWithID:@"ARDAMSv0"
source:self.videoSource];
@@ -177,7 +179,7 @@
#pragma mark - GAEMessageHandler methods
- (void)onOpen {
- if (!self.client.initiator) {
+ if (!self.client.params.isInitiator) {
[self.logger logMessage:@"Callee; waiting for remote offer"];
return;
}
@@ -200,13 +202,8 @@
[self.logger logMessage:[NSString stringWithFormat:@"GAE onMessage type - %@",
type]];
if ([type isEqualToString:@"candidate"]) {
- NSString* mid = messageData[@"id"];
- NSNumber* sdpLineIndex = messageData[@"label"];
- NSString* sdp = messageData[@"candidate"];
RTCICECandidate* candidate =
- [[RTCICECandidate alloc] initWithMid:mid
- index:sdpLineIndex.intValue
- sdp:sdp];
+ [RTCICECandidate candidateFromJSONDictionary:messageData];
if (self.queuedRemoteCandidates) {
[self.queuedRemoteCandidates addObject:candidate];
} else {
@@ -214,10 +211,8 @@
}
} else if ([type isEqualToString:@"offer"] ||
[type isEqualToString:@"answer"]) {
- NSString* sdpString = messageData[@"sdp"];
- RTCSessionDescription* sdp = [[RTCSessionDescription alloc]
- initWithType:type
- sdp:[[self class] preferISAC:sdpString]];
+ RTCSessionDescription* sdp =
+ [RTCSessionDescription descriptionFromJSONDictionary:messageData];
[self.peerConnection setRemoteDescriptionWithDelegate:self
sessionDescription:sdp];
[self.logger logMessage:@"PC - setRemoteDescription."];
@@ -283,26 +278,8 @@
- (void)peerConnection:(RTCPeerConnection*)peerConnection
gotICECandidate:(RTCICECandidate*)candidate {
dispatch_async(dispatch_get_main_queue(), ^{
- NSLog(@"PCO onICECandidate.\n Mid[%@] Index[%li] Sdp[%@]",
- candidate.sdpMid,
- (long)candidate.sdpMLineIndex,
- candidate.sdp);
- NSDictionary* json = @{
- @"type" : @"candidate",
- @"label" : @(candidate.sdpMLineIndex),
- @"id" : candidate.sdpMid,
- @"candidate" : candidate.sdp
- };
- NSError* error;
- NSData* data =
- [NSJSONSerialization dataWithJSONObject:json options:0 error:&error];
- if (!error) {
- [self.client sendData:data];
- } else {
- NSAssert(NO,
- @"Unable to serialize JSON object with error: %@",
- error.localizedDescription);
- }
+ NSLog(@"PCO onICECandidate.\n%@", candidate);
+ [self.client sendData:[candidate JSONData]];
});
}
@@ -330,7 +307,7 @@
#pragma mark - RTCSessionDescriptionDelegate
- (void)peerConnection:(RTCPeerConnection*)peerConnection
- didCreateSessionDescription:(RTCSessionDescription*)origSdp
+ didCreateSessionDescription:(RTCSessionDescription*)sdp
error:(NSError*)error {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
@@ -339,19 +316,10 @@
return;
}
[self.logger logMessage:@"SDP onSuccess(SDP) - set local description."];
- RTCSessionDescription* sdp = [[RTCSessionDescription alloc]
- initWithType:origSdp.type
- sdp:[[self class] preferISAC:origSdp.description]];
[self.peerConnection setLocalDescriptionWithDelegate:self
sessionDescription:sdp];
[self.logger logMessage:@"PC setLocalDescription."];
- NSDictionary* json = @{@"type" : sdp.type, @"sdp" : sdp.description};
- NSError* jsonError;
- NSData* data = [NSJSONSerialization dataWithJSONObject:json
- options:0
- error:&jsonError];
- NSAssert(!jsonError, @"Error: %@", jsonError.description);
- [self.client sendData:data];
+ [self.client sendData:[sdp JSONData]];
});
}
@@ -364,7 +332,7 @@
return;
}
[self.logger logMessage:@"SDP onSuccess() - possibly drain candidates"];
- if (!self.client.initiator) {
+ if (!self.client.params.isInitiator) {
if (self.peerConnection.remoteDescription &&
!self.peerConnection.localDescription) {
[self.logger logMessage:@"Callee, setRemoteDescription succeeded"];
@@ -404,69 +372,6 @@
#pragma mark - Private
-// Match |pattern| to |string| and return the first group of the first
-// match, or nil if no match was found.
-+ (NSString*)firstMatch:(NSRegularExpression*)pattern
- withString:(NSString*)string {
- NSTextCheckingResult* result =
- [pattern firstMatchInString:string
- options:0
- range:NSMakeRange(0, [string length])];
- if (!result)
- return nil;
- return [string substringWithRange:[result rangeAtIndex:1]];
-}
-
-// Mangle |origSDP| to prefer the ISAC/16k audio codec.
-+ (NSString*)preferISAC:(NSString*)origSDP {
- int mLineIndex = -1;
- NSString* isac16kRtpMap = nil;
- NSArray* lines = [origSDP componentsSeparatedByString:@"\n"];
- NSRegularExpression* isac16kRegex = [NSRegularExpression
- regularExpressionWithPattern:@"^a=rtpmap:(\\d+) ISAC/16000[\r]?$"
- options:0
- error:nil];
- for (int i = 0;
- (i < [lines count]) && (mLineIndex == -1 || isac16kRtpMap == nil);
- ++i) {
- NSString* line = [lines objectAtIndex:i];
- if ([line hasPrefix:@"m=audio "]) {
- mLineIndex = i;
- continue;
- }
- isac16kRtpMap = [self firstMatch:isac16kRegex withString:line];
- }
- if (mLineIndex == -1) {
- NSLog(@"No m=audio line, so can't prefer iSAC");
- return origSDP;
- }
- if (isac16kRtpMap == nil) {
- NSLog(@"No ISAC/16000 line, so can't prefer iSAC");
- return origSDP;
- }
- NSArray* origMLineParts =
- [[lines objectAtIndex:mLineIndex] componentsSeparatedByString:@" "];
- NSMutableArray* newMLine =
- [NSMutableArray arrayWithCapacity:[origMLineParts count]];
- int origPartIndex = 0;
- // Format is: m=<media> <port> <proto> <fmt> ...
- [newMLine addObject:[origMLineParts objectAtIndex:origPartIndex++]];
- [newMLine addObject:[origMLineParts objectAtIndex:origPartIndex++]];
- [newMLine addObject:[origMLineParts objectAtIndex:origPartIndex++]];
- [newMLine addObject:isac16kRtpMap];
- for (; origPartIndex < [origMLineParts count]; ++origPartIndex) {
- if (![isac16kRtpMap
- isEqualToString:[origMLineParts objectAtIndex:origPartIndex]]) {
- [newMLine addObject:[origMLineParts objectAtIndex:origPartIndex]];
- }
- }
- NSMutableArray* newLines = [NSMutableArray arrayWithCapacity:[lines count]];
- [newLines addObjectsFromArray:lines];
- [newLines replaceObjectAtIndex:mLineIndex
- withObject:[newMLine componentsJoinedByString:@" "]];
- return [newLines componentsJoinedByString:@"\n"];
-}
-
- (void)drainRemoteCandidates {
for (RTCICECandidate* candidate in self.queuedRemoteCandidates) {
[self.peerConnection addICECandidate:candidate];
diff --git a/talk/examples/objc/AppRTCDemo/ARDSignalingParams.h b/talk/examples/objc/AppRTCDemo/ARDSignalingParams.h
new file mode 100644
index 0000000000..df2114c384
--- /dev/null
+++ b/talk/examples/objc/AppRTCDemo/ARDSignalingParams.h
@@ -0,0 +1,46 @@
+/*
+ * libjingle
+ * Copyright 2014, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "RTCMediaConstraints.h"
+
+// Struct for holding the signaling parameters of an AppRTC room.
+@interface ARDSignalingParams : NSObject
+
+@property(nonatomic, assign) BOOL isInitiator;
+@property(nonatomic, readonly) NSArray *errorMessages;
+@property(nonatomic, readonly) RTCMediaConstraints *offerConstraints;
+@property(nonatomic, readonly) RTCMediaConstraints *mediaConstraints;
+@property(nonatomic, readonly) NSMutableArray *iceServers;
+@property(nonatomic, readonly) NSURL *signalingServerURL;
+@property(nonatomic, readonly) NSURL *turnRequestURL;
+@property(nonatomic, readonly) NSString *channelToken;
+
++ (ARDSignalingParams *)paramsFromJSONData:(NSData *)data;
+
+@end
diff --git a/talk/examples/objc/AppRTCDemo/ARDSignalingParams.m b/talk/examples/objc/AppRTCDemo/ARDSignalingParams.m
new file mode 100644
index 0000000000..58c8684b8a
--- /dev/null
+++ b/talk/examples/objc/AppRTCDemo/ARDSignalingParams.m
@@ -0,0 +1,130 @@
+/*
+ * libjingle
+ * Copyright 2014, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "ARDSignalingParams.h"
+
+#import "ARDUtilities.h"
+#import "RTCICEServer+JSON.h"
+#import "RTCMediaConstraints+JSON.h"
+
+static NSString const *kARDSignalingParamsErrorKey = @"error";
+static NSString const *kARDSignalingParamsErrorMessagesKey = @"error_messages";
+static NSString const *kARDSignalingParamsInitiatorKey = @"initiator";
+static NSString const *kARDSignalingParamsPeerConnectionConfigKey =
+ @"pc_config";
+static NSString const *kARDSignalingParamsICEServersKey = @"iceServers";
+static NSString const *kARDSignalingParamsMediaConstraintsKey =
+ @"media_constraints";
+static NSString const *kARDSignalingParamsMediaConstraintsVideoKey =
+ @"video";
+static NSString const *kARDSignalingParamsTokenKey = @"token";
+static NSString const *kARDSignalingParamsTurnRequestUrlKey = @"turn_url";
+
+@interface ARDSignalingParams ()
+
+@property(nonatomic, strong) NSArray *errorMessages;
+@property(nonatomic, strong) RTCMediaConstraints *offerConstraints;
+@property(nonatomic, strong) RTCMediaConstraints *mediaConstraints;
+@property(nonatomic, strong) NSMutableArray *iceServers;
+@property(nonatomic, strong) NSURL *signalingServerURL;
+@property(nonatomic, strong) NSURL *turnRequestURL;
+@property(nonatomic, strong) NSString *channelToken;
+
+@end
+
+@implementation ARDSignalingParams
+
+@synthesize errorMessages = _errorMessages;
+@synthesize isInitiator = _isInitiator;
+@synthesize offerConstraints = _offerConstraints;
+@synthesize mediaConstraints = _mediaConstraints;
+@synthesize iceServers = _iceServers;
+@synthesize signalingServerURL = _signalingServerURL;
+
++ (ARDSignalingParams *)paramsFromJSONData:(NSData *)data {
+ NSDictionary *paramsJSON = [NSDictionary dictionaryWithJSONData:data];
+ if (!paramsJSON) {
+ return nil;
+ }
+ ARDSignalingParams *params = [[ARDSignalingParams alloc] init];
+
+ // Parse errors.
+ BOOL hasError = NO;
+ NSArray *errorMessages = paramsJSON[kARDSignalingParamsErrorMessagesKey];
+ if (errorMessages.count > 0) {
+ params.errorMessages = errorMessages;
+ return params;
+ }
+
+ // Parse ICE servers.
+ NSString *peerConnectionConfigString =
+ paramsJSON[kARDSignalingParamsPeerConnectionConfigKey];
+ NSDictionary *peerConnectionConfig =
+ [NSDictionary dictionaryWithJSONString:peerConnectionConfigString];
+ NSArray *iceServerJSONArray =
+ peerConnectionConfig[kARDSignalingParamsICEServersKey];
+ NSMutableArray *iceServers = [NSMutableArray array];
+ for (NSDictionary *iceServerJSON in iceServerJSONArray) {
+ RTCICEServer *iceServer =
+ [RTCICEServer serverFromJSONDictionary:iceServerJSON];
+ [iceServers addObject:iceServer];
+ }
+ params.iceServers = iceServers;
+
+ // Parse initiator.
+ BOOL isInitiator = [paramsJSON[kARDSignalingParamsInitiatorKey] boolValue];
+ params.isInitiator = isInitiator;
+
+ // Parse video constraints.
+ RTCMediaConstraints *videoConstraints = nil;
+ NSString *mediaConstraintsJSONString =
+ paramsJSON[kARDSignalingParamsMediaConstraintsKey];
+ NSDictionary *mediaConstraintsJSON =
+ [NSDictionary dictionaryWithJSONString:mediaConstraintsJSONString];
+ id videoJSON =
+ mediaConstraintsJSON[kARDSignalingParamsMediaConstraintsVideoKey];
+ if ([videoJSON isKindOfClass:[NSDictionary class]]) {
+ videoConstraints =
+ [RTCMediaConstraints constraintsFromJSONDictionary:videoJSON];
+ } else if ([videoJSON isKindOfClass:[NSNumber class]] &&
+ [videoJSON boolValue]) {
+ videoConstraints = [[RTCMediaConstraints alloc] init];
+ }
+ params.mediaConstraints = videoConstraints;
+
+ // Parse channel token.
+ NSString *token = paramsJSON[kARDSignalingParamsTokenKey];
+ params.channelToken = token;
+
+ // Parse turn request url.
+ params.turnRequestURL =
+ [NSURL URLWithString:paramsJSON[kARDSignalingParamsTurnRequestUrlKey]];
+
+ return params;
+}
+
+@end
diff --git a/talk/examples/objc/AppRTCDemo/ARDUtilities.h b/talk/examples/objc/AppRTCDemo/ARDUtilities.h
new file mode 100644
index 0000000000..ca4d1d7304
--- /dev/null
+++ b/talk/examples/objc/AppRTCDemo/ARDUtilities.h
@@ -0,0 +1,46 @@
+/*
+ * libjingle
+ * Copyright 2014, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface NSDictionary (ARDUtilites)
+
+// Creates a dictionary with the keys and values in the JSON object.
++ (NSDictionary *)dictionaryWithJSONString:(NSString *)jsonString;
++ (NSDictionary *)dictionaryWithJSONData:(NSData *)jsonData;
+
+@end
+
+@interface NSURLConnection (ARDUtilities)
+
+// Issues an asynchronous request that calls back on main queue.
++ (void)sendAsynchronousRequest:(NSURLRequest *)request
+ completionHandler:(void (^)(NSURLResponse *response,
+ NSData *data,
+ NSError *error))completionHandler;
+
+@end
diff --git a/talk/examples/objc/AppRTCDemo/ARDUtilities.m b/talk/examples/objc/AppRTCDemo/ARDUtilities.m
new file mode 100644
index 0000000000..937013ea65
--- /dev/null
+++ b/talk/examples/objc/AppRTCDemo/ARDUtilities.m
@@ -0,0 +1,72 @@
+/*
+ * libjingle
+ * Copyright 2014, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "ARDUtilities.h"
+
+@implementation NSDictionary (ARDUtilites)
+
++ (NSDictionary *)dictionaryWithJSONString:(NSString *)jsonString {
+ NSParameterAssert(jsonString.length > 0);
+ NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
+ NSError *error = nil;
+ NSDictionary *dict =
+ [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
+ if (error) {
+ NSLog(@"Error parsing JSON: %@", error.localizedDescription);
+ }
+ return dict;
+}
+
++ (NSDictionary *)dictionaryWithJSONData:(NSData *)jsonData {
+ NSError *error = nil;
+ NSDictionary *dict =
+ [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
+ if (error) {
+ NSLog(@"Error parsing JSON: %@", error.localizedDescription);
+ }
+ return dict;
+}
+
+@end
+
+@implementation NSURLConnection (ARDUtilities)
+
++ (void)sendAsynchronousRequest:(NSURLRequest *)request
+ completionHandler:(void (^)(NSURLResponse *response,
+ NSData *data,
+ NSError *error))completionHandler {
+ // Kick off an async request which will call back on main thread.
+ [NSURLConnection sendAsynchronousRequest:request
+ queue:[NSOperationQueue mainQueue]
+ completionHandler:^(NSURLResponse *response,
+ NSData *data,
+ NSError *error) {
+ completionHandler(response, data, error);
+ }];
+}
+
+@end
diff --git a/talk/examples/objc/AppRTCDemo/RTCICECandidate+JSON.h b/talk/examples/objc/AppRTCDemo/RTCICECandidate+JSON.h
new file mode 100644
index 0000000000..f0673cdb0a
--- /dev/null
+++ b/talk/examples/objc/AppRTCDemo/RTCICECandidate+JSON.h
@@ -0,0 +1,35 @@
+/*
+ * libjingle
+ * Copyright 2014, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "RTCICECandidate.h"
+
+@interface RTCICECandidate (JSON)
+
++ (RTCICECandidate *)candidateFromJSONDictionary:(NSDictionary *)dictionary;
+- (NSData *)JSONData;
+
+@end
diff --git a/talk/examples/objc/AppRTCDemo/RTCICECandidate+JSON.m b/talk/examples/objc/AppRTCDemo/RTCICECandidate+JSON.m
new file mode 100644
index 0000000000..62817a5fed
--- /dev/null
+++ b/talk/examples/objc/AppRTCDemo/RTCICECandidate+JSON.m
@@ -0,0 +1,56 @@
+/*
+ * libjingle
+ * Copyright 2014, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "RTCICECandidate+JSON.h"
+
+static NSString const *kRTCICECandidateTypeKey = @"type";
+static NSString const *kRTCICECandidateTypeValue = @"candidate";
+static NSString const *kRTCICECandidateMidKey = @"id";
+static NSString const *kRTCICECandidateMLineIndexKey = @"label";
+static NSString const *kRTCICECandidateSdpKey = @"candidate";
+
+@implementation RTCICECandidate (JSON)
+
++ (RTCICECandidate *)candidateFromJSONDictionary:(NSDictionary *)dictionary {
+ NSString *mid = dictionary[kRTCICECandidateMidKey];
+ NSString *sdp = dictionary[kRTCICECandidateSdpKey];
+ NSNumber *num = dictionary[kRTCICECandidateMLineIndexKey];
+ NSInteger mLineIndex = [num integerValue];
+ return [[RTCICECandidate alloc] initWithMid:mid index:mLineIndex sdp:sdp];
+}
+
+- (NSData *)JSONData {
+ NSDictionary *json = @{
+ kRTCICECandidateTypeKey : kRTCICECandidateTypeValue,
+ kRTCICECandidateMLineIndexKey : @(self.sdpMLineIndex),
+ kRTCICECandidateMidKey : self.sdpMid,
+ kRTCICECandidateSdpKey : self.sdp
+ };
+ return [NSJSONSerialization dataWithJSONObject:json options:0 error:nil];
+}
+
+@end
diff --git a/talk/examples/objc/AppRTCDemo/RTCICEServer+JSON.h b/talk/examples/objc/AppRTCDemo/RTCICEServer+JSON.h
new file mode 100644
index 0000000000..d8a72076ca
--- /dev/null
+++ b/talk/examples/objc/AppRTCDemo/RTCICEServer+JSON.h
@@ -0,0 +1,36 @@
+/*
+ * libjingle
+ * Copyright 2014, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "RTCICEServer.h"
+
+@interface RTCICEServer (JSON)
+
++ (RTCICEServer *)serverFromJSONDictionary:(NSDictionary *)dictionary;
+// CEOD provides different JSON, and this parses that.
++ (RTCICEServer *)serverFromCEODJSONDictionary:(NSDictionary *)dictionary;
+
+@end
diff --git a/talk/examples/objc/AppRTCDemo/RTCICEServer+JSON.m b/talk/examples/objc/AppRTCDemo/RTCICEServer+JSON.m
new file mode 100644
index 0000000000..29321f65ff
--- /dev/null
+++ b/talk/examples/objc/AppRTCDemo/RTCICEServer+JSON.m
@@ -0,0 +1,59 @@
+/*
+ * libjingle
+ * Copyright 2014, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "RTCICEServer+JSON.h"
+
+static NSString const *kRTCICEServerUsernameKey = @"username";
+static NSString const *kRTCICEServerPasswordKey = @"password";
+static NSString const *kRTCICEServerUrisKey = @"uris";
+static NSString const *kRTCICEServerUrlKey = @"urls";
+static NSString const *kRTCICEServerCredentialKey = @"credential";
+
+@implementation RTCICEServer (JSON)
+
++ (RTCICEServer *)serverFromJSONDictionary:(NSDictionary *)dictionary {
+ NSString *url = dictionary[kRTCICEServerUrlKey];
+ NSString *username = dictionary[kRTCICEServerUsernameKey];
+ NSString *credential = dictionary[kRTCICEServerCredentialKey];
+ username = username ? username : @"";
+ credential = credential ? credential : @"";
+ return [[RTCICEServer alloc] initWithURI:[NSURL URLWithString:url]
+ username:username
+ password:credential];
+}
+
++ (RTCICEServer *)serverFromCEODJSONDictionary:(NSDictionary *)dictionary {
+ NSString *username = dictionary[kRTCICEServerUsernameKey];
+ NSString *password = dictionary[kRTCICEServerPasswordKey];
+ NSArray *uris = dictionary[kRTCICEServerUrisKey];
+ NSParameterAssert(uris.count > 0);
+ return [[RTCICEServer alloc] initWithURI:[NSURL URLWithString:uris[0]]
+ username:username
+ password:password];
+}
+
+@end
diff --git a/talk/examples/objc/AppRTCDemo/RTCMediaConstraints+JSON.h b/talk/examples/objc/AppRTCDemo/RTCMediaConstraints+JSON.h
new file mode 100644
index 0000000000..c0c660f350
--- /dev/null
+++ b/talk/examples/objc/AppRTCDemo/RTCMediaConstraints+JSON.h
@@ -0,0 +1,36 @@
+/*
+ * libjingle
+ * Copyright 2014, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "RTCMediaConstraints.h"
+
+@interface RTCMediaConstraints (JSON)
+
++ (RTCMediaConstraints *)constraintsFromJSONDictionary:
+ (NSDictionary *)dictionary;
+
+@end
+
diff --git a/talk/examples/objc/AppRTCDemo/RTCMediaConstraints+JSON.m b/talk/examples/objc/AppRTCDemo/RTCMediaConstraints+JSON.m
new file mode 100644
index 0000000000..6588eb94aa
--- /dev/null
+++ b/talk/examples/objc/AppRTCDemo/RTCMediaConstraints+JSON.m
@@ -0,0 +1,54 @@
+/*
+ * libjingle
+ * Copyright 2014, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "RTCMediaConstraints+JSON.h"
+
+#import "RTCPair.h"
+
+static NSString const *kRTCMediaConstraintsMandatoryKey = @"mandatory";
+
+@implementation RTCMediaConstraints (JSON)
+
++ (RTCMediaConstraints *)constraintsFromJSONDictionary:
+ (NSDictionary *)dictionary {
+ NSDictionary *mandatory = dictionary[kRTCMediaConstraintsMandatoryKey];
+ NSMutableArray *mandatoryContraints =
+ [NSMutableArray arrayWithCapacity:[mandatory count]];
+ [mandatory enumerateKeysAndObjectsUsingBlock:^(
+ id key, id obj, BOOL *stop) {
+ [mandatoryContraints addObject:[[RTCPair alloc] initWithKey:key
+ value:obj]];
+ }];
+ // TODO(tkchin): figure out json formats for optional constraints.
+ RTCMediaConstraints *constraints =
+ [[RTCMediaConstraints alloc]
+ initWithMandatoryConstraints:mandatoryContraints
+ optionalConstraints:nil];
+ return constraints;
+}
+
+@end
diff --git a/talk/examples/objc/AppRTCDemo/RTCSessionDescription+JSON.h b/talk/examples/objc/AppRTCDemo/RTCSessionDescription+JSON.h
new file mode 100644
index 0000000000..2c18d25e4f
--- /dev/null
+++ b/talk/examples/objc/AppRTCDemo/RTCSessionDescription+JSON.h
@@ -0,0 +1,36 @@
+/*
+ * libjingle
+ * Copyright 2014, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "RTCSessionDescription.h"
+
+@interface RTCSessionDescription (JSON)
+
++ (RTCSessionDescription *)descriptionFromJSONDictionary:
+ (NSDictionary *)dictionary;
+- (NSData *)JSONData;
+
+@end
diff --git a/talk/examples/objc/AppRTCDemo/RTCSessionDescription+JSON.m b/talk/examples/objc/AppRTCDemo/RTCSessionDescription+JSON.m
new file mode 100644
index 0000000000..0c1d39cddd
--- /dev/null
+++ b/talk/examples/objc/AppRTCDemo/RTCSessionDescription+JSON.m
@@ -0,0 +1,50 @@
+/*
+ * libjingle
+ * Copyright 2014, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "RTCSessionDescription+JSON.h"
+
+static NSString const *kRTCSessionDescriptionTypeKey = @"type";
+static NSString const *kRTCSessionDescriptionSdpKey = @"sdp";
+
+@implementation RTCSessionDescription (JSON)
+
++ (RTCSessionDescription *)descriptionFromJSONDictionary:
+ (NSDictionary *)dictionary {
+ NSString *type = dictionary[kRTCSessionDescriptionTypeKey];
+ NSString *sdp = dictionary[kRTCSessionDescriptionSdpKey];
+ return [[RTCSessionDescription alloc] initWithType:type sdp:sdp];
+}
+
+- (NSData *)JSONData {
+ NSDictionary *json = @{
+ kRTCSessionDescriptionTypeKey : self.type,
+ kRTCSessionDescriptionSdpKey : self.description
+ };
+ return [NSJSONSerialization dataWithJSONObject:json options:0 error:nil];
+}
+
+@end
diff --git a/talk/libjingle_examples.gyp b/talk/libjingle_examples.gyp
index 740452d183..f17fbfe7a4 100755
--- a/talk/libjingle_examples.gyp
+++ b/talk/libjingle_examples.gyp
@@ -283,8 +283,20 @@
'examples/objc/AppRTCDemo/APPRTCAppClient.m',
'examples/objc/AppRTCDemo/APPRTCConnectionManager.h',
'examples/objc/AppRTCDemo/APPRTCConnectionManager.m',
+ 'examples/objc/AppRTCDemo/ARDSignalingParams.h',
+ 'examples/objc/AppRTCDemo/ARDSignalingParams.m',
+ 'examples/objc/AppRTCDemo/ARDUtilities.h',
+ 'examples/objc/AppRTCDemo/ARDUtilities.m',
'examples/objc/AppRTCDemo/GAEChannelClient.h',
'examples/objc/AppRTCDemo/GAEChannelClient.m',
+ 'examples/objc/AppRTCDemo/RTCICECandidate+JSON.h',
+ 'examples/objc/AppRTCDemo/RTCICECandidate+JSON.m',
+ 'examples/objc/AppRTCDemo/RTCICEServer+JSON.h',
+ 'examples/objc/AppRTCDemo/RTCICEServer+JSON.m',
+ 'examples/objc/AppRTCDemo/RTCMediaConstraints+JSON.h',
+ 'examples/objc/AppRTCDemo/RTCMediaConstraints+JSON.m',
+ 'examples/objc/AppRTCDemo/RTCSessionDescription+JSON.h',
+ 'examples/objc/AppRTCDemo/RTCSessionDescription+JSON.m',
],
'xcode_settings': {
'CLANG_ENABLE_OBJC_ARC': 'YES',