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
This commit is contained in:
tkchin@webrtc.org 2014-11-27 00:52:38 +00:00
parent 79b9eba3ab
commit 3e9ad26112
16 changed files with 734 additions and 258 deletions

View File

@ -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

View File

@ -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

View File

@ -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];

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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',