fcb1dc7de8eed6848ec260e438c4b42fb7670595
[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 != IntPtr.Zero);
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         /// <exception cref="ObjectDisposedException">The WebRTCDataChannel has already been disposed.</exception>
121         /// <since_tizen> 10 </since_tizen>
122         public uint BufferedAmount
123         {
124             get
125             {
126                 ValidateNotDisposed();
127
128                 NativeDataChannel.GetBufferedAmount(Handle, out uint amount).
129                     ThrowIfFailed("Failed to get buffered amount");
130
131                 return amount;
132             }
133         }
134
135         private uint? _bufferThreshold = 0;
136         /// <summary>
137         /// Gets or sets the threshold of data channel buffered amount.<br/>
138         /// If the amount of buffered data is lower than threshold value, <see cref="BufferedAmountLow"/> will be occurred.<br/>
139         /// The default value is 0, which means <see cref="BufferedAmountLow"/> is disabled and will not be raised.
140         /// </summary>
141         /// <exception cref="ObjectDisposedException">The WebRTCDataChannel has already been disposed.</exception>
142         /// <since_tizen> 10 </since_tizen>
143         public uint BufferedAmountLowThreshold
144         {
145             get
146             {
147                 ValidateNotDisposed();
148
149                 if (!_bufferThreshold.HasValue)
150                 {
151                     NativeDataChannel.GetBufferedAmountLowThreshold(Handle, out uint threshold).
152                         ThrowIfFailed("Failed to get buffer threshold value");
153
154                     _bufferThreshold = threshold;
155                 }
156
157                 return _bufferThreshold.Value;
158             }
159             set
160             {
161                 ValidateNotDisposed();
162
163                 _bufferThreshold = value;
164
165                 RegisterDataChannelBufferedAmountLowThresholdCallback();
166             }
167         }
168
169         /// <summary>
170         /// Sends a string data across the data channel to the remote peer.
171         /// </summary>
172         /// <param name="data">The string data to send</param>
173         /// <exception cref="ObjectDisposedException">The WebRTCDataChannel has already been disposed.</exception>
174         /// <since_tizen> 9 </since_tizen>
175         public void Send(string data)
176         {
177             ValidateNotDisposed();
178
179             NativeDataChannel.SendString(Handle, data).
180                 ThrowIfFailed("Failed to send string data");
181         }
182
183         /// <summary>
184         /// Sends byte data across the data channel to the remote peer.
185         /// </summary>
186         /// <param name="data">The byte data to send</param>
187         /// <exception cref="ObjectDisposedException">The WebRTCDataChannel has already been disposed.</exception>
188         /// <since_tizen> 9 </since_tizen>
189         public void Send(byte[] data)
190         {
191             ValidateNotDisposed();
192
193             if (data == null)
194             {
195                 throw new ArgumentNullException(nameof(data), "data is null");
196             }
197
198             NativeDataChannel.SendBytes(Handle, data, (uint)data.Length).
199                 ThrowIfFailed("Failed to send bytes data");
200         }
201
202         #region Dispose support
203         private bool _disposed;
204
205         /// <summary>
206         /// Releases all resources used by the current instance.
207         /// </summary>
208         /// <since_tizen> 9 </since_tizen>
209         public void Dispose()
210         {
211             Dispose(true);
212             GC.SuppressFinalize(this);
213         }
214
215         /// <summary>
216         /// Releases the unmanaged resources used by the <see cref="WebRTCDataChannel"/>.
217         /// </summary>
218         /// <param name="disposing">
219         /// true to release both managed and unmanaged resources;
220         /// false to release only unmanaged resources.
221         /// </param>
222         [EditorBrowsable(EditorBrowsableState.Never)]
223         protected virtual void Dispose(bool disposing)
224         {
225             if (_disposed || !disposing)
226             {
227                 return;
228             }
229
230             if (_handle != IntPtr.Zero)
231             {
232                 NativeDataChannel.Destroy(_handle);
233                 _disposed = true;
234             }
235         }
236
237         private void ValidateNotDisposed()
238         {
239             if (_disposed)
240             {
241                 Log.Warn(WebRTCLog.Tag, "WebRTCDataChannel was disposed");
242                 throw new ObjectDisposedException(nameof(WebRTCDataChannel));
243             }
244         }
245         #endregion Dispose support
246     }
247 }