15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/* 25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle 35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2013, Google Inc. 45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without 65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met: 75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer. 105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer in the documentation 125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * and/or other materials provided with the distribution. 135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 3. The name of the author may not be used to endorse or promote products 145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * derived from this software without specific prior written permission. 155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */ 275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#import "APPRTCAppDelegate.h" 295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#import "APPRTCViewController.h" 31c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org#import "RTCICECandidate.h" 32c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org#import "RTCICEServer.h" 335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#import "RTCMediaConstraints.h" 345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#import "RTCMediaStream.h" 355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#import "RTCPair.h" 365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#import "RTCPeerConnection.h" 375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#import "RTCPeerConnectionDelegate.h" 385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#import "RTCPeerConnectionFactory.h" 395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#import "RTCSessionDescription.h" 405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@interface PCObserver : NSObject<RTCPeerConnectionDelegate> 425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (id)initWithDelegate:(id<APPRTCSendMessage>)delegate; 445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@end 465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@implementation PCObserver { 485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org id<APPRTCSendMessage> _delegate; 495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (id)initWithDelegate:(id<APPRTCSendMessage>)delegate { 525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (self = [super init]) { 535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org _delegate = delegate; 545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return self; 565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)peerConnectionOnError:(RTCPeerConnection *)peerConnection { 595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSLog(@"PCO onError."); 605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSAssert(NO, @"PeerConnection failed."); 615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)peerConnection:(RTCPeerConnection *)peerConnection 64c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org signalingStateChanged:(RTCSignalingState)stateChanged { 655751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org NSLog(@"PCO onSignalingStateChange: %d", stateChanged); 665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)peerConnection:(RTCPeerConnection *)peerConnection 69c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org addedStream:(RTCMediaStream *)stream { 705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSLog(@"PCO onAddStream."); 715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dispatch_async(dispatch_get_main_queue(), ^(void) { 725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSAssert([stream.audioTracks count] >= 1, 735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org @"Expected at least 1 audio stream"); 745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org //NSAssert([stream.videoTracks count] >= 1, 755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // @"Expected at least 1 video stream"); 765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO(hughv): Add video support 775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org }); 785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)peerConnection:(RTCPeerConnection *)peerConnection 81c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org removedStream:(RTCMediaStream *)stream { 825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSLog(@"PCO onRemoveStream."); 835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO(hughv): Remove video track. 845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void) 875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org peerConnectionOnRenegotiationNeeded:(RTCPeerConnection *)peerConnection { 885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSLog(@"PCO onRenegotiationNeeded."); 895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO(hughv): Handle this. 905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)peerConnection:(RTCPeerConnection *)peerConnection 93c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org gotICECandidate:(RTCICECandidate *)candidate { 94c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org NSLog(@"PCO onICECandidate.\n Mid[%@] Index[%d] Sdp[%@]", 955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org candidate.sdpMid, 965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org candidate.sdpMLineIndex, 975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org candidate.sdp); 985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSDictionary *json = 995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org @{ @"type" : @"candidate", 1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org @"label" : [NSNumber numberWithInt:candidate.sdpMLineIndex], 1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org @"id" : candidate.sdpMid, 1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org @"candidate" : candidate.sdp }; 1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSError *error; 1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSData *data = 1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [NSJSONSerialization dataWithJSONObject:json options:0 error:&error]; 1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!error) { 1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [_delegate sendData:data]; 1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSAssert(NO, @"Unable to serialize JSON object with error: %@", 1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error.localizedDescription); 1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)peerConnection:(RTCPeerConnection *)peerConnection 115c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org iceGatheringChanged:(RTCICEGatheringState)newState { 1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSLog(@"PCO onIceGatheringChange. %d", newState); 1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)peerConnection:(RTCPeerConnection *)peerConnection 120c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org iceConnectionChanged:(RTCICEConnectionState)newState { 1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSLog(@"PCO onIceConnectionChange. %d", newState); 1225751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org if (newState == RTCICEConnectionConnected) 1235751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [self displayLogMessage:@"ICE Connection Connected."]; 1245751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org NSAssert(newState != RTCICEConnectionFailed, @"ICE Connection failed!"); 1255751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org} 1265751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org 1275751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org- (void)displayLogMessage:(NSString *)message { 1285751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [_delegate displayLogMessage:message]; 1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@end 1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@interface APPRTCAppDelegate () 1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@property(nonatomic, strong) APPRTCAppClient *client; 1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@property(nonatomic, strong) PCObserver *pcObserver; 1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@property(nonatomic, strong) RTCPeerConnection *peerConnection; 1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@property(nonatomic, strong) RTCPeerConnectionFactory *peerConnectionFactory; 1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@property(nonatomic, strong) NSMutableArray *queuedRemoteCandidates; 1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@end 1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@implementation APPRTCAppDelegate 1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 145582fe818e571fa2571267f5e369715188472f352wu@webrtc.org@synthesize window = _window; 146582fe818e571fa2571267f5e369715188472f352wu@webrtc.org@synthesize viewController = _viewController; 147582fe818e571fa2571267f5e369715188472f352wu@webrtc.org@synthesize client = _client; 148582fe818e571fa2571267f5e369715188472f352wu@webrtc.org@synthesize pcObserver = _pcObserver; 149582fe818e571fa2571267f5e369715188472f352wu@webrtc.org@synthesize peerConnection = _peerConnection; 150582fe818e571fa2571267f5e369715188472f352wu@webrtc.org@synthesize peerConnectionFactory = _peerConnectionFactory; 151582fe818e571fa2571267f5e369715188472f352wu@webrtc.org@synthesize queuedRemoteCandidates = _queuedRemoteCandidates; 152582fe818e571fa2571267f5e369715188472f352wu@webrtc.org 1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#pragma mark - UIApplicationDelegate methods 1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (BOOL)application:(UIApplication *)application 1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 157c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org [RTCPeerConnectionFactory initializeSSL]; 1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.viewController = 160c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org [[APPRTCViewController alloc] initWithNibName:@"APPRTCViewController" 1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bundle:nil]; 1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.window.rootViewController = self.viewController; 1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self.window makeKeyAndVisible]; 1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return YES; 1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)applicationWillResignActive:(UIApplication *)application { 1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage:@"Application lost focus, connection broken."]; 1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self disconnect]; 1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self.viewController resetUI]; 1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)applicationDidEnterBackground:(UIApplication *)application { 1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)applicationWillEnterForeground:(UIApplication *)application { 1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)applicationDidBecomeActive:(UIApplication *)application { 1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)applicationWillTerminate:(UIApplication *)application { 1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (BOOL)application:(UIApplication *)application 1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org openURL:(NSURL *)url 1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sourceApplication:(NSString *)sourceApplication 1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org annotation:(id)annotation { 1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (self.client) { 1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return NO; 1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.client = [[APPRTCAppClient alloc] init]; 193c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org self.client.ICEServerDelegate = self; 1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.client.messageHandler = self; 1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self.client connectToRoom:url]; 1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return YES; 1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)displayLogMessage:(NSString *)message { 2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSLog(@"%@", message); 2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self.viewController displayText:message]; 2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#pragma mark - RTCSendMessage method 2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)sendData:(NSData *)data { 2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self.client sendData:data]; 2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 210c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org#pragma mark - ICEServerDelegate method 2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 212c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org- (void)onICEServers:(NSArray *)servers { 2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.queuedRemoteCandidates = [NSMutableArray array]; 2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.peerConnectionFactory = [[RTCPeerConnectionFactory alloc] init]; 2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] init]; 2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.pcObserver = [[PCObserver alloc] initWithDelegate:self]; 2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.peerConnection = 218c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org [self.peerConnectionFactory peerConnectionWithICEServers:servers 2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org constraints:constraints 2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delegate:self.pcObserver]; 2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org RTCMediaStream *lms = 2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self.peerConnectionFactory mediaStreamWithLabel:@"ARDAMS"]; 2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO(hughv): Add video. 224c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org [lms addAudioTrack:[self.peerConnectionFactory audioTrackWithID:@"ARDAMSa0"]]; 225c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org [self.peerConnection addStream:lms constraints:constraints]; 226c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org [self displayLogMessage:@"onICEServers - add local stream."]; 2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#pragma mark - GAEMessageHandler methods 2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)onOpen { 2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage:@"GAE onOpen - create offer."]; 2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org RTCPair *audio = 2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"]; 2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO(hughv): Add video. 2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // RTCPair *video = [[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" 2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // value:@"true"]; 2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSArray *mandatory = @[ audio /*, video*/ ]; 2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org RTCMediaConstraints *constraints = 2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatory 2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org optionalConstraints:nil]; 2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self.peerConnection createOfferWithDelegate:self constraints:constraints]; 2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage:@"PC - createOffer."]; 2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)onMessage:(NSString *)data { 2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSString *message = [self unHTMLifyString:data]; 2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSError *error; 2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSDictionary *objects = [NSJSONSerialization 2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org JSONObjectWithData:[message dataUsingEncoding:NSUTF8StringEncoding] 2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org options:0 2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org error:&error]; 2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSAssert(!error, 2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org @"%@", 2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [NSString stringWithFormat:@"Error: %@", error.description]); 2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSAssert([objects count] > 0, @"Invalid JSON object"); 2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSString *value = [objects objectForKey:@"type"]; 2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage: 2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [NSString stringWithFormat:@"GAE onMessage type - %@", value]]; 2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ([value compare:@"candidate"] == NSOrderedSame) { 2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSString *mid = [objects objectForKey:@"id"]; 2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSNumber *sdpLineIndex = [objects objectForKey:@"label"]; 2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSString *sdp = [objects objectForKey:@"candidate"]; 264c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org RTCICECandidate *candidate = 265c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org [[RTCICECandidate alloc] initWithMid:mid 2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org index:sdpLineIndex.intValue 2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sdp:sdp]; 2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (self.queuedRemoteCandidates) { 2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self.queuedRemoteCandidates addObject:candidate]; 2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 271c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org [self.peerConnection addICECandidate:candidate]; 2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (([value compare:@"offer"] == NSOrderedSame) || 2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ([value compare:@"answer"] == NSOrderedSame)) { 2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSString *sdpString = [objects objectForKey:@"sdp"]; 2765751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org RTCSessionDescription *sdp = [[RTCSessionDescription alloc] 2775751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org initWithType:value sdp:[APPRTCAppDelegate preferISAC:sdpString]]; 2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self.peerConnection setRemoteDescriptionWithDelegate:self 2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sessionDescription:sdp]; 2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage:@"PC - setRemoteDescription."]; 2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if ([value compare:@"bye"] == NSOrderedSame) { 2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self disconnect]; 2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSAssert(NO, @"Invalid message: %@", data); 2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)onClose { 2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage:@"GAE onClose."]; 2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self disconnect]; 2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)onError:(int)code withDescription:(NSString *)description { 2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage: 2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [NSString stringWithFormat:@"GAE onError: %@", description]]; 2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self disconnect]; 2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#pragma mark - RTCSessionDescriptonDelegate methods 3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3015751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org// Match |pattern| to |string| and return the first group of the first 3025751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org// match, or nil if no match was found. 3035751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org+ (NSString *)firstMatch:(NSRegularExpression *)pattern 3045751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org withString:(NSString *)string { 3055751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org NSTextCheckingResult* result = 3065751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [pattern firstMatchInString:string 3075751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org options:0 3085751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org range:NSMakeRange(0, [string length])]; 3095751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org if (!result) 3105751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org return nil; 3115751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org return [string substringWithRange:[result rangeAtIndex:1]]; 3125751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org} 3135751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org 3145751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org// Mangle |origSDP| to prefer the ISAC/16k audio codec. 3155751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org+ (NSString *)preferISAC:(NSString *)origSDP { 3165751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org int mLineIndex = -1; 3175751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org NSString* isac16kRtpMap = nil; 3185751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org NSArray* lines = [origSDP componentsSeparatedByString:@"\n"]; 3195751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org NSRegularExpression* isac16kRegex = [NSRegularExpression 3205751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org regularExpressionWithPattern:@"^a=rtpmap:(\\d+) ISAC/16000[\r]?$" 3215751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org options:0 3225751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org error:nil]; 3235751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org for (int i = 0; 3245751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org (i < [lines count]) && (mLineIndex == -1 || isac16kRtpMap == nil); 3255751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org ++i) { 3265751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org NSString* line = [lines objectAtIndex:i]; 3275751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org if ([line hasPrefix:@"m=audio "]) { 3285751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org mLineIndex = i; 3295751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org continue; 3305751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org } 3315751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org isac16kRtpMap = [self firstMatch:isac16kRegex withString:line]; 3325751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org } 3335751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org if (mLineIndex == -1) { 3345751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org NSLog(@"No m=audio line, so can't prefer iSAC"); 3355751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org return origSDP; 3365751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org } 3375751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org if (isac16kRtpMap == nil) { 3385751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org NSLog(@"No ISAC/16000 line, so can't prefer iSAC"); 3395751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org return origSDP; 3405751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org } 3415751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org NSArray* origMLineParts = 3425751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [[lines objectAtIndex:mLineIndex] componentsSeparatedByString:@" "]; 3435751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org NSMutableArray* newMLine = 3445751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [NSMutableArray arrayWithCapacity:[origMLineParts count]]; 3455751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org int origPartIndex = 0; 3465751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org // Format is: m=<media> <port> <proto> <fmt> ... 3475751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [newMLine addObject:[origMLineParts objectAtIndex:origPartIndex++]]; 3485751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [newMLine addObject:[origMLineParts objectAtIndex:origPartIndex++]]; 3495751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [newMLine addObject:[origMLineParts objectAtIndex:origPartIndex++]]; 3505751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [newMLine addObject:isac16kRtpMap]; 3515751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org for (; origPartIndex < [origMLineParts count]; ++origPartIndex) { 3525751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org if ([isac16kRtpMap compare:[origMLineParts objectAtIndex:origPartIndex]] 3535751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org != NSOrderedSame) { 3545751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [newMLine addObject:[origMLineParts objectAtIndex:origPartIndex]]; 3555751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org } 3565751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org } 3575751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org NSMutableArray* newLines = [NSMutableArray arrayWithCapacity:[lines count]]; 3585751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [newLines addObjectsFromArray:lines]; 3595751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [newLines replaceObjectAtIndex:mLineIndex 3605751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org withObject:[newMLine componentsJoinedByString:@" "]]; 3615751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org return [newLines componentsJoinedByString:@"\n"]; 3625751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org} 3635751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org 3645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)peerConnection:(RTCPeerConnection *)peerConnection 3655751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org didCreateSessionDescription:(RTCSessionDescription *)origSdp 366c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org error:(NSError *)error { 3675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (error) { 3685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage:@"SDP onFailure."]; 3695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSAssert(NO, error.description); 3705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 3715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage:@"SDP onSuccess(SDP) - set local description."]; 3745751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org RTCSessionDescription* sdp = 3755751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org [[RTCSessionDescription alloc] 3765751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org initWithType:origSdp.type 3775751231c0308f2632caf502bf9f1db6eb3b679f6mikhal@webrtc.org sdp:[APPRTCAppDelegate preferISAC:origSdp.description]]; 3785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self.peerConnection setLocalDescriptionWithDelegate:self 3795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sessionDescription:sdp]; 3805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage:@"PC setLocalDescription."]; 3815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dispatch_async(dispatch_get_main_queue(), ^(void) { 3825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSDictionary *json = @{ @"type" : sdp.type, @"sdp" : sdp.description }; 3835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSError *error; 3845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSData *data = 3855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [NSJSONSerialization dataWithJSONObject:json options:0 error:&error]; 3865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSAssert(!error, 3875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org @"%@", 3885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [NSString stringWithFormat:@"Error: %@", error.description]); 3895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self sendData:data]; 3905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org }); 3915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 3925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)peerConnection:(RTCPeerConnection *)peerConnection 394c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org didSetSessionDescriptionWithError:(NSError *)error { 3955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (error) { 3965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage:@"SDP onFailure."]; 3975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSAssert(NO, error.description); 3985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 3995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage:@"SDP onSuccess() - possibly drain candidates"]; 4025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dispatch_async(dispatch_get_main_queue(), ^(void) { 4035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO(hughv): Handle non-initiator case. http://s10/46622051 4045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (self.peerConnection.remoteDescription) { 4055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self displayLogMessage:@"SDP onSuccess - drain candidates"]; 4065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self drainRemoteCandidates]; 4075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org }); 4095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#pragma mark - internal methods 4125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)disconnect { 4145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [self.client 4155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sendData:[@"{\"type\": \"bye\"}" dataUsingEncoding:NSUTF8StringEncoding]]; 4165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.peerConnection = nil; 4175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.peerConnectionFactory = nil; 4185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.pcObserver = nil; 419c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org self.client.ICEServerDelegate = nil; 4205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.client.messageHandler = nil; 4215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.client = nil; 422c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org [RTCPeerConnectionFactory deinitializeSSL]; 4235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (void)drainRemoteCandidates { 426c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org for (RTCICECandidate *candidate in self.queuedRemoteCandidates) { 427c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org [self.peerConnection addICECandidate:candidate]; 4285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org self.queuedRemoteCandidates = nil; 4305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org- (NSString *)unHTMLifyString:(NSString *)base { 4335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO(hughv): Investigate why percent escapes are being added. Removing 4345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // them isn't necessary on Android. 4355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // convert HTML escaped characters to UTF8. 4365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSString *removePercent = 4375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [base stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 4385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // remove leading and trailing ". 4395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSRange range; 4405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org range.length = [removePercent length] - 2; 4415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org range.location = 1; 4425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSString *removeQuotes = [removePercent substringWithRange:range]; 4435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // convert \" to ". 4445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSString *removeEscapedQuotes = 4455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [removeQuotes stringByReplacingOccurrencesOfString:@"\\\"" 4465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org withString:@"\""]; 4475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // convert \\ to \. 4485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSString *removeBackslash = 4495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org [removeEscapedQuotes stringByReplacingOccurrencesOfString:@"\\\\" 4505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org withString:@"\\"]; 4515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return removeBackslash; 4525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org@end 455