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