d36b713c478998095befb4266a2881a6e68b01bc
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.Remoting / WebRTC / WebRTCDataChannel.cs
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.ComponentModel;
19 using System.Diagnostics;
20 using Tizen.Applications;
21 using static Interop;
22
23 namespace Tizen.Multimedia.Remoting
24 {
25     /// <summary>
26     /// Provides the ability to control WebRTC data channel.
27     /// </summary>
28     /// <since_tizen> 9 </since_tizen>
29     public partial class WebRTCDataChannel : IDisposable
30     {
31         private readonly IntPtr _handle;
32
33         /// <summary>
34         /// Initializes a new instance of the <see cref="WebRTCDataChannel"/> class.
35         /// </summary>
36         /// <param name="webRtc">The owner of this WebRTCDataChannel.</param>
37         /// <param name="label">The name of this data channel.</param>
38         /// <exception cref="ArgumentNullException">The webRtc or label is null.</exception>
39         /// <since_tizen> 9 </since_tizen>
40         public WebRTCDataChannel(WebRTC webRtc, string label)
41             : this(webRtc, label, null)
42         {
43         }
44
45         /// <summary>
46         /// Initializes a new instance of the <see cref="WebRTCDataChannel"/> class.
47         /// </summary>
48         /// <remarks>
49         /// The bundle is similar format as the RTCDataChannelInit members outlined https://www.w3.org/TR/webrtc/#dom-rtcdatachannelinit.<br/>
50         /// The following attributes can be set to options by using <see cref="Bundle"/> API:<br/>
51         /// 'ordered' of type bool            : Whether the channel will send data with guaranteed ordering. The default value is true.<br/>
52         /// 'max-packet-lifetime' of type int : The time in milliseconds to attempt transmitting unacknowledged data. -1 for unset. The default value is -1.<br/>
53         /// 'max-retransmits' of type int     : The number of times data will be attempted to be transmitted without acknowledgement before dropping. The default value is -1.<br/>
54         /// 'protocol' of type string         : The subprotocol used by this channel. The default value is NULL.<br/>
55         /// 'id' of type int                  : Override the default identifier selection of this channel. The default value is -1.<br/>
56         /// 'priority' of type int            : The priority to use for this channel(1:very low, 2:low, 3:medium, 4:high). The default value is 2.<br/>
57         /// </remarks>
58         /// <param name="webRtc">The owner of this WebRTCDataChannel.</param>
59         /// <param name="label">The name of this data channel.</param>
60         /// <param name="bundle">The data channel option.</param>
61         /// <exception cref="ArgumentNullException">The webRtc or label is null.</exception>
62         /// <since_tizen> 9 </since_tizen>
63         public WebRTCDataChannel(WebRTC webRtc, string label, Bundle bundle)
64         {
65             if (webRtc == null)
66             {
67                 throw new ArgumentNullException(nameof(webRtc), "WebRTC is not created successfully.");
68             }
69
70             if (string.IsNullOrEmpty(label))
71             {
72                 throw new ArgumentNullException(nameof(label), "label is null.");
73             }
74
75             var bundle_ = bundle?.SafeBundleHandle ?? new SafeBundleHandle();
76             NativeDataChannel.Create(webRtc.Handle, label, bundle_, out _handle).
77                 ThrowIfFailed("Failed to create webrtc data channel");
78
79             Debug.Assert(_handle != null);
80
81             Label = label;
82         }
83
84         internal WebRTCDataChannel(IntPtr dataChannelHandle)
85         {
86             if (dataChannelHandle == IntPtr.Zero)
87             {
88                 throw new ArgumentNullException(nameof(dataChannelHandle),
89                     "WebRTC is not created successfully in native");
90             }
91
92             _handle = dataChannelHandle;
93
94             NativeDataChannel.GetLabel(_handle, out string label).
95                 ThrowIfFailed("Failed to get label");
96
97             Label = label;
98         }
99
100         private IntPtr Handle
101         {
102             get
103             {
104                 ValidateNotDisposed();
105                 return _handle;
106             }
107         }
108
109         /// <summary>
110         /// Gets the label of this data channel.
111         /// </summary>
112         /// <value>The label.</value>
113         /// <since_tizen> 9 </since_tizen>
114         public string Label { get; }
115
116         /// <summary>
117         /// Gets the amount of buffered data.
118         /// </summary>
119         /// <value>The buffered amount in bytes.</value>
120         /// <since_tizen> 10 </since_tizen>
121         public uint BufferedAmount
122         {
123             get
124             {
125                 ValidateNotDisposed();
126
127                 NativeDataChannel.GetBufferedAmount(Handle, out uint amount).
128                     ThrowIfFailed("Failed to get buffered amount");
129
130                 return amount;
131             }
132         }
133
134         private uint? _bufferThreshold;
135         /// <summary>
136         /// Gets or sets the threshold of data channel buffered amount.<br/>
137         /// If the amount of buffered data is lower than threshold value, <see cref="BufferedAmountLow"/> will be occurred.<br/>
138         /// The default value is 0, which means <see cref="BufferedAmountLow"/> is disabled and will not be raised.
139         /// </summary>
140         /// <since_tizen> 10 </since_tizen>
141         public uint BufferedAmountLowThreshold
142         {
143             get
144             {
145                 ValidateNotDisposed();
146
147                 if (!_bufferThreshold.HasValue)
148                 {
149                     NativeDataChannel.GetBufferedAmountLowThreshold(Handle, out uint threshold).
150                         ThrowIfFailed("Failed to get buffer threshold value");
151
152                     _bufferThreshold = threshold;
153                 }
154
155                 return _bufferThreshold.Value;
156             }
157             set
158             {
159                 ValidateNotDisposed();
160
161                 _bufferThreshold = value;
162
163                 RegisterDataChannelBufferedAmountLowThresholdCallback();
164             }
165         }
166
167         /// <summary>
168         /// Sends a string data across the data channel to the remote peer.
169         /// </summary>
170         /// <param name="data">The string data to send</param>
171         /// <exception cref="ObjectDisposedException">The WebRTCDataChannel has already been disposed.</exception>
172         /// <since_tizen> 9 </since_tizen>
173         public void Send(string data)
174         {
175             ValidateNotDisposed();
176
177             NativeDataChannel.SendString(Handle, data).
178                 ThrowIfFailed("Failed to send string data");
179         }
180
181         /// <summary>
182         /// Sends byte data across the data channel to the remote peer.
183         /// </summary>
184         /// <param name="data">The byte data to send</param>
185         /// <exception cref="ObjectDisposedException">The WebRTCDataChannel has already been disposed.</exception>
186         /// <since_tizen> 9 </since_tizen>
187         public void Send(byte[] data)
188         {
189             ValidateNotDisposed();
190
191             if (data == null)
192             {
193                 throw new ArgumentNullException(nameof(data), "data is null");
194             }
195
196             NativeDataChannel.SendBytes(Handle, data, (uint)data.Length).
197                 ThrowIfFailed("Failed to send bytes data");
198         }
199
200         #region Dispose support
201         private bool _disposed;
202
203         /// <summary>
204         /// Releases all resources used by the current instance.
205         /// </summary>
206         /// <since_tizen> 9 </since_tizen>
207         public void Dispose()
208         {
209             Dispose(true);
210             GC.SuppressFinalize(this);
211         }
212
213         /// <summary>
214         /// Releases the unmanaged resources used by the <see cref="WebRTCDataChannel"/>.
215         /// </summary>
216         /// <param name="disposing">
217         /// true to release both managed and unmanaged resources;
218         /// false to release only unmanaged resources.
219         /// </param>
220         [EditorBrowsable(EditorBrowsableState.Never)]
221         protected virtual void Dispose(bool disposing)
222         {
223             if (_disposed || !disposing)
224             {
225                 return;
226             }
227
228             if (_handle != null)
229             {
230                 NativeDataChannel.Destroy(_handle);
231                 _disposed = true;
232             }
233         }
234
235         private void ValidateNotDisposed()
236         {
237             if (_disposed)
238             {
239                 Log.Warn(WebRTCLog.Tag, "WebRTCDataChannel was disposed");
240                 throw new ObjectDisposedException(nameof(WebRTCDataChannel));
241             }
242         }
243         #endregion Dispose support
244     }
245 }