diff --git a/package-lock.json b/package-lock.json index 30d995e1f506..c07e56001471 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35557,9 +35557,9 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "pusher-js": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-7.0.0.tgz", - "integrity": "sha512-2ZSw8msMe6EKNTebQSthRInrWUK9bo3zXPmQx0bfeDFJdSnTWUROhdAhmpRQREHzqrL+l4imv/3uwgIQHUO0oQ==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-7.0.6.tgz", + "integrity": "sha512-I44FTlF2OfGNg/4xcxmFq/JqFzJswoQWtWCPq+DkCh31MFg3Qkm3bNFvTXU+c5KR19TyBZ9SYlYq2rrpJZzbIA==", "requires": { "tweetnacl": "^1.0.3" } diff --git a/package.json b/package.json index d759b42016ba..c44672d02038 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "moment-timezone": "^0.5.31", "onfido-sdk-ui": "^6.15.2", "prop-types": "^15.7.2", - "pusher-js": "^7.0.0", + "pusher-js": "^7.0.6", "react": "^17.0.2", "react-collapse": "^5.1.0", "react-dom": "^17.0.2", diff --git a/src/CONST.js b/src/CONST.js index 64639ce08d4f..c60a5d15b06e 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -323,6 +323,8 @@ const CONST = { REQUEST_CANCELLED: 'AbortError', FAILED_TO_FETCH: 'Failed to fetch', ENSURE_BUGBOT: 'ENSURE_BUGBOT', + PUSHER_ERROR: 'PusherError', + WEB_SOCKET_ERROR: 'WebSocketError', NETWORK_REQUEST_FAILED: 'Network request failed', SAFARI_DOCUMENT_LOAD_ABORTED: 'cancelled', FIREFOX_DOCUMENT_LOAD_ABORTED: 'NetworkError when attempting to fetch resource.', diff --git a/src/libs/Pusher/pusher.js b/src/libs/Pusher/pusher.js index 45e1fd2699b4..84e8b6fe70db 100644 --- a/src/libs/Pusher/pusher.js +++ b/src/libs/Pusher/pusher.js @@ -214,15 +214,15 @@ function subscribe( onResubscribe(); }); - channel.bind('pusher:subscription_error', (status) => { - if (status === 403) { - Log.hmmm('[Pusher] Issue authenticating with Pusher during subscribe attempt.', { - channelName, - status, - }); - } - - reject(status); + channel.bind('pusher:subscription_error', (data = {}) => { + const {type, error, status} = data; + Log.hmmm('[Pusher] Issue authenticating with Pusher during subscribe attempt.', { + channelName, + status, + type, + error, + }); + reject(error); }); } else { bindEventToChannel(channel, eventName, eventCallback, isChunked); diff --git a/src/libs/PusherConnectionManager.js b/src/libs/PusherConnectionManager.js index 16923e3830d8..7c4b685c90c0 100644 --- a/src/libs/PusherConnectionManager.js +++ b/src/libs/PusherConnectionManager.js @@ -1,6 +1,8 @@ +import lodashGet from 'lodash/get'; import * as Pusher from './Pusher/pusher'; import * as Session from './actions/Session'; import Log from './Log'; +import CONST from '../CONST'; function init() { /** @@ -16,17 +18,29 @@ function init() { })); /** - * Events that happen on the pusher socket are used to determine if the app is online or offline. - * The offline setting is stored in Onyx so the rest of the app has access to it. - * * @params {string} eventName */ - Pusher.registerSocketEventCallback((eventName, data) => { + Pusher.registerSocketEventCallback((eventName, error) => { switch (eventName) { - case 'error': - Log.info('[PusherConnectionManager] error event', false, {error: data}); - Session.reauthenticatePusher(); + case 'error': { + const errorType = lodashGet(error, 'type'); + const code = lodashGet(error, 'data.code'); + if (errorType === CONST.ERROR.PUSHER_ERROR && code === 1006) { + // 1006 code happens when a websocket connection is closed. There may or may not be a reason attached indicating why the connection was closed. + // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5 + Log.hmmm('[PusherConnectionManager] Channels Error 1006', {error}); + } else if (errorType === CONST.ERROR.PUSHER_ERROR && code === 4201) { + // This means the connection was closed because Pusher did not recieve a reply from the client when it pinged them for a response + // https://pusher.com/docs/channels/library_auth_reference/pusher-websockets-protocol/#4200-4299 + Log.hmmm('[PusherConnectionManager] Pong reply not received', {error}); + } else if (errorType === CONST.ERROR.WEB_SOCKET_ERROR) { + // It's not clear why some errors are wrapped in a WebSocketError type - this error could mean different things depending on the contents. + Log.hmmm('[PusherConnectionManager] WebSocketError', {error}); + } else { + Log.alert(`${CONST.ERROR.ENSURE_BUGBOT} [PusherConnectionManager] Unknown error event`, {error}); + } break; + } case 'connected': Log.info('[PusherConnectionManager] connected event'); break; @@ -34,6 +48,7 @@ function init() { Log.info('[PusherConnectionManager] disconnected event'); break; default: + Log.info('[PusherConnectionManager] unhandled event', false, {eventName}); break; } }); diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index eb01d496f6a3..76358e699946 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -755,7 +755,7 @@ function subscribeToPrivateUserChannelEvent(eventName, onEvent, isChunked = fals * @param {*} error */ function onSubscriptionFailed(error) { - Log.info('[Report] Failed to subscribe to Pusher channel', false, {error, pusherChannelName, eventName}); + Log.hmmm('[Report] Failed to subscribe to Pusher channel', false, {error, pusherChannelName, eventName}); } Pusher.subscribe(pusherChannelName, eventName, onEventPush, isChunked, onPusherResubscribeToPrivateUserChannel) @@ -883,7 +883,7 @@ function subscribeToReportTypingEvents(reportID) { }, 1500); }) .catch((error) => { - Log.info('[Report] Failed to initially subscribe to Pusher channel', false, {error, pusherChannelName}); + Log.hmmm('[Report] Failed to initially subscribe to Pusher channel', false, {errorType: error.type, pusherChannelName}); }); } diff --git a/src/libs/actions/Session/index.js b/src/libs/actions/Session/index.js index 49ac81028560..89476d3a5ca3 100644 --- a/src/libs/actions/Session/index.js +++ b/src/libs/actions/Session/index.js @@ -434,7 +434,7 @@ const reauthenticatePusher = _.throttle(() => { * @param {Function} callback */ function authenticatePusher(socketID, channelName, callback) { - Log.info('[PusherConnectionManager] Attempting to authorize Pusher', false, {channelName}); + Log.info('[PusherAuthorizer] Attempting to authorize Pusher', false, {channelName}); API.Push_Authenticate({ socket_id: socketID, @@ -442,30 +442,32 @@ function authenticatePusher(socketID, channelName, callback) { shouldRetry: false, forceNetworkRequest: true, }) - .then((data) => { - if (data.jsonCode === CONST.JSON_CODE.NOT_AUTHENTICATED) { - callback(new Error('Expensify session expired'), {auth: ''}); + .then((response) => { + if (response.jsonCode === CONST.JSON_CODE.NOT_AUTHENTICATED) { + Log.hmmm('[PusherAuthorizer] Unable to authenticate Pusher because authToken is expired'); + callback(new Error('Pusher failed to authenticate because authToken is expired'), {auth: ''}); // Attempt to refresh the authToken then reconnect to Pusher reauthenticatePusher(); return; } - if (data.jsonCode !== CONST.JSON_CODE.SUCCESS) { - Log.hmmm('[PusherConnectionManager] Unable to authenticate Pusher for some reason other than expired session'); + if (response.jsonCode !== CONST.JSON_CODE.SUCCESS) { + Log.hmmm('[PusherAuthorizer] Unable to authenticate Pusher for reason other than expired session'); + callback(new Error(`Pusher failed to authenticate because code: ${response.jsonCode} message: ${response.message}`), {auth: ''}); return; } Log.info( - '[PusherConnectionManager] Pusher authenticated successfully', + '[PusherAuthorizer] Pusher authenticated successfully', false, {channelName}, ); - callback(null, data); + callback(null, response); }) .catch((error) => { - Log.info('[PusherConnectionManager] Unhandled error: ', false, {channelName}); - callback(error, {auth: ''}); + Log.hmmm('[PusherAuthorizer] Unhandled error: ', {channelName, error}); + callback(new Error('Push_Authenticate request failed'), {auth: ''}); }); } diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js index 9c2d3b627604..373cc6c8a8fb 100644 --- a/src/libs/actions/User.js +++ b/src/libs/actions/User.js @@ -305,7 +305,7 @@ function subscribeToUserEvents() { NetworkConnection.triggerReconnectionCallbacks('pusher re-subscribed to private user channel'); }) .catch((error) => { - Log.info( + Log.hmmm( '[User] Failed to subscribe to Pusher channel', false, {error, pusherChannelName, eventName: Pusher.TYPE.PREFERRED_LOCALE}, @@ -318,7 +318,14 @@ function subscribeToUserEvents() { }, false, () => { NetworkConnection.triggerReconnectionCallbacks('pusher re-subscribed to private user channel'); - }); + }) + .catch((error) => { + Log.hmmm( + '[User] Failed to subscribe to Pusher channel', + false, + {error, pusherChannelName, eventName: Pusher.TYPE.SCREEN_SHARE_REQUEST}, + ); + }); } /**