/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.ComponentModel;
using System.Diagnostics;
using Tizen.Applications;
using static Interop;
namespace Tizen.Multimedia.Remoting
{
///
/// Provides the ability to control WebRTC data channel.
///
/// 9
public partial class WebRTCDataChannel : IDisposable
{
private readonly IntPtr _handle;
///
/// Initializes a new instance of the class.
///
/// The owner of this WebRTCDataChannel.
/// The name of this data channel.
/// The webRtc or label is null.
/// 9
public WebRTCDataChannel(WebRTC webRtc, string label)
: this(webRtc, label, null)
{
}
///
/// Initializes a new instance of the class.
///
///
/// The bundle is similar format as the RTCDataChannelInit members outlined https://www.w3.org/TR/webrtc/#dom-rtcdatachannelinit.
/// The following attributes can be set to options by using API:
/// 'ordered' of type bool : Whether the channel will send data with guaranteed ordering. The default value is true.
/// 'max-packet-lifetime' of type int : The time in milliseconds to attempt transmitting unacknowledged data. -1 for unset. The default value is -1.
/// '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.
/// 'protocol' of type string : The subprotocol used by this channel. The default value is NULL.
/// 'id' of type int : Override the default identifier selection of this channel. The default value is -1.
/// '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.
///
/// The owner of this WebRTCDataChannel.
/// The name of this data channel.
/// The data channel option.
/// The webRtc or label is null.
/// 9
public WebRTCDataChannel(WebRTC webRtc, string label, Bundle bundle)
{
if (webRtc == null)
{
throw new ArgumentNullException(nameof(webRtc), "WebRTC is not created successfully.");
}
if (string.IsNullOrEmpty(label))
{
throw new ArgumentNullException(nameof(label), "label is null.");
}
var bundle_ = bundle?.SafeBundleHandle ?? new SafeBundleHandle();
NativeDataChannel.Create(webRtc.Handle, label, bundle_, out _handle).
ThrowIfFailed("Failed to create webrtc data channel");
Debug.Assert(_handle != IntPtr.Zero);
Label = label;
}
internal WebRTCDataChannel(IntPtr dataChannelHandle)
{
if (dataChannelHandle == IntPtr.Zero)
{
throw new ArgumentNullException(nameof(dataChannelHandle),
"WebRTC is not created successfully in native");
}
_handle = dataChannelHandle;
NativeDataChannel.GetLabel(_handle, out string label).
ThrowIfFailed("Failed to get label");
Label = label;
}
private IntPtr Handle
{
get
{
ValidateNotDisposed();
return _handle;
}
}
///
/// Gets the label of this data channel.
///
/// The label.
/// 9
public string Label { get; }
///
/// Gets the amount of buffered data.
///
/// The buffered amount in bytes.
/// The WebRTCDataChannel has already been disposed.
/// 10
public uint BufferedAmount
{
get
{
ValidateNotDisposed();
NativeDataChannel.GetBufferedAmount(Handle, out uint amount).
ThrowIfFailed("Failed to get buffered amount");
return amount;
}
}
private uint? _bufferThreshold = 0;
///
/// Gets or sets the threshold of data channel buffered amount.
/// If the amount of buffered data is lower than threshold value, will be occurred.
/// The default value is 0, which means is disabled and will not be raised.
///
/// The WebRTCDataChannel has already been disposed.
/// 10
public uint BufferedAmountLowThreshold
{
get
{
ValidateNotDisposed();
if (!_bufferThreshold.HasValue)
{
NativeDataChannel.GetBufferedAmountLowThreshold(Handle, out uint threshold).
ThrowIfFailed("Failed to get buffer threshold value");
_bufferThreshold = threshold;
}
return _bufferThreshold.Value;
}
set
{
ValidateNotDisposed();
_bufferThreshold = value;
RegisterDataChannelBufferedAmountLowThresholdCallback();
}
}
///
/// Sends a string data across the data channel to the remote peer.
///
/// The string data to send
/// The WebRTCDataChannel has already been disposed.
/// 9
public void Send(string data)
{
ValidateNotDisposed();
NativeDataChannel.SendString(Handle, data).
ThrowIfFailed("Failed to send string data");
}
///
/// Sends byte data across the data channel to the remote peer.
///
/// The byte data to send
/// The WebRTCDataChannel has already been disposed.
/// 9
public void Send(byte[] data)
{
ValidateNotDisposed();
if (data == null)
{
throw new ArgumentNullException(nameof(data), "data is null");
}
NativeDataChannel.SendBytes(Handle, data, (uint)data.Length).
ThrowIfFailed("Failed to send bytes data");
}
#region Dispose support
private bool _disposed;
///
/// Releases all resources used by the current instance.
///
/// 9
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Releases the unmanaged resources used by the .
///
///
/// true to release both managed and unmanaged resources;
/// false to release only unmanaged resources.
///
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual void Dispose(bool disposing)
{
if (_disposed || !disposing)
{
return;
}
if (_handle != IntPtr.Zero)
{
NativeDataChannel.Destroy(_handle);
_disposed = true;
}
}
private void ValidateNotDisposed()
{
if (_disposed)
{
Log.Warn(WebRTCLog.Tag, "WebRTCDataChannel was disposed");
throw new ObjectDisposedException(nameof(WebRTCDataChannel));
}
}
#endregion Dispose support
}
}