Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions WebRtcInterop/RtcDataChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ namespace WebRtcInterop
return GetNativeDataChannelInterface(true)->ordered();
}

Nullable<uint32_t> RtcDataChannel::MaxPacketLifeTime::get()
Nullable<uint16_t> RtcDataChannel::MaxPacketLifeTime::get()
{
return marshal_as<uint32_t>(GetNativeDataChannelInterface(true)->maxPacketLifeTime());
return marshal_as<uint16_t>(GetNativeDataChannelInterface(true)->maxPacketLifeTime());
}

Nullable<uint32_t> RtcDataChannel::MaxRetransmits::get()
Nullable<uint16_t> RtcDataChannel::MaxRetransmits::get()
{
return marshal_as<uint32_t>(GetNativeDataChannelInterface(true)->maxRetransmitsOpt());
return marshal_as<uint16_t>(GetNativeDataChannelInterface(true)->maxRetransmitsOpt());
}

String^ RtcDataChannel::Protocol::get()
Expand Down
4 changes: 2 additions & 2 deletions WebRtcInterop/RtcDataChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ namespace WebRtcInterop
// Inherited via RtcDataChannel
virtual property String^ Label { String^ get() override; }
virtual property bool Ordered { bool get() override; }
virtual property Nullable<uint32_t> MaxPacketLifeTime { Nullable<uint32_t> get() override; }
virtual property Nullable<uint32_t> MaxRetransmits { Nullable<uint32_t> get() override; }
virtual property Nullable<uint16_t> MaxPacketLifeTime { Nullable<uint16_t> get() override; }
virtual property Nullable<uint16_t> MaxRetransmits { Nullable<uint16_t> get() override; }
virtual property String^ Protocol { String^ get() override; }
virtual property bool Negotiated { bool get() override; }
virtual property Nullable<uint16_t> Id { Nullable<uint16_t> get() override; }
Expand Down
12 changes: 9 additions & 3 deletions WebRtcInterop/RtcPeerConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,16 @@ namespace WebRtcInterop
return task;
}

Task^ RtcPeerConnection::SetLocalDescription(RtcSessionDescription description)
{
Task^ RtcPeerConnection::SetLocalDescription(Nullable<RtcLocalSessionDescriptionInit> description)
{
// TODO: Implement using two native overloads on PeerConnectionInterface:
// - description is null, or description.Value.Type is null:
// -> SetLocalDescription(observer) [native creates offer/answer from signaling state]
// - description.Value.Type has a value:
// -> SetLocalDescription(unique_ptr<SessionDescriptionInterface>, observer)
// Add marshal_as<webrtc::SessionDescriptionInterface*>(RtcLocalSessionDescriptionInit) in
// MarshalPeerConnection.h to support the second path.
throw gcnew NotImplementedException();
// TODO: insert return statement here
}

Task^ RtcPeerConnection::SetRemoteDescription(RtcSessionDescription description)
Expand Down
2 changes: 1 addition & 1 deletion WebRtcInterop/RtcPeerConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ namespace WebRtcInterop
virtual Task^ AddIceCandidate(RtcIceCandidate^ candidate) override;
virtual void RestartIce() override;

virtual Task^ SetLocalDescription(RtcSessionDescription description) override;
virtual Task^ SetLocalDescription(Nullable<RtcLocalSessionDescriptionInit> description) override;
virtual Task^ SetRemoteDescription(RtcSessionDescription description) override;

virtual RtcRtpSender^ AddTrack(WebRtcNet::Media::MediaStreamTrack^ track,
Expand Down
10 changes: 8 additions & 2 deletions WebRtcNet.Api.UnitTests/RtcPeerConnectionContractTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,21 @@ public void RtcPeerConnection_Exposes_Nullable_Optional_SetLocalDescription_And_
{
var setLocalDescription = typeof(RtcPeerConnection).GetMethod(
nameof(RtcPeerConnection.SetLocalDescription),
new[] { typeof(RtcSessionDescription?) });
new[] { typeof(RtcLocalSessionDescriptionInit?) });
var addIceCandidate = typeof(RtcPeerConnection).GetMethod(
nameof(RtcPeerConnection.AddIceCandidate),
new[] { typeof(RtcIceCandidate) });

Assert.That(setLocalDescription, Is.Not.Null);
Assert.That(setLocalDescription, Is.Not.Null,
"SetLocalDescription must accept RtcLocalSessionDescriptionInit? (spec: RTCLocalSessionDescriptionInit, type optional)");
Assert.That(setLocalDescription!.GetParameters()[0].IsOptional, Is.True);
Assert.That(setLocalDescription.GetParameters()[0].DefaultValue, Is.Null);

// Verify the parameter is NOT the old RtcSessionDescription? type — type distinction is spec-required.
Assert.That(setLocalDescription.GetParameters()[0].ParameterType,
Is.Not.EqualTo(typeof(RtcSessionDescription?)),
"SetLocalDescription must use RtcLocalSessionDescriptionInit (RTCLocalSessionDescriptionInit), not RtcSessionDescription (RTCSessionDescriptionInit)");

Assert.That(addIceCandidate, Is.Not.Null);
Assert.That(addIceCandidate!.GetParameters()[0].IsOptional, Is.True);
Assert.That(addIceCandidate.GetParameters()[0].DefaultValue, Is.Null);
Expand Down
9 changes: 5 additions & 4 deletions WebRtcNet.Api/RtcPeerConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -334,15 +334,16 @@ public static Task<RtcCertificate> GenerateCertificate(object keygenAlgorithm)

/// <summary>
/// The SetLocalDescription() method instructs the RtcPeerConnection to apply the supplied
/// <see cref="RtcSessionDescription">RtcSessionDescription</see> as the
/// <see cref="RtcLocalSessionDescriptionInit">description</see> as the
/// <see cref="LocalDescription">local description</see>.
/// </summary>
/// <param name="description">
/// A session description containing the SDP describing the local session, or null to let the implementation
/// infer and apply the next local description.
/// A local session description init whose <c>type</c> may be omitted to let the implementation
/// infer it from the current signaling state, or <see langword="null"/> to use the implementation's
/// default (equivalent to passing an empty <c>RTCLocalSessionDescriptionInit</c>).
/// </param>
/// <seealso href="https://www.w3.org/TR/webrtc/#dom-peerconnection-setlocaldescription" />
public abstract Task SetLocalDescription(RtcSessionDescription? description = null);
public abstract Task SetLocalDescription(RtcLocalSessionDescriptionInit? description = null);

/// <summary>
/// The SetRemoteDescription() method instructs the RTCPeerConnection to apply the supplied
Expand Down
78 changes: 72 additions & 6 deletions WebRtcNet.Api/RtcSessionDescription.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;

namespace WebRtcNet;

/// <summary>
Expand Down Expand Up @@ -32,10 +34,12 @@ public enum RtcSdpType
}

/// <summary>
/// Represents an SDP session description used by <see cref="RtcPeerConnection" /> operations.
/// Represents an SDP session description produced by <see cref="RtcPeerConnection.CreateOffer"/> or
/// <see cref="RtcPeerConnection.CreateAnswer"/>, or received from a remote peer via signaling.
/// Models <c>RTCSessionDescriptionInit</c> where <c>type</c> is required.
/// </summary>
/// <seealso href="https://www.w3.org/TR/webrtc/#dom-rtcsessiondescriptioninit" />
public struct RtcSessionDescription
/// <seealso href="https://www.w3.org/TR/webrtc/#rtcsessiondescription-class" />
public record struct RtcSessionDescription
{
/// <summary>
/// Initializes a session description with a type and SDP payload.
Expand All @@ -51,10 +55,72 @@ public RtcSessionDescription(RtcSdpType type, string sdp)
/// <summary>
/// Gets the SDP description type.
/// </summary>
public readonly RtcSdpType Type;
/// <seealso href="https://www.w3.org/TR/webrtc/#dom-rtcsessiondescriptioninit-type" />
public RtcSdpType Type { get; init; }

/// <summary>
/// Gets the SDP payload string.
/// </summary>
/// <seealso href="https://www.w3.org/TR/webrtc/#dom-rtcsessiondescriptioninit-sdp" />
public string Sdp { get; init; } = string.Empty;

/// <summary>
/// Implicitly converts an <see cref="RtcLocalSessionDescriptionInit"/> to an
/// <see cref="RtcSessionDescription"/>. Throws if <see cref="RtcLocalSessionDescriptionInit.Type"/>
/// is <see langword="null"/>, as <see cref="Type"/> is required.
/// </summary>
/// <exception cref="InvalidOperationException">
/// Thrown when <see cref="RtcLocalSessionDescriptionInit.Type"/> is <see langword="null"/>.
/// </exception>
public static implicit operator RtcSessionDescription(RtcLocalSessionDescriptionInit description) =>
new(description.Type ?? throw new InvalidOperationException(
"Cannot convert RtcLocalSessionDescriptionInit to RtcSessionDescription: Type is null."),
description.Sdp);
}

/// <summary>
/// The description passed to <see cref="RtcPeerConnection.SetLocalDescription"/>.
/// Models <c>RTCLocalSessionDescriptionInit</c> where <c>type</c> is optional — the implementation
/// may infer the type when it is omitted.
/// </summary>
/// <remarks>
/// Implicitly converts from <see cref="RtcSessionDescription"/> so that the value returned by
/// <see cref="RtcPeerConnection.CreateOffer"/> or <see cref="RtcPeerConnection.CreateAnswer"/>
/// can be passed directly to <see cref="RtcPeerConnection.SetLocalDescription"/> without a cast.
/// </remarks>
/// <seealso href="https://www.w3.org/TR/webrtc/#dom-rtclocalsessiondescriptioninit" />
public record struct RtcLocalSessionDescriptionInit
{
/// <summary>
/// Initializes a local session description init with an optional type and SDP payload.
/// </summary>
/// <param name="type">
/// The SDP description type, or <see langword="null"/> to let the implementation infer the type
/// from the current signaling state.
/// </param>
/// <param name="sdp">The SDP payload text. Defaults to empty string.</param>
public RtcLocalSessionDescriptionInit(RtcSdpType? type = null, string sdp = "")
{
Type = type;
Sdp = sdp;
}

/// <summary>
/// Gets the SDP description type, or <see langword="null"/> if the implementation should infer it.
/// </summary>
/// <seealso href="https://www.w3.org/TR/webrtc/#dom-rtclocalsessiondescriptioninit-type" />
public RtcSdpType? Type { get; init; }

/// <summary>
/// Gets the SDP payload string.
/// </summary>
public readonly string Sdp;
}
/// <seealso href="https://www.w3.org/TR/webrtc/#dom-rtclocalsessiondescriptioninit-sdp" />
public string Sdp { get; init; } = string.Empty;

/// <summary>
/// Implicitly converts an <see cref="RtcSessionDescription"/> (required type) to an
/// <see cref="RtcLocalSessionDescriptionInit"/> (optional type).
/// </summary>
public static implicit operator RtcLocalSessionDescriptionInit(RtcSessionDescription description) =>
new(description.Type, description.Sdp);
}
Loading