tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ARDWebSocketChannel.m (8563B)


      1 /*
      2 *  Copyright 2014 The WebRTC Project Authors. All rights reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #import "ARDWebSocketChannel.h"
     12 
     13 #import "sdk/objc/base/RTCLogging.h"
     14 
     15 #import "SRWebSocket.h"
     16 
     17 #import "ARDSignalingMessage.h"
     18 #import "ARDUtilities.h"
     19 
     20 // TODO(tkchin): move these to a configuration object.
     21 static NSString const *kARDWSSMessageErrorKey = @"error";
     22 static NSString const *kARDWSSMessagePayloadKey = @"msg";
     23 
     24 @interface ARDWebSocketChannel () <SRWebSocketDelegate>
     25 @end
     26 
     27 @implementation ARDWebSocketChannel {
     28  NSURL *_url;
     29  NSURL *_restURL;
     30  SRWebSocket *_socket;
     31 }
     32 
     33 @synthesize delegate = _delegate;
     34 @synthesize state = _state;
     35 @synthesize roomId = _roomId;
     36 @synthesize clientId = _clientId;
     37 
     38 - (instancetype)initWithURL:(NSURL *)url
     39                    restURL:(NSURL *)restURL
     40                   delegate:(id<ARDSignalingChannelDelegate>)delegate {
     41  self = [super init];
     42  if (self) {
     43    _url = url;
     44    _restURL = restURL;
     45    _delegate = delegate;
     46    _socket = [[SRWebSocket alloc] initWithURL:url];
     47    _socket.delegate = self;
     48    RTCLog(@"Opening WebSocket.");
     49    [_socket open];
     50  }
     51  return self;
     52 }
     53 
     54 - (void)dealloc {
     55  [self disconnect];
     56 }
     57 
     58 - (void)setState:(ARDSignalingChannelState)state {
     59  if (_state == state) {
     60    return;
     61  }
     62  _state = state;
     63  [_delegate channel:self didChangeState:_state];
     64 }
     65 
     66 - (void)registerForRoomId:(NSString *)roomId clientId:(NSString *)clientId {
     67  NSParameterAssert(roomId.length);
     68  NSParameterAssert(clientId.length);
     69  _roomId = roomId;
     70  _clientId = clientId;
     71  if (_state == kARDSignalingChannelStateOpen) {
     72    [self registerWithCollider];
     73  }
     74 }
     75 
     76 - (void)sendMessage:(ARDSignalingMessage *)message {
     77  NSParameterAssert(_clientId.length);
     78  NSParameterAssert(_roomId.length);
     79  NSData *data = [message JSONData];
     80  if (_state == kARDSignalingChannelStateRegistered) {
     81    NSString *payload = [[NSString alloc] initWithData:data
     82                                              encoding:NSUTF8StringEncoding];
     83    NSData *messageJSONObject = [NSJSONSerialization
     84        dataWithJSONObject:@{@"cmd" : @"send", @"msg" : payload}
     85                   options:NSJSONWritingPrettyPrinted
     86                     error:nil];
     87    NSString *messageString =
     88        [[NSString alloc] initWithData:messageJSONObject
     89                              encoding:NSUTF8StringEncoding];
     90    RTCLog(@"C->WSS: %@", messageString);
     91    [_socket send:messageString];
     92  } else {
     93    NSString *dataString = [[NSString alloc] initWithData:data
     94                                                 encoding:NSUTF8StringEncoding];
     95    RTCLog(@"C->WSS POST: %@", dataString);
     96    NSString *urlString = [NSString stringWithFormat:@"%@/%@/%@",
     97                                                     [_restURL absoluteString],
     98                                                     _roomId,
     99                                                     _clientId];
    100    NSURL *url = [NSURL URLWithString:urlString];
    101    [NSURLConnection sendAsyncPostToURL:url
    102                               withData:data
    103                      completionHandler:nil];
    104  }
    105 }
    106 
    107 - (void)disconnect {
    108  if (_state == kARDSignalingChannelStateClosed ||
    109      _state == kARDSignalingChannelStateError) {
    110    return;
    111  }
    112  [_socket close];
    113  RTCLog(@"C->WSS DELETE rid:%@ cid:%@", _roomId, _clientId);
    114  NSString *urlString = [NSString stringWithFormat:@"%@/%@/%@",
    115                                                   [_restURL absoluteString],
    116                                                   _roomId,
    117                                                   _clientId];
    118  NSURL *url = [NSURL URLWithString:urlString];
    119  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    120  request.HTTPMethod = @"DELETE";
    121  request.HTTPBody = nil;
    122  [NSURLConnection sendAsyncRequest:request completionHandler:nil];
    123 }
    124 
    125 #pragma mark - SRWebSocketDelegate
    126 
    127 - (void)webSocketDidOpen:(SRWebSocket *)webSocket {
    128  RTCLog(@"WebSocket connection opened.");
    129  self.state = kARDSignalingChannelStateOpen;
    130  if (_roomId.length && _clientId.length) {
    131    [self registerWithCollider];
    132  }
    133 }
    134 
    135 - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message {
    136  NSString *messageString = message;
    137  NSData *messageData = [messageString dataUsingEncoding:NSUTF8StringEncoding];
    138  id jsonObject = [NSJSONSerialization JSONObjectWithData:messageData
    139                                                  options:0
    140                                                    error:nil];
    141  if (![jsonObject isKindOfClass:[NSDictionary class]]) {
    142    RTCLogError(@"Unexpected message: %@", jsonObject);
    143    return;
    144  }
    145  NSDictionary *wssMessage = jsonObject;
    146  NSString *errorString = wssMessage[kARDWSSMessageErrorKey];
    147  if (errorString.length) {
    148    RTCLogError(@"WSS error: %@", errorString);
    149    return;
    150  }
    151  NSString *payload = wssMessage[kARDWSSMessagePayloadKey];
    152  ARDSignalingMessage *signalingMessage =
    153      [ARDSignalingMessage messageFromJSONString:payload];
    154  RTCLog(@"WSS->C: %@", payload);
    155  [_delegate channel:self didReceiveMessage:signalingMessage];
    156 }
    157 
    158 - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error {
    159  RTCLogError(@"WebSocket error: %@", error);
    160  self.state = kARDSignalingChannelStateError;
    161 }
    162 
    163 - (void)webSocket:(SRWebSocket *)webSocket
    164    didCloseWithCode:(NSInteger)code
    165              reason:(NSString *)reason
    166            wasClean:(BOOL)wasClean {
    167  RTCLog(@"WebSocket closed with code: %ld reason:%@ wasClean:%d",
    168         (long)code,
    169         reason,
    170         wasClean);
    171  NSParameterAssert(_state != kARDSignalingChannelStateError);
    172  self.state = kARDSignalingChannelStateClosed;
    173 }
    174 
    175 #pragma mark - Private
    176 
    177 - (void)registerWithCollider {
    178  if (_state == kARDSignalingChannelStateRegistered) {
    179    return;
    180  }
    181  NSParameterAssert(_roomId.length);
    182  NSParameterAssert(_clientId.length);
    183  NSDictionary *registerMessage = @{
    184    @"cmd" : @"register",
    185    @"roomid" : _roomId,
    186    @"clientid" : _clientId,
    187  };
    188  NSData *message =
    189      [NSJSONSerialization dataWithJSONObject:registerMessage
    190                                      options:NSJSONWritingPrettyPrinted
    191                                        error:nil];
    192  NSString *messageString =
    193      [[NSString alloc] initWithData:message encoding:NSUTF8StringEncoding];
    194  RTCLog(@"Registering on WSS for rid:%@ cid:%@", _roomId, _clientId);
    195  // Registration can fail if server rejects it. For example, if the room is
    196  // full.
    197  [_socket send:messageString];
    198  self.state = kARDSignalingChannelStateRegistered;
    199 }
    200 
    201 @end
    202 
    203 @interface ARDLoopbackWebSocketChannel () <ARDSignalingChannelDelegate>
    204 @end
    205 
    206 @implementation ARDLoopbackWebSocketChannel
    207 
    208 - (instancetype)initWithURL:(NSURL *)url restURL:(NSURL *)restURL {
    209  return [super initWithURL:url restURL:restURL delegate:self];
    210 }
    211 
    212 #pragma mark - ARDSignalingChannelDelegate
    213 
    214 - (void)channel:(id<ARDSignalingChannel>)channel
    215    didReceiveMessage:(ARDSignalingMessage *)message {
    216  switch (message.type) {
    217    case kARDSignalingMessageTypeOffer: {
    218      // Change message to answer, send back to server.
    219      ARDSessionDescriptionMessage *sdpMessage =
    220          (ARDSessionDescriptionMessage *)message;
    221      RTC_OBJC_TYPE(RTCSessionDescription) *description =
    222          sdpMessage.sessionDescription;
    223      NSString *dsc = description.sdp;
    224      dsc = [dsc stringByReplacingOccurrencesOfString:@"offer"
    225                                           withString:@"answer"];
    226      RTC_OBJC_TYPE(RTCSessionDescription) *answerDescription =
    227          [[RTC_OBJC_TYPE(RTCSessionDescription) alloc]
    228              initWithType:RTCSdpTypeAnswer
    229                       sdp:dsc];
    230      ARDSignalingMessage *answer = [[ARDSessionDescriptionMessage alloc]
    231          initWithDescription:answerDescription];
    232      [self sendMessage:answer];
    233      break;
    234    }
    235    case kARDSignalingMessageTypeAnswer:
    236      // Should not receive answer in loopback scenario.
    237      break;
    238    case kARDSignalingMessageTypeCandidate:
    239    case kARDSignalingMessageTypeCandidateRemoval:
    240      // Send back to server.
    241      [self sendMessage:message];
    242      break;
    243    case kARDSignalingMessageTypeBye:
    244      // Nothing to do.
    245      return;
    246  }
    247 }
    248 
    249 - (void)channel:(id<ARDSignalingChannel>)channel
    250    didChangeState:(ARDSignalingChannelState)state {
    251 }
    252 
    253 @end