Search in sources :

Example 1 with MatrixError

use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.

the class RestAdapterCallback method failure.

/**
 * Default failure implementation that calls the right error handler
 *
 * @param response  the retrofit response
 * @param exception the retrofit exception
 */
public void failure(Response<T> response, Exception exception) {
    if (null != mEventDescription) {
        String error = exception != null ? exception.getMessage() : (response != null ? response.message() : "unknown");
        Log.d(LOG_TAG, "## failure(): [" + mEventDescription + "]" + " with error " + error);
    }
    boolean retry = true;
    if (null != response) {
        retry = (response.code() < 400) || (response.code() > 500);
    }
    // do not retry if the response format is not the expected one.
    retry &= (null == exception.getCause()) || !(exception.getCause() instanceof MalformedJsonException || exception.getCause() instanceof JsonSyntaxException);
    if (retry && (null != mUnsentEventsManager)) {
        Log.d(LOG_TAG, "Add it to the UnsentEventsManager");
        mUnsentEventsManager.onEventSendingFailed(mEventDescription, mIgnoreEventTimeLifeInOffline, response, exception, mApiCallback, mRequestRetryCallBack);
    } else {
        if (exception != null && exception instanceof IOException) {
            try {
                if (null != mApiCallback) {
                    try {
                        mApiCallback.onNetworkError(exception);
                    } catch (Exception e) {
                        Log.e(LOG_TAG, "## failure(): onNetworkError " + exception.getLocalizedMessage(), exception);
                    }
                }
            } catch (Exception e) {
                // privacy
                // Log.e(LOG_TAG, "Exception NetworkError " + e.getMessage() + " while managing " + error.getUrl());
                Log.e(LOG_TAG, "## failure():  NetworkError " + e.getMessage(), e);
            }
        } else {
            // Try to convert this into a Matrix error
            MatrixError mxError;
            try {
                HttpError error = ((HttpException) exception).getHttpError();
                ResponseBody errorBody = response.errorBody();
                String bodyAsString = error.getErrorBody();
                mxError = GsonProvider.provideGson().fromJson(bodyAsString, MatrixError.class);
                mxError.mStatus = response.code();
                mxError.mReason = response.message();
                mxError.mErrorBodyAsString = bodyAsString;
            } catch (Exception e) {
                mxError = null;
            }
            if (mxError != null) {
                if (MatrixError.LIMIT_EXCEEDED.equals(mxError.errcode) && (null != mUnsentEventsManager)) {
                    mUnsentEventsManager.onEventSendingFailed(mEventDescription, mIgnoreEventTimeLifeInOffline, response, exception, mApiCallback, mRequestRetryCallBack);
                } else if (MatrixError.isConfigurationErrorCode(mxError.errcode) && (null != mUnsentEventsManager)) {
                    mUnsentEventsManager.onConfigurationErrorCode(mxError.errcode, mEventDescription);
                } else {
                    try {
                        if (null != mApiCallback) {
                            mApiCallback.onMatrixError(mxError);
                        }
                    } catch (Exception e) {
                        // privacy
                        // Log.e(LOG_TAG, "Exception MatrixError " + e.getMessage() + " while managing " + error.getUrl());
                        Log.e(LOG_TAG, "## failure():  MatrixError " + e.getMessage(), e);
                    }
                }
            } else {
                try {
                    if (null != mApiCallback) {
                        mApiCallback.onUnexpectedError(exception);
                    }
                } catch (Exception e) {
                    // privacy
                    // Log.e(LOG_TAG, "Exception UnexpectedError " + e.getMessage() + " while managing " + error.getUrl());
                    Log.e(LOG_TAG, "## failure():  UnexpectedError " + e.getMessage(), e);
                }
            }
        }
    }
}
Also used : JsonSyntaxException(com.google.gson.JsonSyntaxException) HttpException(org.matrix.androidsdk.core.model.HttpException) IOException(java.io.IOException) HttpError(org.matrix.androidsdk.core.model.HttpError) MatrixError(org.matrix.androidsdk.core.model.MatrixError) JsonSyntaxException(com.google.gson.JsonSyntaxException) IOException(java.io.IOException) MalformedJsonException(com.google.gson.stream.MalformedJsonException) HttpException(org.matrix.androidsdk.core.model.HttpException) MalformedJsonException(com.google.gson.stream.MalformedJsonException) ResponseBody(okhttp3.ResponseBody)

Example 2 with MatrixError

use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.

the class UnsentEventsManager method onEventSendingFailed.

/**
 * warns that an event failed to be sent.
 *
 * @param eventDescription             the event description
 * @param ignoreEventTimeLifeInOffline tell if the event timelife is ignored in offline mode
 * @param response                     Retrofit response
 * @param exception                    Retrofit Exception
 * @param apiCallback                  the apiCallback.
 * @param requestRetryCallBack         requestRetryCallBack.
 */
public void onEventSendingFailed(final String eventDescription, final boolean ignoreEventTimeLifeInOffline, final Response response, final Exception exception, final ApiCallback apiCallback, final RestAdapterCallback.RequestRetryCallBack requestRetryCallBack) {
    boolean isManaged = false;
    if (null != eventDescription) {
        Log.d(LOG_TAG, "Fail to send [" + eventDescription + "]");
    }
    if ((null != requestRetryCallBack) && (null != apiCallback)) {
        synchronized (mUnsentEventsMap) {
            UnsentEventSnapshot snapshot;
            // Try to convert this into a Matrix error
            MatrixError mxError = null;
            if (null != response) {
                try {
                    mxError = GsonProvider.provideGson().fromJson(response.errorBody().string(), MatrixError.class);
                } catch (Exception e) {
                    mxError = null;
                }
            }
            // trace the matrix error.
            if ((null != eventDescription) && (null != mxError)) {
                Log.d(LOG_TAG, "Matrix error " + mxError.errcode + " " + mxError.getMessage() + " [" + eventDescription + "]");
                if (MatrixError.isConfigurationErrorCode(mxError.errcode)) {
                    Log.e(LOG_TAG, "## onEventSendingFailed() : invalid token detected");
                    mDataHandler.onConfigurationError(mxError.errcode);
                    triggerErrorCallback(mDataHandler, eventDescription, response, exception, apiCallback);
                    return;
                }
            }
            int matrixRetryTimeout = -1;
            if ((null != mxError) && MatrixError.LIMIT_EXCEEDED.equals(mxError.errcode) && (null != mxError.retry_after_ms)) {
                matrixRetryTimeout = mxError.retry_after_ms + 200;
            }
            if (null != exception) {
                UnrecognizedCertificateException unrecCertEx = CertUtil.getCertificateException(exception);
                if (null != unrecCertEx) {
                    Log.e(LOG_TAG, "## onEventSendingFailed() : SSL issue detected");
                    mDataHandler.onSSLCertificateError(unrecCertEx);
                    triggerErrorCallback(mDataHandler, eventDescription, response, exception, apiCallback);
                    return;
                }
            }
            // some matrix errors are not trapped.
            if ((null == mxError) || !mxError.isSupportedErrorCode() || MatrixError.LIMIT_EXCEEDED.equals(mxError.errcode)) {
                // is it the first time that the event has been sent ?
                if (mUnsentEventsMap.containsKey(apiCallback)) {
                    snapshot = mUnsentEventsMap.get(apiCallback);
                    snapshot.mIsResending = false;
                    snapshot.stopTimer();
                    // assume that LIMIT_EXCEEDED error is not a default retry
                    if (matrixRetryTimeout < 0) {
                        snapshot.mRetryCount++;
                    }
                    // any event has a time life to avoid very old messages
                    long timeLife = 0;
                    // age < 0 means that the event time life is ignored
                    if (snapshot.mAge > 0) {
                        timeLife = System.currentTimeMillis() - snapshot.mAge;
                    }
                    if ((timeLife > MAX_MESSAGE_LIFETIME_MS) || (snapshot.mRetryCount > MAX_RETRIES)) {
                        snapshot.stopTimers();
                        mUnsentEventsMap.remove(apiCallback);
                        mUnsentEvents.remove(snapshot);
                        if (null != eventDescription) {
                            Log.d(LOG_TAG, "Cancel [" + eventDescription + "]");
                        }
                        isManaged = false;
                    } else {
                        isManaged = true;
                    }
                } else {
                    snapshot = new UnsentEventSnapshot();
                    try {
                        snapshot.mAge = ignoreEventTimeLifeInOffline ? -1 : System.currentTimeMillis();
                        snapshot.mRequestRetryCallBack = requestRetryCallBack;
                        snapshot.mRetryCount = 1;
                        snapshot.mEventDescription = eventDescription;
                        mUnsentEventsMap.put(apiCallback, snapshot);
                        mUnsentEvents.add(snapshot);
                        if (mbIsConnected || !ignoreEventTimeLifeInOffline) {
                            // the event has a life time
                            final UnsentEventSnapshot fSnapshot = snapshot;
                            fSnapshot.mLifeTimeTimer = new Timer();
                            fSnapshot.mLifeTimeTimer.schedule(new TimerTask() {

                                @Override
                                public void run() {
                                    try {
                                        if (null != eventDescription) {
                                            Log.d(LOG_TAG, "Cancel to send [" + eventDescription + "]");
                                        }
                                        fSnapshot.stopTimers();
                                        synchronized (mUnsentEventsMap) {
                                            mUnsentEventsMap.remove(apiCallback);
                                            mUnsentEvents.remove(fSnapshot);
                                        }
                                        triggerErrorCallback(mDataHandler, eventDescription, response, exception, apiCallback);
                                    } catch (Exception e) {
                                        Log.e(LOG_TAG, "## onEventSendingFailed() : failure Msg=" + e.getMessage(), e);
                                    }
                                }
                            }, MAX_MESSAGE_LIFETIME_MS);
                        } else if (ignoreEventTimeLifeInOffline) {
                            Log.d(LOG_TAG, "The request " + eventDescription + " will be sent when a network will be available");
                        }
                    } catch (Throwable throwable) {
                        Log.e(LOG_TAG, "## snapshot creation failed " + throwable.getMessage(), throwable);
                        if (null != snapshot.mLifeTimeTimer) {
                            snapshot.mLifeTimeTimer.cancel();
                        }
                        mUnsentEventsMap.remove(apiCallback);
                        mUnsentEvents.remove(snapshot);
                        try {
                            triggerErrorCallback(mDataHandler, eventDescription, response, exception, apiCallback);
                        } catch (Exception e) {
                            Log.e(LOG_TAG, "## onEventSendingFailed() : failure Msg=" + e.getMessage(), e);
                        }
                    }
                    isManaged = true;
                }
                // retry to send the message ?
                if (isManaged) {
                    // 
                    if (mbIsConnected) {
                        int jitterTime = ((int) Math.pow(2, snapshot.mRetryCount)) + (Math.abs(new Random(System.currentTimeMillis()).nextInt()) % RETRY_JITTER_MS);
                        isManaged = snapshot.resendEventAfter((matrixRetryTimeout > 0) ? matrixRetryTimeout : jitterTime);
                    }
                }
            }
        }
    }
    if (!isManaged) {
        Log.d(LOG_TAG, "Cannot resend it");
        triggerErrorCallback(mDataHandler, eventDescription, response, exception, apiCallback);
    }
}
Also used : Timer(java.util.Timer) TimerTask(java.util.TimerTask) Random(java.util.Random) UnrecognizedCertificateException(org.matrix.androidsdk.ssl.UnrecognizedCertificateException) MatrixError(org.matrix.androidsdk.core.model.MatrixError) IOException(java.io.IOException) UnrecognizedCertificateException(org.matrix.androidsdk.ssl.UnrecognizedCertificateException)

Example 3 with MatrixError

use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.

the class CryptoTest method test07_testAliceAndBobInAEncryptedRoom.

@Test
public void test07_testAliceAndBobInAEncryptedRoom() throws Exception {
    Log.e(LOG_TAG, "test07_testAliceAndBobInAEncryptedRoom");
    Context context = InstrumentationRegistry.getContext();
    final Map<String, Object> results = new HashMap<>();
    CryptoTestData cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true);
    final MXSession aliceSession = cryptoTestData.getFirstSession();
    final String aliceRoomId = cryptoTestData.getRoomId();
    final MXSession bobSession = cryptoTestData.getSecondSession();
    final String messageFromAlice = "Hello I'm Alice!";
    Room roomFromBobPOV = bobSession.getDataHandler().getRoom(aliceRoomId);
    Room roomFromAlicePOV = aliceSession.getDataHandler().getRoom(aliceRoomId);
    Assert.assertTrue(roomFromBobPOV.isEncrypted());
    Assert.assertTrue(roomFromAlicePOV.isEncrypted());
    CountDownLatch lock1 = new CountDownLatch(1);
    roomFromAlicePOV.sendEvent(mCryptoTestHelper.buildTextEvent(messageFromAlice, aliceSession, aliceRoomId), new TestApiCallback<Void>(lock1, false) {

        @Override
        public void onMatrixError(MatrixError e) {
            results.put("sendEventError", e);
            super.onMatrixError(e);
        }
    });
    mTestHelper.await(lock1);
    Assert.assertTrue(results.containsKey("sendEventError"));
    MXCryptoError error = (MXCryptoError) results.get("sendEventError");
    Assert.assertEquals(MXCryptoError.UNKNOWN_DEVICES_CODE, error.errcode);
    MXUsersDevicesMap<MXDeviceInfo> unknownDevices = (MXUsersDevicesMap<MXDeviceInfo>) error.mExceptionData;
    List<String> deviceInfos = unknownDevices.getUserDeviceIds(bobSession.getMyUserId());
    Assert.assertEquals(1, deviceInfos.size());
    Assert.assertEquals(deviceInfos.get(0), bobSession.getCrypto().getMyDevice().deviceId);
    CountDownLatch lock2 = new CountDownLatch(1);
    aliceSession.getCrypto().setDevicesKnown(Arrays.asList(bobSession.getCrypto().getMyDevice()), new TestApiCallback<Void>(lock2) {

        @Override
        public void onSuccess(Void info) {
            results.put("setDevicesKnown", "setDevicesKnown");
            super.onSuccess(info);
        }
    });
    mTestHelper.await(lock2);
    Assert.assertTrue(results.containsKey("setDevicesKnown"));
    final CountDownLatch lock3 = new CountDownLatch(3);
    MXEventListener eventListener = new MXEventListener() {

        @Override
        public void onLiveEvent(Event event, RoomState roomState) {
            if (TextUtils.equals(event.getType(), Event.EVENT_TYPE_MESSAGE)) {
                mCryptoTestHelper.checkEncryptedEvent(event, aliceRoomId, messageFromAlice, aliceSession);
                results.put("onLiveEvent", "onLiveEvent");
                lock3.countDown();
            }
        }
    };
    bobSession.getDataHandler().addListener(new MXEventListener() {

        @Override
        public void onToDeviceEvent(Event event) {
            results.put("onToDeviceEvent", event);
            lock3.countDown();
        }
    });
    roomFromBobPOV.addEventListener(eventListener);
    roomFromAlicePOV.sendEvent(mCryptoTestHelper.buildTextEvent(messageFromAlice, aliceSession, aliceRoomId), new TestApiCallback<Void>(lock3));
    mTestHelper.await(lock3);
    Assert.assertTrue(results.containsKey("onToDeviceEvent"));
    Assert.assertTrue(results.containsKey("onLiveEvent"));
    Assert.assertEquals(MXDeviceList.TRACKING_STATUS_UP_TO_DATE, bobSession.getCrypto().getDeviceTrackingStatus(bobSession.getMyUserId()));
    Assert.assertEquals(MXDeviceList.TRACKING_STATUS_UP_TO_DATE, bobSession.getCrypto().getDeviceTrackingStatus(aliceSession.getMyUserId()));
    Assert.assertEquals(MXDeviceList.TRACKING_STATUS_UP_TO_DATE, aliceSession.getCrypto().getDeviceTrackingStatus(bobSession.getMyUserId()));
    Assert.assertEquals(MXDeviceList.TRACKING_STATUS_UP_TO_DATE, aliceSession.getCrypto().getDeviceTrackingStatus(aliceSession.getMyUserId()));
    cryptoTestData.clear(context);
}
Also used : Context(android.content.Context) HashMap(java.util.HashMap) MXDeviceInfo(org.matrix.androidsdk.crypto.data.MXDeviceInfo) CryptoTestData(org.matrix.androidsdk.common.CryptoTestData) CountDownLatch(java.util.concurrent.CountDownLatch) MXUsersDevicesMap(org.matrix.androidsdk.crypto.data.MXUsersDevicesMap) MXSession(org.matrix.androidsdk.MXSession) MXEventListener(org.matrix.androidsdk.listeners.MXEventListener) Event(org.matrix.androidsdk.rest.model.Event) JsonObject(com.google.gson.JsonObject) MatrixError(org.matrix.androidsdk.core.model.MatrixError) Room(org.matrix.androidsdk.data.Room) RoomState(org.matrix.androidsdk.data.RoomState) Test(org.junit.Test)

Example 4 with MatrixError

use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.

the class MXDataHandler method manageResponse.

/**
 * Manage the sync response in a background thread.
 *
 * @param syncResponse the syncResponse to manage.
 * @param fromToken    the start sync token
 * @param isCatchingUp true when there is a pending catch-up
 */
private void manageResponse(final SyncResponse syncResponse, final String fromToken, final boolean isCatchingUp) {
    if (!isAlive()) {
        Log.e(LOG_TAG, "manageResponse : ignored because the session has been closed");
        return;
    }
    boolean isInitialSync = (null == fromToken);
    boolean isEmptyResponse = true;
    // sanity check
    if (null != syncResponse) {
        Log.d(LOG_TAG, "onSyncComplete");
        // to ensure to decrypt them properly
        if ((null != syncResponse.toDevice) && (null != syncResponse.toDevice.events) && (syncResponse.toDevice.events.size() > 0)) {
            Log.d(LOG_TAG, "manageResponse : receives " + syncResponse.toDevice.events.size() + " toDevice events");
            for (Event toDeviceEvent : syncResponse.toDevice.events) {
                handleToDeviceEvent(toDeviceEvent);
            }
        }
        // to be able to update direct chats dictionary during invites handling.
        if (syncResponse.accountData != null && syncResponse.accountData.accountDataElements != null && !syncResponse.accountData.accountDataElements.isEmpty()) {
            Log.d(LOG_TAG, "Received " + syncResponse.accountData.accountDataElements.size() + " accountData events");
            manageAccountData(syncResponse.accountData.accountDataElements, isInitialSync);
            // Global management, to be sure to handle any account data
            getStore().storeAccountData(syncResponse.accountData);
            for (AccountDataElement accountDataElement : syncResponse.accountData.accountDataElements) {
                mMxEventDispatcher.dispatchOnAccountDataUpdate(accountDataElement);
            }
        }
        // sanity check
        if (null != syncResponse.rooms) {
            // joined rooms events
            if ((null != syncResponse.rooms.join) && (syncResponse.rooms.join.size() > 0)) {
                Log.d(LOG_TAG, "Received " + syncResponse.rooms.join.size() + " joined rooms");
                if (mMetricsListener != null) {
                    mMetricsListener.onRoomsLoaded(syncResponse.rooms.join.size());
                }
                Set<String> roomIds = syncResponse.rooms.join.keySet();
                // Handle first joined rooms
                for (String roomId : roomIds) {
                    try {
                        if (null != mLeftRoomsStore.getRoom(roomId)) {
                            Log.d(LOG_TAG, "the room " + roomId + " moves from left to the joined ones");
                            mLeftRoomsStore.deleteRoom(roomId);
                        }
                        getRoom(roomId).handleJoinedRoomSync(syncResponse.rooms.join.get(roomId), isInitialSync);
                    } catch (Exception e) {
                        Log.e(LOG_TAG, "## manageResponse() : handleJoinedRoomSync failed " + e.getMessage() + " for room " + roomId, e);
                    }
                }
                isEmptyResponse = false;
            }
            // invited room management
            if ((null != syncResponse.rooms.invite) && (syncResponse.rooms.invite.size() > 0)) {
                Log.d(LOG_TAG, "Received " + syncResponse.rooms.invite.size() + " invited rooms");
                Set<String> roomIds = syncResponse.rooms.invite.keySet();
                Map<String, List<String>> updatedDirectChatRoomsDict = null;
                boolean hasChanged = false;
                for (String roomId : roomIds) {
                    try {
                        Log.d(LOG_TAG, "## manageResponse() : the user has been invited to " + roomId);
                        if (null != mLeftRoomsStore.getRoom(roomId)) {
                            Log.d(LOG_TAG, "the room " + roomId + " moves from left to the invited ones");
                            mLeftRoomsStore.deleteRoom(roomId);
                        }
                        Room room = getRoom(roomId);
                        InvitedRoomSync invitedRoomSync = syncResponse.rooms.invite.get(roomId);
                        room.handleInvitedRoomSync(invitedRoomSync);
                        // Handle here the invites to a direct chat.
                        if (room.isDirectChatInvitation()) {
                            // Retrieve the inviter user id.
                            String participantUserId = null;
                            for (Event event : invitedRoomSync.inviteState.events) {
                                if (null != event.sender) {
                                    participantUserId = event.sender;
                                    break;
                                }
                            }
                            if (null != participantUserId) {
                                // Prepare the updated dictionary.
                                if (null == updatedDirectChatRoomsDict) {
                                    if (null != getStore().getDirectChatRoomsDict()) {
                                        // Consider the current dictionary.
                                        updatedDirectChatRoomsDict = new HashMap<>(getStore().getDirectChatRoomsDict());
                                    } else {
                                        updatedDirectChatRoomsDict = new HashMap<>();
                                    }
                                }
                                List<String> roomIdsList;
                                if (updatedDirectChatRoomsDict.containsKey(participantUserId)) {
                                    roomIdsList = new ArrayList<>(updatedDirectChatRoomsDict.get(participantUserId));
                                } else {
                                    roomIdsList = new ArrayList<>();
                                }
                                // Check whether the room was not yet seen as direct chat
                                if (roomIdsList.indexOf(roomId) < 0) {
                                    Log.d(LOG_TAG, "## manageResponse() : add this new invite in direct chats");
                                    // update room list with the new room
                                    roomIdsList.add(roomId);
                                    updatedDirectChatRoomsDict.put(participantUserId, roomIdsList);
                                    hasChanged = true;
                                }
                            }
                        }
                    } catch (Exception e) {
                        Log.e(LOG_TAG, "## manageResponse() : handleInvitedRoomSync failed " + e.getMessage() + " for room " + roomId, e);
                    }
                }
                isEmptyResponse = false;
                if (hasChanged) {
                    // Update account data to add new direct chat room(s)
                    mAccountDataRestClient.setAccountData(mCredentials.userId, AccountDataElement.ACCOUNT_DATA_TYPE_DIRECT_MESSAGES, updatedDirectChatRoomsDict, new ApiCallback<Void>() {

                        @Override
                        public void onSuccess(Void info) {
                            Log.d(LOG_TAG, "## manageResponse() : succeeds");
                        }

                        @Override
                        public void onNetworkError(Exception e) {
                            Log.e(LOG_TAG, "## manageResponse() : update account data failed " + e.getMessage(), e);
                        // TODO: we should try again.
                        }

                        @Override
                        public void onMatrixError(MatrixError e) {
                            Log.e(LOG_TAG, "## manageResponse() : update account data failed " + e.getMessage());
                        }

                        @Override
                        public void onUnexpectedError(Exception e) {
                            Log.e(LOG_TAG, "## manageResponse() : update account data failed " + e.getMessage(), e);
                        }
                    });
                }
            }
            // when inviting after leaving a room, the room is defined in the both leave & invite rooms list.
            if ((null != syncResponse.rooms.leave) && (syncResponse.rooms.leave.size() > 0)) {
                Log.d(LOG_TAG, "Received " + syncResponse.rooms.leave.size() + " left rooms");
                Set<String> roomIds = syncResponse.rooms.leave.keySet();
                for (String roomId : roomIds) {
                    // RoomSync leftRoomSync = syncResponse.rooms.leave.get(roomId);
                    // Presently we remove the existing room from the rooms list.
                    // FIXME SYNC V2 Archive/Display the left rooms!
                    // For that create 'handleArchivedRoomSync' method
                    String membership = RoomMember.MEMBERSHIP_LEAVE;
                    Room room = getRoom(roomId);
                    // check if the room still exists.
                    if (null != room) {
                        // use 'handleJoinedRoomSync' to pass the last events to the room before leaving it.
                        // The room will then be able to notify its listeners.
                        room.handleJoinedRoomSync(syncResponse.rooms.leave.get(roomId), isInitialSync);
                        RoomMember member = room.getMember(getUserId());
                        if (null != member) {
                            membership = member.membership;
                        }
                        Log.d(LOG_TAG, "## manageResponse() : leave the room " + roomId);
                    }
                    if (!TextUtils.equals(membership, RoomMember.MEMBERSHIP_KICK) && !TextUtils.equals(membership, RoomMember.MEMBERSHIP_BAN)) {
                        // ensure that the room data are properly deleted
                        getStore().deleteRoom(roomId);
                        onLeaveRoom(roomId);
                    } else {
                        onRoomKick(roomId);
                    }
                    // don't add to the left rooms if the user has been kicked / banned
                    if ((mAreLeftRoomsSynced) && TextUtils.equals(membership, RoomMember.MEMBERSHIP_LEAVE)) {
                        Room leftRoom = getRoom(mLeftRoomsStore, roomId, true);
                        leftRoom.handleJoinedRoomSync(syncResponse.rooms.leave.get(roomId), isInitialSync);
                    }
                }
                isEmptyResponse = false;
            }
        }
        // groups
        if (null != syncResponse.groups) {
            // Handle invited groups
            if ((null != syncResponse.groups.invite) && !syncResponse.groups.invite.isEmpty()) {
                // Handle invited groups
                for (String groupId : syncResponse.groups.invite.keySet()) {
                    InvitedGroupSync invitedGroupSync = syncResponse.groups.invite.get(groupId);
                    mGroupsManager.onNewGroupInvitation(groupId, invitedGroupSync.profile, invitedGroupSync.inviter, !isInitialSync);
                }
            }
            // Handle joined groups
            if ((null != syncResponse.groups.join) && !syncResponse.groups.join.isEmpty()) {
                for (String groupId : syncResponse.groups.join.keySet()) {
                    mGroupsManager.onJoinGroup(groupId, !isInitialSync);
                }
            }
            // Handle left groups
            if ((null != syncResponse.groups.leave) && !syncResponse.groups.leave.isEmpty()) {
                // Handle joined groups
                for (String groupId : syncResponse.groups.leave.keySet()) {
                    mGroupsManager.onLeaveGroup(groupId, !isInitialSync);
                }
            }
        }
        // Handle presence of other users
        if ((null != syncResponse.presence) && (null != syncResponse.presence.events)) {
            Log.d(LOG_TAG, "Received " + syncResponse.presence.events.size() + " presence events");
            for (Event presenceEvent : syncResponse.presence.events) {
                handlePresenceEvent(presenceEvent);
            }
        }
        if (null != mCrypto) {
            mCrypto.onSyncCompleted(syncResponse, fromToken, isCatchingUp);
        }
        IMXStore store = getStore();
        if (!isEmptyResponse && (null != store)) {
            store.setEventStreamToken(syncResponse.nextBatch);
            store.commit();
        }
    }
    if (isInitialSync) {
        if (!isCatchingUp) {
            startCrypto(true);
        } else {
            // the events thread sends a dummy initial sync event
            // when the application is restarted.
            mIsStartingCryptoWithInitialSync = !isEmptyResponse;
        }
        onInitialSyncComplete((null != syncResponse) ? syncResponse.nextBatch : null);
    } else {
        if (!isCatchingUp) {
            startCrypto(mIsStartingCryptoWithInitialSync);
        }
        try {
            onLiveEventsChunkProcessed(fromToken, (null != syncResponse) ? syncResponse.nextBatch : fromToken);
        } catch (Exception e) {
            Log.e(LOG_TAG, "onLiveEventsChunkProcessed failed " + e.getMessage(), e);
        }
        try {
            // check if an incoming call has been received
            mCallsManager.checkPendingIncomingCalls();
        } catch (Exception e) {
            Log.e(LOG_TAG, "checkPendingIncomingCalls failed " + e + " " + e.getMessage(), e);
        }
    }
}
Also used : IMXStore(org.matrix.androidsdk.data.store.IMXStore) InvitedRoomSync(org.matrix.androidsdk.rest.model.sync.InvitedRoomSync) MXDecryptionException(org.matrix.androidsdk.crypto.MXDecryptionException) UnrecognizedCertificateException(org.matrix.androidsdk.ssl.UnrecognizedCertificateException) InvitedGroupSync(org.matrix.androidsdk.rest.model.group.InvitedGroupSync) AccountDataElement(org.matrix.androidsdk.rest.model.sync.AccountDataElement) RoomMember(org.matrix.androidsdk.rest.model.RoomMember) CryptoEvent(org.matrix.androidsdk.crypto.interfaces.CryptoEvent) Event(org.matrix.androidsdk.rest.model.Event) List(java.util.List) ArrayList(java.util.ArrayList) MatrixError(org.matrix.androidsdk.core.model.MatrixError) Room(org.matrix.androidsdk.data.Room)

Example 5 with MatrixError

use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.

the class MXCallsManager method refreshTurnServer.

/**
 * Refresh the turn servers.
 */
private void refreshTurnServer() {
    if (mSuspendTurnServerRefresh) {
        return;
    }
    Log.d(LOG_TAG, "## refreshTurnServer () starts");
    mUIThreadHandler.post(() -> mCallResClient.getTurnServer(new ApiCallback<JsonObject>() {

        private void restartAfter(int msDelay) {
            // "ttl" seems invalid
            if (msDelay <= 0) {
                Log.e(LOG_TAG, "## refreshTurnServer() : invalid delay " + msDelay);
            } else {
                if (null != mTurnServerTimer) {
                    mTurnServerTimer.cancel();
                }
                try {
                    mTurnServerTimer = new Timer();
                    mTurnServerTimer.schedule(new TimerTask() {

                        @Override
                        public void run() {
                            if (mTurnServerTimer != null) {
                                mTurnServerTimer.cancel();
                                mTurnServerTimer = null;
                            }
                            refreshTurnServer();
                        }
                    }, msDelay);
                } catch (Throwable e) {
                    Log.e(LOG_TAG, "## refreshTurnServer() failed to start the timer", e);
                    if (null != mTurnServerTimer) {
                        mTurnServerTimer.cancel();
                        mTurnServerTimer = null;
                    }
                    refreshTurnServer();
                }
            }
        }

        @Override
        public void onSuccess(JsonObject info) {
            // privacy
            Log.d(LOG_TAG, "## refreshTurnServer () : onSuccess");
            if (null != info) {
                if (info.has("uris")) {
                    synchronized (LOG_TAG) {
                        mTurnServer = info;
                    }
                }
                if (info.has("ttl")) {
                    int ttl = 60000;
                    try {
                        ttl = info.get("ttl").getAsInt();
                        // restart a 90 % before ttl expires
                        ttl = ttl * 9 / 10;
                    } catch (Exception e) {
                        Log.e(LOG_TAG, "Fail to retrieve ttl " + e.getMessage(), e);
                    }
                    Log.d(LOG_TAG, "## refreshTurnServer () : onSuccess : retry after " + ttl + " seconds");
                    restartAfter(ttl * 1000);
                }
            }
        }

        @Override
        public void onNetworkError(Exception e) {
            Log.e(LOG_TAG, "## refreshTurnServer () : onNetworkError", e);
            restartAfter(60000);
        }

        @Override
        public void onMatrixError(MatrixError e) {
            Log.e(LOG_TAG, "## refreshTurnServer () : onMatrixError() : " + e.errcode);
            if (TextUtils.equals(e.errcode, MatrixError.LIMIT_EXCEEDED) && (null != e.retry_after_ms)) {
                Log.e(LOG_TAG, "## refreshTurnServer () : onMatrixError() : retry after " + e.retry_after_ms + " ms");
                restartAfter(e.retry_after_ms);
            }
        }

        @Override
        public void onUnexpectedError(Exception e) {
            // should never happen
            Log.e(LOG_TAG, "## refreshTurnServer () : onUnexpectedError()", e);
        }
    }));
}
Also used : Timer(java.util.Timer) TimerTask(java.util.TimerTask) SimpleApiCallback(org.matrix.androidsdk.core.callback.SimpleApiCallback) ApiCallback(org.matrix.androidsdk.core.callback.ApiCallback) JsonObject(com.google.gson.JsonObject) MatrixError(org.matrix.androidsdk.core.model.MatrixError)

Aggregations

MatrixError (org.matrix.androidsdk.core.model.MatrixError)41 SimpleApiCallback (org.matrix.androidsdk.core.callback.SimpleApiCallback)15 ApiCallback (org.matrix.androidsdk.core.callback.ApiCallback)14 ArrayList (java.util.ArrayList)12 MXDeviceInfo (org.matrix.androidsdk.crypto.data.MXDeviceInfo)9 IOException (java.io.IOException)7 HashMap (java.util.HashMap)7 List (java.util.List)7 Room (org.matrix.androidsdk.data.Room)7 Event (org.matrix.androidsdk.rest.model.Event)7 CountDownLatch (java.util.concurrent.CountDownLatch)6 MXDecryptionException (org.matrix.androidsdk.crypto.MXDecryptionException)6 MXUsersDevicesMap (org.matrix.androidsdk.crypto.data.MXUsersDevicesMap)6 JsonObject (com.google.gson.JsonObject)5 MXCryptoError (org.matrix.androidsdk.crypto.MXCryptoError)4 JsonElement (com.google.gson.JsonElement)3 MXSession (org.matrix.androidsdk.MXSession)3 MXOlmSessionResult (org.matrix.androidsdk.crypto.data.MXOlmSessionResult)3 RoomMember (org.matrix.androidsdk.rest.model.RoomMember)3 Activity (android.app.Activity)2