blob: 6cfa5623c4b3df572405eb2e48789a802c92c7fe [file] [log] [blame]
tkchin@webrtc.orgff273322014-04-30 18:32:33 +00001/*
2 * libjingle
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00003 * Copyright 2014 Google Inc.
tkchin@webrtc.orgff273322014-04-30 18:32:33 +00004 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#if !defined(__has_feature) || !__has_feature(objc_arc)
29#error "This file requires ARC support."
30#endif
31
32#import "RTCDataChannel+Internal.h"
33
kwiberg84cc9182016-03-11 22:12:57 -080034#include <memory>
35
Henrik Kjellander15583c12016-02-10 10:53:12 +010036#include "webrtc/api/datachannelinterface.h"
tkchin@webrtc.orgff273322014-04-30 18:32:33 +000037
38namespace webrtc {
39
40class RTCDataChannelObserver : public DataChannelObserver {
41 public:
42 RTCDataChannelObserver(RTCDataChannel* channel) { _channel = channel; }
43
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000044 void OnStateChange() override {
tkchin@webrtc.orgff273322014-04-30 18:32:33 +000045 [_channel.delegate channelDidChangeState:_channel];
46 }
47
Peter Boström0c4e06b2015-10-07 12:23:21 +020048 void OnBufferedAmountChange(uint64_t previousAmount) override {
bemasc0edd50c2015-07-01 13:34:33 -070049 RTCDataChannel* channel = _channel;
50 id<RTCDataChannelDelegate> delegate = channel.delegate;
51 if ([delegate
52 respondsToSelector:@selector(channel:didChangeBufferedAmount:)]) {
53 [delegate channel:channel didChangeBufferedAmount:previousAmount];
54 }
55 }
56
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000057 void OnMessage(const DataBuffer& buffer) override {
tkchin@webrtc.orgff273322014-04-30 18:32:33 +000058 if (!_channel.delegate) {
59 return;
60 }
61 RTCDataBuffer* dataBuffer =
62 [[RTCDataBuffer alloc] initWithDataBuffer:buffer];
63 [_channel.delegate channel:_channel didReceiveMessageWithBuffer:dataBuffer];
64 }
65
66 private:
67 __weak RTCDataChannel* _channel;
68};
69}
70
henrika1d34fe92015-06-16 10:04:20 +020071// TODO(henrika): move to shared location.
72// See https://code.google.com/p/webrtc/issues/detail?id=4773 for details.
tkchin@webrtc.orgff273322014-04-30 18:32:33 +000073NSString* NSStringFromStdString(const std::string& stdString) {
74 // std::string may contain null termination character so we construct
75 // using length.
76 return [[NSString alloc] initWithBytes:stdString.data()
77 length:stdString.length()
78 encoding:NSUTF8StringEncoding];
79}
80
81std::string StdStringFromNSString(NSString* nsString) {
82 NSData* charData = [nsString dataUsingEncoding:NSUTF8StringEncoding];
83 return std::string(reinterpret_cast<const char*>([charData bytes]),
84 [charData length]);
85}
86
87@implementation RTCDataChannelInit {
88 webrtc::DataChannelInit _dataChannelInit;
89}
90
91- (BOOL)isOrdered {
92 return _dataChannelInit.ordered;
93}
94
95- (void)setIsOrdered:(BOOL)isOrdered {
96 _dataChannelInit.ordered = isOrdered;
97}
98
99- (NSInteger)maxRetransmitTime {
100 return _dataChannelInit.maxRetransmitTime;
101}
102
103- (void)setMaxRetransmitTime:(NSInteger)maxRetransmitTime {
104 _dataChannelInit.maxRetransmitTime = maxRetransmitTime;
105}
106
107- (NSInteger)maxRetransmits {
108 return _dataChannelInit.maxRetransmits;
109}
110
111- (void)setMaxRetransmits:(NSInteger)maxRetransmits {
112 _dataChannelInit.maxRetransmits = maxRetransmits;
113}
114
115- (NSString*)protocol {
116 return NSStringFromStdString(_dataChannelInit.protocol);
117}
118
119- (void)setProtocol:(NSString*)protocol {
120 _dataChannelInit.protocol = StdStringFromNSString(protocol);
121}
122
123- (BOOL)isNegotiated {
124 return _dataChannelInit.negotiated;
125}
126
127- (void)setIsNegotiated:(BOOL)isNegotiated {
128 _dataChannelInit.negotiated = isNegotiated;
129}
130
131- (NSInteger)streamId {
132 return _dataChannelInit.id;
133}
134
135- (void)setStreamId:(NSInteger)streamId {
136 _dataChannelInit.id = streamId;
137}
138
139@end
140
141@implementation RTCDataChannelInit (Internal)
142
143- (const webrtc::DataChannelInit*)dataChannelInit {
144 return &_dataChannelInit;
145}
146
147@end
148
149@implementation RTCDataBuffer {
kwiberg84cc9182016-03-11 22:12:57 -0800150 std::unique_ptr<webrtc::DataBuffer> _dataBuffer;
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000151}
152
153- (instancetype)initWithData:(NSData*)data isBinary:(BOOL)isBinary {
154 NSAssert(data, @"data cannot be nil");
155 if (self = [super init]) {
jbaucheec21bd2016-03-20 06:15:43 -0700156 rtc::CopyOnWriteBuffer buffer(
157 reinterpret_cast<const uint8_t*>([data bytes]), [data length]);
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000158 _dataBuffer.reset(new webrtc::DataBuffer(buffer, isBinary));
159 }
160 return self;
161}
162
163- (NSData*)data {
164 return [NSData dataWithBytes:_dataBuffer->data.data()
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000165 length:_dataBuffer->data.size()];
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000166}
167
168- (BOOL)isBinary {
169 return _dataBuffer->binary;
170}
171
172@end
173
174@implementation RTCDataBuffer (Internal)
175
176- (instancetype)initWithDataBuffer:(const webrtc::DataBuffer&)buffer {
177 if (self = [super init]) {
178 _dataBuffer.reset(new webrtc::DataBuffer(buffer));
179 }
180 return self;
181}
182
183- (const webrtc::DataBuffer*)dataBuffer {
184 return _dataBuffer.get();
185}
186
187@end
188
189@implementation RTCDataChannel {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000190 rtc::scoped_refptr<webrtc::DataChannelInterface> _dataChannel;
kwiberg84cc9182016-03-11 22:12:57 -0800191 std::unique_ptr<webrtc::RTCDataChannelObserver> _observer;
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000192 BOOL _isObserverRegistered;
193}
194
Zeke Chin48253562015-03-31 11:06:26 -0700195- (void)dealloc {
196 // Handles unregistering the observer properly. We need to do this because
197 // there may still be other references to the underlying data channel.
198 self.delegate = nil;
199}
200
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000201- (NSString*)label {
202 return NSStringFromStdString(_dataChannel->label());
203}
204
205- (BOOL)isReliable {
206 return _dataChannel->reliable();
207}
208
209- (BOOL)isOrdered {
210 return _dataChannel->ordered();
211}
212
213- (NSUInteger)maxRetransmitTimeMs {
214 return _dataChannel->maxRetransmitTime();
215}
216
217- (NSUInteger)maxRetransmits {
218 return _dataChannel->maxRetransmits();
219}
220
221- (NSString*)protocol {
222 return NSStringFromStdString(_dataChannel->protocol());
223}
224
225- (BOOL)isNegotiated {
226 return _dataChannel->negotiated();
227}
228
229- (NSInteger)streamId {
230 return _dataChannel->id();
231}
232
233- (RTCDataChannelState)state {
234 switch (_dataChannel->state()) {
235 case webrtc::DataChannelInterface::DataState::kConnecting:
236 return kRTCDataChannelStateConnecting;
237 case webrtc::DataChannelInterface::DataState::kOpen:
238 return kRTCDataChannelStateOpen;
239 case webrtc::DataChannelInterface::DataState::kClosing:
240 return kRTCDataChannelStateClosing;
241 case webrtc::DataChannelInterface::DataState::kClosed:
242 return kRTCDataChannelStateClosed;
243 }
244}
245
246- (NSUInteger)bufferedAmount {
247 return _dataChannel->buffered_amount();
248}
249
250- (void)setDelegate:(id<RTCDataChannelDelegate>)delegate {
251 if (_delegate == delegate) {
252 return;
253 }
254 if (_isObserverRegistered) {
255 _dataChannel->UnregisterObserver();
256 _isObserverRegistered = NO;
257 }
258 _delegate = delegate;
259 if (_delegate) {
260 _dataChannel->RegisterObserver(_observer.get());
261 _isObserverRegistered = YES;
262 }
263}
264
265- (void)close {
266 _dataChannel->Close();
267}
268
269- (BOOL)sendData:(RTCDataBuffer*)data {
270 return _dataChannel->Send(*data.dataBuffer);
271}
272
273@end
274
275@implementation RTCDataChannel (Internal)
276
277- (instancetype)initWithDataChannel:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000278 (rtc::scoped_refptr<webrtc::DataChannelInterface>)
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000279 dataChannel {
280 NSAssert(dataChannel != NULL, @"dataChannel cannot be NULL");
281 if (self = [super init]) {
282 _dataChannel = dataChannel;
283 _observer.reset(new webrtc::RTCDataChannelObserver(self));
284 }
285 return self;
286}
287
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000288- (rtc::scoped_refptr<webrtc::DataChannelInterface>)dataChannel {
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000289 return _dataChannel;
290}
291
292@end