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 36 namespace webrtc { 37 38 class 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 61 NSString* 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 69 std::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