1/* 2 * Copyright 2015 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 "RTCDataChannel+Private.h" 12 13#import "helpers/NSString+StdString.h" 14 15#include <memory> 16 17namespace webrtc { 18 19class DataChannelDelegateAdapter : public DataChannelObserver { 20 public: 21 DataChannelDelegateAdapter(RTC_OBJC_TYPE(RTCDataChannel) * channel) { channel_ = channel; } 22 23 void OnStateChange() override { 24 [channel_.delegate dataChannelDidChangeState:channel_]; 25 } 26 27 void OnMessage(const DataBuffer& buffer) override { 28 RTC_OBJC_TYPE(RTCDataBuffer) *data_buffer = 29 [[RTC_OBJC_TYPE(RTCDataBuffer) alloc] initWithNativeBuffer:buffer]; 30 [channel_.delegate dataChannel:channel_ 31 didReceiveMessageWithBuffer:data_buffer]; 32 } 33 34 void OnBufferedAmountChange(uint64_t previousAmount) override { 35 id<RTC_OBJC_TYPE(RTCDataChannelDelegate)> delegate = channel_.delegate; 36 SEL sel = @selector(dataChannel:didChangeBufferedAmount:); 37 if ([delegate respondsToSelector:sel]) { 38 [delegate dataChannel:channel_ didChangeBufferedAmount:previousAmount]; 39 } 40 } 41 42 private: 43 __weak RTC_OBJC_TYPE(RTCDataChannel) * channel_; 44}; 45} 46 47@implementation RTC_OBJC_TYPE (RTCDataBuffer) { 48 std::unique_ptr<webrtc::DataBuffer> _dataBuffer; 49} 50 51- (instancetype)initWithData:(NSData *)data isBinary:(BOOL)isBinary { 52 NSParameterAssert(data); 53 if (self = [super init]) { 54 rtc::CopyOnWriteBuffer buffer( 55 reinterpret_cast<const uint8_t*>(data.bytes), data.length); 56 _dataBuffer.reset(new webrtc::DataBuffer(buffer, isBinary)); 57 } 58 return self; 59} 60 61- (NSData *)data { 62 return [NSData dataWithBytes:_dataBuffer->data.data() 63 length:_dataBuffer->data.size()]; 64} 65 66- (BOOL)isBinary { 67 return _dataBuffer->binary; 68} 69 70#pragma mark - Private 71 72- (instancetype)initWithNativeBuffer:(const webrtc::DataBuffer&)nativeBuffer { 73 if (self = [super init]) { 74 _dataBuffer.reset(new webrtc::DataBuffer(nativeBuffer)); 75 } 76 return self; 77} 78 79- (const webrtc::DataBuffer *)nativeDataBuffer { 80 return _dataBuffer.get(); 81} 82 83@end 84 85@implementation RTC_OBJC_TYPE (RTCDataChannel) { 86 RTC_OBJC_TYPE(RTCPeerConnectionFactory) * _factory; 87 rtc::scoped_refptr<webrtc::DataChannelInterface> _nativeDataChannel; 88 std::unique_ptr<webrtc::DataChannelDelegateAdapter> _observer; 89 BOOL _isObserverRegistered; 90} 91 92@synthesize delegate = _delegate; 93 94- (void)dealloc { 95 // Handles unregistering the observer properly. We need to do this because 96 // there may still be other references to the underlying data channel. 97 _nativeDataChannel->UnregisterObserver(); 98} 99 100- (NSString *)label { 101 return [NSString stringForStdString:_nativeDataChannel->label()]; 102} 103 104- (BOOL)isReliable { 105 return _nativeDataChannel->reliable(); 106} 107 108- (BOOL)isOrdered { 109 return _nativeDataChannel->ordered(); 110} 111 112- (NSUInteger)maxRetransmitTime { 113 return self.maxPacketLifeTime; 114} 115 116- (uint16_t)maxPacketLifeTime { 117 return _nativeDataChannel->maxRetransmitTime(); 118} 119 120- (uint16_t)maxRetransmits { 121 return _nativeDataChannel->maxRetransmits(); 122} 123 124- (NSString *)protocol { 125 return [NSString stringForStdString:_nativeDataChannel->protocol()]; 126} 127 128- (BOOL)isNegotiated { 129 return _nativeDataChannel->negotiated(); 130} 131 132- (NSInteger)streamId { 133 return self.channelId; 134} 135 136- (int)channelId { 137 return _nativeDataChannel->id(); 138} 139 140- (RTCDataChannelState)readyState { 141 return [[self class] dataChannelStateForNativeState: 142 _nativeDataChannel->state()]; 143} 144 145- (uint64_t)bufferedAmount { 146 return _nativeDataChannel->buffered_amount(); 147} 148 149- (void)close { 150 _nativeDataChannel->Close(); 151} 152 153- (BOOL)sendData:(RTC_OBJC_TYPE(RTCDataBuffer) *)data { 154 return _nativeDataChannel->Send(*data.nativeDataBuffer); 155} 156 157- (NSString *)description { 158 return [NSString stringWithFormat:@"RTC_OBJC_TYPE(RTCDataChannel):\n%ld\n%@\n%@", 159 (long)self.channelId, 160 self.label, 161 [[self class] stringForState:self.readyState]]; 162} 163 164#pragma mark - Private 165 166- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory 167 nativeDataChannel: 168 (rtc::scoped_refptr<webrtc::DataChannelInterface>)nativeDataChannel { 169 NSParameterAssert(nativeDataChannel); 170 if (self = [super init]) { 171 _factory = factory; 172 _nativeDataChannel = nativeDataChannel; 173 _observer.reset(new webrtc::DataChannelDelegateAdapter(self)); 174 _nativeDataChannel->RegisterObserver(_observer.get()); 175 } 176 return self; 177} 178 179+ (webrtc::DataChannelInterface::DataState) 180 nativeDataChannelStateForState:(RTCDataChannelState)state { 181 switch (state) { 182 case RTCDataChannelStateConnecting: 183 return webrtc::DataChannelInterface::DataState::kConnecting; 184 case RTCDataChannelStateOpen: 185 return webrtc::DataChannelInterface::DataState::kOpen; 186 case RTCDataChannelStateClosing: 187 return webrtc::DataChannelInterface::DataState::kClosing; 188 case RTCDataChannelStateClosed: 189 return webrtc::DataChannelInterface::DataState::kClosed; 190 } 191} 192 193+ (RTCDataChannelState)dataChannelStateForNativeState: 194 (webrtc::DataChannelInterface::DataState)nativeState { 195 switch (nativeState) { 196 case webrtc::DataChannelInterface::DataState::kConnecting: 197 return RTCDataChannelStateConnecting; 198 case webrtc::DataChannelInterface::DataState::kOpen: 199 return RTCDataChannelStateOpen; 200 case webrtc::DataChannelInterface::DataState::kClosing: 201 return RTCDataChannelStateClosing; 202 case webrtc::DataChannelInterface::DataState::kClosed: 203 return RTCDataChannelStateClosed; 204 } 205} 206 207+ (NSString *)stringForState:(RTCDataChannelState)state { 208 switch (state) { 209 case RTCDataChannelStateConnecting: 210 return @"Connecting"; 211 case RTCDataChannelStateOpen: 212 return @"Open"; 213 case RTCDataChannelStateClosing: 214 return @"Closing"; 215 case RTCDataChannelStateClosed: 216 return @"Closed"; 217 } 218} 219 220@end 221