Fix socket management for unlinkAndDisconnect

This commit is contained in:
Fedor Indutny 2021-09-15 11:44:27 -07:00 committed by GitHub
parent 039bd072ed
commit 5780c3d4b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 24 deletions

View file

@ -212,7 +212,7 @@ window.encryptAndUpload = async (
const server = WebAPI.connect({
username: username || oldUsername,
password,
disableWebSockets: true,
useWebSocket: false,
});
const uniqueStickers = uniqBy(

View file

@ -636,7 +636,7 @@ export async function startApp(): Promise<void> {
'WebAPI should be initialized together with MessageReceiver'
);
server.unregisterRequestHandler(messageReceiver);
await messageReceiver.stopProcessing();
messageReceiver.stopProcessing();
await window.waitForAllBatchers();
}
@ -3334,18 +3334,23 @@ export async function startApp(): Promise<void> {
): Promise<void> {
window.Whisper.events.trigger('unauthorized');
window.log.warn(
'unlinkAndDisconnect: Client is no longer authorized; ' +
'deleting local configuration'
);
if (messageReceiver) {
window.log.info('unlinkAndDisconnect: logging out');
strictAssert(server !== undefined, 'WebAPI not initialized');
server.unregisterRequestHandler(messageReceiver);
await messageReceiver.stopProcessing();
messageReceiver.stopProcessing();
await server.logout();
await window.waitForAllBatchers();
}
onEmpty();
window.log.warn(
'Client is no longer authorized; deleting local configuration'
);
window.Signal.Util.Registration.remove();
const NUMBER_ID_KEY = 'number_id';
@ -3364,6 +3369,7 @@ export async function startApp(): Promise<void> {
);
try {
window.log.info('unlinkAndDisconnect: removing configuration');
await window.textsecure.storage.protocol.removeAllConfiguration(mode);
// This was already done in the database with removeAllConfiguration; this does it
@ -3398,10 +3404,13 @@ export async function startApp(): Promise<void> {
}
await window.textsecure.storage.put(VERSION_KEY, window.getVersion());
window.log.info('Successfully cleared local configuration');
window.log.info(
'unlinkAndDisconnect: Successfully cleared local configuration'
);
} catch (eraseError) {
window.log.error(
'Something went wrong clearing local configuration',
'unlinkAndDisconnect: Something went wrong clearing ' +
'local configuration',
eraseError && eraseError.stack ? eraseError.stack : eraseError
);
} finally {

View file

@ -187,14 +187,18 @@ export class SocketManager extends EventListener {
authenticated = await process.getResult();
this.status = SocketStatus.OPEN;
} catch (error) {
strictAssert(this.authenticated === process, 'Someone stole our socket');
this.dropAuthenticated(process);
window.log.warn(
'SocketManager: authenticated socket connection failed with ' +
`error: ${Errors.toLogFormat(error)}`
);
// The socket was deliberately closed, don't follow up
if (this.authenticated !== process) {
return;
}
this.dropAuthenticated(process);
if (error instanceof HTTPError) {
const { code } = error;
@ -389,6 +393,16 @@ export class SocketManager extends EventListener {
}
}
public async logout(): Promise<void> {
const { authenticated } = this;
if (authenticated) {
authenticated.abort();
this.dropAuthenticated(authenticated);
}
this.credentials = undefined;
}
//
// Private
//

View file

@ -755,7 +755,7 @@ type AjaxOptionsType = {
};
export type WebAPIConnectOptionsType = WebAPICredentials & {
disableWebSockets?: boolean;
useWebSocket?: boolean;
};
export type WebAPIConnectType = {
@ -964,6 +964,7 @@ export type WebAPIType = {
Array<{ name: string; enabled: boolean; value: string | null }>
>;
authenticate: (credentials: WebAPICredentials) => Promise<void>;
logout: () => Promise<void>;
getSocketStatus: () => SocketStatus;
registerRequestHandler: (handler: IRequestHandler) => void;
unregisterRequestHandler: (handler: IRequestHandler) => void;
@ -1078,7 +1079,7 @@ export function initialize({
function connect({
username: initialUsername,
password: initialPassword,
disableWebSockets = false,
useWebSocket = true,
}: WebAPIConnectOptionsType) {
let username = initialUsername;
let password = initialPassword;
@ -1096,7 +1097,7 @@ export function initialize({
window.Whisper.events.trigger('unlinkAndDisconnect');
});
if (!disableWebSockets) {
if (useWebSocket) {
socketManager.authenticate({ username, password });
}
@ -1109,6 +1110,7 @@ export function initialize({
registerRequestHandler,
unregisterRequestHandler,
authenticate,
logout,
confirmCode,
createGroup,
fetchLinkPreviewImage,
@ -1166,11 +1168,11 @@ export function initialize({
param.urlParameters = '';
}
const useWebSocket =
!disableWebSockets && WEBSOCKET_CALLS.has(param.call);
const useWebSocketForEndpoint =
useWebSocket && WEBSOCKET_CALLS.has(param.call);
return _outerAjax(null, {
socketManager: useWebSocket ? socketManager : undefined,
socketManager: useWebSocketForEndpoint ? socketManager : undefined,
basicAuth: param.basicAuth,
certificateAuthority,
contentType: param.contentType || 'application/json; charset=utf-8',
@ -1221,11 +1223,20 @@ export function initialize({
username = newUsername;
password = newPassword;
if (!disableWebSockets) {
if (useWebSocket) {
await socketManager.authenticate({ username, password });
}
}
async function logout() {
username = '';
password = '';
if (useWebSocket) {
await socketManager.logout();
}
}
function getSocketStatus(): SocketStatus {
return socketManager.getStatus();
}
@ -1530,10 +1541,7 @@ export function initialize({
// Reset old websocket credentials and disconnect.
// AccountManager is our only caller and it will trigger
// `registration_done` which will update credentials.
await socketManager.authenticate({
username: '',
password: '',
});
await logout();
// Update REST credentials, though. We need them for the call below
username = number;

View file

@ -307,7 +307,7 @@ export default class WebSocketResource extends EventTarget {
);
if (this.shuttingDown) {
incomingRequest.respond(500, 'Shutting down');
incomingRequest.respond(-1, 'Shutting down');
return;
}
@ -343,7 +343,7 @@ export default class WebSocketResource extends EventTarget {
for (const resolve of outgoing.values()) {
resolve({
status: 500,
status: -1,
message: 'Connection closed',
response: undefined,
headers: [],