iOS AppRTC: First unit test.
Tests basic session ICE connection by stubbing out network components, which have been refactored to faciliate testing. BUG=3994 R=jiayl@webrtc.org, kjellander@webrtc.org, phoglund@webrtc.org Review URL: https://webrtc-codereview.appspot.com/28349004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@8002 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -25,38 +25,26 @@
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#import "ARDAppClient.h"
|
||||
#import "ARDAppClient+Internal.h"
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
#import "ARDAppEngineClient.h"
|
||||
#import "ARDCEODTURNClient.h"
|
||||
#import "ARDMessageResponse.h"
|
||||
#import "ARDRegisterResponse.h"
|
||||
#import "ARDSignalingMessage.h"
|
||||
#import "ARDUtilities.h"
|
||||
#import "ARDWebSocketChannel.h"
|
||||
#import "RTCICECandidate+JSON.h"
|
||||
#import "RTCICEServer+JSON.h"
|
||||
#import "RTCICEServer.h"
|
||||
#import "RTCMediaConstraints.h"
|
||||
#import "RTCMediaStream.h"
|
||||
#import "RTCPair.h"
|
||||
#import "RTCPeerConnection.h"
|
||||
#import "RTCPeerConnectionDelegate.h"
|
||||
#import "RTCPeerConnectionFactory.h"
|
||||
#import "RTCSessionDescription+JSON.h"
|
||||
#import "RTCSessionDescriptionDelegate.h"
|
||||
#import "RTCVideoCapturer.h"
|
||||
#import "RTCVideoTrack.h"
|
||||
|
||||
// TODO(tkchin): move these to a configuration object.
|
||||
static NSString *kARDRoomServerHostUrl =
|
||||
@"https://apprtc.appspot.com";
|
||||
static NSString *kARDRoomServerRegisterFormat =
|
||||
@"https://apprtc.appspot.com/register/%@";
|
||||
static NSString *kARDRoomServerMessageFormat =
|
||||
@"https://apprtc.appspot.com/message/%@/%@";
|
||||
static NSString *kARDRoomServerByeFormat =
|
||||
@"https://apprtc.appspot.com/bye/%@/%@";
|
||||
|
||||
static NSString *kARDDefaultSTUNServerUrl =
|
||||
@"stun:stun.l.google.com:19302";
|
||||
// TODO(tkchin): figure out a better username for CEOD statistics.
|
||||
@@ -69,34 +57,16 @@ static NSInteger kARDAppClientErrorUnknown = -1;
|
||||
static NSInteger kARDAppClientErrorRoomFull = -2;
|
||||
static NSInteger kARDAppClientErrorCreateSDP = -3;
|
||||
static NSInteger kARDAppClientErrorSetSDP = -4;
|
||||
static NSInteger kARDAppClientErrorNetwork = -5;
|
||||
static NSInteger kARDAppClientErrorInvalidClient = -6;
|
||||
static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
|
||||
@interface ARDAppClient () <ARDWebSocketChannelDelegate,
|
||||
RTCPeerConnectionDelegate, RTCSessionDescriptionDelegate>
|
||||
@property(nonatomic, strong) ARDWebSocketChannel *channel;
|
||||
@property(nonatomic, strong) RTCPeerConnection *peerConnection;
|
||||
@property(nonatomic, strong) RTCPeerConnectionFactory *factory;
|
||||
@property(nonatomic, strong) NSMutableArray *messageQueue;
|
||||
|
||||
@property(nonatomic, assign) BOOL isTurnComplete;
|
||||
@property(nonatomic, assign) BOOL hasReceivedSdp;
|
||||
@property(nonatomic, readonly) BOOL isRegisteredWithRoomServer;
|
||||
|
||||
@property(nonatomic, strong) NSString *roomId;
|
||||
@property(nonatomic, strong) NSString *clientId;
|
||||
@property(nonatomic, assign) BOOL isInitiator;
|
||||
@property(nonatomic, strong) NSMutableArray *iceServers;
|
||||
@property(nonatomic, strong) NSURL *webSocketURL;
|
||||
@property(nonatomic, strong) NSURL *webSocketRestURL;
|
||||
@end
|
||||
static NSInteger kARDAppClientErrorInvalidClient = -5;
|
||||
static NSInteger kARDAppClientErrorInvalidRoom = -6;
|
||||
|
||||
@implementation ARDAppClient
|
||||
|
||||
@synthesize delegate = _delegate;
|
||||
@synthesize state = _state;
|
||||
@synthesize roomServerClient = _roomServerClient;
|
||||
@synthesize channel = _channel;
|
||||
@synthesize turnClient = _turnClient;
|
||||
@synthesize peerConnection = _peerConnection;
|
||||
@synthesize factory = _factory;
|
||||
@synthesize messageQueue = _messageQueue;
|
||||
@@ -108,17 +78,46 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
@synthesize iceServers = _iceServers;
|
||||
@synthesize webSocketURL = _websocketURL;
|
||||
@synthesize webSocketRestURL = _websocketRestURL;
|
||||
@synthesize defaultPeerConnectionConstraints =
|
||||
_defaultPeerConnectionConstraints;
|
||||
|
||||
- (instancetype)initWithDelegate:(id<ARDAppClientDelegate>)delegate {
|
||||
if (self = [super init]) {
|
||||
_roomServerClient = [[ARDAppEngineClient alloc] init];
|
||||
_delegate = delegate;
|
||||
_factory = [[RTCPeerConnectionFactory alloc] init];
|
||||
_messageQueue = [NSMutableArray array];
|
||||
_iceServers = [NSMutableArray arrayWithObject:[self defaultSTUNServer]];
|
||||
NSURL *turnRequestURL = [NSURL URLWithString:kARDTurnRequestUrl];
|
||||
_turnClient = [[ARDCEODTURNClient alloc] initWithURL:turnRequestURL];
|
||||
[self configure];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// TODO(tkchin): Provide signaling channel factory interface so we can recreate
|
||||
// channel if we need to on network failure. Also, make this the default public
|
||||
// constructor.
|
||||
- (instancetype)initWithRoomServerClient:(id<ARDRoomServerClient>)rsClient
|
||||
signalingChannel:(id<ARDSignalingChannel>)channel
|
||||
turnClient:(id<ARDTURNClient>)turnClient
|
||||
delegate:(id<ARDAppClientDelegate>)delegate {
|
||||
NSParameterAssert(rsClient);
|
||||
NSParameterAssert(channel);
|
||||
NSParameterAssert(turnClient);
|
||||
if (self = [super init]) {
|
||||
_roomServerClient = rsClient;
|
||||
_channel = channel;
|
||||
_turnClient = turnClient;
|
||||
_delegate = delegate;
|
||||
[self configure];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)configure {
|
||||
_factory = [[RTCPeerConnectionFactory alloc] init];
|
||||
_messageQueue = [NSMutableArray array];
|
||||
_iceServers = [NSMutableArray arrayWithObject:[self defaultSTUNServer]];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self disconnect];
|
||||
}
|
||||
@@ -139,9 +138,11 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
|
||||
// Request TURN.
|
||||
__weak ARDAppClient *weakSelf = self;
|
||||
NSURL *turnRequestURL = [NSURL URLWithString:kARDTurnRequestUrl];
|
||||
[self requestTURNServersWithURL:turnRequestURL
|
||||
completionHandler:^(NSArray *turnServers) {
|
||||
[_turnClient requestServersWithCompletionHandler:^(NSArray *turnServers,
|
||||
NSError *error) {
|
||||
if (error) {
|
||||
NSLog(@"Error retrieving TURN servers: %@", error);
|
||||
}
|
||||
ARDAppClient *strongSelf = weakSelf;
|
||||
[strongSelf.iceServers addObjectsFromArray:turnServers];
|
||||
strongSelf.isTurnComplete = YES;
|
||||
@@ -149,23 +150,21 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
}];
|
||||
|
||||
// Register with room server.
|
||||
[self registerWithRoomServerForRoomId:roomId
|
||||
completionHandler:^(ARDRegisterResponse *response) {
|
||||
[_roomServerClient registerForRoomId:roomId
|
||||
completionHandler:^(ARDRegisterResponse *response, NSError *error) {
|
||||
ARDAppClient *strongSelf = weakSelf;
|
||||
if (!response || response.result != kARDRegisterResultTypeSuccess) {
|
||||
NSLog(@"Failed to register with room server. Result:%d",
|
||||
(int)response.result);
|
||||
[strongSelf disconnect];
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: @"Room is full.",
|
||||
};
|
||||
NSError *error =
|
||||
[[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
||||
code:kARDAppClientErrorRoomFull
|
||||
userInfo:userInfo];
|
||||
if (error) {
|
||||
[strongSelf.delegate appClient:strongSelf didError:error];
|
||||
return;
|
||||
}
|
||||
NSError *registerError =
|
||||
[[strongSelf class] errorForRegisterResultType:response.result];
|
||||
if (registerError) {
|
||||
NSLog(@"Failed to register with room server.");
|
||||
[strongSelf disconnect];
|
||||
[strongSelf.delegate appClient:strongSelf didError:registerError];
|
||||
return;
|
||||
}
|
||||
NSLog(@"Registered with room server.");
|
||||
strongSelf.roomId = response.roomId;
|
||||
strongSelf.clientId = response.clientId;
|
||||
@@ -191,14 +190,15 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
return;
|
||||
}
|
||||
if (self.isRegisteredWithRoomServer) {
|
||||
[self unregisterWithRoomServer];
|
||||
[_roomServerClient deregisterForRoomId:_roomId
|
||||
clientId:_clientId
|
||||
completionHandler:nil];
|
||||
}
|
||||
if (_channel) {
|
||||
if (_channel.state == kARDWebSocketChannelStateRegistered) {
|
||||
if (_channel.state == kARDSignalingChannelStateRegistered) {
|
||||
// Tell the other client we're hanging up.
|
||||
ARDByeMessage *byeMessage = [[ARDByeMessage alloc] init];
|
||||
NSData *byeData = [byeMessage JSONData];
|
||||
[_channel sendData:byeData];
|
||||
[_channel sendMessage:byeMessage];
|
||||
}
|
||||
// Disconnect from collider.
|
||||
_channel = nil;
|
||||
@@ -212,9 +212,9 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
self.state = kARDAppClientStateDisconnected;
|
||||
}
|
||||
|
||||
#pragma mark - ARDWebSocketChannelDelegate
|
||||
#pragma mark - ARDSignalingChannelDelegate
|
||||
|
||||
- (void)channel:(ARDWebSocketChannel *)channel
|
||||
- (void)channel:(id<ARDSignalingChannel>)channel
|
||||
didReceiveMessage:(ARDSignalingMessage *)message {
|
||||
switch (message.type) {
|
||||
case kARDSignalingMessageTypeOffer:
|
||||
@@ -232,15 +232,15 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
[self drainMessageQueueIfReady];
|
||||
}
|
||||
|
||||
- (void)channel:(ARDWebSocketChannel *)channel
|
||||
didChangeState:(ARDWebSocketChannelState)state {
|
||||
- (void)channel:(id<ARDSignalingChannel>)channel
|
||||
didChangeState:(ARDSignalingChannelState)state {
|
||||
switch (state) {
|
||||
case kARDWebSocketChannelStateOpen:
|
||||
case kARDSignalingChannelStateOpen:
|
||||
break;
|
||||
case kARDWebSocketChannelStateRegistered:
|
||||
case kARDSignalingChannelStateRegistered:
|
||||
break;
|
||||
case kARDWebSocketChannelStateClosed:
|
||||
case kARDWebSocketChannelStateError:
|
||||
case kARDSignalingChannelStateClosed:
|
||||
case kARDSignalingChannelStateError:
|
||||
// TODO(tkchin): reconnection scenarios. Right now we just disconnect
|
||||
// completely if the websocket connection fails.
|
||||
[self disconnect];
|
||||
@@ -281,6 +281,9 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
- (void)peerConnection:(RTCPeerConnection *)peerConnection
|
||||
iceConnectionChanged:(RTCICEConnectionState)newState {
|
||||
NSLog(@"ICE state changed: %d", newState);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[_delegate appClient:self didChangeConnectionState:newState];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)peerConnection:(RTCPeerConnection *)peerConnection
|
||||
@@ -430,9 +433,26 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
|
||||
- (void)sendSignalingMessage:(ARDSignalingMessage *)message {
|
||||
if (_isInitiator) {
|
||||
[self sendSignalingMessageToRoomServer:message completionHandler:nil];
|
||||
__weak ARDAppClient *weakSelf = self;
|
||||
[_roomServerClient sendMessage:message
|
||||
forRoomId:_roomId
|
||||
clientId:_clientId
|
||||
completionHandler:^(ARDMessageResponse *response,
|
||||
NSError *error) {
|
||||
ARDAppClient *strongSelf = weakSelf;
|
||||
if (error) {
|
||||
[strongSelf.delegate appClient:strongSelf didError:error];
|
||||
return;
|
||||
}
|
||||
NSError *messageError =
|
||||
[[strongSelf class] errorForMessageResultType:response.result];
|
||||
if (messageError) {
|
||||
[strongSelf.delegate appClient:strongSelf didError:messageError];
|
||||
return;
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
[self sendSignalingMessageToCollider:message];
|
||||
[_channel sendMessage:message];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,142 +493,6 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
return localStream;
|
||||
}
|
||||
|
||||
- (void)requestTURNServersWithURL:(NSURL *)requestURL
|
||||
completionHandler:(void (^)(NSArray *turnServers))completionHandler {
|
||||
NSParameterAssert([requestURL absoluteString].length);
|
||||
NSMutableURLRequest *request =
|
||||
[NSMutableURLRequest requestWithURL:requestURL];
|
||||
// We need to set origin because TURN provider whitelists requests based on
|
||||
// origin.
|
||||
[request addValue:@"Mozilla/5.0" forHTTPHeaderField:@"user-agent"];
|
||||
[request addValue:kARDRoomServerHostUrl forHTTPHeaderField:@"origin"];
|
||||
[NSURLConnection sendAsyncRequest:request
|
||||
completionHandler:^(NSURLResponse *response,
|
||||
NSData *data,
|
||||
NSError *error) {
|
||||
NSArray *turnServers = [NSArray array];
|
||||
if (error) {
|
||||
NSLog(@"Unable to get TURN server.");
|
||||
completionHandler(turnServers);
|
||||
return;
|
||||
}
|
||||
NSDictionary *dict = [NSDictionary dictionaryWithJSONData:data];
|
||||
turnServers = [RTCICEServer serversFromCEODJSONDictionary:dict];
|
||||
completionHandler(turnServers);
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Room server methods
|
||||
|
||||
- (void)registerWithRoomServerForRoomId:(NSString *)roomId
|
||||
completionHandler:(void (^)(ARDRegisterResponse *))completionHandler {
|
||||
NSString *urlString =
|
||||
[NSString stringWithFormat:kARDRoomServerRegisterFormat, roomId];
|
||||
NSURL *roomURL = [NSURL URLWithString:urlString];
|
||||
NSLog(@"Registering with room server.");
|
||||
__weak ARDAppClient *weakSelf = self;
|
||||
[NSURLConnection sendAsyncPostToURL:roomURL
|
||||
withData:nil
|
||||
completionHandler:^(BOOL succeeded, NSData *data) {
|
||||
ARDAppClient *strongSelf = weakSelf;
|
||||
if (!succeeded) {
|
||||
NSError *error = [self roomServerNetworkError];
|
||||
[strongSelf.delegate appClient:strongSelf didError:error];
|
||||
completionHandler(nil);
|
||||
return;
|
||||
}
|
||||
ARDRegisterResponse *response =
|
||||
[ARDRegisterResponse responseFromJSONData:data];
|
||||
completionHandler(response);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)sendSignalingMessageToRoomServer:(ARDSignalingMessage *)message
|
||||
completionHandler:(void (^)(ARDMessageResponse *))completionHandler {
|
||||
NSData *data = [message JSONData];
|
||||
NSString *urlString =
|
||||
[NSString stringWithFormat:
|
||||
kARDRoomServerMessageFormat, _roomId, _clientId];
|
||||
NSURL *url = [NSURL URLWithString:urlString];
|
||||
NSLog(@"C->RS POST: %@", message);
|
||||
__weak ARDAppClient *weakSelf = self;
|
||||
[NSURLConnection sendAsyncPostToURL:url
|
||||
withData:data
|
||||
completionHandler:^(BOOL succeeded, NSData *data) {
|
||||
ARDAppClient *strongSelf = weakSelf;
|
||||
if (!succeeded) {
|
||||
NSError *error = [self roomServerNetworkError];
|
||||
[strongSelf.delegate appClient:strongSelf didError:error];
|
||||
return;
|
||||
}
|
||||
ARDMessageResponse *response =
|
||||
[ARDMessageResponse responseFromJSONData:data];
|
||||
NSError *error = nil;
|
||||
switch (response.result) {
|
||||
case kARDMessageResultTypeSuccess:
|
||||
break;
|
||||
case kARDMessageResultTypeUnknown:
|
||||
error =
|
||||
[[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
||||
code:kARDAppClientErrorUnknown
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Unknown error.",
|
||||
}];
|
||||
case kARDMessageResultTypeInvalidClient:
|
||||
error =
|
||||
[[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
||||
code:kARDAppClientErrorInvalidClient
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Invalid client.",
|
||||
}];
|
||||
break;
|
||||
case kARDMessageResultTypeInvalidRoom:
|
||||
error =
|
||||
[[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
||||
code:kARDAppClientErrorInvalidRoom
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Invalid room.",
|
||||
}];
|
||||
break;
|
||||
};
|
||||
if (error) {
|
||||
[strongSelf.delegate appClient:strongSelf didError:error];
|
||||
}
|
||||
if (completionHandler) {
|
||||
completionHandler(response);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)unregisterWithRoomServer {
|
||||
NSString *urlString =
|
||||
[NSString stringWithFormat:kARDRoomServerByeFormat, _roomId, _clientId];
|
||||
NSURL *url = [NSURL URLWithString:urlString];
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:url];
|
||||
NSURLResponse *response = nil;
|
||||
// We want a synchronous request so that we know that we're unregistered from
|
||||
// room server before we do any further unregistration.
|
||||
NSLog(@"C->RS: BYE");
|
||||
NSError *error = nil;
|
||||
[NSURLConnection sendSynchronousRequest:request
|
||||
returningResponse:&response
|
||||
error:&error];
|
||||
if (error) {
|
||||
NSLog(@"Error unregistering from room server: %@", error);
|
||||
}
|
||||
NSLog(@"Unregistered from room server.");
|
||||
}
|
||||
|
||||
- (NSError *)roomServerNetworkError {
|
||||
NSError *error =
|
||||
[[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
||||
code:kARDAppClientErrorNetwork
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Room server network error",
|
||||
}];
|
||||
return error;
|
||||
}
|
||||
|
||||
#pragma mark - Collider methods
|
||||
|
||||
- (void)registerWithColliderIfReady {
|
||||
@@ -616,18 +500,15 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
return;
|
||||
}
|
||||
// Open WebSocket connection.
|
||||
_channel =
|
||||
[[ARDWebSocketChannel alloc] initWithURL:_websocketURL
|
||||
restURL:_websocketRestURL
|
||||
delegate:self];
|
||||
if (!_channel) {
|
||||
_channel =
|
||||
[[ARDWebSocketChannel alloc] initWithURL:_websocketURL
|
||||
restURL:_websocketRestURL
|
||||
delegate:self];
|
||||
}
|
||||
[_channel registerForRoomId:_roomId clientId:_clientId];
|
||||
}
|
||||
|
||||
- (void)sendSignalingMessageToCollider:(ARDSignalingMessage *)message {
|
||||
NSData *data = [message JSONData];
|
||||
[_channel sendData:data];
|
||||
}
|
||||
|
||||
#pragma mark - Defaults
|
||||
|
||||
- (RTCMediaConstraints *)defaultMediaStreamConstraints {
|
||||
@@ -655,6 +536,9 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
}
|
||||
|
||||
- (RTCMediaConstraints *)defaultPeerConnectionConstraints {
|
||||
if (_defaultPeerConnectionConstraints) {
|
||||
return _defaultPeerConnectionConstraints;
|
||||
}
|
||||
NSArray *optionalConstraints = @[
|
||||
[[RTCPair alloc] initWithKey:@"DtlsSrtpKeyAgreement" value:@"true"]
|
||||
];
|
||||
@@ -672,4 +556,61 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7;
|
||||
password:@""];
|
||||
}
|
||||
|
||||
#pragma mark - Errors
|
||||
|
||||
+ (NSError *)errorForRegisterResultType:(ARDRegisterResultType)resultType {
|
||||
NSError *error = nil;
|
||||
switch (resultType) {
|
||||
case kARDRegisterResultTypeSuccess:
|
||||
break;
|
||||
case kARDRegisterResultTypeUnknown: {
|
||||
error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
||||
code:kARDAppClientErrorUnknown
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Unknown error.",
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case kARDRegisterResultTypeFull: {
|
||||
error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
||||
code:kARDAppClientErrorRoomFull
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Room is full.",
|
||||
}];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
+ (NSError *)errorForMessageResultType:(ARDMessageResultType)resultType {
|
||||
NSError *error = nil;
|
||||
switch (resultType) {
|
||||
case kARDMessageResultTypeSuccess:
|
||||
break;
|
||||
case kARDMessageResultTypeUnknown:
|
||||
error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
||||
code:kARDAppClientErrorUnknown
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Unknown error.",
|
||||
}];
|
||||
break;
|
||||
case kARDMessageResultTypeInvalidClient:
|
||||
error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
||||
code:kARDAppClientErrorInvalidClient
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Invalid client.",
|
||||
}];
|
||||
break;
|
||||
case kARDMessageResultTypeInvalidRoom:
|
||||
error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
||||
code:kARDAppClientErrorInvalidRoom
|
||||
userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Invalid room.",
|
||||
}];
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
@end
|
||||
|
Reference in New Issue
Block a user