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#if !defined(__has_feature) || !__has_feature(objc_arc) 29#error "This file requires ARC support." 30#endif 31 32#import "RTCDataChannel+Internal.h" 33 34#include "talk/app/webrtc/datachannelinterface.h" 35 36namespace webrtc { 37 38class RTCDataChannelObserver : public DataChannelObserver { 39 public: 40 RTCDataChannelObserver(RTCDataChannel* channel) { _channel = channel; } 41 42 void OnStateChange() override { 43 [_channel.delegate channelDidChangeState:_channel]; 44 } 45 46 void OnBufferedAmountChange(uint64_t previousAmount) override { 47 RTCDataChannel* channel = _channel; 48 id<RTCDataChannelDelegate> delegate = channel.delegate; 49 if ([delegate 50 respondsToSelector:@selector(channel:didChangeBufferedAmount:)]) { 51 [delegate channel:channel didChangeBufferedAmount:previousAmount]; 52 } 53 } 54 55 void OnMessage(const DataBuffer& buffer) override { 56 if (!_channel.delegate) { 57 return; 58 } 59 RTCDataBuffer* dataBuffer = 60 [[RTCDataBuffer alloc] initWithDataBuffer:buffer]; 61 [_channel.delegate channel:_channel didReceiveMessageWithBuffer:dataBuffer]; 62 } 63 64 private: 65 __weak RTCDataChannel* _channel; 66}; 67} 68 69// TODO(henrika): move to shared location. 70// See https://code.google.com/p/webrtc/issues/detail?id=4773 for details. 71NSString* NSStringFromStdString(const std::string& stdString) { 72 // std::string may contain null termination character so we construct 73 // using length. 74 return [[NSString alloc] initWithBytes:stdString.data() 75 length:stdString.length() 76 encoding:NSUTF8StringEncoding]; 77} 78 79std::string StdStringFromNSString(NSString* nsString) { 80 NSData* charData = [nsString dataUsingEncoding:NSUTF8StringEncoding]; 81 return std::string(reinterpret_cast<const char*>([charData bytes]), 82 [charData length]); 83} 84 85@implementation RTCDataChannelInit { 86 webrtc::DataChannelInit _dataChannelInit; 87} 88 89- (BOOL)isOrdered { 90 return _dataChannelInit.ordered; 91} 92 93- (void)setIsOrdered:(BOOL)isOrdered { 94 _dataChannelInit.ordered = isOrdered; 95} 96 97- (NSInteger)maxRetransmitTime { 98 return _dataChannelInit.maxRetransmitTime; 99} 100 101- (void)setMaxRetransmitTime:(NSInteger)maxRetransmitTime { 102 _dataChannelInit.maxRetransmitTime = maxRetransmitTime; 103} 104 105- (NSInteger)maxRetransmits { 106 return _dataChannelInit.maxRetransmits; 107} 108 109- (void)setMaxRetransmits:(NSInteger)maxRetransmits { 110 _dataChannelInit.maxRetransmits = maxRetransmits; 111} 112 113- (NSString*)protocol { 114 return NSStringFromStdString(_dataChannelInit.protocol); 115} 116 117- (void)setProtocol:(NSString*)protocol { 118 _dataChannelInit.protocol = StdStringFromNSString(protocol); 119} 120 121- (BOOL)isNegotiated { 122 return _dataChannelInit.negotiated; 123} 124 125- (void)setIsNegotiated:(BOOL)isNegotiated { 126 _dataChannelInit.negotiated = isNegotiated; 127} 128 129- (NSInteger)streamId { 130 return _dataChannelInit.id; 131} 132 133- (void)setStreamId:(NSInteger)streamId { 134 _dataChannelInit.id = streamId; 135} 136 137@end 138 139@implementation RTCDataChannelInit (Internal) 140 141- (const webrtc::DataChannelInit*)dataChannelInit { 142 return &_dataChannelInit; 143} 144 145@end 146 147@implementation RTCDataBuffer { 148 rtc::scoped_ptr<webrtc::DataBuffer> _dataBuffer; 149} 150 151- (instancetype)initWithData:(NSData*)data isBinary:(BOOL)isBinary { 152 NSAssert(data, @"data cannot be nil"); 153 if (self = [super init]) { 154 rtc::Buffer buffer(reinterpret_cast<const uint8_t*>([data bytes]), 155 [data length]); 156 _dataBuffer.reset(new webrtc::DataBuffer(buffer, isBinary)); 157 } 158 return self; 159} 160 161- (NSData*)data { 162 return [NSData dataWithBytes:_dataBuffer->data.data() 163 length:_dataBuffer->data.size()]; 164} 165 166- (BOOL)isBinary { 167 return _dataBuffer->binary; 168} 169 170@end 171 172@implementation RTCDataBuffer (Internal) 173 174- (instancetype)initWithDataBuffer:(const webrtc::DataBuffer&)buffer { 175 if (self = [super init]) { 176 _dataBuffer.reset(new webrtc::DataBuffer(buffer)); 177 } 178 return self; 179} 180 181- (const webrtc::DataBuffer*)dataBuffer { 182 return _dataBuffer.get(); 183} 184 185@end 186 187@implementation RTCDataChannel { 188 rtc::scoped_refptr<webrtc::DataChannelInterface> _dataChannel; 189 rtc::scoped_ptr<webrtc::RTCDataChannelObserver> _observer; 190 BOOL _isObserverRegistered; 191} 192 193- (void)dealloc { 194 // Handles unregistering the observer properly. We need to do this because 195 // there may still be other references to the underlying data channel. 196 self.delegate = nil; 197} 198 199- (NSString*)label { 200 return NSStringFromStdString(_dataChannel->label()); 201} 202 203- (BOOL)isReliable { 204 return _dataChannel->reliable(); 205} 206 207- (BOOL)isOrdered { 208 return _dataChannel->ordered(); 209} 210 211- (NSUInteger)maxRetransmitTimeMs { 212 return _dataChannel->maxRetransmitTime(); 213} 214 215- (NSUInteger)maxRetransmits { 216 return _dataChannel->maxRetransmits(); 217} 218 219- (NSString*)protocol { 220 return NSStringFromStdString(_dataChannel->protocol()); 221} 222 223- (BOOL)isNegotiated { 224 return _dataChannel->negotiated(); 225} 226 227- (NSInteger)streamId { 228 return _dataChannel->id(); 229} 230 231- (RTCDataChannelState)state { 232 switch (_dataChannel->state()) { 233 case webrtc::DataChannelInterface::DataState::kConnecting: 234 return kRTCDataChannelStateConnecting; 235 case webrtc::DataChannelInterface::DataState::kOpen: 236 return kRTCDataChannelStateOpen; 237 case webrtc::DataChannelInterface::DataState::kClosing: 238 return kRTCDataChannelStateClosing; 239 case webrtc::DataChannelInterface::DataState::kClosed: 240 return kRTCDataChannelStateClosed; 241 } 242} 243 244- (NSUInteger)bufferedAmount { 245 return _dataChannel->buffered_amount(); 246} 247 248- (void)setDelegate:(id<RTCDataChannelDelegate>)delegate { 249 if (_delegate == delegate) { 250 return; 251 } 252 if (_isObserverRegistered) { 253 _dataChannel->UnregisterObserver(); 254 _isObserverRegistered = NO; 255 } 256 _delegate = delegate; 257 if (_delegate) { 258 _dataChannel->RegisterObserver(_observer.get()); 259 _isObserverRegistered = YES; 260 } 261} 262 263- (void)close { 264 _dataChannel->Close(); 265} 266 267- (BOOL)sendData:(RTCDataBuffer*)data { 268 return _dataChannel->Send(*data.dataBuffer); 269} 270 271@end 272 273@implementation RTCDataChannel (Internal) 274 275- (instancetype)initWithDataChannel: 276 (rtc::scoped_refptr<webrtc::DataChannelInterface>) 277 dataChannel { 278 NSAssert(dataChannel != NULL, @"dataChannel cannot be NULL"); 279 if (self = [super init]) { 280 _dataChannel = dataChannel; 281 _observer.reset(new webrtc::RTCDataChannelObserver(self)); 282 } 283 return self; 284} 285 286- (rtc::scoped_refptr<webrtc::DataChannelInterface>)dataChannel { 287 return _dataChannel; 288} 289 290@end 291