blob: f7ca288f151f06ea30d274653114d10eb49e9a12 [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
11#import "RTCDataChannel.h"
12
13#import "webrtc/api/objc/RTCDataChannel+Private.h"
14#import "webrtc/base/objc/NSString+StdString.h"
15
16namespace webrtc {
17
18class DataChannelDelegateAdapter : public DataChannelObserver {
19 public:
20 DataChannelDelegateAdapter(RTCDataChannel *channel) { channel_ = channel; }
21
22 void OnStateChange() override {
23 [channel_.delegate dataChannelDidChangeState:channel_];
24 }
25
26 void OnMessage(const DataBuffer& buffer) override {
27 RTCDataBuffer *data_buffer =
28 [[RTCDataBuffer alloc] initWithNativeBuffer:buffer];
29 [channel_.delegate dataChannel:channel_
30 didReceiveMessageWithBuffer:data_buffer];
31 }
32
33 void OnBufferedAmountChange(uint64_t previousAmount) override {
34 id<RTCDataChannelDelegate> delegate = channel_.delegate;
35 if ([delegate
36 respondsToSelector:@selector(channel:didChangeBufferedAmount:)]) {
37 [delegate dataChannel:channel_ didChangeBufferedAmount:previousAmount];
38 }
39 }
40
41 private:
42 __weak RTCDataChannel *channel_;
43};
44}
45
46
47@implementation RTCDataBuffer {
48 rtc::scoped_ptr<webrtc::DataBuffer> _dataBuffer;
49}
50
51- (instancetype)initWithData:(NSData *)data isBinary:(BOOL)isBinary {
52 NSParameterAssert(data);
53 if (self = [super init]) {
54 rtc::Buffer buffer(reinterpret_cast<const uint8_t*>(data.bytes),
55 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
86@implementation RTCDataChannel {
87 rtc::scoped_refptr<webrtc::DataChannelInterface> _nativDataChannel;
88 rtc::scoped_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 self.delegate = nil;
98}
99
100- (NSString *)label {
101 return [NSString stringForStdString:_nativDataChannel->label()];
102}
103
104- (BOOL)isOrdered {
105 return _nativDataChannel->ordered();
106}
107
108- (uint16_t)maxPacketLifeTime {
109 return _nativDataChannel->maxRetransmitTime();
110}
111
112- (uint16_t)maxRetransmits {
113 return _nativDataChannel->maxRetransmits();
114}
115
116- (NSString *)protocol {
117 return [NSString stringForStdString:_nativDataChannel->protocol()];
118}
119
120- (BOOL)isNegotiated {
121 return _nativDataChannel->negotiated();
122}
123
124- (int)id {
125 return _nativDataChannel->id();
126}
127
128- (RTCDataChannelState)readyState {
129 return [[self class] dataChannelStateForNativeState:
130 _nativDataChannel->state()];
131}
132
133- (uint64_t)bufferedAmount {
134 return _nativDataChannel->buffered_amount();
135}
136
137- (void)setDelegate:(id<RTCDataChannelDelegate>)delegate {
138 if (_delegate == delegate) {
139 return;
140 }
141 if (_isObserverRegistered) {
142 _nativDataChannel->UnregisterObserver();
143 _isObserverRegistered = NO;
144 }
145 _delegate = delegate;
146 if (_delegate) {
147 _nativDataChannel->RegisterObserver(_observer.get());
148 _isObserverRegistered = YES;
149 }
150}
151
152- (void)close {
153 _nativDataChannel->Close();
154}
155
156- (BOOL)sendData:(RTCDataBuffer *)data {
157 return _nativDataChannel->Send(*data.nativeDataBuffer);
158}
159
160- (NSString *)description {
161 return [NSString stringWithFormat:@"RTCDataChannel:\n%ld\n%@\n%@",
162 (long)self.id,
163 self.label,
164 [[self class]
165 stringForState:self.readyState]];
166}
167
168#pragma mark - Private
169
170- (instancetype)initWithNativeDataChannel:
171 (rtc::scoped_refptr<webrtc::DataChannelInterface>)nativeDataChannel {
172 NSParameterAssert(nativeDataChannel);
173 if (self = [super init]) {
174 _nativDataChannel = nativeDataChannel;
175 _observer.reset(new webrtc::DataChannelDelegateAdapter(self));
176 }
177 return self;
178}
179
180+ (webrtc::DataChannelInterface::DataState)
181 nativeDataChannelStateForState:(RTCDataChannelState)state {
182 switch (state) {
183 case RTCDataChannelStateConnecting:
184 return webrtc::DataChannelInterface::DataState::kConnecting;
185 case RTCDataChannelStateOpen:
186 return webrtc::DataChannelInterface::DataState::kOpen;
187 case RTCDataChannelStateClosing:
188 return webrtc::DataChannelInterface::DataState::kClosing;
189 case RTCDataChannelStateClosed:
190 return webrtc::DataChannelInterface::DataState::kClosed;
191 }
192}
193
194+ (RTCDataChannelState)dataChannelStateForNativeState:
195 (webrtc::DataChannelInterface::DataState)nativeState {
196 switch (nativeState) {
197 case webrtc::DataChannelInterface::DataState::kConnecting:
198 return RTCDataChannelStateConnecting;
199 case webrtc::DataChannelInterface::DataState::kOpen:
200 return RTCDataChannelStateOpen;
201 case webrtc::DataChannelInterface::DataState::kClosing:
202 return RTCDataChannelStateClosing;
203 case webrtc::DataChannelInterface::DataState::kClosed:
204 return RTCDataChannelStateClosed;
205 }
206}
207
208+ (NSString *)stringForState:(RTCDataChannelState)state {
209 switch (state) {
210 case RTCDataChannelStateConnecting:
211 return @"Connecting";
212 case RTCDataChannelStateOpen:
213 return @"Open";
214 case RTCDataChannelStateClosing:
215 return @"Closing";
216 case RTCDataChannelStateClosed:
217 return @"Closed";
218 }
219}
220
221@end