Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Side by Side Diff: talk/examples/objc/AppRTCDemo/ARDAppClient.m

Issue 1235563006: Move talk/examples/* to webrtc/examples. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: 201508051337 Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * libjingle
3 * Copyright 2014 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #import "ARDAppClient+Internal.h"
29
30 #if defined(WEBRTC_IOS)
31 #import "RTCAVFoundationVideoSource.h"
32 #endif
33 #import "RTCFileLogger.h"
34 #import "RTCICEServer.h"
35 #import "RTCLogging.h"
36 #import "RTCMediaConstraints.h"
37 #import "RTCMediaStream.h"
38 #import "RTCPair.h"
39 #import "RTCPeerConnectionInterface.h"
40 #import "RTCVideoCapturer.h"
41
42 #import "ARDAppEngineClient.h"
43 #import "ARDCEODTURNClient.h"
44 #import "ARDJoinResponse.h"
45 #import "ARDMessageResponse.h"
46 #import "ARDSDPUtils.h"
47 #import "ARDSignalingMessage.h"
48 #import "ARDUtilities.h"
49 #import "ARDWebSocketChannel.h"
50 #import "RTCICECandidate+JSON.h"
51 #import "RTCSessionDescription+JSON.h"
52
53
54 static NSString * const kARDDefaultSTUNServerUrl =
55 @"stun:stun.l.google.com:19302";
56 // TODO(tkchin): figure out a better username for CEOD statistics.
57 static NSString * const kARDTurnRequestUrl =
58 @"https://computeengineondemand.appspot.com"
59 @"/turn?username=iapprtc&key=4080218913";
60
61 static NSString * const kARDAppClientErrorDomain = @"ARDAppClient";
62 static NSInteger const kARDAppClientErrorUnknown = -1;
63 static NSInteger const kARDAppClientErrorRoomFull = -2;
64 static NSInteger const kARDAppClientErrorCreateSDP = -3;
65 static NSInteger const kARDAppClientErrorSetSDP = -4;
66 static NSInteger const kARDAppClientErrorInvalidClient = -5;
67 static NSInteger const kARDAppClientErrorInvalidRoom = -6;
68
69 @implementation ARDAppClient {
70 RTCFileLogger *_fileLogger;
71 }
72
73 @synthesize delegate = _delegate;
74 @synthesize state = _state;
75 @synthesize roomServerClient = _roomServerClient;
76 @synthesize channel = _channel;
77 @synthesize turnClient = _turnClient;
78 @synthesize peerConnection = _peerConnection;
79 @synthesize factory = _factory;
80 @synthesize messageQueue = _messageQueue;
81 @synthesize isTurnComplete = _isTurnComplete;
82 @synthesize hasReceivedSdp = _hasReceivedSdp;
83 @synthesize roomId = _roomId;
84 @synthesize clientId = _clientId;
85 @synthesize isInitiator = _isInitiator;
86 @synthesize iceServers = _iceServers;
87 @synthesize webSocketURL = _websocketURL;
88 @synthesize webSocketRestURL = _websocketRestURL;
89 @synthesize defaultPeerConnectionConstraints =
90 _defaultPeerConnectionConstraints;
91
92 - (instancetype)init {
93 if (self = [super init]) {
94 _roomServerClient = [[ARDAppEngineClient alloc] init];
95 NSURL *turnRequestURL = [NSURL URLWithString:kARDTurnRequestUrl];
96 _turnClient = [[ARDCEODTURNClient alloc] initWithURL:turnRequestURL];
97 [self configure];
98 }
99 return self;
100 }
101
102 - (instancetype)initWithDelegate:(id<ARDAppClientDelegate>)delegate {
103 if (self = [super init]) {
104 _roomServerClient = [[ARDAppEngineClient alloc] init];
105 _delegate = delegate;
106 NSURL *turnRequestURL = [NSURL URLWithString:kARDTurnRequestUrl];
107 _turnClient = [[ARDCEODTURNClient alloc] initWithURL:turnRequestURL];
108 [self configure];
109 }
110 return self;
111 }
112
113 // TODO(tkchin): Provide signaling channel factory interface so we can recreate
114 // channel if we need to on network failure. Also, make this the default public
115 // constructor.
116 - (instancetype)initWithRoomServerClient:(id<ARDRoomServerClient>)rsClient
117 signalingChannel:(id<ARDSignalingChannel>)channel
118 turnClient:(id<ARDTURNClient>)turnClient
119 delegate:(id<ARDAppClientDelegate>)delegate {
120 NSParameterAssert(rsClient);
121 NSParameterAssert(channel);
122 NSParameterAssert(turnClient);
123 if (self = [super init]) {
124 _roomServerClient = rsClient;
125 _channel = channel;
126 _turnClient = turnClient;
127 _delegate = delegate;
128 [self configure];
129 }
130 return self;
131 }
132
133 - (void)configure {
134 _factory = [[RTCPeerConnectionFactory alloc] init];
135 _messageQueue = [NSMutableArray array];
136 _iceServers = [NSMutableArray arrayWithObject:[self defaultSTUNServer]];
137 _fileLogger = [[RTCFileLogger alloc] init];
138 [_fileLogger start];
139 }
140
141 - (void)dealloc {
142 [self disconnect];
143 }
144
145 - (void)setState:(ARDAppClientState)state {
146 if (_state == state) {
147 return;
148 }
149 _state = state;
150 [_delegate appClient:self didChangeState:_state];
151 }
152
153 - (void)connectToRoomWithId:(NSString *)roomId
154 options:(NSDictionary *)options {
155 NSParameterAssert(roomId.length);
156 NSParameterAssert(_state == kARDAppClientStateDisconnected);
157 self.state = kARDAppClientStateConnecting;
158
159 // Request TURN.
160 __weak ARDAppClient *weakSelf = self;
161 [_turnClient requestServersWithCompletionHandler:^(NSArray *turnServers,
162 NSError *error) {
163 if (error) {
164 RTCLogError("Error retrieving TURN servers: %@",
165 error.localizedDescription);
166 }
167 ARDAppClient *strongSelf = weakSelf;
168 [strongSelf.iceServers addObjectsFromArray:turnServers];
169 strongSelf.isTurnComplete = YES;
170 [strongSelf startSignalingIfReady];
171 }];
172
173 // Join room on room server.
174 [_roomServerClient joinRoomWithRoomId:roomId
175 completionHandler:^(ARDJoinResponse *response, NSError *error) {
176 ARDAppClient *strongSelf = weakSelf;
177 if (error) {
178 [strongSelf.delegate appClient:strongSelf didError:error];
179 return;
180 }
181 NSError *joinError =
182 [[strongSelf class] errorForJoinResultType:response.result];
183 if (joinError) {
184 RTCLogError(@"Failed to join room:%@ on room server.", roomId);
185 [strongSelf disconnect];
186 [strongSelf.delegate appClient:strongSelf didError:joinError];
187 return;
188 }
189 RTCLog(@"Joined room:%@ on room server.", roomId);
190 strongSelf.roomId = response.roomId;
191 strongSelf.clientId = response.clientId;
192 strongSelf.isInitiator = response.isInitiator;
193 for (ARDSignalingMessage *message in response.messages) {
194 if (message.type == kARDSignalingMessageTypeOffer ||
195 message.type == kARDSignalingMessageTypeAnswer) {
196 strongSelf.hasReceivedSdp = YES;
197 [strongSelf.messageQueue insertObject:message atIndex:0];
198 } else {
199 [strongSelf.messageQueue addObject:message];
200 }
201 }
202 strongSelf.webSocketURL = response.webSocketURL;
203 strongSelf.webSocketRestURL = response.webSocketRestURL;
204 [strongSelf registerWithColliderIfReady];
205 [strongSelf startSignalingIfReady];
206 }];
207 }
208
209 - (void)disconnect {
210 if (_state == kARDAppClientStateDisconnected) {
211 return;
212 }
213 if (self.hasJoinedRoomServerRoom) {
214 [_roomServerClient leaveRoomWithRoomId:_roomId
215 clientId:_clientId
216 completionHandler:nil];
217 }
218 if (_channel) {
219 if (_channel.state == kARDSignalingChannelStateRegistered) {
220 // Tell the other client we're hanging up.
221 ARDByeMessage *byeMessage = [[ARDByeMessage alloc] init];
222 [_channel sendMessage:byeMessage];
223 }
224 // Disconnect from collider.
225 _channel = nil;
226 }
227 _clientId = nil;
228 _roomId = nil;
229 _isInitiator = NO;
230 _hasReceivedSdp = NO;
231 _messageQueue = [NSMutableArray array];
232 _peerConnection = nil;
233 self.state = kARDAppClientStateDisconnected;
234 }
235
236 #pragma mark - ARDSignalingChannelDelegate
237
238 - (void)channel:(id<ARDSignalingChannel>)channel
239 didReceiveMessage:(ARDSignalingMessage *)message {
240 switch (message.type) {
241 case kARDSignalingMessageTypeOffer:
242 case kARDSignalingMessageTypeAnswer:
243 // Offers and answers must be processed before any other message, so we
244 // place them at the front of the queue.
245 _hasReceivedSdp = YES;
246 [_messageQueue insertObject:message atIndex:0];
247 break;
248 case kARDSignalingMessageTypeCandidate:
249 [_messageQueue addObject:message];
250 break;
251 case kARDSignalingMessageTypeBye:
252 // Disconnects can be processed immediately.
253 [self processSignalingMessage:message];
254 return;
255 }
256 [self drainMessageQueueIfReady];
257 }
258
259 - (void)channel:(id<ARDSignalingChannel>)channel
260 didChangeState:(ARDSignalingChannelState)state {
261 switch (state) {
262 case kARDSignalingChannelStateOpen:
263 break;
264 case kARDSignalingChannelStateRegistered:
265 break;
266 case kARDSignalingChannelStateClosed:
267 case kARDSignalingChannelStateError:
268 // TODO(tkchin): reconnection scenarios. Right now we just disconnect
269 // completely if the websocket connection fails.
270 [self disconnect];
271 break;
272 }
273 }
274
275 #pragma mark - RTCPeerConnectionDelegate
276 // Callbacks for this delegate occur on non-main thread and need to be
277 // dispatched back to main queue as needed.
278
279 - (void)peerConnection:(RTCPeerConnection *)peerConnection
280 signalingStateChanged:(RTCSignalingState)stateChanged {
281 RTCLog(@"Signaling state changed: %d", stateChanged);
282 }
283
284 - (void)peerConnection:(RTCPeerConnection *)peerConnection
285 addedStream:(RTCMediaStream *)stream {
286 dispatch_async(dispatch_get_main_queue(), ^{
287 RTCLog(@"Received %lu video tracks and %lu audio tracks",
288 (unsigned long)stream.videoTracks.count,
289 (unsigned long)stream.audioTracks.count);
290 if (stream.videoTracks.count) {
291 RTCVideoTrack *videoTrack = stream.videoTracks[0];
292 [_delegate appClient:self didReceiveRemoteVideoTrack:videoTrack];
293 }
294 });
295 }
296
297 - (void)peerConnection:(RTCPeerConnection *)peerConnection
298 removedStream:(RTCMediaStream *)stream {
299 RTCLog(@"Stream was removed.");
300 }
301
302 - (void)peerConnectionOnRenegotiationNeeded:
303 (RTCPeerConnection *)peerConnection {
304 RTCLog(@"WARNING: Renegotiation needed but unimplemented.");
305 }
306
307 - (void)peerConnection:(RTCPeerConnection *)peerConnection
308 iceConnectionChanged:(RTCICEConnectionState)newState {
309 RTCLog(@"ICE state changed: %d", newState);
310 dispatch_async(dispatch_get_main_queue(), ^{
311 [_delegate appClient:self didChangeConnectionState:newState];
312 });
313 }
314
315 - (void)peerConnection:(RTCPeerConnection *)peerConnection
316 iceGatheringChanged:(RTCICEGatheringState)newState {
317 RTCLog(@"ICE gathering state changed: %d", newState);
318 }
319
320 - (void)peerConnection:(RTCPeerConnection *)peerConnection
321 gotICECandidate:(RTCICECandidate *)candidate {
322 dispatch_async(dispatch_get_main_queue(), ^{
323 ARDICECandidateMessage *message =
324 [[ARDICECandidateMessage alloc] initWithCandidate:candidate];
325 [self sendSignalingMessage:message];
326 });
327 }
328
329 - (void)peerConnection:(RTCPeerConnection*)peerConnection
330 didOpenDataChannel:(RTCDataChannel*)dataChannel {
331 }
332
333 #pragma mark - RTCSessionDescriptionDelegate
334 // Callbacks for this delegate occur on non-main thread and need to be
335 // dispatched back to main queue as needed.
336
337 - (void)peerConnection:(RTCPeerConnection *)peerConnection
338 didCreateSessionDescription:(RTCSessionDescription *)sdp
339 error:(NSError *)error {
340 dispatch_async(dispatch_get_main_queue(), ^{
341 if (error) {
342 RTCLogError(@"Failed to create session description. Error: %@", error);
343 [self disconnect];
344 NSDictionary *userInfo = @{
345 NSLocalizedDescriptionKey: @"Failed to create session description.",
346 };
347 NSError *sdpError =
348 [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
349 code:kARDAppClientErrorCreateSDP
350 userInfo:userInfo];
351 [_delegate appClient:self didError:sdpError];
352 return;
353 }
354 // Prefer H264 if available.
355 RTCSessionDescription *sdpPreferringH264 =
356 [ARDSDPUtils descriptionForDescription:sdp
357 preferredVideoCodec:@"H264"];
358 [_peerConnection setLocalDescriptionWithDelegate:self
359 sessionDescription:sdpPreferringH264];
360 ARDSessionDescriptionMessage *message =
361 [[ARDSessionDescriptionMessage alloc]
362 initWithDescription:sdpPreferringH264];
363 [self sendSignalingMessage:message];
364 });
365 }
366
367 - (void)peerConnection:(RTCPeerConnection *)peerConnection
368 didSetSessionDescriptionWithError:(NSError *)error {
369 dispatch_async(dispatch_get_main_queue(), ^{
370 if (error) {
371 RTCLogError(@"Failed to set session description. Error: %@", error);
372 [self disconnect];
373 NSDictionary *userInfo = @{
374 NSLocalizedDescriptionKey: @"Failed to set session description.",
375 };
376 NSError *sdpError =
377 [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
378 code:kARDAppClientErrorSetSDP
379 userInfo:userInfo];
380 [_delegate appClient:self didError:sdpError];
381 return;
382 }
383 // If we're answering and we've just set the remote offer we need to create
384 // an answer and set the local description.
385 if (!_isInitiator && !_peerConnection.localDescription) {
386 RTCMediaConstraints *constraints = [self defaultAnswerConstraints];
387 [_peerConnection createAnswerWithDelegate:self
388 constraints:constraints];
389
390 }
391 });
392 }
393
394 #pragma mark - Private
395
396 - (BOOL)hasJoinedRoomServerRoom {
397 return _clientId.length;
398 }
399
400 // Begins the peer connection connection process if we have both joined a room
401 // on the room server and tried to obtain a TURN server. Otherwise does nothing.
402 // A peer connection object will be created with a stream that contains local
403 // audio and video capture. If this client is the caller, an offer is created as
404 // well, otherwise the client will wait for an offer to arrive.
405 - (void)startSignalingIfReady {
406 if (!_isTurnComplete || !self.hasJoinedRoomServerRoom) {
407 return;
408 }
409 self.state = kARDAppClientStateConnected;
410
411 // Create peer connection.
412 RTCMediaConstraints *constraints = [self defaultPeerConnectionConstraints];
413 RTCConfiguration *config = [[RTCConfiguration alloc] init];
414 config.iceServers = _iceServers;
415 _peerConnection = [_factory peerConnectionWithConfiguration:config
416 constraints:constraints
417 delegate:self];
418 // Create AV media stream and add it to the peer connection.
419 RTCMediaStream *localStream = [self createLocalMediaStream];
420 [_peerConnection addStream:localStream];
421 if (_isInitiator) {
422 // Send offer.
423 [_peerConnection createOfferWithDelegate:self
424 constraints:[self defaultOfferConstraints]];
425 } else {
426 // Check if we've received an offer.
427 [self drainMessageQueueIfReady];
428 }
429 }
430
431 // Processes the messages that we've received from the room server and the
432 // signaling channel. The offer or answer message must be processed before other
433 // signaling messages, however they can arrive out of order. Hence, this method
434 // only processes pending messages if there is a peer connection object and
435 // if we have received either an offer or answer.
436 - (void)drainMessageQueueIfReady {
437 if (!_peerConnection || !_hasReceivedSdp) {
438 return;
439 }
440 for (ARDSignalingMessage *message in _messageQueue) {
441 [self processSignalingMessage:message];
442 }
443 [_messageQueue removeAllObjects];
444 }
445
446 // Processes the given signaling message based on its type.
447 - (void)processSignalingMessage:(ARDSignalingMessage *)message {
448 NSParameterAssert(_peerConnection ||
449 message.type == kARDSignalingMessageTypeBye);
450 switch (message.type) {
451 case kARDSignalingMessageTypeOffer:
452 case kARDSignalingMessageTypeAnswer: {
453 ARDSessionDescriptionMessage *sdpMessage =
454 (ARDSessionDescriptionMessage *)message;
455 RTCSessionDescription *description = sdpMessage.sessionDescription;
456 // Prefer H264 if available.
457 RTCSessionDescription *sdpPreferringH264 =
458 [ARDSDPUtils descriptionForDescription:description
459 preferredVideoCodec:@"H264"];
460 [_peerConnection setRemoteDescriptionWithDelegate:self
461 sessionDescription:sdpPreferringH264];
462 break;
463 }
464 case kARDSignalingMessageTypeCandidate: {
465 ARDICECandidateMessage *candidateMessage =
466 (ARDICECandidateMessage *)message;
467 [_peerConnection addICECandidate:candidateMessage.candidate];
468 break;
469 }
470 case kARDSignalingMessageTypeBye:
471 // Other client disconnected.
472 // TODO(tkchin): support waiting in room for next client. For now just
473 // disconnect.
474 [self disconnect];
475 break;
476 }
477 }
478
479 // Sends a signaling message to the other client. The caller will send messages
480 // through the room server, whereas the callee will send messages over the
481 // signaling channel.
482 - (void)sendSignalingMessage:(ARDSignalingMessage *)message {
483 if (_isInitiator) {
484 __weak ARDAppClient *weakSelf = self;
485 [_roomServerClient sendMessage:message
486 forRoomId:_roomId
487 clientId:_clientId
488 completionHandler:^(ARDMessageResponse *response,
489 NSError *error) {
490 ARDAppClient *strongSelf = weakSelf;
491 if (error) {
492 [strongSelf.delegate appClient:strongSelf didError:error];
493 return;
494 }
495 NSError *messageError =
496 [[strongSelf class] errorForMessageResultType:response.result];
497 if (messageError) {
498 [strongSelf.delegate appClient:strongSelf didError:messageError];
499 return;
500 }
501 }];
502 } else {
503 [_channel sendMessage:message];
504 }
505 }
506
507 - (RTCMediaStream *)createLocalMediaStream {
508 RTCMediaStream* localStream = [_factory mediaStreamWithLabel:@"ARDAMS"];
509 RTCVideoTrack* localVideoTrack = [self createLocalVideoTrack];
510 if (localVideoTrack) {
511 [localStream addVideoTrack:localVideoTrack];
512 [_delegate appClient:self didReceiveLocalVideoTrack:localVideoTrack];
513 }
514 [localStream addAudioTrack:[_factory audioTrackWithID:@"ARDAMSa0"]];
515 return localStream;
516 }
517
518 - (RTCVideoTrack *)createLocalVideoTrack {
519 RTCVideoTrack* localVideoTrack = nil;
520 // The iOS simulator doesn't provide any sort of camera capture
521 // support or emulation (http://goo.gl/rHAnC1) so don't bother
522 // trying to open a local stream.
523 // TODO(tkchin): local video capture for OSX. See
524 // https://code.google.com/p/webrtc/issues/detail?id=3417.
525 #if !TARGET_IPHONE_SIMULATOR && TARGET_OS_IPHONE
526 RTCMediaConstraints *mediaConstraints = [self defaultMediaStreamConstraints];
527 RTCAVFoundationVideoSource *source =
528 [[RTCAVFoundationVideoSource alloc] initWithFactory:_factory
529 constraints:mediaConstraints];
530 localVideoTrack =
531 [[RTCVideoTrack alloc] initWithFactory:_factory
532 source:source
533 trackId:@"ARDAMSv0"];
534 #endif
535 return localVideoTrack;
536 }
537
538 #pragma mark - Collider methods
539
540 - (void)registerWithColliderIfReady {
541 if (!self.hasJoinedRoomServerRoom) {
542 return;
543 }
544 // Open WebSocket connection.
545 if (!_channel) {
546 _channel =
547 [[ARDWebSocketChannel alloc] initWithURL:_websocketURL
548 restURL:_websocketRestURL
549 delegate:self];
550 }
551 [_channel registerForRoomId:_roomId clientId:_clientId];
552 }
553
554 #pragma mark - Defaults
555
556 - (RTCMediaConstraints *)defaultMediaStreamConstraints {
557 RTCMediaConstraints* constraints =
558 [[RTCMediaConstraints alloc]
559 initWithMandatoryConstraints:nil
560 optionalConstraints:nil];
561 return constraints;
562 }
563
564 - (RTCMediaConstraints *)defaultAnswerConstraints {
565 return [self defaultOfferConstraints];
566 }
567
568 - (RTCMediaConstraints *)defaultOfferConstraints {
569 NSArray *mandatoryConstraints = @[
570 [[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"],
571 [[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" value:@"true"]
572 ];
573 RTCMediaConstraints* constraints =
574 [[RTCMediaConstraints alloc]
575 initWithMandatoryConstraints:mandatoryConstraints
576 optionalConstraints:nil];
577 return constraints;
578 }
579
580 - (RTCMediaConstraints *)defaultPeerConnectionConstraints {
581 if (_defaultPeerConnectionConstraints) {
582 return _defaultPeerConnectionConstraints;
583 }
584 NSArray *optionalConstraints = @[
585 [[RTCPair alloc] initWithKey:@"DtlsSrtpKeyAgreement" value:@"true"]
586 ];
587 RTCMediaConstraints* constraints =
588 [[RTCMediaConstraints alloc]
589 initWithMandatoryConstraints:nil
590 optionalConstraints:optionalConstraints];
591 return constraints;
592 }
593
594 - (RTCICEServer *)defaultSTUNServer {
595 NSURL *defaultSTUNServerURL = [NSURL URLWithString:kARDDefaultSTUNServerUrl];
596 return [[RTCICEServer alloc] initWithURI:defaultSTUNServerURL
597 username:@""
598 password:@""];
599 }
600
601 #pragma mark - Errors
602
603 + (NSError *)errorForJoinResultType:(ARDJoinResultType)resultType {
604 NSError *error = nil;
605 switch (resultType) {
606 case kARDJoinResultTypeSuccess:
607 break;
608 case kARDJoinResultTypeUnknown: {
609 error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
610 code:kARDAppClientErrorUnknown
611 userInfo:@{
612 NSLocalizedDescriptionKey: @"Unknown error.",
613 }];
614 break;
615 }
616 case kARDJoinResultTypeFull: {
617 error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
618 code:kARDAppClientErrorRoomFull
619 userInfo:@{
620 NSLocalizedDescriptionKey: @"Room is full.",
621 }];
622 break;
623 }
624 }
625 return error;
626 }
627
628 + (NSError *)errorForMessageResultType:(ARDMessageResultType)resultType {
629 NSError *error = nil;
630 switch (resultType) {
631 case kARDMessageResultTypeSuccess:
632 break;
633 case kARDMessageResultTypeUnknown:
634 error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
635 code:kARDAppClientErrorUnknown
636 userInfo:@{
637 NSLocalizedDescriptionKey: @"Unknown error.",
638 }];
639 break;
640 case kARDMessageResultTypeInvalidClient:
641 error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
642 code:kARDAppClientErrorInvalidClient
643 userInfo:@{
644 NSLocalizedDescriptionKey: @"Invalid client.",
645 }];
646 break;
647 case kARDMessageResultTypeInvalidRoom:
648 error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
649 code:kARDAppClientErrorInvalidRoom
650 userInfo:@{
651 NSLocalizedDescriptionKey: @"Invalid room.",
652 }];
653 break;
654 }
655 return error;
656 }
657
658 @end
OLDNEW
« no previous file with comments | « talk/examples/objc/AppRTCDemo/ARDAppClient.h ('k') | talk/examples/objc/AppRTCDemo/ARDAppClient+Internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698