@signalapp/ringrtc 2.26.4 → 2.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { RingRTCType } from './ringrtc/Service';
2
- export { AnswerMessage, AudioDevice, BandwidthMode, BusyMessage, Call, CallEndedReason, CallId, CallLogLevel, CallMessageUrgency, CallSettings, CallState, CallingMessage, ConnectionState, DeviceId, GroupCall, GroupCallEndReason, GroupCallObserver, GroupMemberInfo, HangupMessage, HangupType, HttpMethod, IceCandidateMessage, JoinState, LocalDeviceState, OfferMessage, OfferType, OpaqueMessage, PeekInfo, RemoteDeviceState, RingCancelReason, RingRTCType, RingUpdate, UserId, VideoCapturer, VideoRenderer, VideoRequest, callIdFromEra, callIdFromRingId, } from './ringrtc/Service';
2
+ export { AnswerMessage, AudioDevice, DataMode, BusyMessage, Call, CallEndedReason, CallId, CallLogLevel, CallMessageUrgency, CallSettings, CallState, CallingMessage, ConnectionState, DeviceId, GroupCall, GroupCallEndReason, GroupCallObserver, GroupMemberInfo, HangupMessage, HangupType, HttpMethod, HttpResult, IceCandidateMessage, JoinState, LocalDeviceState, OfferMessage, OfferType, OpaqueMessage, PeekDeviceInfo, PeekInfo, PeekStatusCodes, RemoteDeviceState, RingCancelReason, RingRTCType, RingUpdate, UserId, VideoCapturer, VideoRenderer, VideoRequest, callIdFromEra, callIdFromRingId, } from './ringrtc/Service';
3
3
  export { CanvasVideoRenderer, GumVideoCapturer, VideoFrameSource, MAX_VIDEO_CAPTURE_AREA, MAX_VIDEO_CAPTURE_BUFFER_SIZE, MAX_VIDEO_CAPTURE_HEIGHT, MAX_VIDEO_CAPTURE_WIDTH, } from './ringrtc/VideoSupport';
4
+ export { CallLinkRootKey, CallLinkRestrictions, CallLinkState, } from './ringrtc/CallLinks';
4
5
  export declare const RingRTC: RingRTCType;
package/dist/index.js CHANGED
@@ -4,11 +4,11 @@
4
4
  // SPDX-License-Identifier: AGPL-3.0-only
5
5
  //
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.RingRTC = exports.MAX_VIDEO_CAPTURE_WIDTH = exports.MAX_VIDEO_CAPTURE_HEIGHT = exports.MAX_VIDEO_CAPTURE_BUFFER_SIZE = exports.MAX_VIDEO_CAPTURE_AREA = exports.GumVideoCapturer = exports.CanvasVideoRenderer = exports.callIdFromRingId = exports.callIdFromEra = exports.VideoRequest = exports.RingUpdate = exports.RingRTCType = exports.RingCancelReason = exports.RemoteDeviceState = exports.PeekInfo = exports.OpaqueMessage = exports.OfferType = exports.OfferMessage = exports.LocalDeviceState = exports.JoinState = exports.IceCandidateMessage = exports.HttpMethod = exports.HangupType = exports.HangupMessage = exports.GroupMemberInfo = exports.GroupCallEndReason = exports.GroupCall = exports.ConnectionState = exports.CallingMessage = exports.CallState = exports.CallMessageUrgency = exports.CallLogLevel = exports.CallEndedReason = exports.Call = exports.BusyMessage = exports.BandwidthMode = exports.AnswerMessage = void 0;
7
+ exports.RingRTC = exports.CallLinkState = exports.CallLinkRestrictions = exports.CallLinkRootKey = exports.MAX_VIDEO_CAPTURE_WIDTH = exports.MAX_VIDEO_CAPTURE_HEIGHT = exports.MAX_VIDEO_CAPTURE_BUFFER_SIZE = exports.MAX_VIDEO_CAPTURE_AREA = exports.GumVideoCapturer = exports.CanvasVideoRenderer = exports.callIdFromRingId = exports.callIdFromEra = exports.VideoRequest = exports.RingUpdate = exports.RingRTCType = exports.RingCancelReason = exports.RemoteDeviceState = exports.PeekStatusCodes = exports.OpaqueMessage = exports.OfferType = exports.OfferMessage = exports.LocalDeviceState = exports.JoinState = exports.IceCandidateMessage = exports.HttpMethod = exports.HangupType = exports.HangupMessage = exports.GroupMemberInfo = exports.GroupCallEndReason = exports.GroupCall = exports.ConnectionState = exports.CallingMessage = exports.CallState = exports.CallMessageUrgency = exports.CallLogLevel = exports.CallEndedReason = exports.Call = exports.BusyMessage = exports.DataMode = exports.AnswerMessage = void 0;
8
8
  const Service_1 = require("./ringrtc/Service");
9
9
  var Service_2 = require("./ringrtc/Service");
10
10
  Object.defineProperty(exports, "AnswerMessage", { enumerable: true, get: function () { return Service_2.AnswerMessage; } });
11
- Object.defineProperty(exports, "BandwidthMode", { enumerable: true, get: function () { return Service_2.BandwidthMode; } });
11
+ Object.defineProperty(exports, "DataMode", { enumerable: true, get: function () { return Service_2.DataMode; } });
12
12
  Object.defineProperty(exports, "BusyMessage", { enumerable: true, get: function () { return Service_2.BusyMessage; } });
13
13
  Object.defineProperty(exports, "Call", { enumerable: true, get: function () { return Service_2.Call; } });
14
14
  Object.defineProperty(exports, "CallEndedReason", { enumerable: true, get: function () { return Service_2.CallEndedReason; } });
@@ -29,7 +29,7 @@ Object.defineProperty(exports, "LocalDeviceState", { enumerable: true, get: func
29
29
  Object.defineProperty(exports, "OfferMessage", { enumerable: true, get: function () { return Service_2.OfferMessage; } });
30
30
  Object.defineProperty(exports, "OfferType", { enumerable: true, get: function () { return Service_2.OfferType; } });
31
31
  Object.defineProperty(exports, "OpaqueMessage", { enumerable: true, get: function () { return Service_2.OpaqueMessage; } });
32
- Object.defineProperty(exports, "PeekInfo", { enumerable: true, get: function () { return Service_2.PeekInfo; } });
32
+ Object.defineProperty(exports, "PeekStatusCodes", { enumerable: true, get: function () { return Service_2.PeekStatusCodes; } });
33
33
  Object.defineProperty(exports, "RemoteDeviceState", { enumerable: true, get: function () { return Service_2.RemoteDeviceState; } });
34
34
  Object.defineProperty(exports, "RingCancelReason", { enumerable: true, get: function () { return Service_2.RingCancelReason; } });
35
35
  Object.defineProperty(exports, "RingRTCType", { enumerable: true, get: function () { return Service_2.RingRTCType; } });
@@ -44,5 +44,9 @@ Object.defineProperty(exports, "MAX_VIDEO_CAPTURE_AREA", { enumerable: true, get
44
44
  Object.defineProperty(exports, "MAX_VIDEO_CAPTURE_BUFFER_SIZE", { enumerable: true, get: function () { return VideoSupport_1.MAX_VIDEO_CAPTURE_BUFFER_SIZE; } });
45
45
  Object.defineProperty(exports, "MAX_VIDEO_CAPTURE_HEIGHT", { enumerable: true, get: function () { return VideoSupport_1.MAX_VIDEO_CAPTURE_HEIGHT; } });
46
46
  Object.defineProperty(exports, "MAX_VIDEO_CAPTURE_WIDTH", { enumerable: true, get: function () { return VideoSupport_1.MAX_VIDEO_CAPTURE_WIDTH; } });
47
+ var CallLinks_1 = require("./ringrtc/CallLinks");
48
+ Object.defineProperty(exports, "CallLinkRootKey", { enumerable: true, get: function () { return CallLinks_1.CallLinkRootKey; } });
49
+ Object.defineProperty(exports, "CallLinkRestrictions", { enumerable: true, get: function () { return CallLinks_1.CallLinkRestrictions; } });
50
+ Object.defineProperty(exports, "CallLinkState", { enumerable: true, get: function () { return CallLinks_1.CallLinkState; } });
47
51
  exports.RingRTC = new Service_1.RingRTCType();
48
52
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,23 @@
1
+ /// <reference types="node" />
2
+ export declare class CallLinkRootKey {
3
+ readonly bytes: Buffer;
4
+ private constructor();
5
+ static parse(str: string): CallLinkRootKey;
6
+ static fromBytes(bytes: Buffer): CallLinkRootKey;
7
+ static generate(): CallLinkRootKey;
8
+ static generateAdminPassKey(): Buffer;
9
+ deriveRoomId(): Buffer;
10
+ toString(): string;
11
+ }
12
+ export declare class CallLinkState {
13
+ name: string;
14
+ restrictions: CallLinkRestrictions;
15
+ revoked: boolean;
16
+ expiration: Date;
17
+ constructor(name: string, restrictions: CallLinkRestrictions, revoked: boolean, expiration: Date);
18
+ }
19
+ export declare enum CallLinkRestrictions {
20
+ None = 0,
21
+ AdminApproval = 1,
22
+ Unknown = 2
23
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ //
3
+ // Copyright 2023 Signal Messenger, LLC
4
+ // SPDX-License-Identifier: AGPL-3.0-only
5
+ //
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.CallLinkRestrictions = exports.CallLinkState = exports.CallLinkRootKey = void 0;
11
+ const Native_1 = __importDefault(require("./Native"));
12
+ class CallLinkRootKey {
13
+ constructor(bytes) {
14
+ this.bytes = bytes;
15
+ }
16
+ static parse(str) {
17
+ return new CallLinkRootKey(Native_1.default.CallLinkRootKey_parse(str));
18
+ }
19
+ static fromBytes(bytes) {
20
+ Native_1.default.CallLinkRootKey_validate(bytes);
21
+ return new CallLinkRootKey(bytes);
22
+ }
23
+ static generate() {
24
+ return new CallLinkRootKey(Native_1.default.CallLinkRootKey_generate());
25
+ }
26
+ static generateAdminPassKey() {
27
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
28
+ return Native_1.default.CallLinkRootKey_generateAdminPasskey();
29
+ }
30
+ deriveRoomId() {
31
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
32
+ return Native_1.default.CallLinkRootKey_deriveRoomId(this.bytes);
33
+ }
34
+ toString() {
35
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
36
+ return Native_1.default.CallLinkRootKey_toFormattedString(this.bytes);
37
+ }
38
+ }
39
+ exports.CallLinkRootKey = CallLinkRootKey;
40
+ class CallLinkState {
41
+ constructor(name, restrictions, revoked, expiration) {
42
+ this.name = name;
43
+ this.restrictions = restrictions;
44
+ this.revoked = revoked;
45
+ this.expiration = expiration;
46
+ }
47
+ }
48
+ exports.CallLinkState = CallLinkState;
49
+ var CallLinkRestrictions;
50
+ (function (CallLinkRestrictions) {
51
+ CallLinkRestrictions[CallLinkRestrictions["None"] = 0] = "None";
52
+ CallLinkRestrictions[CallLinkRestrictions["AdminApproval"] = 1] = "AdminApproval";
53
+ CallLinkRestrictions[CallLinkRestrictions["Unknown"] = 2] = "Unknown";
54
+ })(CallLinkRestrictions = exports.CallLinkRestrictions || (exports.CallLinkRestrictions = {}));
55
+ //# sourceMappingURL=CallLinks.js.map
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ //
3
+ // Copyright 2023 Signal Messenger, LLC
4
+ // SPDX-License-Identifier: AGPL-3.0-only
5
+ //
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || function (mod) {
23
+ if (mod && mod.__esModule) return mod;
24
+ var result = {};
25
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
26
+ __setModuleDefault(result, mod);
27
+ return result;
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ const os = __importStar(require("os"));
31
+ const process = __importStar(require("process"));
32
+ // eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require
33
+ exports.default = require(`../../build/${os.platform()}/libringrtc-${process.arch}.node`);
34
+ //# sourceMappingURL=Native.js.map
@@ -1,5 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { GumVideoCaptureOptions, VideoPixelFormatEnum } from './VideoSupport';
3
+ import { CallLinkState, CallLinkRestrictions, CallLinkRootKey } from './CallLinks';
3
4
  export declare const callIdFromEra: (era: string) => CallId;
4
5
  export declare function callIdFromRingId(ringId: bigint): CallId;
5
6
  declare class Config {
@@ -8,18 +9,20 @@ declare class Config {
8
9
  }
9
10
  type GroupId = Buffer;
10
11
  type GroupCallUserId = Buffer;
11
- export declare class PeekDeviceInfo {
12
+ export interface PeekDeviceInfo {
12
13
  demuxId: number;
13
14
  userId?: GroupCallUserId;
14
- constructor(demuxId: number, userId: GroupCallUserId | undefined);
15
15
  }
16
- export declare class PeekInfo {
16
+ export interface PeekInfo {
17
17
  devices: Array<PeekDeviceInfo>;
18
18
  creator?: GroupCallUserId;
19
19
  eraId?: string;
20
20
  maxDevices?: number;
21
21
  deviceCount: number;
22
- constructor();
22
+ }
23
+ export declare enum PeekStatusCodes {
24
+ EXPIRED_CALL_LINK = 703,
25
+ INVALID_CALL_LINK = 704
23
26
  }
24
27
  declare enum NetworkAdapterType {
25
28
  Unknown = 0,
@@ -45,11 +48,19 @@ export declare class ReceivedAudioLevel {
45
48
  level: RawAudioLevel;
46
49
  constructor(demuxId: number, level: RawAudioLevel);
47
50
  }
51
+ export type HttpResult<T> = {
52
+ success: true;
53
+ value: T;
54
+ } | {
55
+ success: false;
56
+ errorStatusCode: number;
57
+ };
48
58
  export declare class RingRTCType {
49
59
  private readonly callManager;
50
60
  private _call;
51
61
  private _groupCallByClientId;
52
62
  private _peekRequests;
63
+ private _callLinkRequests;
53
64
  private _callInfoByCallId;
54
65
  private getCallInfoKey;
55
66
  handleOutgoingSignaling: ((remoteUserId: UserId, message: CallingMessage) => Promise<boolean>) | null;
@@ -84,10 +95,107 @@ export declare class RingRTCType {
84
95
  onSendHangup(remoteUserId: UserId, remoteDeviceId: DeviceId, callId: CallId, broadcast: boolean, hangupType: HangupType, deviceId: DeviceId | null): void;
85
96
  onSendBusy(remoteUserId: UserId, remoteDeviceId: DeviceId, callId: CallId, broadcast: boolean): void;
86
97
  private sendSignaling;
98
+ /**
99
+ * Asynchronous request to get information about a call link.
100
+ *
101
+ * @param sfuUrl - the URL to use when accessing the SFU
102
+ * @param authCredentialPresentation - a serialized CallLinkAuthCredentialPresentation
103
+ * @param linkRootKey - the root key for the call link
104
+ *
105
+ * Expected failure codes include:
106
+ * - 404: the room does not exist (or expired so long ago that it has been removed from the server)
107
+ */
108
+ readCallLink(sfuUrl: string, authCredentialPresentation: Buffer, linkRootKey: CallLinkRootKey): Promise<HttpResult<CallLinkState>>;
109
+ /**
110
+ * Asynchronous request to create a new call link.
111
+ *
112
+ * This request is idempotent; if it fails due to a network issue, it is safe to retry.
113
+ *
114
+ * @example
115
+ * const linkKey = CallLinkRootKey.generate();
116
+ * const adminPasskey = CallLinkRootKey.generateAdminPasskey();
117
+ * const roomId = linkKey.deriveRoomId();
118
+ * const credential = requestCreateCredentialFromChatServer(roomId); // using libsignal
119
+ * const secretParams = CallLinkSecretParams.deriveFromRootKey(linkKey.bytes);
120
+ * const credentialPresentation = credential.present(roomId, secretParams).serialize();
121
+ * const serializedPublicParams = secretParams.getPublicParams().serialize();
122
+ * const result = await RingRTC.createCallLink(sfuUrl, credentialPresentation, linkKey, adminPasskey, serializedPublicParams);
123
+ * if (result.success) {
124
+ * const state = result.value;
125
+ * // In actuality you may not want to do this until the user clicks Done.
126
+ * saveToDatabase(linkKey.bytes, adminPasskey, state);
127
+ * syncToOtherDevices(linkKey.bytes, adminPasskey);
128
+ * } else {
129
+ * switch (result.errorStatusCode) {
130
+ * case 409:
131
+ * // The room already exists (and isn't yours), i.e. you've hit a 1-in-a-billion conflict.
132
+ * // Fall through to kicking the user out to try again later.
133
+ * default:
134
+ * // Unexpected error, kick the user out for now.
135
+ * }
136
+ * }
137
+ *
138
+ * @param sfuUrl - the URL to use when accessing the SFU
139
+ * @param createCredentialPresentation - a serialized CreateCallLinkCredentialPresentation
140
+ * @param linkRootKey - the root key for the call link
141
+ * @param adminPasskey - the arbitrary passkey to use for the new room
142
+ * @param callLinkPublicParams - the serialized CallLinkPublicParams for the new room
143
+ */
144
+ createCallLink(sfuUrl: string, createCredentialPresentation: Buffer, linkRootKey: CallLinkRootKey, adminPasskey: Buffer, callLinkPublicParams: Buffer): Promise<HttpResult<CallLinkState>>;
145
+ /**
146
+ * Asynchronous request to update a call link's name.
147
+ *
148
+ * Possible failure codes include:
149
+ * - 401: the room does not exist (and this is the wrong API to create a new room)
150
+ * - 403: the admin passkey is incorrect
151
+ *
152
+ * This request is idempotent; if it fails due to a network issue, it is safe to retry.
153
+ *
154
+ * @param sfuUrl - the URL to use when accessing the SFU
155
+ * @param authCredentialPresentation - a serialized CallLinkAuthCredentialPresentation
156
+ * @param linkRootKey - the root key for the call link
157
+ * @param adminPasskey - the passkey specified when the link was created
158
+ * @param newName - the new name to use
159
+ */
160
+ updateCallLinkName(sfuUrl: string, authCredentialPresentation: Buffer, linkRootKey: CallLinkRootKey, adminPasskey: Buffer, newName: string): Promise<HttpResult<CallLinkState>>;
161
+ /**
162
+ * Asynchronous request to update a call link's restrictions.
163
+ *
164
+ * Possible failure codes include:
165
+ * - 401: the room does not exist (and this is the wrong API to create a new room)
166
+ * - 403: the admin passkey is incorrect
167
+ *
168
+ * This request is idempotent; if it fails due to a network issue, it is safe to retry.
169
+ *
170
+ * @param sfuUrl - the URL to use when accessing the SFU
171
+ * @param authCredentialPresentation - a serialized CallLinkAuthCredentialPresentation
172
+ * @param linkRootKey - the root key for the call link
173
+ * @param adminPasskey - the passkey specified when the link was created
174
+ * @param restrictions - the new restrictions to use
175
+ */
176
+ updateCallLinkRestrictions(sfuUrl: string, authCredentialPresentation: Buffer, linkRootKey: CallLinkRootKey, adminPasskey: Buffer, restrictions: Exclude<CallLinkRestrictions, CallLinkRestrictions.Unknown>): Promise<HttpResult<CallLinkState>>;
177
+ /**
178
+ * Asynchronous request to revoke or un-revoke a call link.
179
+ *
180
+ * Possible failure codes include:
181
+ * - 401: the room does not exist (and this is the wrong API to create a new room)
182
+ * - 403: the admin passkey is incorrect
183
+ *
184
+ * This request is idempotent; if it fails due to a network issue, it is safe to retry.
185
+ *
186
+ * @param sfuUrl - the URL to use when accessing the SFU
187
+ * @param authCredentialPresentation - a serialized CallLinkAuthCredentialPresentation
188
+ * @param linkRootKey - the root key for the call link
189
+ * @param adminPasskey - the passkey specified when the link was created
190
+ * @param revoked - whether the link should now be revoked
191
+ */
192
+ updateCallLinkRevocation(sfuUrl: string, authCredentialPresentation: Buffer, linkRootKey: CallLinkRootKey, adminPasskey: Buffer, revoked: boolean): Promise<HttpResult<CallLinkState>>;
87
193
  receivedHttpResponse(requestId: number, status: number, body: Buffer): void;
88
194
  httpRequestFailed(requestId: number, debugInfo: string | undefined): void;
89
195
  getGroupCall(groupId: Buffer, sfuUrl: string, hkdfExtraInfo: Buffer, audioLevelsIntervalMillis: number | undefined, observer: GroupCallObserver): GroupCall | undefined;
196
+ getCallLinkCall(sfuUrl: string, authCredentialPresentation: Buffer, rootKey: CallLinkRootKey, adminPasskey: Buffer | undefined, hkdfExtraInfo: Buffer, audioLevelsIntervalMillis: number | undefined, observer: GroupCallObserver): GroupCall | undefined;
90
197
  peekGroupCall(sfuUrl: string, membershipProof: Buffer, groupMembers: Array<GroupMemberInfo>): Promise<PeekInfo>;
198
+ peekCallLinkCall(sfuUrl: string, authCredentialPresentation: Buffer, rootKey: CallLinkRootKey): Promise<HttpResult<PeekInfo>>;
91
199
  requestMembershipProof(clientId: GroupCallClientId): void;
92
200
  requestGroupMembers(clientId: GroupCallClientId): void;
93
201
  handleConnectionStateChanged(clientId: GroupCallClientId, connectionState: ConnectionState): void;
@@ -96,7 +204,13 @@ export declare class RingRTCType {
96
204
  handleAudioLevels(clientId: GroupCallClientId, capturedLevel: RawAudioLevel, receivedLevels: Array<ReceivedAudioLevel>): void;
97
205
  handleRemoteDevicesChanged(clientId: GroupCallClientId, remoteDeviceStates: Array<RemoteDeviceState>): void;
98
206
  handlePeekChanged(clientId: GroupCallClientId, info: PeekInfo): void;
99
- handlePeekResponse(requestId: number, info: PeekInfo): void;
207
+ handlePeekResponse(requestId: number, statusCode: number, info: PeekInfo | undefined): void;
208
+ handleCallLinkResponse(requestId: number, statusCode: number, state: {
209
+ name: string;
210
+ rawRestrictions: number;
211
+ revoked: boolean;
212
+ expiration: Date;
213
+ } | undefined): void;
100
214
  handleEnded(clientId: GroupCallClientId, reason: GroupCallEndReason): void;
101
215
  groupCallRingUpdate(groupId: GroupId, ringIdString: string, sender: GroupCallUserId, state: RingUpdate): void;
102
216
  onLogMessage(level: number, fileName: string, line: number, message: string): void;
@@ -128,7 +242,7 @@ export declare class RingRTCType {
128
242
  export interface CallSettings {
129
243
  iceServer: IceServer;
130
244
  hideIp: boolean;
131
- bandwidthMode: BandwidthMode;
245
+ dataMode: DataMode;
132
246
  audioLevelsIntervalMillis?: number;
133
247
  }
134
248
  interface IceServer {
@@ -199,7 +313,7 @@ export declare class Call {
199
313
  receiveVideoFrame(buffer: Buffer, maxWidth: number, maxHeight: number): [number, number] | undefined;
200
314
  private enableOrDisableCapturer;
201
315
  private setOutgoingVideoEnabled;
202
- updateBandwidthMode(bandwidthMode: BandwidthMode): void;
316
+ updateDataMode(dataMode: DataMode): void;
203
317
  private enableOrDisableRenderer;
204
318
  }
205
319
  export type GroupCallClientId = number;
@@ -306,7 +420,7 @@ export declare class GroupCall {
306
420
  private _localDeviceState;
307
421
  private _remoteDeviceStates;
308
422
  private _peekInfo;
309
- constructor(callManager: CallManager, groupId: Buffer, sfuUrl: string, hkdfExtraInfo: Buffer, audioLevelsIntervalMillis: number | undefined, observer: GroupCallObserver);
423
+ constructor(callManager: CallManager, observer: GroupCallObserver, clientId: GroupCallClientId);
310
424
  connect(): void;
311
425
  join(): void;
312
426
  leave(): void;
@@ -320,7 +434,7 @@ export declare class GroupCall {
320
434
  setOutgoingVideoIsScreenShare(isScreenShare: boolean): void;
321
435
  ringAll(): void;
322
436
  resendMediaKeys(): void;
323
- setBandwidthMode(bandwidthMode: BandwidthMode): void;
437
+ setDataMode(dataMode: DataMode): void;
324
438
  requestVideo(resolutions: Array<VideoRequest>, activeSpeakerHeight: number): void;
325
439
  setGroupMembers(members: Array<GroupMemberInfo>): void;
326
440
  setMembershipProof(proof: Buffer): void;
@@ -405,7 +519,7 @@ export declare enum HangupType {
405
519
  Busy = 3,
406
520
  NeedPermission = 4
407
521
  }
408
- export declare enum BandwidthMode {
522
+ export declare enum DataMode {
409
523
  Low = 0,
410
524
  Normal = 1
411
525
  }
@@ -417,7 +531,7 @@ export interface CallManager {
417
531
  setConfig(config: Config): void;
418
532
  setSelfUuid(uuid: Buffer): void;
419
533
  createOutgoingCall(remoteUserId: UserId, isVideoCall: boolean, localDeviceId: DeviceId): CallId;
420
- proceed(callId: CallId, iceServerUsername: string, iceServerPassword: string, iceServerUrls: Array<string>, hideIp: boolean, bandwidthMode: BandwidthMode, audioLevelsIntervalMillis: number): void;
534
+ proceed(callId: CallId, iceServerUsername: string, iceServerPassword: string, iceServerUrls: Array<string>, hideIp: boolean, dataMode: DataMode, audioLevelsIntervalMillis: number): void;
421
535
  accept(callId: CallId): void;
422
536
  ignore(callId: CallId): void;
423
537
  hangup(): void;
@@ -427,7 +541,7 @@ export interface CallManager {
427
541
  setOutgoingAudioEnabled(enabled: boolean): void;
428
542
  setOutgoingVideoEnabled(enabled: boolean): void;
429
543
  setOutgoingVideoIsScreenShare(enabled: boolean): void;
430
- updateBandwidthMode(bandwidthMode: BandwidthMode): void;
544
+ updateDataMode(dataMode: DataMode): void;
431
545
  sendVideoFrame(width: number, height: number, format: VideoPixelFormatEnum, buffer: Buffer): void;
432
546
  receiveVideoFrame(buffer: Buffer, maxWidth: number, maxHeight: number): [number, number] | undefined;
433
547
  receivedOffer(remoteUserId: UserId, remoteDeviceId: DeviceId, localDeviceId: DeviceId, messageAgeSec: number, callId: CallId, offerType: OfferType, opaque: Buffer, senderIdentityKey: Buffer, receiverIdentityKey: Buffer): void;
@@ -439,6 +553,7 @@ export interface CallManager {
439
553
  receivedHttpResponse(requestId: number, status: number, body: Buffer): void;
440
554
  httpRequestFailed(requestId: number, debugInfo: string | undefined): void;
441
555
  createGroupCallClient(groupId: Buffer, sfuUrl: string, hkdfExtraInfo: Buffer, audioLevelsIntervalMillis: number): GroupCallClientId;
556
+ createCallLinkCallClient(sfuUrl: string, authCredentialPresentation: Buffer, linkRootKey: Buffer, adminPasskey: Buffer | undefined, hkdfExtraInfo: Buffer, audioLevelsIntervalMillis: number): GroupCallClientId;
442
557
  deleteGroupCallClient(clientId: GroupCallClientId): void;
443
558
  connect(clientId: GroupCallClientId): void;
444
559
  join(clientId: GroupCallClientId): void;
@@ -450,12 +565,16 @@ export interface CallManager {
450
565
  setOutgoingGroupCallVideoIsScreenShare(clientId: GroupCallClientId, isScreenShare: boolean): void;
451
566
  groupRing(clientId: GroupCallClientId, recipient: Buffer | undefined): void;
452
567
  resendMediaKeys(clientId: GroupCallClientId): void;
453
- setBandwidthMode(clientId: GroupCallClientId, bandwidthMode: BandwidthMode): void;
568
+ setDataMode(clientId: GroupCallClientId, dataMode: DataMode): void;
454
569
  requestVideo(clientId: GroupCallClientId, resolutions: Array<VideoRequest>, activeSpeakerHeight: number): void;
455
570
  setGroupMembers(clientId: GroupCallClientId, members: Array<GroupMemberInfo>): void;
456
571
  setMembershipProof(clientId: GroupCallClientId, proof: Buffer): void;
457
572
  receiveGroupCallVideoFrame(clientId: GroupCallClientId, remoteDemuxId: number, buffer: Buffer, maxWidth: number, maxHeight: number): [number, number] | undefined;
573
+ readCallLink(requestId: number, sfuUrl: string, authCredentialPresentation: Buffer, linkRootKey: Buffer): void;
574
+ createCallLink(requestId: number, sfuUrl: string, createCredentialPresentation: Buffer, linkRootKey: Buffer, adminPasskey: Buffer, callLinkPublicParams: Buffer): void;
575
+ updateCallLink(requestId: number, sfuUrl: string, authCredentialPresentation: Buffer, linkRootKey: Buffer, adminPasskey: Buffer, newName: string | undefined, newRestrictions: number | undefined, newRevoked: boolean | undefined): void;
458
576
  peekGroupCall(requestId: number, sfu_url: string, membership_proof: Buffer, group_members: Array<GroupMemberInfo>): void;
577
+ peekCallLinkCall(requestId: number, sfuUrl: string, authCredentialPresentation: Buffer, linkRootKey: Buffer): void;
459
578
  getAudioInputs(): Array<AudioDevice>;
460
579
  setAudioInput(index: number): void;
461
580
  getAudioOutputs(): Array<AudioDevice>;
@@ -484,7 +603,7 @@ export interface CallManagerCallbacks {
484
603
  handleJoinStateChanged(clientId: GroupCallClientId, joinState: JoinState, demuxId: number | undefined): void;
485
604
  handleRemoteDevicesChanged(clientId: GroupCallClientId, remoteDeviceStates: Array<RemoteDeviceState>): void;
486
605
  handlePeekChanged(clientId: GroupCallClientId, info: PeekInfo): void;
487
- handlePeekResponse(requestId: number, info: PeekInfo): void;
606
+ handlePeekResponse(requestId: number, statusCode: number, info: PeekInfo | undefined): void;
488
607
  handleEnded(clientId: GroupCallClientId, reason: GroupCallEndReason): void;
489
608
  onLogMessage(level: number, fileName: string, line: number, message: string): void;
490
609
  }
@@ -35,14 +35,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
35
35
  step((generator = generator.apply(thisArg, _arguments || [])).next());
36
36
  });
37
37
  };
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
38
41
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.CallLogLevel = exports.CallEndedReason = exports.CallState = exports.RingCancelReason = exports.BandwidthMode = exports.HangupType = exports.OpaqueMessage = exports.HangupMessage = exports.BusyMessage = exports.IceCandidateMessage = exports.AnswerMessage = exports.OfferType = exports.OfferMessage = exports.CallingMessage = exports.GroupCall = exports.VideoRequest = exports.GroupMemberInfo = exports.RemoteDeviceState = exports.LocalDeviceState = exports.HttpMethod = exports.RingUpdate = exports.CallMessageUrgency = exports.GroupCallEndReason = exports.JoinState = exports.ConnectionState = exports.Call = exports.RingRTCType = exports.ReceivedAudioLevel = exports.NetworkRoute = exports.PeekInfo = exports.PeekDeviceInfo = exports.callIdFromRingId = exports.callIdFromEra = void 0;
42
+ exports.CallLogLevel = exports.CallEndedReason = exports.CallState = exports.RingCancelReason = exports.DataMode = exports.HangupType = exports.OpaqueMessage = exports.HangupMessage = exports.BusyMessage = exports.IceCandidateMessage = exports.AnswerMessage = exports.OfferType = exports.OfferMessage = exports.CallingMessage = exports.GroupCall = exports.VideoRequest = exports.GroupMemberInfo = exports.RemoteDeviceState = exports.LocalDeviceState = exports.HttpMethod = exports.RingUpdate = exports.CallMessageUrgency = exports.GroupCallEndReason = exports.JoinState = exports.ConnectionState = exports.Call = exports.RingRTCType = exports.ReceivedAudioLevel = exports.NetworkRoute = exports.PeekStatusCodes = exports.callIdFromRingId = exports.callIdFromEra = void 0;
40
43
  /* eslint-disable max-classes-per-file */
41
- const os = __importStar(require("os"));
42
44
  const process = __importStar(require("process"));
43
- // eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require
44
- const Native = require(`../../build/${os.platform()}/libringrtc-${process.arch}.node`);
45
- exports.callIdFromEra = Native.callIdFromEra;
45
+ const CallLinks_1 = require("./CallLinks");
46
+ const Native_1 = __importDefault(require("./Native"));
47
+ exports.callIdFromEra = Native_1.default.callIdFromEra;
46
48
  function callIdFromRingId(ringId) {
47
49
  return {
48
50
  low: Number(BigInt.asIntN(32, ringId)),
@@ -65,22 +67,25 @@ class NativeCallManager {
65
67
  this.createCallEndpoint(config);
66
68
  }
67
69
  createCallEndpoint(config) {
68
- const fieldTrials = Object.assign({ 'RingRTC-AnyAddressPortsKillSwitch': 'Enabled' }, config.field_trials);
70
+ const fieldTrials = Object.assign({
71
+ 'RingRTC-AnyAddressPortsKillSwitch': 'Enabled',
72
+ 'WebRTC-Audio-OpusSetSignalVoiceWithDtx': 'Enabled',
73
+ }, config.field_trials);
69
74
  /* eslint-disable prefer-template */
70
75
  const fieldTrialsString = Object.entries(fieldTrials)
71
76
  .map(([k, v]) => `${k}/${v}`)
72
77
  .join('/') + '/';
73
78
  /* eslint-enable prefer-template */
74
- Object.defineProperty(this, Native.callEndpointPropertyKey, {
79
+ Object.defineProperty(this, Native_1.default.callEndpointPropertyKey, {
75
80
  configurable: true,
76
81
  get() {
77
- const callEndpoint = Native.createCallEndpoint(this, config.use_new_audio_device_module, fieldTrialsString);
82
+ const callEndpoint = Native_1.default.createCallEndpoint(this, config.use_new_audio_device_module, fieldTrialsString);
78
83
  if (process.platform === 'darwin') {
79
84
  // Preload devices to work around
80
85
  // https://bugs.chromium.org/p/chromium/issues/detail?id=1287628
81
86
  void window.navigator.mediaDevices.enumerateDevices();
82
87
  }
83
- Object.defineProperty(this, Native.callEndpointPropertyKey, {
88
+ Object.defineProperty(this, Native_1.default.callEndpointPropertyKey, {
84
89
  configurable: true,
85
90
  value: callEndpoint,
86
91
  });
@@ -92,90 +97,86 @@ class NativeCallManager {
92
97
  }
93
98
  // Mirror methods onto NativeCallManager.
94
99
  // This is done through direct assignment rather than wrapper methods to avoid indirection.
95
- NativeCallManager.prototype.setSelfUuid = Native.cm_setSelfUuid;
100
+ NativeCallManager.prototype.setSelfUuid = Native_1.default.cm_setSelfUuid;
96
101
  NativeCallManager.prototype.createOutgoingCall =
97
- Native.cm_createOutgoingCall;
98
- NativeCallManager.prototype.proceed = Native.cm_proceed;
99
- NativeCallManager.prototype.accept = Native.cm_accept;
100
- NativeCallManager.prototype.ignore = Native.cm_ignore;
101
- NativeCallManager.prototype.hangup = Native.cm_hangup;
102
+ Native_1.default.cm_createOutgoingCall;
103
+ NativeCallManager.prototype.proceed = Native_1.default.cm_proceed;
104
+ NativeCallManager.prototype.accept = Native_1.default.cm_accept;
105
+ NativeCallManager.prototype.ignore = Native_1.default.cm_ignore;
106
+ NativeCallManager.prototype.hangup = Native_1.default.cm_hangup;
102
107
  NativeCallManager.prototype.cancelGroupRing =
103
- Native.cm_cancelGroupRing;
108
+ Native_1.default.cm_cancelGroupRing;
104
109
  NativeCallManager.prototype.signalingMessageSent =
105
- Native.cm_signalingMessageSent;
110
+ Native_1.default.cm_signalingMessageSent;
106
111
  NativeCallManager.prototype.signalingMessageSendFailed =
107
- Native.cm_signalingMessageSendFailed;
108
- NativeCallManager.prototype.updateBandwidthMode =
109
- Native.cm_updateBandwidthMode;
110
- NativeCallManager.prototype.receivedOffer = Native.cm_receivedOffer;
111
- NativeCallManager.prototype.receivedAnswer = Native.cm_receivedAnswer;
112
+ Native_1.default.cm_signalingMessageSendFailed;
113
+ NativeCallManager.prototype.updateDataMode = Native_1.default.cm_updateDataMode;
114
+ NativeCallManager.prototype.receivedOffer = Native_1.default.cm_receivedOffer;
115
+ NativeCallManager.prototype.receivedAnswer = Native_1.default.cm_receivedAnswer;
112
116
  NativeCallManager.prototype.receivedIceCandidates =
113
- Native.cm_receivedIceCandidates;
114
- NativeCallManager.prototype.receivedHangup = Native.cm_receivedHangup;
115
- NativeCallManager.prototype.receivedBusy = Native.cm_receivedBusy;
117
+ Native_1.default.cm_receivedIceCandidates;
118
+ NativeCallManager.prototype.receivedHangup = Native_1.default.cm_receivedHangup;
119
+ NativeCallManager.prototype.receivedBusy = Native_1.default.cm_receivedBusy;
116
120
  NativeCallManager.prototype.receivedCallMessage =
117
- Native.cm_receivedCallMessage;
121
+ Native_1.default.cm_receivedCallMessage;
118
122
  NativeCallManager.prototype.receivedHttpResponse =
119
- Native.cm_receivedHttpResponse;
123
+ Native_1.default.cm_receivedHttpResponse;
120
124
  NativeCallManager.prototype.httpRequestFailed =
121
- Native.cm_httpRequestFailed;
125
+ Native_1.default.cm_httpRequestFailed;
122
126
  NativeCallManager.prototype.setOutgoingAudioEnabled =
123
- Native.cm_setOutgoingAudioEnabled;
127
+ Native_1.default.cm_setOutgoingAudioEnabled;
124
128
  NativeCallManager.prototype.setOutgoingVideoEnabled =
125
- Native.cm_setOutgoingVideoEnabled;
129
+ Native_1.default.cm_setOutgoingVideoEnabled;
126
130
  NativeCallManager.prototype.setOutgoingVideoIsScreenShare =
127
- Native.cm_setOutgoingVideoIsScreenShare;
128
- NativeCallManager.prototype.sendVideoFrame = Native.cm_sendVideoFrame;
131
+ Native_1.default.cm_setOutgoingVideoIsScreenShare;
132
+ NativeCallManager.prototype.sendVideoFrame = Native_1.default.cm_sendVideoFrame;
129
133
  NativeCallManager.prototype.receiveVideoFrame =
130
- Native.cm_receiveVideoFrame;
134
+ Native_1.default.cm_receiveVideoFrame;
131
135
  NativeCallManager.prototype.receiveGroupCallVideoFrame =
132
- Native.cm_receiveGroupCallVideoFrame;
136
+ Native_1.default.cm_receiveGroupCallVideoFrame;
133
137
  NativeCallManager.prototype.createGroupCallClient =
134
- Native.cm_createGroupCallClient;
138
+ Native_1.default.cm_createGroupCallClient;
139
+ NativeCallManager.prototype.createCallLinkCallClient =
140
+ Native_1.default.cm_createCallLinkCallClient;
135
141
  NativeCallManager.prototype.deleteGroupCallClient =
136
- Native.cm_deleteGroupCallClient;
137
- NativeCallManager.prototype.connect = Native.cm_connect;
138
- NativeCallManager.prototype.join = Native.cm_join;
139
- NativeCallManager.prototype.leave = Native.cm_leave;
140
- NativeCallManager.prototype.disconnect = Native.cm_disconnect;
141
- NativeCallManager.prototype.groupRing = Native.cm_groupRing;
142
+ Native_1.default.cm_deleteGroupCallClient;
143
+ NativeCallManager.prototype.connect = Native_1.default.cm_connect;
144
+ NativeCallManager.prototype.join = Native_1.default.cm_join;
145
+ NativeCallManager.prototype.leave = Native_1.default.cm_leave;
146
+ NativeCallManager.prototype.disconnect = Native_1.default.cm_disconnect;
147
+ NativeCallManager.prototype.groupRing = Native_1.default.cm_groupRing;
142
148
  NativeCallManager.prototype.setOutgoingAudioMuted =
143
- Native.cm_setOutgoingAudioMuted;
149
+ Native_1.default.cm_setOutgoingAudioMuted;
144
150
  NativeCallManager.prototype.setOutgoingVideoMuted =
145
- Native.cm_setOutgoingVideoMuted;
151
+ Native_1.default.cm_setOutgoingVideoMuted;
146
152
  NativeCallManager.prototype.setOutgoingGroupCallVideoIsScreenShare =
147
- Native.cm_setOutgoingGroupCallVideoIsScreenShare;
148
- NativeCallManager.prototype.setPresenting = Native.cm_setPresenting;
153
+ Native_1.default.cm_setOutgoingGroupCallVideoIsScreenShare;
154
+ NativeCallManager.prototype.setPresenting = Native_1.default.cm_setPresenting;
149
155
  NativeCallManager.prototype.resendMediaKeys =
150
- Native.cm_resendMediaKeys;
151
- NativeCallManager.prototype.setBandwidthMode =
152
- Native.cm_setBandwidthMode;
153
- NativeCallManager.prototype.requestVideo = Native.cm_requestVideo;
156
+ Native_1.default.cm_resendMediaKeys;
157
+ NativeCallManager.prototype.setDataMode = Native_1.default.cm_setDataMode;
158
+ NativeCallManager.prototype.requestVideo = Native_1.default.cm_requestVideo;
154
159
  NativeCallManager.prototype.setGroupMembers =
155
- Native.cm_setGroupMembers;
160
+ Native_1.default.cm_setGroupMembers;
156
161
  NativeCallManager.prototype.setMembershipProof =
157
- Native.cm_setMembershipProof;
158
- NativeCallManager.prototype.peekGroupCall = Native.cm_peekGroupCall;
159
- NativeCallManager.prototype.getAudioInputs = Native.cm_getAudioInputs;
160
- NativeCallManager.prototype.setAudioInput = Native.cm_setAudioInput;
162
+ Native_1.default.cm_setMembershipProof;
163
+ NativeCallManager.prototype.readCallLink = Native_1.default.cm_readCallLink;
164
+ NativeCallManager.prototype.createCallLink = Native_1.default.cm_createCallLink;
165
+ NativeCallManager.prototype.updateCallLink = Native_1.default.cm_updateCallLink;
166
+ NativeCallManager.prototype.peekGroupCall = Native_1.default.cm_peekGroupCall;
167
+ NativeCallManager.prototype.peekCallLinkCall =
168
+ Native_1.default.cm_peekCallLinkCall;
169
+ NativeCallManager.prototype.getAudioInputs = Native_1.default.cm_getAudioInputs;
170
+ NativeCallManager.prototype.setAudioInput = Native_1.default.cm_setAudioInput;
161
171
  NativeCallManager.prototype.getAudioOutputs =
162
- Native.cm_getAudioOutputs;
163
- NativeCallManager.prototype.setAudioOutput = Native.cm_setAudioOutput;
164
- NativeCallManager.prototype.processEvents = Native.cm_processEvents;
165
- class PeekDeviceInfo {
166
- constructor(demuxId, userId) {
167
- this.demuxId = demuxId;
168
- this.userId = userId;
169
- }
170
- }
171
- exports.PeekDeviceInfo = PeekDeviceInfo;
172
- class PeekInfo {
173
- constructor() {
174
- this.devices = [];
175
- this.deviceCount = 0;
176
- }
177
- }
178
- exports.PeekInfo = PeekInfo;
172
+ Native_1.default.cm_getAudioOutputs;
173
+ NativeCallManager.prototype.setAudioOutput = Native_1.default.cm_setAudioOutput;
174
+ NativeCallManager.prototype.processEvents = Native_1.default.cm_processEvents;
175
+ var PeekStatusCodes;
176
+ (function (PeekStatusCodes) {
177
+ PeekStatusCodes[PeekStatusCodes["EXPIRED_CALL_LINK"] = 703] = "EXPIRED_CALL_LINK";
178
+ PeekStatusCodes[PeekStatusCodes["INVALID_CALL_LINK"] = 704] = "INVALID_CALL_LINK";
179
+ })(PeekStatusCodes = exports.PeekStatusCodes || (exports.PeekStatusCodes = {}));
179
180
  // In sync with WebRTC's PeerConnection.AdapterType.
180
181
  // Despite how it looks, this is not an option set.
181
182
  // A network adapter type can only be one of the listed values.
@@ -270,6 +271,7 @@ class RingRTCType {
270
271
  this._call = null;
271
272
  this._groupCallByClientId = new Map();
272
273
  this._peekRequests = new Requests();
274
+ this._callLinkRequests = new Requests();
273
275
  this._callInfoByCallId = new Map();
274
276
  }
275
277
  setConfig(config) {
@@ -375,7 +377,7 @@ class RingRTCType {
375
377
  }
376
378
  proceed(callId, settings) {
377
379
  sillyDeadlockProtection(() => {
378
- this.callManager.proceed(callId, settings.iceServer.username || '', settings.iceServer.password || '', settings.iceServer.urls, settings.hideIp, settings.bandwidthMode, settings.audioLevelsIntervalMillis || 0);
380
+ this.callManager.proceed(callId, settings.iceServer.username || '', settings.iceServer.password || '', settings.iceServer.urls, settings.hideIp, settings.dataMode, settings.audioLevelsIntervalMillis || 0);
379
381
  });
380
382
  }
381
383
  // Called by Rust
@@ -542,6 +544,138 @@ class RingRTCType {
542
544
  }
543
545
  }))().catch(e => this.logError(e.toString()));
544
546
  }
547
+ // Call Links
548
+ /**
549
+ * Asynchronous request to get information about a call link.
550
+ *
551
+ * @param sfuUrl - the URL to use when accessing the SFU
552
+ * @param authCredentialPresentation - a serialized CallLinkAuthCredentialPresentation
553
+ * @param linkRootKey - the root key for the call link
554
+ *
555
+ * Expected failure codes include:
556
+ * - 404: the room does not exist (or expired so long ago that it has been removed from the server)
557
+ */
558
+ readCallLink(sfuUrl, authCredentialPresentation, linkRootKey) {
559
+ const [requestId, promise] = this._callLinkRequests.add();
560
+ // Response comes back via handleCallLinkResponse
561
+ sillyDeadlockProtection(() => {
562
+ this.callManager.readCallLink(requestId, sfuUrl, authCredentialPresentation, linkRootKey.bytes);
563
+ });
564
+ return promise;
565
+ }
566
+ /**
567
+ * Asynchronous request to create a new call link.
568
+ *
569
+ * This request is idempotent; if it fails due to a network issue, it is safe to retry.
570
+ *
571
+ * @example
572
+ * const linkKey = CallLinkRootKey.generate();
573
+ * const adminPasskey = CallLinkRootKey.generateAdminPasskey();
574
+ * const roomId = linkKey.deriveRoomId();
575
+ * const credential = requestCreateCredentialFromChatServer(roomId); // using libsignal
576
+ * const secretParams = CallLinkSecretParams.deriveFromRootKey(linkKey.bytes);
577
+ * const credentialPresentation = credential.present(roomId, secretParams).serialize();
578
+ * const serializedPublicParams = secretParams.getPublicParams().serialize();
579
+ * const result = await RingRTC.createCallLink(sfuUrl, credentialPresentation, linkKey, adminPasskey, serializedPublicParams);
580
+ * if (result.success) {
581
+ * const state = result.value;
582
+ * // In actuality you may not want to do this until the user clicks Done.
583
+ * saveToDatabase(linkKey.bytes, adminPasskey, state);
584
+ * syncToOtherDevices(linkKey.bytes, adminPasskey);
585
+ * } else {
586
+ * switch (result.errorStatusCode) {
587
+ * case 409:
588
+ * // The room already exists (and isn't yours), i.e. you've hit a 1-in-a-billion conflict.
589
+ * // Fall through to kicking the user out to try again later.
590
+ * default:
591
+ * // Unexpected error, kick the user out for now.
592
+ * }
593
+ * }
594
+ *
595
+ * @param sfuUrl - the URL to use when accessing the SFU
596
+ * @param createCredentialPresentation - a serialized CreateCallLinkCredentialPresentation
597
+ * @param linkRootKey - the root key for the call link
598
+ * @param adminPasskey - the arbitrary passkey to use for the new room
599
+ * @param callLinkPublicParams - the serialized CallLinkPublicParams for the new room
600
+ */
601
+ createCallLink(sfuUrl, createCredentialPresentation, linkRootKey, adminPasskey, callLinkPublicParams) {
602
+ const [requestId, promise] = this._callLinkRequests.add();
603
+ // Response comes back via handleCallLinkResponse
604
+ sillyDeadlockProtection(() => {
605
+ this.callManager.createCallLink(requestId, sfuUrl, createCredentialPresentation, linkRootKey.bytes, adminPasskey, callLinkPublicParams);
606
+ });
607
+ return promise;
608
+ }
609
+ /**
610
+ * Asynchronous request to update a call link's name.
611
+ *
612
+ * Possible failure codes include:
613
+ * - 401: the room does not exist (and this is the wrong API to create a new room)
614
+ * - 403: the admin passkey is incorrect
615
+ *
616
+ * This request is idempotent; if it fails due to a network issue, it is safe to retry.
617
+ *
618
+ * @param sfuUrl - the URL to use when accessing the SFU
619
+ * @param authCredentialPresentation - a serialized CallLinkAuthCredentialPresentation
620
+ * @param linkRootKey - the root key for the call link
621
+ * @param adminPasskey - the passkey specified when the link was created
622
+ * @param newName - the new name to use
623
+ */
624
+ updateCallLinkName(sfuUrl, authCredentialPresentation, linkRootKey, adminPasskey, newName) {
625
+ const [requestId, promise] = this._callLinkRequests.add();
626
+ // Response comes back via handleCallLinkResponse
627
+ sillyDeadlockProtection(() => {
628
+ this.callManager.updateCallLink(requestId, sfuUrl, authCredentialPresentation, linkRootKey.bytes, adminPasskey, newName, undefined, undefined);
629
+ });
630
+ return promise;
631
+ }
632
+ /**
633
+ * Asynchronous request to update a call link's restrictions.
634
+ *
635
+ * Possible failure codes include:
636
+ * - 401: the room does not exist (and this is the wrong API to create a new room)
637
+ * - 403: the admin passkey is incorrect
638
+ *
639
+ * This request is idempotent; if it fails due to a network issue, it is safe to retry.
640
+ *
641
+ * @param sfuUrl - the URL to use when accessing the SFU
642
+ * @param authCredentialPresentation - a serialized CallLinkAuthCredentialPresentation
643
+ * @param linkRootKey - the root key for the call link
644
+ * @param adminPasskey - the passkey specified when the link was created
645
+ * @param restrictions - the new restrictions to use
646
+ */
647
+ updateCallLinkRestrictions(sfuUrl, authCredentialPresentation, linkRootKey, adminPasskey, restrictions) {
648
+ const [requestId, promise] = this._callLinkRequests.add();
649
+ // Response comes back via handleCallLinkResponse
650
+ sillyDeadlockProtection(() => {
651
+ this.callManager.updateCallLink(requestId, sfuUrl, authCredentialPresentation, linkRootKey.bytes, adminPasskey, undefined, restrictions, undefined);
652
+ });
653
+ return promise;
654
+ }
655
+ /**
656
+ * Asynchronous request to revoke or un-revoke a call link.
657
+ *
658
+ * Possible failure codes include:
659
+ * - 401: the room does not exist (and this is the wrong API to create a new room)
660
+ * - 403: the admin passkey is incorrect
661
+ *
662
+ * This request is idempotent; if it fails due to a network issue, it is safe to retry.
663
+ *
664
+ * @param sfuUrl - the URL to use when accessing the SFU
665
+ * @param authCredentialPresentation - a serialized CallLinkAuthCredentialPresentation
666
+ * @param linkRootKey - the root key for the call link
667
+ * @param adminPasskey - the passkey specified when the link was created
668
+ * @param revoked - whether the link should now be revoked
669
+ */
670
+ updateCallLinkRevocation(sfuUrl, authCredentialPresentation, linkRootKey, adminPasskey, revoked) {
671
+ const [requestId, promise] = this._callLinkRequests.add();
672
+ // Response comes back via handleCallLinkResponse
673
+ sillyDeadlockProtection(() => {
674
+ this.callManager.updateCallLink(requestId, sfuUrl, authCredentialPresentation, linkRootKey.bytes, adminPasskey, undefined, undefined, revoked);
675
+ });
676
+ return promise;
677
+ }
678
+ // HTTP callbacks
545
679
  receivedHttpResponse(requestId, status, body) {
546
680
  sillyDeadlockProtection(() => {
547
681
  try {
@@ -567,7 +701,15 @@ class RingRTCType {
567
701
  // Group Calls
568
702
  // Called by UX
569
703
  getGroupCall(groupId, sfuUrl, hkdfExtraInfo, audioLevelsIntervalMillis, observer) {
570
- const groupCall = new GroupCall(this.callManager, groupId, sfuUrl, hkdfExtraInfo, audioLevelsIntervalMillis, observer);
704
+ const clientId = this.callManager.createGroupCallClient(groupId, sfuUrl, hkdfExtraInfo, audioLevelsIntervalMillis || 0);
705
+ const groupCall = new GroupCall(this.callManager, observer, clientId);
706
+ this._groupCallByClientId.set(groupCall.clientId, groupCall);
707
+ return groupCall;
708
+ }
709
+ // Called by UX
710
+ getCallLinkCall(sfuUrl, authCredentialPresentation, rootKey, adminPasskey, hkdfExtraInfo, audioLevelsIntervalMillis, observer) {
711
+ const clientId = this.callManager.createCallLinkCallClient(sfuUrl, authCredentialPresentation, rootKey.bytes, adminPasskey, hkdfExtraInfo, audioLevelsIntervalMillis || 0);
712
+ const groupCall = new GroupCall(this.callManager, observer, clientId);
571
713
  this._groupCallByClientId.set(groupCall.clientId, groupCall);
572
714
  return groupCall;
573
715
  }
@@ -579,6 +721,22 @@ class RingRTCType {
579
721
  sillyDeadlockProtection(() => {
580
722
  this.callManager.peekGroupCall(requestId, sfuUrl, membershipProof, groupMembers);
581
723
  });
724
+ return promise.then(result => {
725
+ if (result.success) {
726
+ return result.value;
727
+ }
728
+ else {
729
+ return { devices: [], deviceCount: 0 };
730
+ }
731
+ });
732
+ }
733
+ // Called by UX
734
+ peekCallLinkCall(sfuUrl, authCredentialPresentation, rootKey) {
735
+ const [requestId, promise] = this._peekRequests.add();
736
+ // Response comes back via handlePeekResponse
737
+ sillyDeadlockProtection(() => {
738
+ this.callManager.peekCallLinkCall(requestId, sfuUrl, authCredentialPresentation, rootKey.bytes);
739
+ });
582
740
  return promise;
583
741
  }
584
742
  // Called by Rust
@@ -668,14 +826,52 @@ class RingRTCType {
668
826
  });
669
827
  }
670
828
  // Called by Rust
671
- handlePeekResponse(requestId, info) {
829
+ handlePeekResponse(requestId, statusCode, info) {
672
830
  sillyDeadlockProtection(() => {
673
- if (!this._peekRequests.resolve(requestId, info)) {
831
+ let result;
832
+ if (info) {
833
+ result = { success: true, value: info };
834
+ }
835
+ else {
836
+ result = { success: false, errorStatusCode: statusCode };
837
+ }
838
+ if (!this._peekRequests.resolve(requestId, result)) {
674
839
  this.logWarn(`Invalid request ID for handlePeekResponse: ${requestId}`);
675
840
  }
676
841
  });
677
842
  }
678
843
  // Called by Rust
844
+ handleCallLinkResponse(requestId, statusCode, state) {
845
+ sillyDeadlockProtection(() => {
846
+ // Recreate the state so that we have the correct prototype, in case we add more methods to CallLinkState.
847
+ let result;
848
+ if (state) {
849
+ let restrictions;
850
+ switch (state.rawRestrictions) {
851
+ case 0:
852
+ restrictions = CallLinks_1.CallLinkRestrictions.None;
853
+ break;
854
+ case 1:
855
+ restrictions = CallLinks_1.CallLinkRestrictions.AdminApproval;
856
+ break;
857
+ default:
858
+ restrictions = CallLinks_1.CallLinkRestrictions.Unknown;
859
+ break;
860
+ }
861
+ result = {
862
+ success: true,
863
+ value: new CallLinks_1.CallLinkState(state.name, restrictions, state.revoked, state.expiration),
864
+ };
865
+ }
866
+ else {
867
+ result = { success: false, errorStatusCode: statusCode };
868
+ }
869
+ if (!this._callLinkRequests.resolve(requestId, result)) {
870
+ this.logWarn(`Invalid request ID for handleCallLinkResponse: ${requestId}`);
871
+ }
872
+ });
873
+ }
874
+ // Called by Rust
679
875
  handleEnded(clientId, reason) {
680
876
  sillyDeadlockProtection(() => {
681
877
  const groupCall = this._groupCallByClientId.get(clientId);
@@ -1087,10 +1283,10 @@ class Call {
1087
1283
  }
1088
1284
  });
1089
1285
  }
1090
- updateBandwidthMode(bandwidthMode) {
1286
+ updateDataMode(dataMode) {
1091
1287
  sillyDeadlockProtection(() => {
1092
1288
  try {
1093
- this._callManager.updateBandwidthMode(bandwidthMode);
1289
+ this._callManager.updateDataMode(dataMode);
1094
1290
  }
1095
1291
  catch (_a) {
1096
1292
  // We may not have an active connection any more.
@@ -1238,11 +1434,11 @@ class GroupCall {
1238
1434
  return this._clientId;
1239
1435
  }
1240
1436
  // Called by UI via RingRTC object
1241
- constructor(callManager, groupId, sfuUrl, hkdfExtraInfo, audioLevelsIntervalMillis, observer) {
1437
+ constructor(callManager, observer, clientId) {
1242
1438
  this._callManager = callManager;
1243
1439
  this._observer = observer;
1440
+ this._clientId = clientId;
1244
1441
  this._localDeviceState = new LocalDeviceState();
1245
- this._clientId = this._callManager.createGroupCallClient(groupId, sfuUrl, hkdfExtraInfo, audioLevelsIntervalMillis || 0);
1246
1442
  }
1247
1443
  // Called by UI
1248
1444
  connect() {
@@ -1305,8 +1501,8 @@ class GroupCall {
1305
1501
  this._callManager.resendMediaKeys(this._clientId);
1306
1502
  }
1307
1503
  // Called by UI
1308
- setBandwidthMode(bandwidthMode) {
1309
- this._callManager.setBandwidthMode(this._clientId, bandwidthMode);
1504
+ setDataMode(dataMode) {
1505
+ this._callManager.setDataMode(this._clientId, dataMode);
1310
1506
  }
1311
1507
  // Called by UI
1312
1508
  requestVideo(resolutions, activeSpeakerHeight) {
@@ -1484,11 +1680,11 @@ var HangupType;
1484
1680
  HangupType[HangupType["Busy"] = 3] = "Busy";
1485
1681
  HangupType[HangupType["NeedPermission"] = 4] = "NeedPermission";
1486
1682
  })(HangupType = exports.HangupType || (exports.HangupType = {}));
1487
- var BandwidthMode;
1488
- (function (BandwidthMode) {
1489
- BandwidthMode[BandwidthMode["Low"] = 0] = "Low";
1490
- BandwidthMode[BandwidthMode["Normal"] = 1] = "Normal";
1491
- })(BandwidthMode = exports.BandwidthMode || (exports.BandwidthMode = {}));
1683
+ var DataMode;
1684
+ (function (DataMode) {
1685
+ DataMode[DataMode["Low"] = 0] = "Low";
1686
+ DataMode[DataMode["Normal"] = 1] = "Normal";
1687
+ })(DataMode = exports.DataMode || (exports.DataMode = {}));
1492
1688
  /// Describes why a ring was cancelled.
1493
1689
  var RingCancelReason;
1494
1690
  (function (RingCancelReason) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signalapp/ringrtc",
3
- "version": "2.26.4",
3
+ "version": "2.28.0",
4
4
  "description": "Signal Messenger voice and video calling library.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "config": {
25
25
  "prebuildUrl": "https://build-artifacts.signal.org/libraries/ringrtc-desktop-build-v${npm_package_version}.tar.gz",
26
- "prebuildChecksum": "6152f6a46abca73e62644fc82e36b2ffa7927cbae1f671a2ba04a7519eb670a1"
26
+ "prebuildChecksum": "5d4bd3c13ee3373d0e67dacce7e64a422fdc4e0eb8f9c551495fa5b90ec1f322"
27
27
  },
28
28
  "author": "",
29
29
  "license": "AGPL-3.0-only",