blob: 00d51b10eeac6009edfa534915a5a2192ba7c005 [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
Henrik Kjellander15583c12016-02-10 10:53:12 +010034#include "webrtc/api/datachannelinterface.h"
kwiberg8fb35572016-02-11 13:36:43 -080035#include "webrtc/base/scoped_ptr.h"
tkchin@webrtc.orgff273322014-04-30 18:32:33 +000036
37namespace webrtc {
38
39class RTCDataChannelObserver : public DataChannelObserver {
40 public:
41 RTCDataChannelObserver(RTCDataChannel* channel) { _channel = channel; }
42
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000043 void OnStateChange() override {
tkchin@webrtc.orgff273322014-04-30 18:32:33 +000044 [_channel.delegate channelDidChangeState:_channel];
45 }
46
Peter Boström0c4e06b2015-10-07 12:23:21 +020047 void OnBufferedAmountChange(uint64_t previousAmount) override {
bemasc0edd50c2015-07-01 13:34:33 -070048 RTCDataChannel* channel = _channel;
49 id<RTCDataChannelDelegate> delegate = channel.delegate;
50 if ([delegate
51 respondsToSelector:@selector(channel:didChangeBufferedAmount:)]) {
52 [delegate channel:channel didChangeBufferedAmount:previousAmount];
53 }
54 }
55
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000056 void OnMessage(const DataBuffer& buffer) override {
tkchin@webrtc.orgff273322014-04-30 18:32:33 +000057 if (!_channel.delegate) {
58 return;
59 }
60 RTCDataBuffer* dataBuffer =
61 [[RTCDataBuffer alloc] initWithDataBuffer:buffer];
62 [_channel.delegate channel:_channel didReceiveMessageWithBuffer:dataBuffer];
63 }
64
65 private:
66 __weak RTCDataChannel* _channel;
67};
68}
69
henrika1d34fe92015-06-16 10:04:20 +020070// TODO(henrika): move to shared location.
71// See https://code.google.com/p/webrtc/issues/detail?id=4773 for details.
tkchin@webrtc.orgff273322014-04-30 18:32:33 +000072NSString* NSStringFromStdString(const std::string& stdString) {
73 // std::string may contain null termination character so we construct
74 // using length.
75 return [[NSString alloc] initWithBytes:stdString.data()
76 length:stdString.length()
77 encoding:NSUTF8StringEncoding];
78}
79
80std::string StdStringFromNSString(NSString* nsString) {
81 NSData* charData = [nsString dataUsingEncoding:NSUTF8StringEncoding];
82 return std::string(reinterpret_cast<const char*>([charData bytes]),
83 [charData length]);
84}
85
86@implementation RTCDataChannelInit {
87 webrtc::DataChannelInit _dataChannelInit;
88}
89
90- (BOOL)isOrdered {
91 return _dataChannelInit.ordered;
92}
93
94- (void)setIsOrdered:(BOOL)isOrdered {
95 _dataChannelInit.ordered = isOrdered;
96}
97
98- (NSInteger)maxRetransmitTime {
99 return _dataChannelInit.maxRetransmitTime;
100}
101
102- (void)setMaxRetransmitTime:(NSInteger)maxRetransmitTime {
103 _dataChannelInit.maxRetransmitTime = maxRetransmitTime;
104}
105
106- (NSInteger)maxRetransmits {
107 return _dataChannelInit.maxRetransmits;
108}
109
110- (void)setMaxRetransmits:(NSInteger)maxRetransmits {
111 _dataChannelInit.maxRetransmits = maxRetransmits;
112}
113
114- (NSString*)protocol {
115 return NSStringFromStdString(_dataChannelInit.protocol);
116}
117
118- (void)setProtocol:(NSString*)protocol {
119 _dataChannelInit.protocol = StdStringFromNSString(protocol);
120}
121
122- (BOOL)isNegotiated {
123 return _dataChannelInit.negotiated;
124}
125
126- (void)setIsNegotiated:(BOOL)isNegotiated {
127 _dataChannelInit.negotiated = isNegotiated;
128}
129
130- (NSInteger)streamId {
131 return _dataChannelInit.id;
132}
133
134- (void)setStreamId:(NSInteger)streamId {
135 _dataChannelInit.id = streamId;
136}
137
138@end
139
140@implementation RTCDataChannelInit (Internal)
141
142- (const webrtc::DataChannelInit*)dataChannelInit {
143 return &_dataChannelInit;
144}
145
146@end
147
148@implementation RTCDataBuffer {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000149 rtc::scoped_ptr<webrtc::DataBuffer> _dataBuffer;
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000150}
151
152- (instancetype)initWithData:(NSData*)data isBinary:(BOOL)isBinary {
153 NSAssert(data, @"data cannot be nil");
154 if (self = [super init]) {
Karl Wiberg94784372015-04-20 14:03:07 +0200155 rtc::Buffer buffer(reinterpret_cast<const uint8_t*>([data bytes]),
156 [data length]);
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000157 _dataBuffer.reset(new webrtc::DataBuffer(buffer, isBinary));
158 }
159 return self;
160}
161
162- (NSData*)data {
163 return [NSData dataWithBytes:_dataBuffer->data.data()
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000164 length:_dataBuffer->data.size()];
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000165}
166
167- (BOOL)isBinary {
168 return _dataBuffer->binary;
169}
170
171@end
172
173@implementation RTCDataBuffer (Internal)
174
175- (instancetype)initWithDataBuffer:(const webrtc::DataBuffer&)buffer {
176 if (self = [super init]) {
177 _dataBuffer.reset(new webrtc::DataBuffer(buffer));
178 }
179 return self;
180}
181
182- (const webrtc::DataBuffer*)dataBuffer {
183 return _dataBuffer.get();
184}
185
186@end
187
188@implementation RTCDataChannel {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000189 rtc::scoped_refptr<webrtc::DataChannelInterface> _dataChannel;
190 rtc::scoped_ptr<webrtc::RTCDataChannelObserver> _observer;
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000191 BOOL _isObserverRegistered;
192}
193
Zeke Chin48253562015-03-31 11:06:26 -0700194- (void)dealloc {
195 // Handles unregistering the observer properly. We need to do this because
196 // there may still be other references to the underlying data channel.
197 self.delegate = nil;
198}
199
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000200- (NSString*)label {
201 return NSStringFromStdString(_dataChannel->label());
202}
203
204- (BOOL)isReliable {
205 return _dataChannel->reliable();
206}
207
208- (BOOL)isOrdered {
209 return _dataChannel->ordered();
210}
211
212- (NSUInteger)maxRetransmitTimeMs {
213 return _dataChannel->maxRetransmitTime();
214}
215
216- (NSUInteger)maxRetransmits {
217 return _dataChannel->maxRetransmits();
218}
219
220- (NSString*)protocol {
221 return NSStringFromStdString(_dataChannel->protocol());
222}
223
224- (BOOL)isNegotiated {
225 return _dataChannel->negotiated();
226}
227
228- (NSInteger)streamId {
229 return _dataChannel->id();
230}
231
232- (RTCDataChannelState)state {
233 switch (_dataChannel->state()) {
234 case webrtc::DataChannelInterface::DataState::kConnecting:
235 return kRTCDataChannelStateConnecting;
236 case webrtc::DataChannelInterface::DataState::kOpen:
237 return kRTCDataChannelStateOpen;
238 case webrtc::DataChannelInterface::DataState::kClosing:
239 return kRTCDataChannelStateClosing;
240 case webrtc::DataChannelInterface::DataState::kClosed:
241 return kRTCDataChannelStateClosed;
242 }
243}
244
245- (NSUInteger)bufferedAmount {
246 return _dataChannel->buffered_amount();
247}
248
249- (void)setDelegate:(id<RTCDataChannelDelegate>)delegate {
250 if (_delegate == delegate) {
251 return;
252 }
253 if (_isObserverRegistered) {
254 _dataChannel->UnregisterObserver();
255 _isObserverRegistered = NO;
256 }
257 _delegate = delegate;
258 if (_delegate) {
259 _dataChannel->RegisterObserver(_observer.get());
260 _isObserverRegistered = YES;
261 }
262}
263
264- (void)close {
265 _dataChannel->Close();
266}
267
268- (BOOL)sendData:(RTCDataBuffer*)data {
269 return _dataChannel->Send(*data.dataBuffer);
270}
271
272@end
273
274@implementation RTCDataChannel (Internal)
275
276- (instancetype)initWithDataChannel:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000277 (rtc::scoped_refptr<webrtc::DataChannelInterface>)
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000278 dataChannel {
279 NSAssert(dataChannel != NULL, @"dataChannel cannot be NULL");
280 if (self = [super init]) {
281 _dataChannel = dataChannel;
282 _observer.reset(new webrtc::RTCDataChannelObserver(self));
283 }
284 return self;
285}
286
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000287- (rtc::scoped_refptr<webrtc::DataChannelInterface>)dataChannel {
tkchin@webrtc.orgff273322014-04-30 18:32:33 +0000288 return _dataChannel;
289}
290
291@end