Improve error handling during group sends

This commit is contained in:
Fedor Indutny 2022-11-22 10:43:43 -08:00 committed by GitHub
parent f0a3735ca2
commit 991580a1ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
58 changed files with 299 additions and 324 deletions

View file

@ -575,7 +575,7 @@ export default class AccountManager extends EventTarget {
} catch (error) {
log.error(
'Something went wrong deleting data from previous number',
error && error.stack ? error.stack : error
Errors.toLogFormat(error)
);
}
} else {

View file

@ -8,6 +8,7 @@ import protobuf from '../protobuf/wrap';
import { SignalService as Proto } from '../protobuf';
import { normalizeUuid } from '../util/normalizeUuid';
import { DurationInSeconds } from '../util/durations';
import * as Errors from '../types/errors';
import * as log from '../logging/log';
import Avatar = Proto.ContactDetails.IAvatar;
@ -90,10 +91,7 @@ abstract class ParserBase<
expireTimer,
};
} catch (error) {
log.error(
'ProtoParser.next error:',
error && error.stack ? error.stack : error
);
log.error('ProtoParser.next error:', Errors.toLogFormat(error));
return undefined;
}
}

View file

@ -54,8 +54,9 @@ export class ReplayableError extends Error {
name?: string;
message: string;
functionCode?: number;
cause?: unknown;
}) {
super(options.message);
super(options.message, { cause: options.cause });
this.name = options.name || 'ReplayableError';
this.message = options.message;
@ -71,7 +72,7 @@ export class ReplayableError extends Error {
}
export class OutgoingIdentityKeyError extends ReplayableError {
identifier: string;
public readonly identifier: string;
// Note: Data to resend message is no longer captured
constructor(incomingIdentifier: string) {
@ -162,6 +163,7 @@ export class SendMessageChallengeError extends ReplayableError {
super({
name: 'SendMessageChallengeError',
message: httpError.message,
cause: httpError,
});
[this.identifier] = identifier.split('.');
@ -237,9 +239,7 @@ export class SendMessageProtoError extends Error implements CallbackResultType {
return 'No errors';
}
return errors
.map(error => (error.stackForLog ? error.stackForLog : error.toString()))
.join(', ');
return errors.map(error => error.toString()).join(', ');
}
}

View file

@ -13,6 +13,8 @@ import type {
PlaintextContent,
} from '@signalapp/libsignal-client';
import {
ErrorCode,
LibSignalErrorBase,
CiphertextMessageType,
ProtocolAddress,
sealedSenderEncrypt,
@ -34,6 +36,7 @@ import {
import type { CallbackResultType, CustomError } from './Types.d';
import { isValidNumber } from '../types/PhoneNumber';
import { Address } from '../types/Address';
import * as Errors from '../types/errors';
import { QualifiedAddress } from '../types/QualifiedAddress';
import { UUID, isValidUuid } from '../types/UUID';
import { Sessions, IdentityKeys } from '../LibSignalStores';
@ -244,8 +247,7 @@ export default class OutgoingMessage {
}
}
error.reason = reason;
error.stackForLog = providedError ? providedError.stack : undefined;
error.cause = reason;
this.errors[this.errors.length] = error;
this.numberCompleted();
@ -284,21 +286,14 @@ export default class OutgoingMessage {
: { accessKey: undefined };
const { accessKey } = info;
try {
const { accessKeyFailed } = await getKeysForIdentifier(
identifier,
this.server,
updateDevices,
accessKey
);
if (accessKeyFailed && !this.failoverIdentifiers.includes(identifier)) {
this.failoverIdentifiers.push(identifier);
}
} catch (error) {
if (error?.message?.includes('untrusted identity for address')) {
error.timestamp = this.timestamp;
}
throw error;
const { accessKeyFailed } = await getKeysForIdentifier(
identifier,
this.server,
updateDevices,
accessKey
);
if (accessKeyFailed && !this.failoverIdentifiers.includes(identifier)) {
this.failoverIdentifiers.push(identifier);
}
}
@ -626,8 +621,13 @@ export default class OutgoingMessage {
);
});
}
if (error?.message?.includes('untrusted identity for address')) {
error.timestamp = this.timestamp;
let newError = error;
if (
error instanceof LibSignalErrorBase &&
error.code === ErrorCode.UntrustedIdentity
) {
newError = new OutgoingIdentityKeyError(identifier);
log.error(
'Got "key changed" error from encrypt - no identityKey for application layer',
identifier,
@ -643,7 +643,8 @@ export default class OutgoingMessage {
},
innerError => {
log.error(
`doSendMessage: Error closing sessions: ${innerError.stack}`
'doSendMessage: Error closing sessions: ' +
`${Errors.toLogFormat(innerError)}`
);
throw error;
}
@ -653,7 +654,7 @@ export default class OutgoingMessage {
this.registerError(
identifier,
'Failed to create or send message',
error
newError
);
return undefined;
@ -712,7 +713,7 @@ export default class OutgoingMessage {
} catch (error) {
log.error(
`sendToIdentifier: Failed to fetch UUID for identifier ${identifier}`,
error && error.stack ? error.stack : error
Errors.toLogFormat(error)
);
}
} else {
@ -731,7 +732,10 @@ export default class OutgoingMessage {
}
await this.reloadDevicesAndSend(identifier, true)();
} catch (error) {
if (error?.message?.includes('untrusted identity for address')) {
if (
error instanceof LibSignalErrorBase &&
error.code === ErrorCode.UntrustedIdentity
) {
const newError = new OutgoingIdentityKeyError(identifier);
this.registerError(identifier, 'Untrusted identity', newError);
} else {

View file

@ -2,6 +2,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
import {
ErrorCode,
LibSignalErrorBase,
PreKeyBundle,
processPreKeyBundle,
ProtocolAddress,
@ -9,9 +11,9 @@ import {
} from '@signalapp/libsignal-client';
import {
OutgoingIdentityKeyError,
UnregisteredUserError,
HTTPError,
OutgoingIdentityKeyError,
} from './Errors';
import { Sessions, IdentityKeys } from '../LibSignalStores';
import { Address } from '../types/Address';
@ -72,13 +74,6 @@ async function getServerKeys(
}),
};
} catch (error: unknown) {
if (
error instanceof Error &&
error.message.includes('untrusted identity')
) {
throw new OutgoingIdentityKeyError(identifier);
}
if (
accessKey &&
isRecord(error) &&
@ -155,22 +150,27 @@ async function handleServerKeys(
ourUuid,
new Address(theirUuid, deviceId)
);
await window.textsecure.storage.protocol
.enqueueSessionJob(address, () =>
processPreKeyBundle(
preKeyBundle,
protocolAddress,
sessionStore,
identityKeyStore
)
)
.catch(error => {
if (error?.message?.includes('untrusted identity for address')) {
// eslint-disable-next-line no-param-reassign
error.identityKey = response.identityKey;
}
throw error;
});
try {
await window.textsecure.storage.protocol.enqueueSessionJob(
address,
() =>
processPreKeyBundle(
preKeyBundle,
protocolAddress,
sessionStore,
identityKeyStore
)
);
} catch (error) {
if (
error instanceof LibSignalErrorBase &&
error.code === ErrorCode.UntrustedIdentity
) {
throw new OutgoingIdentityKeyError(identifier);
}
throw error;
}
})
);
}