blob: 9948615a6a2b4d351ed8ad312c04a8a4e2d9d84a [file] [log] [blame]
hjone373dc22016-01-22 14:04:27 -08001/*
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
tkchin9eeb6242016-04-27 01:54:20 -070011#import "RTCDataChannel+Private.h"
hjone373dc22016-01-22 14:04:27 -080012
tkchin9eeb6242016-04-27 01:54:20 -070013#import "NSString+StdString.h"
hjone373dc22016-01-22 14:04:27 -080014
kwibergbfefb032016-05-01 14:53:46 -070015#include <memory>
kwiberg8fb35572016-02-11 13:36:43 -080016
hjone373dc22016-01-22 14:04:27 -080017namespace webrtc {
18
19class DataChannelDelegateAdapter : public DataChannelObserver {
20 public:
21 DataChannelDelegateAdapter(RTCDataChannel *channel) { channel_ = channel; }
22
23 void OnStateChange() override {
24 [channel_.delegate dataChannelDidChangeState:channel_];
25 }
26
27 void OnMessage(const DataBuffer& buffer) override {
28 RTCDataBuffer *data_buffer =
29 [[RTCDataBuffer alloc] initWithNativeBuffer:buffer];
30 [channel_.delegate dataChannel:channel_
31 didReceiveMessageWithBuffer:data_buffer];
32 }
33
34 void OnBufferedAmountChange(uint64_t previousAmount) override {
35 id<RTCDataChannelDelegate> delegate = channel_.delegate;
tkchin121ac122016-03-21 09:08:40 -070036 SEL sel = @selector(dataChannel:didChangeBufferedAmount:);
37 if ([delegate respondsToSelector:sel]) {
hjone373dc22016-01-22 14:04:27 -080038 [delegate dataChannel:channel_ didChangeBufferedAmount:previousAmount];
39 }
40 }
41
42 private:
43 __weak RTCDataChannel *channel_;
44};
45}
46
47
48@implementation RTCDataBuffer {
kwibergbfefb032016-05-01 14:53:46 -070049 std::unique_ptr<webrtc::DataBuffer> _dataBuffer;
hjone373dc22016-01-22 14:04:27 -080050}
51
52- (instancetype)initWithData:(NSData *)data isBinary:(BOOL)isBinary {
53 NSParameterAssert(data);
54 if (self = [super init]) {
jbaucheec21bd2016-03-20 06:15:43 -070055 rtc::CopyOnWriteBuffer buffer(
56 reinterpret_cast<const uint8_t*>(data.bytes), data.length);
hjone373dc22016-01-22 14:04:27 -080057 _dataBuffer.reset(new webrtc::DataBuffer(buffer, isBinary));
58 }
59 return self;
60}
61
62- (NSData *)data {
63 return [NSData dataWithBytes:_dataBuffer->data.data()
64 length:_dataBuffer->data.size()];
65}
66
67- (BOOL)isBinary {
68 return _dataBuffer->binary;
69}
70
71#pragma mark - Private
72
73- (instancetype)initWithNativeBuffer:(const webrtc::DataBuffer&)nativeBuffer {
74 if (self = [super init]) {
75 _dataBuffer.reset(new webrtc::DataBuffer(nativeBuffer));
76 }
77 return self;
78}
79
80- (const webrtc::DataBuffer *)nativeDataBuffer {
81 return _dataBuffer.get();
82}
83
84@end
85
86
87@implementation RTCDataChannel {
tkchin8b9ca952016-03-31 12:08:03 -070088 rtc::scoped_refptr<webrtc::DataChannelInterface> _nativeDataChannel;
kwibergbfefb032016-05-01 14:53:46 -070089 std::unique_ptr<webrtc::DataChannelDelegateAdapter> _observer;
hjone373dc22016-01-22 14:04:27 -080090 BOOL _isObserverRegistered;
91}
92
93@synthesize delegate = _delegate;
94
95- (void)dealloc {
96 // Handles unregistering the observer properly. We need to do this because
97 // there may still be other references to the underlying data channel.
98 self.delegate = nil;
99}
100
101- (NSString *)label {
tkchin8b9ca952016-03-31 12:08:03 -0700102 return [NSString stringForStdString:_nativeDataChannel->label()];
103}
104
105- (BOOL)isReliable {
106 return _nativeDataChannel->reliable();
hjone373dc22016-01-22 14:04:27 -0800107}
108
109- (BOOL)isOrdered {
tkchin8b9ca952016-03-31 12:08:03 -0700110 return _nativeDataChannel->ordered();
111}
112
113- (NSUInteger)maxRetransmitTime {
114 return self.maxPacketLifeTime;
hjone373dc22016-01-22 14:04:27 -0800115}
116
117- (uint16_t)maxPacketLifeTime {
tkchin8b9ca952016-03-31 12:08:03 -0700118 return _nativeDataChannel->maxRetransmitTime();
hjone373dc22016-01-22 14:04:27 -0800119}
120
121- (uint16_t)maxRetransmits {
tkchin8b9ca952016-03-31 12:08:03 -0700122 return _nativeDataChannel->maxRetransmits();
hjone373dc22016-01-22 14:04:27 -0800123}
124
125- (NSString *)protocol {
tkchin8b9ca952016-03-31 12:08:03 -0700126 return [NSString stringForStdString:_nativeDataChannel->protocol()];
hjone373dc22016-01-22 14:04:27 -0800127}
128
129- (BOOL)isNegotiated {
tkchin8b9ca952016-03-31 12:08:03 -0700130 return _nativeDataChannel->negotiated();
131}
132
133- (NSInteger)streamId {
134 return self.channelId;
hjone373dc22016-01-22 14:04:27 -0800135}
136
hjona2f77982016-03-04 07:09:09 -0800137- (int)channelId {
tkchin8b9ca952016-03-31 12:08:03 -0700138 return _nativeDataChannel->id();
hjone373dc22016-01-22 14:04:27 -0800139}
140
141- (RTCDataChannelState)readyState {
142 return [[self class] dataChannelStateForNativeState:
tkchin8b9ca952016-03-31 12:08:03 -0700143 _nativeDataChannel->state()];
hjone373dc22016-01-22 14:04:27 -0800144}
145
146- (uint64_t)bufferedAmount {
tkchin8b9ca952016-03-31 12:08:03 -0700147 return _nativeDataChannel->buffered_amount();
hjone373dc22016-01-22 14:04:27 -0800148}
149
150- (void)setDelegate:(id<RTCDataChannelDelegate>)delegate {
151 if (_delegate == delegate) {
152 return;
153 }
154 if (_isObserverRegistered) {
tkchin8b9ca952016-03-31 12:08:03 -0700155 _nativeDataChannel->UnregisterObserver();
hjone373dc22016-01-22 14:04:27 -0800156 _isObserverRegistered = NO;
157 }
158 _delegate = delegate;
159 if (_delegate) {
tkchin8b9ca952016-03-31 12:08:03 -0700160 _nativeDataChannel->RegisterObserver(_observer.get());
hjone373dc22016-01-22 14:04:27 -0800161 _isObserverRegistered = YES;
162 }
163}
164
165- (void)close {
tkchin8b9ca952016-03-31 12:08:03 -0700166 _nativeDataChannel->Close();
hjone373dc22016-01-22 14:04:27 -0800167}
168
169- (BOOL)sendData:(RTCDataBuffer *)data {
tkchin8b9ca952016-03-31 12:08:03 -0700170 return _nativeDataChannel->Send(*data.nativeDataBuffer);
hjone373dc22016-01-22 14:04:27 -0800171}
172
173- (NSString *)description {
174 return [NSString stringWithFormat:@"RTCDataChannel:\n%ld\n%@\n%@",
hjona2f77982016-03-04 07:09:09 -0800175 (long)self.channelId,
hjone373dc22016-01-22 14:04:27 -0800176 self.label,
177 [[self class]
178 stringForState:self.readyState]];
179}
180
181#pragma mark - Private
182
183- (instancetype)initWithNativeDataChannel:
184 (rtc::scoped_refptr<webrtc::DataChannelInterface>)nativeDataChannel {
185 NSParameterAssert(nativeDataChannel);
186 if (self = [super init]) {
tkchin8b9ca952016-03-31 12:08:03 -0700187 _nativeDataChannel = nativeDataChannel;
hjone373dc22016-01-22 14:04:27 -0800188 _observer.reset(new webrtc::DataChannelDelegateAdapter(self));
189 }
190 return self;
191}
192
193+ (webrtc::DataChannelInterface::DataState)
194 nativeDataChannelStateForState:(RTCDataChannelState)state {
195 switch (state) {
196 case RTCDataChannelStateConnecting:
197 return webrtc::DataChannelInterface::DataState::kConnecting;
198 case RTCDataChannelStateOpen:
199 return webrtc::DataChannelInterface::DataState::kOpen;
200 case RTCDataChannelStateClosing:
201 return webrtc::DataChannelInterface::DataState::kClosing;
202 case RTCDataChannelStateClosed:
203 return webrtc::DataChannelInterface::DataState::kClosed;
204 }
205}
206
207+ (RTCDataChannelState)dataChannelStateForNativeState:
208 (webrtc::DataChannelInterface::DataState)nativeState {
209 switch (nativeState) {
210 case webrtc::DataChannelInterface::DataState::kConnecting:
211 return RTCDataChannelStateConnecting;
212 case webrtc::DataChannelInterface::DataState::kOpen:
213 return RTCDataChannelStateOpen;
214 case webrtc::DataChannelInterface::DataState::kClosing:
215 return RTCDataChannelStateClosing;
216 case webrtc::DataChannelInterface::DataState::kClosed:
217 return RTCDataChannelStateClosed;
218 }
219}
220
221+ (NSString *)stringForState:(RTCDataChannelState)state {
222 switch (state) {
223 case RTCDataChannelStateConnecting:
224 return @"Connecting";
225 case RTCDataChannelStateOpen:
226 return @"Open";
227 case RTCDataChannelStateClosing:
228 return @"Closing";
229 case RTCDataChannelStateClosed:
230 return @"Closed";
231 }
232}
233
234@end