/* * Copyright 2015 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #import "RTCDataChannel+Private.h" #import "helpers/NSString+StdString.h" #include namespace webrtc { class DataChannelDelegateAdapter : public DataChannelObserver { public: DataChannelDelegateAdapter(RTC_OBJC_TYPE(RTCDataChannel) * channel) { channel_ = channel; } void OnStateChange() override { [channel_.delegate dataChannelDidChangeState:channel_]; } void OnMessage(const DataBuffer& buffer) override { RTC_OBJC_TYPE(RTCDataBuffer) *data_buffer = [[RTC_OBJC_TYPE(RTCDataBuffer) alloc] initWithNativeBuffer:buffer]; [channel_.delegate dataChannel:channel_ didReceiveMessageWithBuffer:data_buffer]; } void OnBufferedAmountChange(uint64_t previousAmount) override { id delegate = channel_.delegate; SEL sel = @selector(dataChannel:didChangeBufferedAmount:); if ([delegate respondsToSelector:sel]) { [delegate dataChannel:channel_ didChangeBufferedAmount:previousAmount]; } } private: __weak RTC_OBJC_TYPE(RTCDataChannel) * channel_; }; } @implementation RTC_OBJC_TYPE (RTCDataBuffer) { std::unique_ptr _dataBuffer; } - (instancetype)initWithData:(NSData *)data isBinary:(BOOL)isBinary { NSParameterAssert(data); if (self = [super init]) { rtc::CopyOnWriteBuffer buffer( reinterpret_cast(data.bytes), data.length); _dataBuffer.reset(new webrtc::DataBuffer(buffer, isBinary)); } return self; } - (NSData *)data { return [NSData dataWithBytes:_dataBuffer->data.data() length:_dataBuffer->data.size()]; } - (BOOL)isBinary { return _dataBuffer->binary; } #pragma mark - Private - (instancetype)initWithNativeBuffer:(const webrtc::DataBuffer&)nativeBuffer { if (self = [super init]) { _dataBuffer.reset(new webrtc::DataBuffer(nativeBuffer)); } return self; } - (const webrtc::DataBuffer *)nativeDataBuffer { return _dataBuffer.get(); } @end @implementation RTC_OBJC_TYPE (RTCDataChannel) { RTC_OBJC_TYPE(RTCPeerConnectionFactory) * _factory; rtc::scoped_refptr _nativeDataChannel; std::unique_ptr _observer; BOOL _isObserverRegistered; } @synthesize delegate = _delegate; - (void)dealloc { // Handles unregistering the observer properly. We need to do this because // there may still be other references to the underlying data channel. _nativeDataChannel->UnregisterObserver(); } - (NSString *)label { return [NSString stringForStdString:_nativeDataChannel->label()]; } - (BOOL)isReliable { return _nativeDataChannel->reliable(); } - (BOOL)isOrdered { return _nativeDataChannel->ordered(); } - (NSUInteger)maxRetransmitTime { return self.maxPacketLifeTime; } - (uint16_t)maxPacketLifeTime { return _nativeDataChannel->maxRetransmitTime(); } - (uint16_t)maxRetransmits { return _nativeDataChannel->maxRetransmits(); } - (NSString *)protocol { return [NSString stringForStdString:_nativeDataChannel->protocol()]; } - (BOOL)isNegotiated { return _nativeDataChannel->negotiated(); } - (NSInteger)streamId { return self.channelId; } - (int)channelId { return _nativeDataChannel->id(); } - (RTCDataChannelState)readyState { return [[self class] dataChannelStateForNativeState: _nativeDataChannel->state()]; } - (uint64_t)bufferedAmount { return _nativeDataChannel->buffered_amount(); } - (void)close { _nativeDataChannel->Close(); } - (BOOL)sendData:(RTC_OBJC_TYPE(RTCDataBuffer) *)data { return _nativeDataChannel->Send(*data.nativeDataBuffer); } - (NSString *)description { return [NSString stringWithFormat:@"RTC_OBJC_TYPE(RTCDataChannel):\n%ld\n%@\n%@", (long)self.channelId, self.label, [[self class] stringForState:self.readyState]]; } #pragma mark - Private - (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory nativeDataChannel: (rtc::scoped_refptr)nativeDataChannel { NSParameterAssert(nativeDataChannel); if (self = [super init]) { _factory = factory; _nativeDataChannel = nativeDataChannel; _observer.reset(new webrtc::DataChannelDelegateAdapter(self)); _nativeDataChannel->RegisterObserver(_observer.get()); } return self; } + (webrtc::DataChannelInterface::DataState) nativeDataChannelStateForState:(RTCDataChannelState)state { switch (state) { case RTCDataChannelStateConnecting: return webrtc::DataChannelInterface::DataState::kConnecting; case RTCDataChannelStateOpen: return webrtc::DataChannelInterface::DataState::kOpen; case RTCDataChannelStateClosing: return webrtc::DataChannelInterface::DataState::kClosing; case RTCDataChannelStateClosed: return webrtc::DataChannelInterface::DataState::kClosed; } } + (RTCDataChannelState)dataChannelStateForNativeState: (webrtc::DataChannelInterface::DataState)nativeState { switch (nativeState) { case webrtc::DataChannelInterface::DataState::kConnecting: return RTCDataChannelStateConnecting; case webrtc::DataChannelInterface::DataState::kOpen: return RTCDataChannelStateOpen; case webrtc::DataChannelInterface::DataState::kClosing: return RTCDataChannelStateClosing; case webrtc::DataChannelInterface::DataState::kClosed: return RTCDataChannelStateClosed; } } + (NSString *)stringForState:(RTCDataChannelState)state { switch (state) { case RTCDataChannelStateConnecting: return @"Connecting"; case RTCDataChannelStateOpen: return @"Open"; case RTCDataChannelStateClosing: return @"Closing"; case RTCDataChannelStateClosed: return @"Closed"; } } @end