From 2c479eb8d50b8bce32593af6a4b24ed50fac2020 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 9 Jan 2024 11:46:56 +1100 Subject: [PATCH 1/2] fix: make fileserver request retry --- _locales/en/messages.json | 2 +- ts/models/message.ts | 6 +++- .../apis/file_server_api/FileServerApi.ts | 4 ++- ts/session/apis/snode_api/onions.ts | 17 ++++++----- ts/session/onions/onionSend.ts | 28 +++++++++---------- 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 84dcfd6d3..9e4bd087b 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -191,7 +191,7 @@ "confirm": "Confirm", "followSetting": "Follow Setting", "followSettingDisabled": "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?", - "followSettingTimeAndType": "Set your messages to disappear $time$ after they have been $type$?", + "followSettingTimeAndType": "Set your messages to disappear $time$ after they have been $type$?", "youChangedTheTimer": "You have set messages to disappear $time$ after they have been $mode$", "youChangedTheTimerLegacy": "You set the disappearing message timer to $time$", "theyChangedTheTimer": "$name$ has set messages to disappear $time$ after they have been $mode$", diff --git a/ts/models/message.ts b/ts/models/message.ts index fbb533016..706e44464 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -756,6 +756,7 @@ export class MessageModel extends Backbone.Model { * Also returns the uploaded ids to include in the message post so that those attachments are linked to that message. */ public async uploadData() { + const start = Date.now(); const finalAttachments = await Promise.all( (this.get('attachments') || []).map(loadAttachmentData) ); @@ -816,7 +817,10 @@ export class MessageModel extends Backbone.Model { attachments[0].flags = SignalService.AttachmentPointer.Flags.VOICE_MESSAGE; } - window.log.info(`Upload of message data for message ${this.idForLogging()} is finished.`); + window.log.info( + `Upload of message data for message ${this.idForLogging()} is finished in ${Date.now() - + start}ms.` + ); return { body, attachments, diff --git a/ts/session/apis/file_server_api/FileServerApi.ts b/ts/session/apis/file_server_api/FileServerApi.ts index b3720fa97..eb47c164d 100644 --- a/ts/session/apis/file_server_api/FileServerApi.ts +++ b/ts/session/apis/file_server_api/FileServerApi.ts @@ -5,7 +5,9 @@ import { parseBatchGlobalStatusCode, } from '../open_group_api/sogsv3/sogsV3BatchPoll'; -export const fileServerURL = 'http://filev2.getsession.org'; +export const fileServerHost = 'filev2.getsession.org'; +export const fileServerURL = `http://${fileServerHost}`; + export const fileServerPubKey = 'da21e1d886c6fbaea313f75298bd64aab03a97ce985b46bb2dad9f2089c8ee59'; const RELEASE_VERSION_ENDPOINT = '/session_version?platform=desktop'; diff --git a/ts/session/apis/snode_api/onions.ts b/ts/session/apis/snode_api/onions.ts index 58e272c7a..616421a27 100644 --- a/ts/session/apis/snode_api/onions.ts +++ b/ts/session/apis/snode_api/onions.ts @@ -1,25 +1,26 @@ import https from 'https'; // eslint-disable-next-line import/no-named-default -import { default as insecureNodeFetch, RequestInit, Response } from 'node-fetch'; -import ByteBuffer from 'bytebuffer'; -import pRetry from 'p-retry'; -import { cloneDeep, isEmpty, isString, omit } from 'lodash'; import { AbortSignal } from 'abort-controller'; +import ByteBuffer from 'bytebuffer'; import { to_string } from 'libsodium-wrappers-sumo'; +import { cloneDeep, isEmpty, isString, omit } from 'lodash'; +import { RequestInit, Response, default as insecureNodeFetch } from 'node-fetch'; +import pRetry from 'p-retry'; // eslint-disable-next-line import/no-unresolved import { AbortSignal as AbortSignalNode } from 'node-fetch/externals'; import { dropSnodeFromSnodePool, dropSnodeFromSwarmIfNeeded, updateSwarmFor } from './snodePool'; import { OnionPaths } from '../../onions'; -import { toHex } from '../../utils/String'; import { ed25519Str, incrementBadPathCountOrDrop } from '../../onions/onionPath'; +import { toHex } from '../../utils/String'; import { Snode } from '../../../data/data'; -import { ERROR_CODE_NO_CONNECT } from './SNodeAPI'; -import { hrefPnServerProd } from '../push_notification_api/PnServer'; import { callUtilsWorker } from '../../../webworker/workers/browser/util_worker_interface'; import { encodeV4Request } from '../../onions/onionv4'; +import { fileServerHost } from '../file_server_api/FileServerApi'; +import { hrefPnServerProd } from '../push_notification_api/PnServer'; +import { ERROR_CODE_NO_CONNECT } from './SNodeAPI'; // hold the ed25519 key of a snode against the time it fails. Used to remove a snode only after a few failures (snodeFailureThreshold failures) let snodeFailureCount: Record = {}; @@ -839,6 +840,7 @@ async function sendOnionRequestHandlingSnodeEject({ response = result.response; if ( !isEmpty(finalRelayOptions) && + finalRelayOptions.host !== fileServerHost && response.status === 502 && response.statusText === 'Bad Gateway' ) { @@ -848,6 +850,7 @@ async function sendOnionRequestHandlingSnodeEject({ decodingSymmetricKey = result.decodingSymmetricKey; } catch (e) { window?.log?.warn('sendOnionRequestNoRetries error message: ', e.message); + if (e.code === 'ENETUNREACH' || e.message === 'ENETUNREACH' || throwErrors) { throw e; } diff --git a/ts/session/onions/onionSend.ts b/ts/session/onions/onionSend.ts index 48146a5bb..22dbf80a5 100644 --- a/ts/session/onions/onionSend.ts +++ b/ts/session/onions/onionSend.ts @@ -1,27 +1,27 @@ +import { AbortSignal } from 'abort-controller'; import { toNumber } from 'lodash'; import pRetry from 'p-retry'; -import { AbortSignal } from 'abort-controller'; import { OnionPaths } from '.'; +import { Snode } from '../../data/data'; +import { fileServerPubKey, fileServerURL } from '../apis/file_server_api/FileServerApi'; +import { OpenGroupPollingUtils } from '../apis/open_group_api/opengroupV2/OpenGroupPollingUtils'; +import { invalidAuthRequiresBlinding } from '../apis/open_group_api/opengroupV2/OpenGroupServerPoller'; +import { + addBinaryContentTypeToHeaders, + addJsonContentTypeToHeaders, +} from '../apis/open_group_api/sogsv3/sogsV3SendMessage'; +import { pnServerPubkeyHex, pnServerUrl } from '../apis/push_notification_api/PnServer'; import { - buildErrorMessageWithFailedCode, FinalDestNonSnodeOptions, FinalRelayOptions, Onions, - SnodeResponse, STATUS_NO_STATUS, + SnodeResponse, + buildErrorMessageWithFailedCode, } from '../apis/snode_api/onions'; import { PROTOCOLS } from '../constants'; -import { Snode } from '../../data/data'; import { OnionV4 } from './onionv4'; -import { OpenGroupPollingUtils } from '../apis/open_group_api/opengroupV2/OpenGroupPollingUtils'; -import { - addBinaryContentTypeToHeaders, - addJsonContentTypeToHeaders, -} from '../apis/open_group_api/sogsv3/sogsV3SendMessage'; -import { pnServerPubkeyHex, pnServerUrl } from '../apis/push_notification_api/PnServer'; -import { fileServerPubKey, fileServerURL } from '../apis/file_server_api/FileServerApi'; -import { invalidAuthRequiresBlinding } from '../apis/open_group_api/opengroupV2/OpenGroupServerPoller'; export type OnionFetchOptions = { method: string; @@ -239,13 +239,13 @@ const sendViaOnionV4ToNonSnodeWithRetries = async ( minTimeout: 100, onFailedAttempt: e => { window?.log?.warn( - `sendViaOnionV4ToNonSnodeRetryable attempt #${e.attemptNumber} failed. ${e.retriesLeft} retries left...: ${e.message}` + `sendViaOnionV4ToNonSnodeWithRetries attempt #${e.attemptNumber} failed. ${e.retriesLeft} retries left...: ${e.message}` ); }, } ); } catch (e) { - window?.log?.warn('sendViaOnionV4ToNonSnodeRetryable failed ', e.message, throwErrors); + window?.log?.warn('sendViaOnionV4ToNonSnodeWithRetries failed ', e.message, throwErrors); if (throwErrors) { throw e; } From 36c297f36874bdff1c50699d37346f6cae094483 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 9 Jan 2024 14:26:18 +1100 Subject: [PATCH 2/2] chore: wrap text of dialog desc when more than 90c long --- .../conversation/TimerNotification.tsx | 2 +- ts/components/dialog/SessionConfirm.tsx | 17 ++++++++++++----- ts/themes/globals.tsx | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/ts/components/conversation/TimerNotification.tsx b/ts/components/conversation/TimerNotification.tsx index 185b9e76c..7e5150cd7 100644 --- a/ts/components/conversation/TimerNotification.tsx +++ b/ts/components/conversation/TimerNotification.tsx @@ -78,7 +78,7 @@ function useFollowSettingsButtonClick( props.timespanSeconds ?? undefined ); }, - showExitIcon: true, + showExitIcon: false, onClickClose: onExit, }) ); diff --git a/ts/components/dialog/SessionConfirm.tsx b/ts/components/dialog/SessionConfirm.tsx index 18cec46c9..3687461ec 100644 --- a/ts/components/dialog/SessionConfirm.tsx +++ b/ts/components/dialog/SessionConfirm.tsx @@ -1,6 +1,7 @@ -import { shell } from 'electron'; import { Dispatch } from '@reduxjs/toolkit'; +import { shell } from 'electron'; import React, { useState } from 'react'; +import styled from 'styled-components'; import { MessageInteraction } from '../../interactions'; import { updateConfirmModal } from '../../state/ducks/modalDialog'; import { SessionWrapperModal } from '../SessionWrapperModal'; @@ -10,6 +11,15 @@ import { SessionSpinner } from '../basic/SessionSpinner'; import { SpacerLG } from '../basic/Text'; import { SessionIcon, SessionIconSize, SessionIconType } from '../icon'; +const StyledSubText = styled(SessionHtmlRenderer)<{ textLength: number }>` + font-size: var(--font-size-md); + line-height: 1.5; + max-width: ${props => + props.textLength > 90 + ? '60ch' + : '33ch'}; // this is ugly, but we want the dialog description to have multiple lines when a short text is displayed +`; + export interface SessionConfirmDialogProps { message?: string; messageSub?: string; @@ -64,8 +74,6 @@ export const SessionConfirm = (props: SessionConfirmDialogProps) => { const cancelText = props.cancelText || window.i18n('cancel'); const showHeader = !!props.title; - const messageSubText = messageSub ? 'session-confirm-main-message' : undefined; - const onClickOkHandler = async () => { if (onClickOk) { setIsLoading(true); @@ -101,7 +109,6 @@ export const SessionConfirm = (props: SessionConfirmDialogProps) => { window.inboxStore?.dispatch(updateConfirmModal(null)); }; - return ( { )} - + diff --git a/ts/themes/globals.tsx b/ts/themes/globals.tsx index 680fca95f..4ff6d175a 100644 --- a/ts/themes/globals.tsx +++ b/ts/themes/globals.tsx @@ -141,7 +141,7 @@ export const THEME_GLOBALS: ThemeGlobals = { '--button-path-connecting-color': COLORS.PATH.CONNECTING, '--button-path-error-color': COLORS.PATH.ERROR, - '--modal-background-color': `rgba(${hexColorToRGB(COLORS.BLACK)}, 0.3)`, + '--modal-background-color': `rgba(${hexColorToRGB(COLORS.BLACK)}, 0.6)`, '--modal-drop-shadow': `0px 0px 10px rgba(${hexColorToRGB(COLORS.BLACK)}, 0.22)`, '--lightbox-background-color': `rgba(${hexColorToRGB(COLORS.BLACK)}, 0.8)`,