diff options
Diffstat (limited to 'third_party/libwebrtc/examples/objc/AppRTCMobile/ARDWebSocketChannel.m')
-rw-r--r-- | third_party/libwebrtc/examples/objc/AppRTCMobile/ARDWebSocketChannel.m | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/third_party/libwebrtc/examples/objc/AppRTCMobile/ARDWebSocketChannel.m b/third_party/libwebrtc/examples/objc/AppRTCMobile/ARDWebSocketChannel.m new file mode 100644 index 0000000000..bbb0bf87f8 --- /dev/null +++ b/third_party/libwebrtc/examples/objc/AppRTCMobile/ARDWebSocketChannel.m @@ -0,0 +1,252 @@ +/* + * Copyright 2014 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#import "ARDWebSocketChannel.h" + +#import "sdk/objc/base/RTCLogging.h" + +#import "SRWebSocket.h" + +#import "ARDSignalingMessage.h" +#import "ARDUtilities.h" + +// TODO(tkchin): move these to a configuration object. +static NSString const *kARDWSSMessageErrorKey = @"error"; +static NSString const *kARDWSSMessagePayloadKey = @"msg"; + +@interface ARDWebSocketChannel () <SRWebSocketDelegate> +@end + +@implementation ARDWebSocketChannel { + NSURL *_url; + NSURL *_restURL; + SRWebSocket *_socket; +} + +@synthesize delegate = _delegate; +@synthesize state = _state; +@synthesize roomId = _roomId; +@synthesize clientId = _clientId; + +- (instancetype)initWithURL:(NSURL *)url + restURL:(NSURL *)restURL + delegate:(id<ARDSignalingChannelDelegate>)delegate { + if (self = [super init]) { + _url = url; + _restURL = restURL; + _delegate = delegate; + _socket = [[SRWebSocket alloc] initWithURL:url]; + _socket.delegate = self; + RTCLog(@"Opening WebSocket."); + [_socket open]; + } + return self; +} + +- (void)dealloc { + [self disconnect]; +} + +- (void)setState:(ARDSignalingChannelState)state { + if (_state == state) { + return; + } + _state = state; + [_delegate channel:self didChangeState:_state]; +} + +- (void)registerForRoomId:(NSString *)roomId + clientId:(NSString *)clientId { + NSParameterAssert(roomId.length); + NSParameterAssert(clientId.length); + _roomId = roomId; + _clientId = clientId; + if (_state == kARDSignalingChannelStateOpen) { + [self registerWithCollider]; + } +} + +- (void)sendMessage:(ARDSignalingMessage *)message { + NSParameterAssert(_clientId.length); + NSParameterAssert(_roomId.length); + NSData *data = [message JSONData]; + if (_state == kARDSignalingChannelStateRegistered) { + NSString *payload = + [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + NSDictionary *message = @{ + @"cmd": @"send", + @"msg": payload, + }; + NSData *messageJSONObject = + [NSJSONSerialization dataWithJSONObject:message + options:NSJSONWritingPrettyPrinted + error:nil]; + NSString *messageString = + [[NSString alloc] initWithData:messageJSONObject + encoding:NSUTF8StringEncoding]; + RTCLog(@"C->WSS: %@", messageString); + [_socket send:messageString]; + } else { + NSString *dataString = + [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + RTCLog(@"C->WSS POST: %@", dataString); + NSString *urlString = + [NSString stringWithFormat:@"%@/%@/%@", + [_restURL absoluteString], _roomId, _clientId]; + NSURL *url = [NSURL URLWithString:urlString]; + [NSURLConnection sendAsyncPostToURL:url + withData:data + completionHandler:nil]; + } +} + +- (void)disconnect { + if (_state == kARDSignalingChannelStateClosed || + _state == kARDSignalingChannelStateError) { + return; + } + [_socket close]; + RTCLog(@"C->WSS DELETE rid:%@ cid:%@", _roomId, _clientId); + NSString *urlString = + [NSString stringWithFormat:@"%@/%@/%@", + [_restURL absoluteString], _roomId, _clientId]; + NSURL *url = [NSURL URLWithString:urlString]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + request.HTTPMethod = @"DELETE"; + request.HTTPBody = nil; + [NSURLConnection sendAsyncRequest:request completionHandler:nil]; +} + +#pragma mark - SRWebSocketDelegate + +- (void)webSocketDidOpen:(SRWebSocket *)webSocket { + RTCLog(@"WebSocket connection opened."); + self.state = kARDSignalingChannelStateOpen; + if (_roomId.length && _clientId.length) { + [self registerWithCollider]; + } +} + +- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message { + NSString *messageString = message; + NSData *messageData = [messageString dataUsingEncoding:NSUTF8StringEncoding]; + id jsonObject = [NSJSONSerialization JSONObjectWithData:messageData + options:0 + error:nil]; + if (![jsonObject isKindOfClass:[NSDictionary class]]) { + RTCLogError(@"Unexpected message: %@", jsonObject); + return; + } + NSDictionary *wssMessage = jsonObject; + NSString *errorString = wssMessage[kARDWSSMessageErrorKey]; + if (errorString.length) { + RTCLogError(@"WSS error: %@", errorString); + return; + } + NSString *payload = wssMessage[kARDWSSMessagePayloadKey]; + ARDSignalingMessage *signalingMessage = + [ARDSignalingMessage messageFromJSONString:payload]; + RTCLog(@"WSS->C: %@", payload); + [_delegate channel:self didReceiveMessage:signalingMessage]; +} + +- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error { + RTCLogError(@"WebSocket error: %@", error); + self.state = kARDSignalingChannelStateError; +} + +- (void)webSocket:(SRWebSocket *)webSocket + didCloseWithCode:(NSInteger)code + reason:(NSString *)reason + wasClean:(BOOL)wasClean { + RTCLog(@"WebSocket closed with code: %ld reason:%@ wasClean:%d", + (long)code, reason, wasClean); + NSParameterAssert(_state != kARDSignalingChannelStateError); + self.state = kARDSignalingChannelStateClosed; +} + +#pragma mark - Private + +- (void)registerWithCollider { + if (_state == kARDSignalingChannelStateRegistered) { + return; + } + NSParameterAssert(_roomId.length); + NSParameterAssert(_clientId.length); + NSDictionary *registerMessage = @{ + @"cmd": @"register", + @"roomid" : _roomId, + @"clientid" : _clientId, + }; + NSData *message = + [NSJSONSerialization dataWithJSONObject:registerMessage + options:NSJSONWritingPrettyPrinted + error:nil]; + NSString *messageString = + [[NSString alloc] initWithData:message encoding:NSUTF8StringEncoding]; + RTCLog(@"Registering on WSS for rid:%@ cid:%@", _roomId, _clientId); + // Registration can fail if server rejects it. For example, if the room is + // full. + [_socket send:messageString]; + self.state = kARDSignalingChannelStateRegistered; +} + +@end + +@interface ARDLoopbackWebSocketChannel () <ARDSignalingChannelDelegate> +@end + +@implementation ARDLoopbackWebSocketChannel + +- (instancetype)initWithURL:(NSURL *)url restURL:(NSURL *)restURL { + return [super initWithURL:url restURL:restURL delegate:self]; +} + +#pragma mark - ARDSignalingChannelDelegate + +- (void)channel:(id<ARDSignalingChannel>)channel + didReceiveMessage:(ARDSignalingMessage *)message { + switch (message.type) { + case kARDSignalingMessageTypeOffer: { + // Change message to answer, send back to server. + ARDSessionDescriptionMessage *sdpMessage = + (ARDSessionDescriptionMessage *)message; + RTC_OBJC_TYPE(RTCSessionDescription) *description = sdpMessage.sessionDescription; + NSString *dsc = description.sdp; + dsc = [dsc stringByReplacingOccurrencesOfString:@"offer" + withString:@"answer"]; + RTC_OBJC_TYPE(RTCSessionDescription) *answerDescription = + [[RTC_OBJC_TYPE(RTCSessionDescription) alloc] initWithType:RTCSdpTypeAnswer sdp:dsc]; + ARDSignalingMessage *answer = + [[ARDSessionDescriptionMessage alloc] + initWithDescription:answerDescription]; + [self sendMessage:answer]; + break; + } + case kARDSignalingMessageTypeAnswer: + // Should not receive answer in loopback scenario. + break; + case kARDSignalingMessageTypeCandidate: + case kARDSignalingMessageTypeCandidateRemoval: + // Send back to server. + [self sendMessage:message]; + break; + case kARDSignalingMessageTypeBye: + // Nothing to do. + return; + } +} + +- (void)channel:(id<ARDSignalingChannel>)channel + didChangeState:(ARDSignalingChannelState)state { +} + +@end + |