diff --git a/Linphone/core/App.cpp b/Linphone/core/App.cpp index 4cd92c1aa..eae386612 100644 --- a/Linphone/core/App.cpp +++ b/Linphone/core/App.cpp @@ -368,6 +368,7 @@ void App::setSelf(QSharedPointer(me)) { bool askForConfirmation) { mCoreModelConnection->invokeToCore([this, path, askForConfirmation]() { auto apply = [this, path] { + lInfo() << log().arg("Apply fetch config"); mCoreModelConnection->invokeToModel([this, path]() { CoreModel::getInstance()->setFetchConfig(path); }); }; auto callback = [this, path, askForConfirmation]() { @@ -385,9 +386,10 @@ void App::setSelf(QSharedPointer(me)) { QMetaObject::invokeMethod(getMainWindow(), "showConfirmationPopup", QVariant::fromValue(obj)); }; if (!getMainWindow()) { // Delay - if (askForConfirmation) + if (askForConfirmation) { + lInfo() << log() << "App wants confirmation before applying config, wait for main window to open"; connect(this, &App::mainWindowChanged, this, callback, Qt::SingleShotConnection); - else connect(this, &App::mainWindowChanged, this, apply, Qt::SingleShotConnection); + } else connect(this, &App::mainWindowChanged, this, apply, Qt::SingleShotConnection); } else { if (askForConfirmation) callback(); else apply(); @@ -398,6 +400,7 @@ void App::setSelf(QSharedPointer(me)) { &CoreModel::globalStateChanged, [this](const std::shared_ptr &core, linphone::GlobalState gstate, const std::string &message) { mCoreModelConnection->invokeToCore([this, gstate] { + lInfo() << log().arg("Core global state changed :") << (int)gstate; setCoreStarted(gstate == linphone::GlobalState::On); if (gstate == linphone::GlobalState::Configuring) { if (mMainWindow) { @@ -465,6 +468,7 @@ void App::setSelf(QSharedPointer(me)) { // Synchronize state for because linphoneCore was ran before any connections. mCoreModelConnection->invokeToModel([this]() { auto state = CoreModel::getInstance()->getCore()->getGlobalState(); + lInfo() << log().arg("Start app, core global state =") << (int)state; mCoreModelConnection->invokeToCore([this, state] { setCoreStarted(state == linphone::GlobalState::On); if (state == linphone::GlobalState::Configuring) { @@ -547,6 +551,10 @@ void App::setSelf(QSharedPointer(me)) { emit remainingTimeBeforeOidcTimeoutChanged(); }); }); + mCoreModelConnection->makeConnectToModel(&CoreModel::oidcRequestFailed, [this](const QString &error) { + mCoreModelConnection->invokeToCore( + [this, error] { Utils::showInformationPopup("info_popup_error_title", error, false); }); + }); mCoreModelConnection->makeConnectToCore(&App::lForceOidcTimeout, [this] { qDebug() << "App: force oidc timeout"; mCoreModelConnection->invokeToModel([this] { emit CoreModel::getInstance()->forceOidcTimeout(); }); @@ -1421,6 +1429,7 @@ void App::onAuthenticationRequested(const std::shared_ptr &core, const std::shared_ptr &authInfo, linphone::AuthMethod method) { bool authInfoIsInAccounts = false; + lInfo() << log().arg("onAuthenticationRequested, method =") << (int)method; if (authInfo) { for (auto &account : core->getAccountList()) { if (!account) continue; diff --git a/Linphone/model/auth/OIDCModel.cpp b/Linphone/model/auth/OIDCModel.cpp index 6659fe498..db1b722cd 100644 --- a/Linphone/model/auth/OIDCModel.cpp +++ b/Linphone/model/auth/OIDCModel.cpp @@ -49,12 +49,12 @@ QString OAuthHttpServerReplyHandler::callback() const { OIDCModel::OIDCModel(const std::shared_ptr &authInfo, QObject *parent) { auto port = CoreModel::getInstance()->getCore()->getConfig()->getInt("app", "oidc_redirect_uri_port", 0); - qDebug() << "OIDC Redirect URI Port set to [" << port << "]"; + lInfo() << "OIDC Redirect URI Port set to [" << port << "]"; auto replyHandler = new OAuthHttpServerReplyHandler(port, this); if (!replyHandler->isListening()) { lWarning() << log().arg("OAuthHttpServerReplyHandler is not listening on port") << port; emit requestFailed(tr("OAuthHttpServerReplyHandler is not listening")); - emit finished(); + // emit finished(); return; } mAuthInfo = authInfo; @@ -72,12 +72,12 @@ OIDCModel::OIDCModel(const std::shared_ptr &authInfo, QObjec } mOidc.setClientIdentifier(clientid); mAuthInfo->setClientId(clientid.toStdString()); - qDebug() << "OIDC Client ID set to [" << clientid << "]"; + lInfo() << "OIDC Client ID set to [" << clientid << "]"; // find an auth info from LinphoneCore where username = clientid auto clientSecret = CoreModel::getInstance()->getCore()->findAuthInfo("", clientid.toStdString(), ""); if (clientSecret != nullptr) { - qDebug() << "client secret found for client id [" << clientid << "]"; + lInfo() << "client secret found for client id [" << clientid << "]"; mOidc.setClientIdentifierSharedKey(clientSecret->getPassword().c_str()); } @@ -121,6 +121,7 @@ OIDCModel::OIDCModel(const std::shared_ptr &authInfo, QObjec connect(&mOidc, &QOAuth2AuthorizationCodeFlow::statusChanged, [=](QAbstractOAuth::Status status) { switch (status) { case QAbstractOAuth::Status::Granted: { + lInfo() << log().arg("Authentication granted"); stopTimeoutTimer(); //: Authentication granted emit statusChanged(tr("oidc_authentication_granted_message")); @@ -128,6 +129,7 @@ OIDCModel::OIDCModel(const std::shared_ptr &authInfo, QObjec break; } case QAbstractOAuth::Status::NotAuthenticated: { + lInfo() << log().arg("Not authenticated"); stopTimeoutTimer(); //: Not authenticated emit statusChanged(tr("oidc_authentication_not_authenticated_message")); @@ -135,11 +137,13 @@ OIDCModel::OIDCModel(const std::shared_ptr &authInfo, QObjec break; } case QAbstractOAuth::Status::RefreshingToken: { + lInfo() << log().arg("Refreshing token"); //: Refreshing token emit statusChanged(tr("oidc_authentication_refresh_message")); break; } case QAbstractOAuth::Status::TemporaryCredentialsReceived: { + lInfo() << log().arg("Temporary credentials received"); //: Temporary credentials received emit statusChanged(tr("oidc_authentication_temporary_credentials_message")); break; @@ -158,22 +162,27 @@ OIDCModel::OIDCModel(const std::shared_ptr &authInfo, QObjec lWarning() << log().arg("RequestFailed:") << metaEnum.valueToKey(static_cast(error)); switch (error) { case QAbstractOAuth::Error::NetworkError: + lWarning() << log().arg("Network error"); //: Network error emit requestFailed(tr("oidc_authentication_network_error")); break; case QAbstractOAuth::Error::ServerError: + lWarning() << log().arg("Server error"); //: Server error emit requestFailed(tr("oidc_authentication_server_error")); break; case QAbstractOAuth::Error::OAuthTokenNotFoundError: + lWarning() << log().arg("OAuth token not found"); //: OAuth token not found emit requestFailed(tr("oidc_authentication_token_not_found_error")); break; case QAbstractOAuth::Error::OAuthTokenSecretNotFoundError: + lWarning() << log().arg("OAuth token secret not found"); //: OAuth token secret not found emit requestFailed(tr("oidc_authentication_token_secret_not_found_error")); break; case QAbstractOAuth::Error::OAuthCallbackNotVerified: + lWarning() << log().arg("OAuth callback not verified"); //: OAuth callback not verified emit requestFailed(tr("oidc_authentication_callback_not_verified_error")); break; @@ -185,7 +194,7 @@ OIDCModel::OIDCModel(const std::shared_ptr &authInfo, QObjec connect(&mOidc, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, [this](const QUrl &url) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); - qDebug() << "Browser authentication url : " << url; + lInfo() << "Browser authentication url : " << url; //: Requesting authorization from browser emit statusChanged(tr("oidc_authentication_request_auth_message")); mTimeout.start(); @@ -222,7 +231,7 @@ OIDCModel::OIDCModel(const std::shared_ptr &authInfo, QObjec mIdToken.clear(); lWarning() << "No ID Token or Access Token found in the tokens."; emit requestFailed(tr("oidc_authentication_no_token_found_error")); - emit finished(); + // emit finished(); } }); #endif @@ -258,9 +267,9 @@ OIDCModel::OIDCModel(const std::shared_ptr &authInfo, QObjec }); connect(this, &OIDCModel::finished, this, &OIDCModel::deleteLater); - auto url = QUrl(Utils::coreStringToAppString(authInfo->getAuthorizationServer())); url.setPath(url.path() + OIDCWellKnown); + lInfo() << log().arg("Get request") << url; QNetworkRequest request(url); auto reply = mOidc.networkAccessManager()->get(request); connect(reply, &QNetworkReply::finished, this, &OIDCModel::openIdConfigReceived); @@ -290,9 +299,17 @@ void OIDCModel::stopTimeoutTimer() { } void OIDCModel::openIdConfigReceived() { + lInfo() << log().arg("OpenID config received"); auto reply = dynamic_cast(sender()); + lInfo() << log().arg("Reply :") << reply->readAll(); auto document = QJsonDocument::fromJson(reply->readAll()); - if (document.isNull()) return; + if (document.isNull()) { + lWarning() << log().arg("Reply is empty"); + //: OIDC reply is empty ! + emit requestFailed(tr("oidc_authentication_empty_reply_error")); + // emit finished(); + return; + } auto rootArray = document.toVariant().toMap(); if (rootArray.contains("authorization_endpoint")) { mOidc.setAuthorizationUrl(QUrl(rootArray["authorization_endpoint"].toString())); @@ -300,10 +317,11 @@ void OIDCModel::openIdConfigReceived() { lWarning() << log().arg("No authorization endpoint found in OpenID configuration"); //: No authorization endpoint found in OpenID configuration emit requestFailed(tr("oidc_authentication_no_auth_found_in_config_error")); - emit finished(); + // emit finished(); return; } if (rootArray.contains("token_endpoint")) { + lInfo() << log().arg("Set token url %1").arg(rootArray["token_endpoint"].toString()); #if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0) mOidc.setTokenUrl(QUrl(rootArray["token_endpoint"].toString())); #else @@ -315,9 +333,10 @@ void OIDCModel::openIdConfigReceived() { lWarning() << log().arg("No token endpoint found in OpenID configuration"); //: No token endpoint found in OpenID configuration emit requestFailed(tr("oidc_authentication_no_token_found_in_config_error")); - emit finished(); + // emit finished(); return; } + lInfo() << log().arg("Grant open id config"); mOidc.grant(); reply->deleteLater(); } @@ -325,7 +344,7 @@ void OIDCModel::openIdConfigReceived() { void OIDCModel::setBearers() { auto expiration = QDateTime::currentDateTime().secsTo(mOidc.expirationAt()); auto timeT = mOidc.expirationAt().toSecsSinceEpoch(); - qDebug() << "Authenticated for " << expiration << "s"; + lInfo() << "Authenticated for " << expiration << "s"; auto accessBearer = linphone::Factory::get()->createBearerToken(Utils::appStringToCoreString(idToken()), timeT); mAuthInfo->setAccessToken(accessBearer); diff --git a/Linphone/model/cli/CliModel.cpp b/Linphone/model/cli/CliModel.cpp index 3e88506bd..6a8fa226a 100644 --- a/Linphone/model/cli/CliModel.cpp +++ b/Linphone/model/cli/CliModel.cpp @@ -128,12 +128,17 @@ void CliModel::cliShow(QHash args) { } void CliModel::cliFetchConfig(QHash args) { + lInfo() << log().arg("Run fetch-config function"); if (args.contains("fetch-config")) { - if (CoreModel::getInstance()->getCore()->getGlobalState() != linphone::GlobalState::On) + if (CoreModel::getInstance()->getCore()->getGlobalState() != linphone::GlobalState::On) { + lInfo() << log().arg("Global state is not on, wait for change of state to use config"); connect( CoreModel::getInstance().get(), &CoreModel::globalStateChanged, this, [this, args]() { cliFetchConfig(args); }, Qt::SingleShotConnection); - else CoreModel::getInstance()->useFetchConfig(args["fetch-config"], false); + } else { + lInfo() << log().arg("Global state is on, use config"); + CoreModel::getInstance()->useFetchConfig(args["fetch-config"], false); + } } } @@ -240,7 +245,7 @@ void CliModel::Command::execute(QHash &args, CliModel *parent) if (!mGenericArguments) { // Check arguments validity. for (const auto &argName : args.keys()) { if (!mArgsScheme.contains(argName)) { - qWarning() + lWarning() << QStringLiteral("Command with invalid argument: `%1 (%2)`.").arg(mFunctionName).arg(argName); return; diff --git a/Linphone/model/core/CoreModel.cpp b/Linphone/model/core/CoreModel.cpp index 8c2930ae1..680759823 100644 --- a/Linphone/model/core/CoreModel.cpp +++ b/Linphone/model/core/CoreModel.cpp @@ -210,13 +210,14 @@ void CoreModel::setPathAfterStart() { QString CoreModel::getFetchConfig(QString filePath, bool *error) { *error = false; + lInfo() << log().arg("Get config %1").arg(filePath); if (!filePath.isEmpty()) { if (QUrl(filePath).isRelative()) { // this is a file path filePath = Paths::getConfigFilePath(filePath, false); if (!filePath.isEmpty()) filePath = "file://" + filePath; } if (filePath.isEmpty()) { - qWarning() << "Remote provisioning cannot be retrieved. Command have been cleaned"; + lWarning() << "Remote provisioning path cannot be retrieved. Command have been cleaned"; Utils::showInformationPopup(tr("info_popup_error_title"), //: "Remote provisioning cannot be retrieved" tr("fetching_config_failed_error_message"), false); @@ -229,23 +230,28 @@ QString CoreModel::getFetchConfig(QString filePath, bool *error) { void CoreModel::useFetchConfig(QString filePath, bool askForConfirmation) { bool error = false; filePath = getFetchConfig(filePath, &error); + lInfo() << log().arg("Use fetch config"); if (!error && !filePath.isEmpty()) { - if (mCore && mCore->getGlobalState() == linphone::GlobalState::On) { // TODO // if (mSettings->getAutoApplyProvisioningConfigUriHandlerEnabled()) setFetchConfig(filePath); else + lInfo() << log().arg("Request fetch config"); emit requestFetchConfig(filePath, askForConfirmation); } else { + lInfo() << log().arg("Global state is off, wait for requesting fetch config"); connect( - this, &CoreModel::globalStateChanged, this, [filePath, this]() { useFetchConfig(filePath); }, + this, &CoreModel::globalStateChanged, this, + [filePath, askForConfirmation, this]() { useFetchConfig(filePath, askForConfirmation); }, Qt::SingleShotConnection); } + } else { + lWarning() << log().arg("Could not get file path for fetching config, return"); } } bool CoreModel::setFetchConfig(QString filePath) { bool fetched = false; - qDebug() << "setFetchConfig with " << filePath; + lInfo() << "setFetchConfig with " << filePath; if (!filePath.isEmpty()) { if (mCore) { filePath.replace('\\', '/'); @@ -254,8 +260,11 @@ bool CoreModel::setFetchConfig(QString filePath) { } } if (!fetched) { - qWarning() << "Remote provisionning cannot be retrieved. Command have been cleaned"; - } else emit requestRestart(); + lWarning() << "Remote provisionning cannot be retrieved. Command have been cleaned"; + } else { + lInfo() << "Remote provisionning has been retrieved. Restart"; + emit requestRestart(); + } return fetched; } @@ -411,8 +420,8 @@ void CoreModel::onAuthenticationRequested(const std::shared_ptr auto username = Utils::coreStringToAppString(authInfo->getUsername()); auto realm = Utils::coreStringToAppString(authInfo->getRealm()); if (!serverUrl.isEmpty()) { - qDebug() << "onAuthenticationRequested for Bearer. Initialize OpenID connection for " << username << "@" - << realm << " at " << serverUrl; + lInfo() << "onAuthenticationRequested for Bearer. Initialize OpenID connection for " << username << "@" + << realm << " at " << serverUrl; QString key = username + '@' + realm + ' ' + serverUrl; if (mOpenIdConnections.contains(key)) mOpenIdConnections[key]->deleteLater(); auto oidcModel = new OIDCModel(authInfo, this); @@ -422,6 +431,12 @@ void CoreModel::onAuthenticationRequested(const std::shared_ptr emit timeoutTimerStarted(); qDebug() << "start refresh timer"; }); + connect(oidcModel, &OIDCModel::requestFailed, this, [this, oidcModel](const QString &error) { + mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); + lWarning() << log().arg("Request failed") << error; + emit oidcRequestFailed(error); + oidcModel->forceTimeout(); + }); if (oidcModel->isTimerRunning()) { emit timeoutTimerStarted(); } diff --git a/Linphone/model/core/CoreModel.hpp b/Linphone/model/core/CoreModel.hpp index 8170da951..f9b6c2bbd 100644 --- a/Linphone/model/core/CoreModel.hpp +++ b/Linphone/model/core/CoreModel.hpp @@ -101,6 +101,7 @@ signals: void messageReadInChatRoom(std::shared_ptr chatRoom); void oidcRemainingTimeBeforeTimeoutChanged(int remainingTime); void forceOidcTimeout(); + void oidcRequestFailed(const QString &error); void timeoutTimerStarted(); void timeoutTimerStopped();