zrtp authentication token
This commit is contained in:
parent
92f7d05b18
commit
c33b35724a
18 changed files with 420 additions and 110 deletions
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include "CallCore.hpp"
|
||||
#include "core/App.hpp"
|
||||
#include "model/object/VariantObject.hpp"
|
||||
#include "model/tool/ToolModel.hpp"
|
||||
#include "tool/Utils.hpp"
|
||||
#include "tool/thread/SafeConnection.hpp"
|
||||
|
|
@ -51,11 +50,11 @@ CallCore::CallCore(const std::shared_ptr<linphone::Call> &call) : QObject(nullpt
|
|||
mPeerAddress = Utils::coreStringToAppString(mCallModel->getRemoteAddress()->asString());
|
||||
mStatus = LinphoneEnums::fromLinphone(call->getCallLog()->getStatus());
|
||||
mTransferState = LinphoneEnums::fromLinphone(call->getTransferState());
|
||||
auto encryption = LinphoneEnums::fromLinphone(call->getCurrentParams()->getMediaEncryption());
|
||||
mEncryption = LinphoneEnums::fromLinphone(call->getParams()->getMediaEncryption());
|
||||
auto tokenVerified = mCallModel->getAuthenticationTokenVerified();
|
||||
mPeerSecured = (encryption == LinphoneEnums::MediaEncryption::Zrtp && tokenVerified) ||
|
||||
encryption == LinphoneEnums::MediaEncryption::Srtp ||
|
||||
encryption == LinphoneEnums::MediaEncryption::Dtls;
|
||||
mIsSecured = (mEncryption == LinphoneEnums::MediaEncryption::Zrtp && tokenVerified) ||
|
||||
mEncryption == LinphoneEnums::MediaEncryption::Srtp ||
|
||||
mEncryption == LinphoneEnums::MediaEncryption::Dtls;
|
||||
mPaused = mState == LinphoneEnums::CallState::Pausing || mState == LinphoneEnums::CallState::Paused ||
|
||||
mState == LinphoneEnums::CallState::PausedByRemote;
|
||||
mRecording = call->getParams() && call->getParams()->isRecording();
|
||||
|
|
@ -70,75 +69,82 @@ CallCore::~CallCore() {
|
|||
}
|
||||
|
||||
void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||
mAccountModelConnection = QSharedPointer<SafeConnection<CallCore, CallModel>>(
|
||||
mCallModelConnection = QSharedPointer<SafeConnection<CallCore, CallModel>>(
|
||||
new SafeConnection<CallCore, CallModel>(me, mCallModel), &QObject::deleteLater);
|
||||
mAccountModelConnection->makeConnectToCore(&CallCore::lSetMicrophoneMuted, [this](bool isMuted) {
|
||||
mAccountModelConnection->invokeToModel([this, isMuted]() { mCallModel->setMicrophoneMuted(isMuted); });
|
||||
mCallModelConnection->makeConnectToCore(&CallCore::lSetMicrophoneMuted, [this](bool isMuted) {
|
||||
mCallModelConnection->invokeToModel([this, isMuted]() { mCallModel->setMicrophoneMuted(isMuted); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(&CallModel::microphoneMutedChanged, [this](bool isMuted) {
|
||||
mAccountModelConnection->invokeToCore([this, isMuted]() { setMicrophoneMuted(isMuted); });
|
||||
mCallModelConnection->makeConnectToModel(&CallModel::microphoneMutedChanged, [this](bool isMuted) {
|
||||
mCallModelConnection->invokeToCore([this, isMuted]() { setMicrophoneMuted(isMuted); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(&CallModel::remoteVideoEnabledChanged, [this](bool enabled) {
|
||||
mAccountModelConnection->invokeToCore([this, enabled]() { setRemoteVideoEnabled(enabled); });
|
||||
mCallModelConnection->makeConnectToModel(&CallModel::remoteVideoEnabledChanged, [this](bool enabled) {
|
||||
mCallModelConnection->invokeToCore([this, enabled]() { setRemoteVideoEnabled(enabled); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToCore(&CallCore::lSetSpeakerMuted, [this](bool isMuted) {
|
||||
mAccountModelConnection->invokeToModel([this, isMuted]() { mCallModel->setSpeakerMuted(isMuted); });
|
||||
mCallModelConnection->makeConnectToCore(&CallCore::lSetSpeakerMuted, [this](bool isMuted) {
|
||||
mCallModelConnection->invokeToModel([this, isMuted]() { mCallModel->setSpeakerMuted(isMuted); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(&CallModel::speakerMutedChanged, [this](bool isMuted) {
|
||||
mAccountModelConnection->invokeToCore([this, isMuted]() { setSpeakerMuted(isMuted); });
|
||||
mCallModelConnection->makeConnectToModel(&CallModel::speakerMutedChanged, [this](bool isMuted) {
|
||||
mCallModelConnection->invokeToCore([this, isMuted]() { setSpeakerMuted(isMuted); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToCore(&CallCore::lSetCameraEnabled, [this](bool enabled) {
|
||||
mAccountModelConnection->invokeToModel([this, enabled]() { mCallModel->setCameraEnabled(enabled); });
|
||||
mCallModelConnection->makeConnectToCore(&CallCore::lSetCameraEnabled, [this](bool enabled) {
|
||||
mCallModelConnection->invokeToModel([this, enabled]() { mCallModel->setCameraEnabled(enabled); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToCore(&CallCore::lStartRecording, [this]() {
|
||||
mAccountModelConnection->invokeToModel([this]() { mCallModel->startRecording(); });
|
||||
mCallModelConnection->makeConnectToCore(&CallCore::lStartRecording, [this]() {
|
||||
mCallModelConnection->invokeToModel([this]() { mCallModel->startRecording(); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToCore(&CallCore::lStopRecording, [this]() {
|
||||
mAccountModelConnection->invokeToModel([this]() { mCallModel->stopRecording(); });
|
||||
mCallModelConnection->makeConnectToCore(&CallCore::lStopRecording, [this]() {
|
||||
mCallModelConnection->invokeToModel([this]() { mCallModel->stopRecording(); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(&CallModel::recordingChanged, [this](bool recording) {
|
||||
mAccountModelConnection->invokeToCore([this, recording]() { setRecording(recording); });
|
||||
mCallModelConnection->makeConnectToModel(&CallModel::recordingChanged, [this](bool recording) {
|
||||
mCallModelConnection->invokeToCore([this, recording]() { setRecording(recording); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(
|
||||
mCallModelConnection->makeConnectToCore(&CallCore::lVerifyAuthenticationToken, [this](bool verified) {
|
||||
mCallModelConnection->invokeToModel(
|
||||
[this, verified]() { mCallModel->setAuthenticationTokenVerified(verified); });
|
||||
});
|
||||
mCallModelConnection->makeConnectToModel(&CallModel::authenticationTokenVerifiedChanged, [this](bool verified) {
|
||||
mCallModelConnection->invokeToCore([this, verified]() { setIsSecured(verified); });
|
||||
});
|
||||
mCallModelConnection->makeConnectToModel(
|
||||
&CallModel::remoteRecording, [this](const std::shared_ptr<linphone::Call> &call, bool recording) {
|
||||
mAccountModelConnection->invokeToCore([this, recording]() { setRemoteRecording(recording); });
|
||||
mCallModelConnection->invokeToCore([this, recording]() { setRemoteRecording(recording); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(&CallModel::cameraEnabledChanged, [this](bool enabled) {
|
||||
mAccountModelConnection->invokeToCore([this, enabled]() { setCameraEnabled(enabled); });
|
||||
mCallModelConnection->makeConnectToModel(&CallModel::cameraEnabledChanged, [this](bool enabled) {
|
||||
mCallModelConnection->invokeToCore([this, enabled]() { setCameraEnabled(enabled); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(&CallModel::durationChanged, [this](int duration) {
|
||||
mAccountModelConnection->invokeToCore([this, duration]() { setDuration(duration); });
|
||||
mCallModelConnection->makeConnectToModel(&CallModel::durationChanged, [this](int duration) {
|
||||
mCallModelConnection->invokeToCore([this, duration]() { setDuration(duration); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(
|
||||
mCallModelConnection->makeConnectToModel(
|
||||
&CallModel::stateChanged, [this](linphone::Call::State state, const std::string &message) {
|
||||
mAccountModelConnection->invokeToCore([this, state, message]() {
|
||||
mCallModelConnection->invokeToCore([this, state, message]() {
|
||||
setState(LinphoneEnums::fromLinphone(state), Utils::coreStringToAppString(message));
|
||||
});
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(&CallModel::statusChanged, [this](linphone::Call::Status status) {
|
||||
mAccountModelConnection->invokeToCore([this, status]() { setStatus(LinphoneEnums::fromLinphone(status)); });
|
||||
mCallModelConnection->makeConnectToModel(&CallModel::statusChanged, [this](linphone::Call::Status status) {
|
||||
mCallModelConnection->invokeToCore([this, status]() { setStatus(LinphoneEnums::fromLinphone(status)); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(&CallModel::stateChanged,
|
||||
[this](linphone::Call::State state, const std::string &message) {
|
||||
mAccountModelConnection->invokeToCore([this, state]() {
|
||||
setRecordable(state == linphone::Call::State::StreamsRunning);
|
||||
});
|
||||
});
|
||||
mAccountModelConnection->makeConnectToCore(&CallCore::lSetPaused, [this](bool paused) {
|
||||
mAccountModelConnection->invokeToModel([this, paused]() { mCallModel->setPaused(paused); });
|
||||
mCallModelConnection->makeConnectToModel(&CallModel::stateChanged,
|
||||
[this](linphone::Call::State state, const std::string &message) {
|
||||
mCallModelConnection->invokeToCore([this, state]() {
|
||||
setRecordable(state == linphone::Call::State::StreamsRunning);
|
||||
});
|
||||
});
|
||||
mCallModelConnection->makeConnectToCore(&CallCore::lSetPaused, [this](bool paused) {
|
||||
mCallModelConnection->invokeToModel([this, paused]() { mCallModel->setPaused(paused); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(&CallModel::pausedChanged, [this](bool paused) {
|
||||
mAccountModelConnection->invokeToCore([this, paused]() { setPaused(paused); });
|
||||
mCallModelConnection->makeConnectToModel(&CallModel::pausedChanged, [this](bool paused) {
|
||||
mCallModelConnection->invokeToCore([this, paused]() { setPaused(paused); });
|
||||
});
|
||||
|
||||
mAccountModelConnection->makeConnectToCore(&CallCore::lTransferCall, [this](const QString &address) {
|
||||
mAccountModelConnection->invokeToModel(
|
||||
mCallModelConnection->makeConnectToCore(&CallCore::lTransferCall, [this](const QString &address) {
|
||||
mCallModelConnection->invokeToModel(
|
||||
[this, address]() { mCallModel->transferTo(ToolModel::interpretUrl(address)); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(
|
||||
mCallModelConnection->makeConnectToModel(
|
||||
&CallModel::transferStateChanged,
|
||||
[this](const std::shared_ptr<linphone::Call> &call, linphone::Call::State state) {
|
||||
mAccountModelConnection->invokeToCore([this, state]() {
|
||||
mCallModelConnection->invokeToCore([this, state]() {
|
||||
QString message;
|
||||
if (state == linphone::Call::State::Error) {
|
||||
message = "L'appel n'a pas pu être transféré.";
|
||||
|
|
@ -146,27 +152,35 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
|||
setTransferState(LinphoneEnums::fromLinphone(state), message);
|
||||
});
|
||||
});
|
||||
mAccountModelConnection->makeConnectToModel(
|
||||
mCallModelConnection->makeConnectToModel(
|
||||
&CallModel::encryptionChanged,
|
||||
[this](const std::shared_ptr<linphone::Call> &call, bool on, const std::string &authenticationToken) {
|
||||
auto encryption = LinphoneEnums::fromLinphone(call->getCurrentParams()->getMediaEncryption());
|
||||
auto tokenVerified = mCallModel->getAuthenticationTokenVerified();
|
||||
mAccountModelConnection->invokeToCore([this, call, encryption, tokenVerified]() {
|
||||
setPeerSecured((encryption == LinphoneEnums::MediaEncryption::Zrtp && tokenVerified) ||
|
||||
encryption == LinphoneEnums::MediaEncryption::Srtp ||
|
||||
encryption == LinphoneEnums::MediaEncryption::Dtls);
|
||||
auto token = Utils::coreStringToAppString(mCallModel->getAuthenticationToken());
|
||||
mCallModelConnection->invokeToCore([this, call, encryption, tokenVerified, token]() {
|
||||
auto localToken =
|
||||
mDir == LinphoneEnums::CallDir::Incoming ? token.left(2).toUpper() : token.right(2).toUpper();
|
||||
auto remoteToken =
|
||||
mDir == LinphoneEnums::CallDir::Outgoing ? token.left(2).toUpper() : token.right(2).toUpper();
|
||||
setLocalSas(localToken);
|
||||
setRemoteSas(remoteToken);
|
||||
setEncryption(encryption);
|
||||
setIsSecured((encryption == LinphoneEnums::MediaEncryption::Zrtp && tokenVerified) ||
|
||||
encryption == LinphoneEnums::MediaEncryption::Srtp ||
|
||||
encryption == LinphoneEnums::MediaEncryption::Dtls);
|
||||
});
|
||||
});
|
||||
mAccountModelConnection->makeConnectToCore(&CallCore::lAccept, [this](bool withVideo) {
|
||||
mAccountModelConnection->invokeToModel([this, withVideo]() { mCallModel->accept(withVideo); });
|
||||
mCallModelConnection->makeConnectToCore(&CallCore::lAccept, [this](bool withVideo) {
|
||||
mCallModelConnection->invokeToModel([this, withVideo]() { mCallModel->accept(withVideo); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToCore(
|
||||
&CallCore::lDecline, [this]() { mAccountModelConnection->invokeToModel([this]() { mCallModel->decline(); }); });
|
||||
mAccountModelConnection->makeConnectToCore(&CallCore::lTerminate, [this]() {
|
||||
mAccountModelConnection->invokeToModel([this]() { mCallModel->terminate(); });
|
||||
mCallModelConnection->makeConnectToCore(
|
||||
&CallCore::lDecline, [this]() { mCallModelConnection->invokeToModel([this]() { mCallModel->decline(); }); });
|
||||
mCallModelConnection->makeConnectToCore(&CallCore::lTerminate, [this]() {
|
||||
mCallModelConnection->invokeToModel([this]() { mCallModel->terminate(); });
|
||||
});
|
||||
mAccountModelConnection->makeConnectToCore(&CallCore::lTerminateAllCalls, [this]() {
|
||||
mAccountModelConnection->invokeToModel([this]() { mCallModel->terminateAllCalls(); });
|
||||
mCallModelConnection->makeConnectToCore(&CallCore::lTerminateAllCalls, [this]() {
|
||||
mCallModelConnection->invokeToModel([this]() { mCallModel->terminateAllCalls(); });
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -276,13 +290,47 @@ void CallCore::setPaused(bool paused) {
|
|||
}
|
||||
}
|
||||
|
||||
bool CallCore::getPeerSecured() const {
|
||||
return mPeerSecured;
|
||||
bool CallCore::isSecured() const {
|
||||
return mIsSecured;
|
||||
}
|
||||
void CallCore::setPeerSecured(bool secured) {
|
||||
if (mPeerSecured != secured) {
|
||||
mPeerSecured = secured;
|
||||
emit peerSecuredChanged();
|
||||
|
||||
void CallCore::setIsSecured(bool secured) {
|
||||
if (mIsSecured != secured) {
|
||||
mIsSecured = secured;
|
||||
emit securityUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
QString CallCore::getLocalSas() {
|
||||
return mLocalSas;
|
||||
}
|
||||
|
||||
QString CallCore::getRemoteSas() {
|
||||
return mRemoteSas;
|
||||
}
|
||||
|
||||
void CallCore::setLocalSas(const QString &sas) {
|
||||
if (mLocalSas != sas) {
|
||||
mLocalSas = sas;
|
||||
emit localSasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void CallCore::setRemoteSas(const QString &sas) {
|
||||
if (mRemoteSas != sas) {
|
||||
mRemoteSas = sas;
|
||||
emit remoteSasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneEnums::MediaEncryption CallCore::getEncryption() const {
|
||||
return mEncryption;
|
||||
}
|
||||
|
||||
void CallCore::setEncryption(LinphoneEnums::MediaEncryption encryption) {
|
||||
if (mEncryption != encryption) {
|
||||
mEncryption = encryption;
|
||||
emit securityUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,10 @@ class CallCore : public QObject, public AbstractObject {
|
|||
Q_PROPERTY(bool cameraEnabled READ getCameraEnabled WRITE lSetCameraEnabled NOTIFY cameraEnabledChanged)
|
||||
Q_PROPERTY(bool paused READ getPaused WRITE lSetPaused NOTIFY pausedChanged)
|
||||
Q_PROPERTY(QString peerAddress READ getPeerAddress CONSTANT)
|
||||
Q_PROPERTY(bool peerSecured READ getPeerSecured WRITE setPeerSecured NOTIFY peerSecuredChanged)
|
||||
Q_PROPERTY(bool isSecured READ isSecured NOTIFY securityUpdated)
|
||||
Q_PROPERTY(LinphoneEnums::MediaEncryption encryption READ getEncryption NOTIFY securityUpdated)
|
||||
Q_PROPERTY(QString localSas READ getLocalSas WRITE setLocalSas MEMBER mLocalSas NOTIFY localSasChanged)
|
||||
Q_PROPERTY(QString remoteSas WRITE setRemoteSas MEMBER mRemoteSas NOTIFY remoteSasChanged)
|
||||
Q_PROPERTY(
|
||||
bool remoteVideoEnabled READ getRemoteVideoEnabled WRITE setRemoteVideoEnabled NOTIFY remoteVideoEnabledChanged)
|
||||
Q_PROPERTY(bool recording READ getRecording WRITE setRecording NOTIFY recordingChanged)
|
||||
|
|
@ -86,8 +89,16 @@ public:
|
|||
bool getPaused() const;
|
||||
void setPaused(bool paused);
|
||||
|
||||
bool getPeerSecured() const;
|
||||
void setPeerSecured(bool secured);
|
||||
bool isSecured() const;
|
||||
void setIsSecured(bool secured);
|
||||
|
||||
QString getLocalSas();
|
||||
void setLocalSas(const QString &sas);
|
||||
QString getRemoteSas();
|
||||
void setRemoteSas(const QString &sas);
|
||||
|
||||
LinphoneEnums::MediaEncryption getEncryption() const;
|
||||
void setEncryption(LinphoneEnums::MediaEncryption encryption);
|
||||
|
||||
bool getRemoteVideoEnabled() const;
|
||||
void setRemoteVideoEnabled(bool enabled);
|
||||
|
|
@ -118,7 +129,9 @@ signals:
|
|||
void cameraEnabledChanged();
|
||||
void pausedChanged();
|
||||
void transferStateChanged();
|
||||
void peerSecuredChanged();
|
||||
void securityUpdated();
|
||||
void localSasChanged();
|
||||
void remoteSasChanged();
|
||||
void remoteVideoEnabledChanged(bool remoteVideoEnabled);
|
||||
void recordingChanged();
|
||||
void remoteRecordingChanged();
|
||||
|
|
@ -136,6 +149,7 @@ signals:
|
|||
void lTransferCall(const QString &dest);
|
||||
void lStartRecording();
|
||||
void lStopRecording();
|
||||
void lVerifyAuthenticationToken(bool verified);
|
||||
|
||||
/* TODO
|
||||
Q_INVOKABLE void acceptWithVideo();
|
||||
|
|
@ -161,9 +175,10 @@ private:
|
|||
LinphoneEnums::CallState mState;
|
||||
LinphoneEnums::CallState mTransferState;
|
||||
LinphoneEnums::CallDir mDir;
|
||||
LinphoneEnums::MediaEncryption mEncryption;
|
||||
QString mLastErrorMessage;
|
||||
QString mPeerAddress;
|
||||
bool mPeerSecured;
|
||||
bool mIsSecured;
|
||||
int mDuration = 0;
|
||||
bool mSpeakerMuted;
|
||||
bool mMicrophoneMuted;
|
||||
|
|
@ -173,7 +188,9 @@ private:
|
|||
bool mRecording = false;
|
||||
bool mRemoteRecording = false;
|
||||
bool mRecordable = false;
|
||||
QSharedPointer<SafeConnection<CallCore, CallModel>> mAccountModelConnection;
|
||||
QString mLocalSas;
|
||||
QString mRemoteSas;
|
||||
QSharedPointer<SafeConnection<CallCore, CallModel>> mCallModelConnection;
|
||||
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ list(APPEND _LINPHONEAPP_RC_FILES data/assistant/use-app-sip-account.rc
|
|||
"data/image/heart.svg"
|
||||
"data/image/heart-fill.svg"
|
||||
"data/image/record-fill.svg"
|
||||
"data/image/media_encryption_zrtp_pq.svg"
|
||||
|
||||
data/shaders/roundEffect.vert.qsb
|
||||
data/shaders/roundEffect.frag.qsb
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ void CallModel::stopRecording() {
|
|||
}
|
||||
|
||||
void CallModel::setRecordFile(const std::string &path) {
|
||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||
auto core = CoreModel::getInstance()->getCore();
|
||||
auto params = core->createCallParams(mMonitor);
|
||||
params->setRecordFile(path);
|
||||
|
|
@ -143,6 +144,7 @@ void CallModel::setRecordFile(const std::string &path) {
|
|||
}
|
||||
|
||||
std::string CallModel::getRecordFile() const {
|
||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||
return mMonitor->getParams()->getRecordFile();
|
||||
}
|
||||
|
||||
|
|
@ -151,11 +153,23 @@ std::shared_ptr<const linphone::Address> CallModel::getRemoteAddress() {
|
|||
return mMonitor->getRemoteAddress();
|
||||
}
|
||||
|
||||
bool CallModel::getAuthenticationTokenVerified() {
|
||||
bool CallModel::getAuthenticationTokenVerified() const {
|
||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||
return mMonitor->getAuthenticationTokenVerified();
|
||||
}
|
||||
|
||||
void CallModel::setAuthenticationTokenVerified(bool verified) {
|
||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||
mMonitor->setAuthenticationTokenVerified(verified);
|
||||
emit authenticationTokenVerifiedChanged(verified);
|
||||
}
|
||||
|
||||
std::string CallModel::getAuthenticationToken() const {
|
||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||
auto token = mMonitor->getAuthenticationToken();
|
||||
return token;
|
||||
}
|
||||
|
||||
void CallModel::onDtmfReceived(const std::shared_ptr<linphone::Call> &call, int dtmf) {
|
||||
emit dtmfReceived(call, dtmf);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,9 @@ public:
|
|||
|
||||
std::string getRecordFile() const;
|
||||
std::shared_ptr<const linphone::Address> getRemoteAddress();
|
||||
bool getAuthenticationTokenVerified();
|
||||
bool getAuthenticationTokenVerified() const;
|
||||
void setAuthenticationTokenVerified(bool verified);
|
||||
std::string getAuthenticationToken() const;
|
||||
|
||||
signals:
|
||||
void microphoneMutedChanged(bool isMuted);
|
||||
|
|
@ -63,6 +65,7 @@ signals:
|
|||
void pausedChanged(bool paused);
|
||||
void remoteVideoEnabledChanged(bool remoteVideoEnabled);
|
||||
void recordingChanged(bool recording);
|
||||
void authenticationTokenVerifiedChanged(bool verified);
|
||||
|
||||
private:
|
||||
QTimer mDurationTimer;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ QString ToolModel::getDisplayName(QString address) {
|
|||
|
||||
QSharedPointer<CallCore> ToolModel::createCall(const QString &sipAddress,
|
||||
const QString &prepareTransfertAddress,
|
||||
const QHash<QString, QString> &headers) {
|
||||
const QHash<QString, QString> &headers,
|
||||
linphone::MediaEncryption mediaEncryption) {
|
||||
bool waitRegistrationForCall = true; // getSettingsModel()->getWaitRegistrationForCall()
|
||||
std::shared_ptr<linphone::Core> core = CoreModel::getInstance()->getCore();
|
||||
|
||||
|
|
@ -88,6 +89,7 @@ QSharedPointer<CallCore> ToolModel::createCall(const QString &sipAddress,
|
|||
|
||||
std::shared_ptr<linphone::CallParams> params = core->createCallParams(nullptr);
|
||||
params->enableVideo(false);
|
||||
params->setMediaEncryption(mediaEncryption);
|
||||
if (Utils::coreStringToAppString(params->getRecordFile()).isEmpty()) {
|
||||
|
||||
params->setRecordFile(
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ public:
|
|||
|
||||
static QSharedPointer<CallCore> createCall(const QString &sipAddress,
|
||||
const QString &prepareTransfertAddress = "",
|
||||
const QHash<QString, QString> &headers = {});
|
||||
const QHash<QString, QString> &headers = {},
|
||||
linphone::MediaEncryption = linphone::MediaEncryption::None);
|
||||
|
||||
private:
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
|
|
|
|||
|
|
@ -312,7 +312,6 @@ Q_DECLARE_METATYPE(LinphoneEnums::ConferenceInfoState)
|
|||
Q_DECLARE_METATYPE(LinphoneEnums::ConferenceSchedulerState)
|
||||
Q_DECLARE_METATYPE(LinphoneEnums::EventLogType)
|
||||
Q_DECLARE_METATYPE(LinphoneEnums::FriendCapability)
|
||||
Q_DECLARE_METATYPE(LinphoneEnums::MediaEncryption)
|
||||
Q_DECLARE_METATYPE(LinphoneEnums::ParticipantDeviceState)
|
||||
Q_DECLARE_METATYPE(LinphoneEnums::RecorderState)
|
||||
Q_DECLARE_METATYPE(LinphoneEnums::TunnelMode)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "tool/providers/AvatarProvider.hpp"
|
||||
#include <QImageReader>
|
||||
#include <QQuickWindow>
|
||||
#include <QRandomGenerator>
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
|
@ -261,3 +262,29 @@ QString Utils::generateSavedFilename(const QString &from, const QString &to) {
|
|||
.arg(escape(from))
|
||||
.arg(escape(to));
|
||||
}
|
||||
|
||||
QStringList Utils::generateSecurityLettersArray(int arraySize, int correctIndex, QString correctCode) {
|
||||
QStringList vec;
|
||||
const QString possibleCharacters(tr("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"));
|
||||
const int n = 2;
|
||||
for (int i = 0; i < arraySize; ++i) {
|
||||
QString randomString;
|
||||
if (i == correctIndex) randomString = correctCode;
|
||||
else {
|
||||
do {
|
||||
randomString.clear();
|
||||
for (int j = 0; j < n; ++j) {
|
||||
int index = rand() % possibleCharacters.length();
|
||||
QChar nextChar = possibleCharacters.at(index);
|
||||
randomString.append(nextChar);
|
||||
}
|
||||
} while (vec.contains(randomString) || randomString == correctCode);
|
||||
}
|
||||
vec.append(randomString);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
int Utils::getRandomIndex(int size) {
|
||||
return QRandomGenerator::global()->bounded(size);
|
||||
}
|
||||
|
|
@ -69,7 +69,9 @@ public:
|
|||
Q_INVOKABLE static QString formatElapsedTime(int seconds,
|
||||
bool dotsSeparator = true); // Return the elapsed time formated
|
||||
Q_INVOKABLE static QString formatDate(const QDateTime &date, bool includeTime = true); // Return the date formated
|
||||
Q_INVOKABLE static QString formatDateElapsedTime(const QDateTime &date); // Return the date formated
|
||||
Q_INVOKABLE static QString formatDateElapsedTime(const QDateTime &date);
|
||||
Q_INVOKABLE static QStringList generateSecurityLettersArray(int arraySize, int correctIndex, QString correctCode);
|
||||
Q_INVOKABLE static int getRandomIndex(int size);
|
||||
static QString generateSavedFilename(const QString &from, const QString &to);
|
||||
|
||||
static inline QString coreStringToAppString(const std::string &str) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,15 @@ Window {
|
|||
Connections {
|
||||
target: call.core
|
||||
onRemoteVideoEnabledChanged: console.log("remote video enabled", call.core.remoteVideoEnabled)
|
||||
onSecurityUpdated: {
|
||||
if (call.core.isSecured) {
|
||||
zrtpValidation.close()
|
||||
}
|
||||
else if(call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp) {
|
||||
zrtpValidation.open()
|
||||
// mainWindow.attachVirtualWindow(Utils.buildLinphoneDialogUri('ZrtpTokenAuthenticationDialog'), {call:callModel})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onCallChanged: {
|
||||
|
|
@ -29,7 +38,12 @@ Window {
|
|||
property var callState: call.core.state
|
||||
onCallStateChanged: {
|
||||
console.log("State:", callState)
|
||||
if (callState === LinphoneEnums.CallState.Error || callState === LinphoneEnums.CallState.End) {
|
||||
if (callState === LinphoneEnums.CallState.Connected) {
|
||||
if(!call.core.isSecured && call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp) {
|
||||
zrtpValidation.open()
|
||||
}
|
||||
}
|
||||
else if (callState === LinphoneEnums.CallState.Error || callState === LinphoneEnums.CallState.End) {
|
||||
endCall(call)
|
||||
}
|
||||
}
|
||||
|
|
@ -122,6 +136,10 @@ Window {
|
|||
colorizationColor: disabledIcon && bottomButton.checked ? DefaultStyle.main2_0 : DefaultStyle.grey_0
|
||||
}
|
||||
}
|
||||
ZrtpTokenAuthenticationDialog {
|
||||
id: zrtpValidation
|
||||
call: mainWindow.call
|
||||
}
|
||||
Popup {
|
||||
id: waitingPopup
|
||||
visible: mainWindow.call.core.transferState === LinphoneEnums.CallState.OutgoingInit
|
||||
|
|
@ -259,8 +277,7 @@ Window {
|
|||
bottomPadding: 8 * DefaultStyle.dp
|
||||
leftPadding: 10 * DefaultStyle.dp
|
||||
rightPadding: 10 * DefaultStyle.dp
|
||||
visible: mainWindow.call.core.peerSecured
|
||||
onVisibleChanged: console.log("peer secured", mainWindow.call.core.peerSecured)
|
||||
visible: mainWindow.call.core.isSecured
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
border.color: DefaultStyle.info_500_main
|
||||
|
|
@ -483,8 +500,6 @@ Window {
|
|||
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Liste d'appel")
|
||||
// width: callList.width
|
||||
// height: callList.height
|
||||
onHeightChanged: console.log("control height changed", height)
|
||||
|
||||
// padding: 15 * DefaultStyle.dp
|
||||
topPadding: 15 * DefaultStyle.dp
|
||||
bottomPadding: 15 * DefaultStyle.dp
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
|||
view/Item/TextInput.qml
|
||||
view/Item/ToolTip.qml
|
||||
view/Item/VerticalTabBar.qml
|
||||
view/Item/ZrtpTokenAuthenticationDialog.qml
|
||||
|
||||
view/Item/Form/LoginForm.qml
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,12 @@ import Linphone
|
|||
Control.Button {
|
||||
id: mainItem
|
||||
property int capitalization
|
||||
property color color: DefaultStyle.main1_500_main
|
||||
property color pressedColor: DefaultStyle.main1_500_main_darker
|
||||
property bool inversedColors: false
|
||||
property int textSize: 18 * DefaultStyle.dp
|
||||
property int textWeight: 600 * DefaultStyle.dp
|
||||
property bool underline: false
|
||||
property bool shadowEnabled: false
|
||||
hoverEnabled: true
|
||||
|
||||
|
|
@ -26,10 +29,10 @@ Control.Button {
|
|||
? DefaultStyle.grey_100
|
||||
: DefaultStyle.grey_0
|
||||
: mainItem.pressed
|
||||
? DefaultStyle.main1_500_main_darker
|
||||
: DefaultStyle.main1_500_main
|
||||
? mainItem.pressedColor
|
||||
: mainItem.color
|
||||
radius: 48 * DefaultStyle.dp
|
||||
border.color: inversedColors ? DefaultStyle.main1_500_main : DefaultStyle.grey_0
|
||||
border.color: inversedColors ? mainItem.color : DefaultStyle.grey_0
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
|
@ -49,16 +52,18 @@ Control.Button {
|
|||
}
|
||||
|
||||
contentItem: Text {
|
||||
id: contentText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors.centerIn: parent
|
||||
wrapMode: Text.WordWrap
|
||||
text: mainItem.text
|
||||
color: inversedColors ? DefaultStyle.main1_500_main : DefaultStyle.grey_0
|
||||
color: inversedColors ? mainItem.color : DefaultStyle.grey_0
|
||||
font {
|
||||
pixelSize: mainItem.textSize
|
||||
weight: mainItem.textWeight
|
||||
family: DefaultStyle.defaultFont
|
||||
capitalization: mainItem.capitalization
|
||||
underline: mainItem.underline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,11 @@ Popup {
|
|||
rightPadding: 10 * DefaultStyle.dp
|
||||
leftPadding: 10 * DefaultStyle.dp
|
||||
topPadding: 10 * DefaultStyle.dp
|
||||
bottomPadding: 10 * DefaultStyle.dp + buttonsLayout.height
|
||||
bottomPadding: 10 * DefaultStyle.dp
|
||||
property int radius: 16 * DefaultStyle.dp
|
||||
property color underlineColor: DefaultStyle.main1_500_main
|
||||
property alias buttons: buttonsLayout.data
|
||||
property alias content: contentLayout.data
|
||||
property string text
|
||||
signal accepted()
|
||||
signal rejected()
|
||||
|
|
@ -24,14 +26,17 @@ Popup {
|
|||
Rectangle {
|
||||
visible: mainItem.underlineColor != undefined
|
||||
width: mainItem.width
|
||||
height: mainItem.height + 2 * DefaultStyle.dp
|
||||
x: backgroundItem.x
|
||||
y: backgroundItem.y
|
||||
height: backgroundItem.height + 2 * DefaultStyle.dp
|
||||
color: mainItem.underlineColor
|
||||
radius: mainItem.radius
|
||||
}
|
||||
Rectangle{
|
||||
Rectangle {
|
||||
id: backgroundItem
|
||||
anchors.fill: parent
|
||||
width: mainItem.width
|
||||
height: mainItem.height
|
||||
height: mainItem.implicitHeight
|
||||
radius: mainItem.radius
|
||||
color: DefaultStyle.grey_0
|
||||
border.color: DefaultStyle.grey_0
|
||||
|
|
@ -44,13 +49,39 @@ Popup {
|
|||
shadowBlur: 1.0
|
||||
shadowOpacity: 0.1
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 20 * DefaultStyle.dp
|
||||
ColumnLayout {
|
||||
id: contentLayout
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
Text {
|
||||
id: defaultText
|
||||
visible: text.length != 0
|
||||
width: parent.width
|
||||
Layout.preferredWidth: 278 * DefaultStyle.dp
|
||||
text: mainItem.text
|
||||
font {
|
||||
pixelSize: 14 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
}
|
||||
wrapMode: Text.Wrap
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: buttonsLayout
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.bottomMargin: 10 * DefaultStyle.dp
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
|
||||
spacing: 10 * DefaultStyle.dp
|
||||
|
||||
// Default buttons only visible if no other children
|
||||
// have been set
|
||||
Button {
|
||||
visible: mainItem.buttons.length === 2
|
||||
text: qsTr("Oui")
|
||||
onClicked: {
|
||||
mainItem.accepted()
|
||||
|
|
@ -58,6 +89,7 @@ Popup {
|
|||
}
|
||||
}
|
||||
Button {
|
||||
visible: mainItem.buttons.length === 2
|
||||
text: qsTr("Non")
|
||||
onClicked: {
|
||||
mainItem.rejected()
|
||||
|
|
@ -66,16 +98,4 @@ Popup {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
width: parent.width
|
||||
Layout.preferredWidth: 278 * DefaultStyle.dp
|
||||
text: mainItem.text
|
||||
font {
|
||||
pixelSize: 14 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
}
|
||||
wrapMode: Text.Wrap
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
155
Linphone/view/Item/ZrtpTokenAuthenticationDialog.qml
Normal file
155
Linphone/view/Item/ZrtpTokenAuthenticationDialog.qml
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Effects
|
||||
|
||||
import Linphone
|
||||
import UtilsCpp 1.0
|
||||
|
||||
// =============================================================================
|
||||
Dialog {
|
||||
id: mainItem
|
||||
|
||||
property var call
|
||||
|
||||
width: 436 * DefaultStyle.dp
|
||||
height: 549 * DefaultStyle.dp
|
||||
|
||||
rightPadding: 15 * DefaultStyle.dp
|
||||
leftPadding: 15 * DefaultStyle.dp
|
||||
topPadding: 40 * DefaultStyle.dp
|
||||
bottomPadding: 40 * DefaultStyle.dp
|
||||
|
||||
onCallChanged: if(!call) close()
|
||||
|
||||
Connections {
|
||||
target: call.core
|
||||
onStatusChanged: if (status === CallModel.CallStatusEnded) close()
|
||||
}
|
||||
|
||||
buttons: ColumnLayout {
|
||||
spacing: 15 * DefaultStyle.dp
|
||||
Button {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
background: Item{}
|
||||
contentItem: Text {
|
||||
text: qsTr("Skip")
|
||||
font {
|
||||
pixelSize: 13 * DefaultStyle.dp
|
||||
weight: 600 * DefaultStyle.dp
|
||||
underline: true
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
if(mainItem.call) mainItem.call.core.lVerifyAuthenticationToken(false)
|
||||
mainItem.close()
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: qsTr("Letters doesn't match")
|
||||
color: DefaultStyle.danger_500main
|
||||
inversedColors: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
width: 330 * DefaultStyle.dp
|
||||
onClicked: {
|
||||
if(mainItem.call) mainItem.call.core.lVerifyAuthenticationToken(false)
|
||||
mainItem.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
content: ColumnLayout {
|
||||
spacing: 32 * DefaultStyle.dp
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
ColumnLayout {
|
||||
spacing: 10 * DefaultStyle.dp
|
||||
Text {
|
||||
Layout.preferredWidth: 330 * DefaultStyle.dp
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
text: qsTr("Vérifier l'appareil")
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
font {
|
||||
pixelSize: 16 * DefaultStyle.dp
|
||||
weight: 800 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.preferredWidth: 330 * DefaultStyle.dp
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
//: 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check.
|
||||
text: qsTr("Dites %1 et cliquez sur les lettres votre interlocuteur vous dit :".arg(mainItem.call && mainItem.call.core.localSas || ""))
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 14 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
id: securityGridView
|
||||
// Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
|
||||
rows: 2
|
||||
columns: 2
|
||||
rowSpacing: 32 * DefaultStyle.dp
|
||||
columnSpacing: 32 * DefaultStyle.dp
|
||||
property var correctIndex
|
||||
property var modelList
|
||||
Connections {
|
||||
target: mainItem.call.core
|
||||
// this connection is needed to get the remoteSas when available
|
||||
// due to the asynchronous connection between core and ui
|
||||
onRemoteSasChanged: {
|
||||
securityGridView.correctIndex = UtilsCpp.getRandomIndex(4)
|
||||
securityGridView.modelList = UtilsCpp.generateSecurityLettersArray(4, securityGridView.correctIndex, mainItem.call.core.remoteSas)
|
||||
}
|
||||
}
|
||||
Repeater {
|
||||
model: securityGridView.modelList
|
||||
Item {
|
||||
// implicitWidth: 70 * DefaultStyle.dp
|
||||
// implicitHeight: 70 * DefaultStyle.dp
|
||||
width: 70 * DefaultStyle.dp
|
||||
height: 70 * DefaultStyle.dp
|
||||
Rectangle {
|
||||
id: code
|
||||
anchors.fill: parent
|
||||
color: DefaultStyle.grey_0
|
||||
radius: 71 * DefaultStyle.dp
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: modelData
|
||||
font {
|
||||
pixelSize: 32 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
console.log("correct", index == securityGridView.correctIndex, index)
|
||||
if (index == securityGridView.correctIndex) {
|
||||
if(mainItem.call) mainItem.call.core.lVerifyAuthenticationToken(true)
|
||||
} else {
|
||||
if(mainItem.call) mainItem.call.core.lVerifyAuthenticationToken(false)
|
||||
mainItem.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MultiEffect {
|
||||
source: code
|
||||
anchors.fill: code
|
||||
shadowEnabled: true
|
||||
shadowOpacity: 0.1
|
||||
shadowBlur: 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,6 @@ AbstractMainPage {
|
|||
listStackView.push(newCallItem)
|
||||
}
|
||||
|
||||
|
||||
Dialog {
|
||||
id: deleteHistoryPopup
|
||||
width: 278 * DefaultStyle.dp
|
||||
|
|
|
|||
|
|
@ -66,4 +66,5 @@ QtObject {
|
|||
property string heart: "image://internal/heart.svg"
|
||||
property string heartFill: "image://internal/heart-fill.svg"
|
||||
property string recordFill: "image://internal/record-fill.svg"
|
||||
property string mediaEncryptionZrtpPq: "image://internal/media_encryption_zrtp_pq.svg"
|
||||
}
|
||||
Loading…
Reference in a new issue