xref: /aosp_15_r20/external/webrtc/sdk/objc/api/peerconnection/RTCDataChannel.mm (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker/*
2*d9f75844SAndroid Build Coastguard Worker *  Copyright 2015 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker#import "RTCDataChannel+Private.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker#import "helpers/NSString+StdString.h"
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker#include <memory>
16*d9f75844SAndroid Build Coastguard Worker
17*d9f75844SAndroid Build Coastguard Workernamespace webrtc {
18*d9f75844SAndroid Build Coastguard Worker
19*d9f75844SAndroid Build Coastguard Workerclass DataChannelDelegateAdapter : public DataChannelObserver {
20*d9f75844SAndroid Build Coastguard Worker public:
21*d9f75844SAndroid Build Coastguard Worker  DataChannelDelegateAdapter(RTC_OBJC_TYPE(RTCDataChannel) * channel) { channel_ = channel; }
22*d9f75844SAndroid Build Coastguard Worker
23*d9f75844SAndroid Build Coastguard Worker  void OnStateChange() override {
24*d9f75844SAndroid Build Coastguard Worker    [channel_.delegate dataChannelDidChangeState:channel_];
25*d9f75844SAndroid Build Coastguard Worker  }
26*d9f75844SAndroid Build Coastguard Worker
27*d9f75844SAndroid Build Coastguard Worker  void OnMessage(const DataBuffer& buffer) override {
28*d9f75844SAndroid Build Coastguard Worker    RTC_OBJC_TYPE(RTCDataBuffer) *data_buffer =
29*d9f75844SAndroid Build Coastguard Worker        [[RTC_OBJC_TYPE(RTCDataBuffer) alloc] initWithNativeBuffer:buffer];
30*d9f75844SAndroid Build Coastguard Worker    [channel_.delegate dataChannel:channel_
31*d9f75844SAndroid Build Coastguard Worker       didReceiveMessageWithBuffer:data_buffer];
32*d9f75844SAndroid Build Coastguard Worker  }
33*d9f75844SAndroid Build Coastguard Worker
34*d9f75844SAndroid Build Coastguard Worker  void OnBufferedAmountChange(uint64_t previousAmount) override {
35*d9f75844SAndroid Build Coastguard Worker    id<RTC_OBJC_TYPE(RTCDataChannelDelegate)> delegate = channel_.delegate;
36*d9f75844SAndroid Build Coastguard Worker    SEL sel = @selector(dataChannel:didChangeBufferedAmount:);
37*d9f75844SAndroid Build Coastguard Worker    if ([delegate respondsToSelector:sel]) {
38*d9f75844SAndroid Build Coastguard Worker      [delegate dataChannel:channel_ didChangeBufferedAmount:previousAmount];
39*d9f75844SAndroid Build Coastguard Worker    }
40*d9f75844SAndroid Build Coastguard Worker  }
41*d9f75844SAndroid Build Coastguard Worker
42*d9f75844SAndroid Build Coastguard Worker private:
43*d9f75844SAndroid Build Coastguard Worker  __weak RTC_OBJC_TYPE(RTCDataChannel) * channel_;
44*d9f75844SAndroid Build Coastguard Worker};
45*d9f75844SAndroid Build Coastguard Worker}
46*d9f75844SAndroid Build Coastguard Worker
47*d9f75844SAndroid Build Coastguard Worker@implementation RTC_OBJC_TYPE (RTCDataBuffer) {
48*d9f75844SAndroid Build Coastguard Worker  std::unique_ptr<webrtc::DataBuffer> _dataBuffer;
49*d9f75844SAndroid Build Coastguard Worker}
50*d9f75844SAndroid Build Coastguard Worker
51*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithData:(NSData *)data isBinary:(BOOL)isBinary {
52*d9f75844SAndroid Build Coastguard Worker  NSParameterAssert(data);
53*d9f75844SAndroid Build Coastguard Worker  if (self = [super init]) {
54*d9f75844SAndroid Build Coastguard Worker    rtc::CopyOnWriteBuffer buffer(
55*d9f75844SAndroid Build Coastguard Worker        reinterpret_cast<const uint8_t*>(data.bytes), data.length);
56*d9f75844SAndroid Build Coastguard Worker    _dataBuffer.reset(new webrtc::DataBuffer(buffer, isBinary));
57*d9f75844SAndroid Build Coastguard Worker  }
58*d9f75844SAndroid Build Coastguard Worker  return self;
59*d9f75844SAndroid Build Coastguard Worker}
60*d9f75844SAndroid Build Coastguard Worker
61*d9f75844SAndroid Build Coastguard Worker- (NSData *)data {
62*d9f75844SAndroid Build Coastguard Worker  return [NSData dataWithBytes:_dataBuffer->data.data()
63*d9f75844SAndroid Build Coastguard Worker                        length:_dataBuffer->data.size()];
64*d9f75844SAndroid Build Coastguard Worker}
65*d9f75844SAndroid Build Coastguard Worker
66*d9f75844SAndroid Build Coastguard Worker- (BOOL)isBinary {
67*d9f75844SAndroid Build Coastguard Worker  return _dataBuffer->binary;
68*d9f75844SAndroid Build Coastguard Worker}
69*d9f75844SAndroid Build Coastguard Worker
70*d9f75844SAndroid Build Coastguard Worker#pragma mark - Private
71*d9f75844SAndroid Build Coastguard Worker
72*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithNativeBuffer:(const webrtc::DataBuffer&)nativeBuffer {
73*d9f75844SAndroid Build Coastguard Worker  if (self = [super init]) {
74*d9f75844SAndroid Build Coastguard Worker    _dataBuffer.reset(new webrtc::DataBuffer(nativeBuffer));
75*d9f75844SAndroid Build Coastguard Worker  }
76*d9f75844SAndroid Build Coastguard Worker  return self;
77*d9f75844SAndroid Build Coastguard Worker}
78*d9f75844SAndroid Build Coastguard Worker
79*d9f75844SAndroid Build Coastguard Worker- (const webrtc::DataBuffer *)nativeDataBuffer {
80*d9f75844SAndroid Build Coastguard Worker  return _dataBuffer.get();
81*d9f75844SAndroid Build Coastguard Worker}
82*d9f75844SAndroid Build Coastguard Worker
83*d9f75844SAndroid Build Coastguard Worker@end
84*d9f75844SAndroid Build Coastguard Worker
85*d9f75844SAndroid Build Coastguard Worker@implementation RTC_OBJC_TYPE (RTCDataChannel) {
86*d9f75844SAndroid Build Coastguard Worker  RTC_OBJC_TYPE(RTCPeerConnectionFactory) * _factory;
87*d9f75844SAndroid Build Coastguard Worker  rtc::scoped_refptr<webrtc::DataChannelInterface> _nativeDataChannel;
88*d9f75844SAndroid Build Coastguard Worker  std::unique_ptr<webrtc::DataChannelDelegateAdapter> _observer;
89*d9f75844SAndroid Build Coastguard Worker  BOOL _isObserverRegistered;
90*d9f75844SAndroid Build Coastguard Worker}
91*d9f75844SAndroid Build Coastguard Worker
92*d9f75844SAndroid Build Coastguard Worker@synthesize delegate = _delegate;
93*d9f75844SAndroid Build Coastguard Worker
94*d9f75844SAndroid Build Coastguard Worker- (void)dealloc {
95*d9f75844SAndroid Build Coastguard Worker  // Handles unregistering the observer properly. We need to do this because
96*d9f75844SAndroid Build Coastguard Worker  // there may still be other references to the underlying data channel.
97*d9f75844SAndroid Build Coastguard Worker  _nativeDataChannel->UnregisterObserver();
98*d9f75844SAndroid Build Coastguard Worker}
99*d9f75844SAndroid Build Coastguard Worker
100*d9f75844SAndroid Build Coastguard Worker- (NSString *)label {
101*d9f75844SAndroid Build Coastguard Worker  return [NSString stringForStdString:_nativeDataChannel->label()];
102*d9f75844SAndroid Build Coastguard Worker}
103*d9f75844SAndroid Build Coastguard Worker
104*d9f75844SAndroid Build Coastguard Worker- (BOOL)isReliable {
105*d9f75844SAndroid Build Coastguard Worker  return _nativeDataChannel->reliable();
106*d9f75844SAndroid Build Coastguard Worker}
107*d9f75844SAndroid Build Coastguard Worker
108*d9f75844SAndroid Build Coastguard Worker- (BOOL)isOrdered {
109*d9f75844SAndroid Build Coastguard Worker  return _nativeDataChannel->ordered();
110*d9f75844SAndroid Build Coastguard Worker}
111*d9f75844SAndroid Build Coastguard Worker
112*d9f75844SAndroid Build Coastguard Worker- (NSUInteger)maxRetransmitTime {
113*d9f75844SAndroid Build Coastguard Worker  return self.maxPacketLifeTime;
114*d9f75844SAndroid Build Coastguard Worker}
115*d9f75844SAndroid Build Coastguard Worker
116*d9f75844SAndroid Build Coastguard Worker- (uint16_t)maxPacketLifeTime {
117*d9f75844SAndroid Build Coastguard Worker  return _nativeDataChannel->maxRetransmitTime();
118*d9f75844SAndroid Build Coastguard Worker}
119*d9f75844SAndroid Build Coastguard Worker
120*d9f75844SAndroid Build Coastguard Worker- (uint16_t)maxRetransmits {
121*d9f75844SAndroid Build Coastguard Worker  return _nativeDataChannel->maxRetransmits();
122*d9f75844SAndroid Build Coastguard Worker}
123*d9f75844SAndroid Build Coastguard Worker
124*d9f75844SAndroid Build Coastguard Worker- (NSString *)protocol {
125*d9f75844SAndroid Build Coastguard Worker  return [NSString stringForStdString:_nativeDataChannel->protocol()];
126*d9f75844SAndroid Build Coastguard Worker}
127*d9f75844SAndroid Build Coastguard Worker
128*d9f75844SAndroid Build Coastguard Worker- (BOOL)isNegotiated {
129*d9f75844SAndroid Build Coastguard Worker  return _nativeDataChannel->negotiated();
130*d9f75844SAndroid Build Coastguard Worker}
131*d9f75844SAndroid Build Coastguard Worker
132*d9f75844SAndroid Build Coastguard Worker- (NSInteger)streamId {
133*d9f75844SAndroid Build Coastguard Worker  return self.channelId;
134*d9f75844SAndroid Build Coastguard Worker}
135*d9f75844SAndroid Build Coastguard Worker
136*d9f75844SAndroid Build Coastguard Worker- (int)channelId {
137*d9f75844SAndroid Build Coastguard Worker  return _nativeDataChannel->id();
138*d9f75844SAndroid Build Coastguard Worker}
139*d9f75844SAndroid Build Coastguard Worker
140*d9f75844SAndroid Build Coastguard Worker- (RTCDataChannelState)readyState {
141*d9f75844SAndroid Build Coastguard Worker  return [[self class] dataChannelStateForNativeState:
142*d9f75844SAndroid Build Coastguard Worker      _nativeDataChannel->state()];
143*d9f75844SAndroid Build Coastguard Worker}
144*d9f75844SAndroid Build Coastguard Worker
145*d9f75844SAndroid Build Coastguard Worker- (uint64_t)bufferedAmount {
146*d9f75844SAndroid Build Coastguard Worker  return _nativeDataChannel->buffered_amount();
147*d9f75844SAndroid Build Coastguard Worker}
148*d9f75844SAndroid Build Coastguard Worker
149*d9f75844SAndroid Build Coastguard Worker- (void)close {
150*d9f75844SAndroid Build Coastguard Worker  _nativeDataChannel->Close();
151*d9f75844SAndroid Build Coastguard Worker}
152*d9f75844SAndroid Build Coastguard Worker
153*d9f75844SAndroid Build Coastguard Worker- (BOOL)sendData:(RTC_OBJC_TYPE(RTCDataBuffer) *)data {
154*d9f75844SAndroid Build Coastguard Worker  return _nativeDataChannel->Send(*data.nativeDataBuffer);
155*d9f75844SAndroid Build Coastguard Worker}
156*d9f75844SAndroid Build Coastguard Worker
157*d9f75844SAndroid Build Coastguard Worker- (NSString *)description {
158*d9f75844SAndroid Build Coastguard Worker  return [NSString stringWithFormat:@"RTC_OBJC_TYPE(RTCDataChannel):\n%ld\n%@\n%@",
159*d9f75844SAndroid Build Coastguard Worker                                    (long)self.channelId,
160*d9f75844SAndroid Build Coastguard Worker                                    self.label,
161*d9f75844SAndroid Build Coastguard Worker                                    [[self class] stringForState:self.readyState]];
162*d9f75844SAndroid Build Coastguard Worker}
163*d9f75844SAndroid Build Coastguard Worker
164*d9f75844SAndroid Build Coastguard Worker#pragma mark - Private
165*d9f75844SAndroid Build Coastguard Worker
166*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory
167*d9f75844SAndroid Build Coastguard Worker              nativeDataChannel:
168*d9f75844SAndroid Build Coastguard Worker                  (rtc::scoped_refptr<webrtc::DataChannelInterface>)nativeDataChannel {
169*d9f75844SAndroid Build Coastguard Worker  NSParameterAssert(nativeDataChannel);
170*d9f75844SAndroid Build Coastguard Worker  if (self = [super init]) {
171*d9f75844SAndroid Build Coastguard Worker    _factory = factory;
172*d9f75844SAndroid Build Coastguard Worker    _nativeDataChannel = nativeDataChannel;
173*d9f75844SAndroid Build Coastguard Worker    _observer.reset(new webrtc::DataChannelDelegateAdapter(self));
174*d9f75844SAndroid Build Coastguard Worker    _nativeDataChannel->RegisterObserver(_observer.get());
175*d9f75844SAndroid Build Coastguard Worker  }
176*d9f75844SAndroid Build Coastguard Worker  return self;
177*d9f75844SAndroid Build Coastguard Worker}
178*d9f75844SAndroid Build Coastguard Worker
179*d9f75844SAndroid Build Coastguard Worker+ (webrtc::DataChannelInterface::DataState)
180*d9f75844SAndroid Build Coastguard Worker    nativeDataChannelStateForState:(RTCDataChannelState)state {
181*d9f75844SAndroid Build Coastguard Worker  switch (state) {
182*d9f75844SAndroid Build Coastguard Worker    case RTCDataChannelStateConnecting:
183*d9f75844SAndroid Build Coastguard Worker      return webrtc::DataChannelInterface::DataState::kConnecting;
184*d9f75844SAndroid Build Coastguard Worker    case RTCDataChannelStateOpen:
185*d9f75844SAndroid Build Coastguard Worker      return webrtc::DataChannelInterface::DataState::kOpen;
186*d9f75844SAndroid Build Coastguard Worker    case RTCDataChannelStateClosing:
187*d9f75844SAndroid Build Coastguard Worker      return webrtc::DataChannelInterface::DataState::kClosing;
188*d9f75844SAndroid Build Coastguard Worker    case RTCDataChannelStateClosed:
189*d9f75844SAndroid Build Coastguard Worker      return webrtc::DataChannelInterface::DataState::kClosed;
190*d9f75844SAndroid Build Coastguard Worker  }
191*d9f75844SAndroid Build Coastguard Worker}
192*d9f75844SAndroid Build Coastguard Worker
193*d9f75844SAndroid Build Coastguard Worker+ (RTCDataChannelState)dataChannelStateForNativeState:
194*d9f75844SAndroid Build Coastguard Worker    (webrtc::DataChannelInterface::DataState)nativeState {
195*d9f75844SAndroid Build Coastguard Worker  switch (nativeState) {
196*d9f75844SAndroid Build Coastguard Worker    case webrtc::DataChannelInterface::DataState::kConnecting:
197*d9f75844SAndroid Build Coastguard Worker      return RTCDataChannelStateConnecting;
198*d9f75844SAndroid Build Coastguard Worker    case webrtc::DataChannelInterface::DataState::kOpen:
199*d9f75844SAndroid Build Coastguard Worker      return RTCDataChannelStateOpen;
200*d9f75844SAndroid Build Coastguard Worker    case webrtc::DataChannelInterface::DataState::kClosing:
201*d9f75844SAndroid Build Coastguard Worker      return RTCDataChannelStateClosing;
202*d9f75844SAndroid Build Coastguard Worker    case webrtc::DataChannelInterface::DataState::kClosed:
203*d9f75844SAndroid Build Coastguard Worker      return RTCDataChannelStateClosed;
204*d9f75844SAndroid Build Coastguard Worker  }
205*d9f75844SAndroid Build Coastguard Worker}
206*d9f75844SAndroid Build Coastguard Worker
207*d9f75844SAndroid Build Coastguard Worker+ (NSString *)stringForState:(RTCDataChannelState)state {
208*d9f75844SAndroid Build Coastguard Worker  switch (state) {
209*d9f75844SAndroid Build Coastguard Worker    case RTCDataChannelStateConnecting:
210*d9f75844SAndroid Build Coastguard Worker      return @"Connecting";
211*d9f75844SAndroid Build Coastguard Worker    case RTCDataChannelStateOpen:
212*d9f75844SAndroid Build Coastguard Worker      return @"Open";
213*d9f75844SAndroid Build Coastguard Worker    case RTCDataChannelStateClosing:
214*d9f75844SAndroid Build Coastguard Worker      return @"Closing";
215*d9f75844SAndroid Build Coastguard Worker    case RTCDataChannelStateClosed:
216*d9f75844SAndroid Build Coastguard Worker      return @"Closed";
217*d9f75844SAndroid Build Coastguard Worker  }
218*d9f75844SAndroid Build Coastguard Worker}
219*d9f75844SAndroid Build Coastguard Worker
220*d9f75844SAndroid Build Coastguard Worker@end
221