Skip to content

Commit d678f44

Browse files
committed
feat: support setting ICE ufrag and pwd, and missing config values
Updates the implementation to match the latest libdatachannel with features for setting ICE ufrag/pwd and reading the remote cert fingerprint. Also adds pass-through for missing config values.
1 parent b0caa62 commit d678f44

File tree

5 files changed

+119
-4
lines changed

5 files changed

+119
-4
lines changed

API.md

+28
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,19 @@ export interface RtcConfig {
1616
bindAddress?: string;
1717
enableIceTcp?: boolean;
1818
enableIceUdpMux?: boolean;
19+
disableAutoNegotiation?: boolean;
20+
disableFingerprintVerification?: boolean;
21+
disableAutoGathering?: boolean;
22+
forceMediaTransport?: boolean;
1923
portRangeBegin?: number;
2024
portRangeEnd?: number;
2125
maxMessageSize?: number;
2226
mtu?: number;
2327
iceTransportPolicy?: TransportPolicy;
2428
disableFingerprintVerification?: boolean;
29+
certificatePemFile?: string;
30+
keyPemFile?: string;
31+
keyPemPass?: string;
2532
}
2633
2734
export const enum RelayType {
@@ -69,6 +76,27 @@ export const enum DescriptionType {
6976
}
7077
```
7178

79+
**setLocalDescription: (sdp: string, init?: LocalDescriptionInit) => void**
80+
81+
Set Local Description and optionally the ICE ufrag/pwd to use. These should not
82+
be set as they will be generated automatically as per the spec.
83+
```
84+
export interface LocalDescriptionInit {
85+
iceUfrag?: string;
86+
icePwd?: string;
87+
}
88+
```
89+
90+
**remoteFingerprint: () => CertificateFingerprint**
91+
92+
Returns the certificate fingerprint used by the remote peer
93+
```
94+
export interface CertificateFingerprint {
95+
value: string;
96+
algorithm: 'sha-1' | 'sha-224' | 'sha-256' | 'sha-384' | 'sha-512' | 'md5' | 'md2';
97+
}
98+
```
99+
72100
**addRemoteCandidate: (candidate: string, mid: string) => void**
73101

74102
Add remote candidate info

src/cpp/peer-connection-wrapper.cpp

+68-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Napi::Object PeerConnectionWrapper::Init(Napi::Env env, Napi::Object exports)
4141
InstanceMethod("setRemoteDescription", &PeerConnectionWrapper::setRemoteDescription),
4242
InstanceMethod("localDescription", &PeerConnectionWrapper::localDescription),
4343
InstanceMethod("remoteDescription", &PeerConnectionWrapper::remoteDescription),
44+
InstanceMethod("remoteFingerprint", &PeerConnectionWrapper::remoteFingerprint),
4445
InstanceMethod("addRemoteCandidate", &PeerConnectionWrapper::addRemoteCandidate),
4546
InstanceMethod("createDataChannel", &PeerConnectionWrapper::createDataChannel),
4647
InstanceMethod("addTrack", &PeerConnectionWrapper::addTrack),
@@ -214,6 +215,10 @@ PeerConnectionWrapper::PeerConnectionWrapper(const Napi::CallbackInfo &info) : N
214215
if (config.Get("disableAutoNegotiation").IsBoolean())
215216
rtcConfig.disableAutoNegotiation = config.Get("disableAutoNegotiation").As<Napi::Boolean>();
216217

218+
// disableAutoGathering option
219+
if (config.Get("disableAutoGathering").IsBoolean())
220+
rtcConfig.disableAutoGathering = config.Get("disableAutoGathering").As<Napi::Boolean>();
221+
217222
// forceMediaTransport option
218223
if (config.Get("forceMediaTransport").IsBoolean())
219224
rtcConfig.forceMediaTransport = config.Get("forceMediaTransport").As<Napi::Boolean>();
@@ -251,6 +256,17 @@ PeerConnectionWrapper::PeerConnectionWrapper(const Napi::CallbackInfo &info) : N
251256
rtcConfig.disableFingerprintVerification = config.Get("disableFingerprintVerification").As<Napi::Boolean>();
252257
}
253258

259+
// Specify certificate to use if set
260+
if (config.Get("certificatePemFile").IsString()) {
261+
rtcConfig.certificatePemFile = config.Get("certificatePemFile").As<Napi::String>().ToString();
262+
}
263+
if (config.Get("keyPemFile").IsString()) {
264+
rtcConfig.keyPemFile = config.Get("keyPemFile").As<Napi::String>().ToString();
265+
}
266+
if (config.Get("keyPemPass").IsString()) {
267+
rtcConfig.keyPemPass = config.Get("keyPemPass").As<Napi::String>().ToString();
268+
}
269+
254270
// Create peer-connection
255271
try
256272
{
@@ -331,6 +347,7 @@ void PeerConnectionWrapper::setLocalDescription(const Napi::CallbackInfo &info)
331347
}
332348

333349
rtc::Description::Type type = rtc::Description::Type::Unspec;
350+
rtc::LocalDescriptionInit init;
334351

335352
// optional
336353
if (length > 0)
@@ -356,7 +373,29 @@ void PeerConnectionWrapper::setLocalDescription(const Napi::CallbackInfo &info)
356373
type = rtc::Description::Type::Rollback;
357374
}
358375

359-
mRtcPeerConnPtr->setLocalDescription(type);
376+
// optional
377+
if (length > 1)
378+
{
379+
PLOG_DEBUG << "setLocalDescription() called with LocalDescriptionInit";
380+
381+
if (info[1].IsObject())
382+
{
383+
PLOG_DEBUG << "setLocalDescription() called with LocalDescriptionInit as object";
384+
Napi::Object obj = info[1].As<Napi::Object>();
385+
386+
if (obj.Get("iceUfrag").IsString()) {
387+
PLOG_DEBUG << "setLocalDescription() has ufrag";
388+
init.iceUfrag = obj.Get("iceUfrag").As<Napi::String>();
389+
}
390+
391+
if (obj.Get("icePwd").IsString()) {
392+
PLOG_DEBUG << "setLocalDescription() has password";
393+
init.icePwd = obj.Get("icePwd").As<Napi::String>();
394+
}
395+
}
396+
}
397+
398+
mRtcPeerConnPtr->setLocalDescription(type, init);
360399
}
361400

362401
void PeerConnectionWrapper::setRemoteDescription(const Napi::CallbackInfo &info)
@@ -1002,7 +1041,34 @@ Napi::Value PeerConnectionWrapper::maxMessageSize(const Napi::CallbackInfo &info
10021041

10031042
try
10041043
{
1005-
return Napi::Number::New(env, mRtcPeerConnPtr->remoteMaxMessageSize());
1044+
return Napi::Array::New(env, mRtcPeerConnPtr->remoteMaxMessageSize());
1045+
}
1046+
catch (std::exception &ex)
1047+
{
1048+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
1049+
return Napi::Number::New(info.Env(), 0);
1050+
}
1051+
}
1052+
1053+
Napi::Value PeerConnectionWrapper::remoteFingerprint(const Napi::CallbackInfo &info)
1054+
{
1055+
PLOG_DEBUG << "remoteFingerprints() called";
1056+
Napi::Env env = info.Env();
1057+
1058+
if (!mRtcPeerConnPtr)
1059+
{
1060+
return Napi::Number::New(info.Env(), 0);
1061+
}
1062+
1063+
try
1064+
{
1065+
auto fingerprint = mRtcPeerConnPtr->remoteFingerprint();
1066+
1067+
Napi::Object fingerprintObject = Napi::Object::New(env);
1068+
fingerprintObject.Set("value", fingerprint.value);
1069+
fingerprintObject.Set("algorithm", rtc::CertificateFingerprint::AlgorithmIdentifier(fingerprint.algorithm));
1070+
1071+
return fingerprintObject;
10061072
}
10071073
catch (std::exception &ex)
10081074
{

src/cpp/peer-connection-wrapper.h

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class PeerConnectionWrapper : public Napi::ObjectWrap<PeerConnectionWrapper>
3333
Napi::Value iceState(const Napi::CallbackInfo &info);
3434
Napi::Value signalingState(const Napi::CallbackInfo &info);
3535
Napi::Value gatheringState(const Napi::CallbackInfo &info);
36+
Napi::Value remoteFingerprint(const Napi::CallbackInfo &info);
3637

3738
// Callbacks
3839
void onLocalDescription(const Napi::CallbackInfo &info);

src/lib/index.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import nodeDataChannel from './node-datachannel';
22
import _DataChannelStream from './datachannel-stream';
33
import { WebSocketServer } from './websocket-server';
4-
import { Channel, DataChannelInitConfig, DescriptionType, Direction, LogLevel, RtcConfig, RTCIceConnectionState, RTCIceGatheringState, RTCPeerConnectionState, RTCSignalingState, SctpSettings, SelectedCandidateInfo } from './types';
4+
import { CertificateFingerprint, Channel, DataChannelInitConfig, DescriptionType, Direction, LocalDescriptionInit, LogLevel, RtcConfig, RTCIceConnectionState, RTCIceGatheringState, RTCPeerConnectionState, RTCSignalingState, SctpSettings, SelectedCandidateInfo } from './types';
55
import { WebSocket } from './websocket';
66

77
export function preload(): void { nodeDataChannel.preload(); }
@@ -113,10 +113,11 @@ export const DataChannel: {
113113

114114
export interface PeerConnection {
115115
close(): void;
116-
setLocalDescription(type?: DescriptionType): void;
116+
setLocalDescription(type?: DescriptionType, init?: LocalDescriptionInit): void;
117117
setRemoteDescription(sdp: string, type: DescriptionType): void;
118118
localDescription(): { type: DescriptionType; sdp: string } | null;
119119
remoteDescription(): { type: DescriptionType; sdp: string } | null;
120+
remoteFingerprint(): CertificateFingerprint;
120121
addRemoteCandidate(candidate: string, mid: string): void;
121122
createDataChannel(label: string, config?: DataChannelInitConfig): DataChannel;
122123
addTrack(media: Video | Audio): Track;

src/lib/types.ts

+19
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ export interface RtcConfig {
7777
mtu?: number;
7878
iceTransportPolicy?: TransportPolicy;
7979
disableFingerprintVerification?: boolean;
80+
disableAutoGathering?: boolean;
81+
certificatePemFile?: string;
82+
keyPemFile?: string;
83+
keyPemPass?: string;
8084
}
8185

8286
// Lowercase to match the description type string from libdatachannel
@@ -97,6 +101,10 @@ export type RTCIceGathererState = "complete" | "gathering" | "new";
97101
export type RTCIceGatheringState = "complete" | "gathering" | "new";
98102
export type RTCSignalingState = "closed" | "have-local-offer" | "have-local-pranswer" | "have-remote-offer" | "have-remote-pranswer" | "stable";
99103

104+
export interface LocalDescriptionInit {
105+
iceUfrag?: string;
106+
icePwd?: string;
107+
}
100108

101109
export interface DataChannelInitConfig {
102110
protocol?: string;
@@ -107,6 +115,17 @@ export interface DataChannelInitConfig {
107115
maxRetransmits?: number; // Reliability
108116
}
109117

118+
export interface CertificateFingerprint {
119+
/**
120+
* @see https://developer.mozilla.org/en-US/docs/Web/API/RTCCertificate/getFingerprints#value
121+
*/
122+
value: string;
123+
/**
124+
* @see https://developer.mozilla.org/en-US/docs/Web/API/RTCCertificate/getFingerprints#algorithm
125+
*/
126+
algorithm: 'sha-1' | 'sha-224' | 'sha-256' | 'sha-384' | 'sha-512' | 'md5' | 'md2';
127+
}
128+
110129
export interface SelectedCandidateInfo {
111130
address: string;
112131
port: number;

0 commit comments

Comments
 (0)