diff --git a/package.json b/package.json index e88249ac05..fe56a00fa6 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "@react-spring/web": "9.5.5", "@signalapp/better-sqlite3": "8.4.3", "@signalapp/libsignal-client": "0.22.0", - "@signalapp/ringrtc": "2.25.2", + "@signalapp/ringrtc": "2.26.2", "@types/fabric": "4.5.3", "backbone": "1.4.0", "blob-util": "2.0.2", diff --git a/ts/services/calling.ts b/ts/services/calling.ts index 592657b6f1..a68a2683cb 100644 --- a/ts/services/calling.ts +++ b/ts/services/calling.ts @@ -14,6 +14,8 @@ import type { VideoRequest, } from '@signalapp/ringrtc'; import { + AnswerMessage, + BusyMessage, Call, CallEndedReason, CallingMessage, @@ -28,6 +30,8 @@ import { GumVideoCapturer, HangupMessage, HangupType, + IceCandidateMessage, + OfferMessage, OpaqueMessage, RingCancelReason, RingRTC, @@ -72,7 +76,7 @@ import type { ConversationModel } from '../models/conversations'; import * as Bytes from '../Bytes'; import { uuidToBytes, bytesToUuid } from '../Crypto'; import { drop } from '../util/drop'; -import { dropNull, shallowDropNull } from '../util/dropNull'; +import { dropNull } from '../util/dropNull'; import { getOwn } from '../util/getOwn'; import { isNormalNumber } from '../util/isNormalNumber'; import * as durations from '../util/durations'; @@ -220,44 +224,51 @@ function protoToCallingMessage({ destinationDeviceId, opaque, }: Proto.ICallingMessage): CallingMessage { - return { - offer: offer - ? { - ...shallowDropNull(offer), + const newIceCandidates: Array = []; + if (iceCandidates) { + iceCandidates.forEach(candidate => { + if (candidate.callId && candidate.opaque) { + newIceCandidates.push( + new IceCandidateMessage( + candidate.callId, + Buffer.from(candidate.opaque) + ) + ); + } + }); + } - type: dropNull(offer.type) as number, - opaque: offer.opaque ? Buffer.from(offer.opaque) : undefined, - } - : undefined, - answer: answer - ? { - ...shallowDropNull(answer), - opaque: answer.opaque ? Buffer.from(answer.opaque) : undefined, - } - : undefined, - iceCandidates: iceCandidates - ? iceCandidates.map(candidate => { - return { - ...shallowDropNull(candidate), - opaque: candidate.opaque - ? Buffer.from(candidate.opaque) - : undefined, - }; - }) - : undefined, - legacyHangup: legacyHangup - ? { - ...shallowDropNull(legacyHangup), - type: dropNull(legacyHangup.type) as number, - } - : undefined, - busy: shallowDropNull(busy), - hangup: hangup - ? { - ...shallowDropNull(hangup), - type: dropNull(hangup.type) as number, - } - : undefined, + return { + offer: + offer && offer.callId && offer.opaque + ? new OfferMessage( + offer.callId, + dropNull(offer.type) as number, + Buffer.from(offer.opaque) + ) + : undefined, + answer: + answer && answer.callId && answer.opaque + ? new AnswerMessage(answer.callId, Buffer.from(answer.opaque)) + : undefined, + iceCandidates: newIceCandidates.length > 0 ? newIceCandidates : undefined, + legacyHangup: + legacyHangup && legacyHangup.callId + ? new HangupMessage( + legacyHangup.callId, + dropNull(legacyHangup.type) as number, + legacyHangup.deviceId || 0 + ) + : undefined, + busy: busy && busy.callId ? new BusyMessage(busy.callId) : undefined, + hangup: + hangup && hangup.callId + ? new HangupMessage( + hangup.callId, + dropNull(hangup.type) as number, + hangup.deviceId || 0 + ) + : undefined, supportsMultiRing: dropNull(supportsMultiRing), destinationDeviceId: dropNull(destinationDeviceId), opaque: opaque @@ -1536,25 +1547,26 @@ export class CallingClass { 'Conversation was not approved by user; rejecting call message.' ); - const hangup = new HangupMessage(); - hangup.callId = callingMessage.offer.callId; - hangup.deviceId = remoteDeviceId; - hangup.type = HangupType.NeedPermission; + const { callId } = callingMessage.offer; + assertDev(callId != null, 'Call ID missing from offer'); + + const hangup = new HangupMessage( + callId, + HangupType.NeedPermission, + remoteDeviceId + ); const message = new CallingMessage(); message.legacyHangup = hangup; await this.handleOutgoingSignaling(remoteUserId, message); - const callId = callingMessage.offer.callId?.toString(); - assertDev(callId != null, 'Call ID missing from offer'); - const ProtoOfferType = Proto.CallingMessage.Offer.Type; await this.addCallHistoryForFailedIncomingCall( conversation, callingMessage.offer.type === ProtoOfferType.OFFER_VIDEO_CALL, envelope.timestamp, - callId + callId.toString() ); return; diff --git a/ts/test-node/util/callingMessageToProto_test.ts b/ts/test-node/util/callingMessageToProto_test.ts index ccd05fd728..6f33780773 100644 --- a/ts/test-node/util/callingMessageToProto_test.ts +++ b/ts/test-node/util/callingMessageToProto_test.ts @@ -2,6 +2,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import { assert } from 'chai'; +import type { CallId } from '@signalapp/ringrtc'; import { CallMessageUrgency, CallingMessage, @@ -23,9 +24,10 @@ describe('callingMessageToProto', () => { }); it('attaches the type if provided', () => { + const callId: CallId = { high: 0, low: 0, unsigned: false }; + const callingMessage = new CallingMessage(); - callingMessage.hangup = new HangupMessage(); - callingMessage.hangup.type = HangupType.Busy; + callingMessage.hangup = new HangupMessage(callId, HangupType.Busy, 1); const result = callingMessageToProto(callingMessage); diff --git a/ts/util/callingMessageToProto.ts b/ts/util/callingMessageToProto.ts index 66f98376fe..7b91c24a2e 100644 --- a/ts/util/callingMessageToProto.ts +++ b/ts/util/callingMessageToProto.ts @@ -3,6 +3,7 @@ import type { CallingMessage } from '@signalapp/ringrtc'; import { CallMessageUrgency } from '@signalapp/ringrtc'; +import Long from 'long'; import { SignalService as Proto } from '../protobuf'; import * as log from '../logging/log'; import { missingCaseError } from './missingCaseError'; @@ -39,6 +40,7 @@ export function callingMessageToProto( offer: offer ? { ...offer, + callId: Long.fromValue(offer.callId), type: offer.type as number, opaque: bufferToProto(offer.opaque), } @@ -46,6 +48,7 @@ export function callingMessageToProto( answer: answer ? { ...answer, + callId: Long.fromValue(answer.callId), opaque: bufferToProto(answer.opaque), } : undefined, @@ -53,6 +56,7 @@ export function callingMessageToProto( ? iceCandidates.map(candidate => { return { ...candidate, + callId: Long.fromValue(candidate.callId), opaque: bufferToProto(candidate.opaque), }; }) @@ -60,13 +64,20 @@ export function callingMessageToProto( legacyHangup: legacyHangup ? { ...legacyHangup, + callId: Long.fromValue(legacyHangup.callId), type: legacyHangup.type as number, } : undefined, - busy, + busy: busy + ? { + ...busy, + callId: Long.fromValue(busy.callId), + } + : undefined, hangup: hangup ? { ...hangup, + callId: Long.fromValue(hangup.callId), type: hangup.type as number, } : undefined, diff --git a/yarn.lock b/yarn.lock index 4b2a81650c..a831a1afa1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2269,10 +2269,10 @@ ws "^8.4.2" zod "^3.20.2" -"@signalapp/ringrtc@2.25.2": - version "2.25.2" - resolved "https://registry.yarnpkg.com/@signalapp/ringrtc/-/ringrtc-2.25.2.tgz#6e6e32fe3e507f1ead7cd287d53eb35d1f9b5ef9" - integrity sha512-3uy0e7gdPCkPFQGO7d74+wJYdPM/eAwvyW/tqnZ2FAqS2ybjF3XyoP9UI+jmrz8UF+IWGeu1ZZqy96XuxgJlfA== +"@signalapp/ringrtc@2.26.2": + version "2.26.2" + resolved "https://registry.yarnpkg.com/@signalapp/ringrtc/-/ringrtc-2.26.2.tgz#6ca91cd4b2d3ed545eb87c4aaddcb3f8735ad85a" + integrity sha512-Z80SrSuZl8EufG5cS6PEKo+vYYTKQ6mXD7Ybc1L8ambIYf2PsmLDI++ZN+NsEQVFXPQr9nwie/oQJGi145ffLQ== dependencies: tar "^6.1.0"