diff --git a/ts/services/calling.ts b/ts/services/calling.ts index b5f1ff3c6f..0c674c6127 100644 --- a/ts/services/calling.ts +++ b/ts/services/calling.ts @@ -165,11 +165,7 @@ export class CallingClass { return; } - const now = new Date(); - const serverTimestamp = envelope.serverTimestamp - ? envelope.serverTimestamp - : now.valueOf(); - const messageAgeSec = Math.floor((now.valueOf() - serverTimestamp) / 1000); + const messageAgeSec = envelope.messageAgeSec ? envelope.messageAgeSec : 0; RingRTC.handleCallingMessage( remoteUserId, diff --git a/ts/textsecure.d.ts b/ts/textsecure.d.ts index 0a9876b816..fc44d06765 100644 --- a/ts/textsecure.d.ts +++ b/ts/textsecure.d.ts @@ -372,6 +372,7 @@ export declare class EnvelopeClass { // Note: these additional properties are added in the course of processing id: string; unidentifiedDeliveryReceived?: boolean; + messageAgeSec?: number; } // Note: we need to use namespaces to express nested classes in Typescript diff --git a/ts/textsecure/MessageReceiver.ts b/ts/textsecure/MessageReceiver.ts index 88d2cb97db..2a1aff9b51 100644 --- a/ts/textsecure/MessageReceiver.ts +++ b/ts/textsecure/MessageReceiver.ts @@ -369,6 +369,12 @@ class MessageReceiverInner extends EventTarget { ? envelope.serverTimestamp.toNumber() : null; + // Calculate the message age (time on server). + envelope.messageAgeSec = this.calculateMessageAge( + headers, + envelope.serverTimestamp + ); + this.cacheAndQueue(envelope, plaintext, request); } catch (e) { request.respond(500, 'Bad encrypted websocket message'); @@ -385,6 +391,33 @@ class MessageReceiverInner extends EventTarget { // tslint:disable-next-line no-floating-promises this.incomingQueue.add(job); } + calculateMessageAge( + headers: Array, + serverTimestamp?: number + ): number { + let messageAgeSec = 0; // Default to 0 in case of unreliable parameters. + + if (serverTimestamp) { + // The 'X-Signal-Timestamp' is usually the last item, so start there. + let it = headers.length; + while (--it >= 0) { + const match = headers[it].match(/^X-Signal-Timestamp:\s*(\d+)\s*$/); + if (match && match.length === 2) { + const timestamp = Number(match[1]); + + // One final sanity check, the timestamp when a message is pulled from + // the server should be later than when it was pushed. + if (timestamp > serverTimestamp) { + messageAgeSec = Math.floor((timestamp - serverTimestamp) / 1000); + } + + break; + } + } + } + + return messageAgeSec; + } async addToQueue(task: () => Promise) { this.count += 1;