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