mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-14 01:54:07 +02:00
Pull a bunch of code out of HatchetAccount and into HatchetHelpers; make some things more modular; prepare for the Kiva/Dreamcatcher split
This commit is contained in:
@@ -37,11 +37,13 @@ tomahawk_add_plugin(hatchet
|
|||||||
TYPE account
|
TYPE account
|
||||||
EXPORT_MACRO ACCOUNTDLLEXPORT_PRO
|
EXPORT_MACRO ACCOUNTDLLEXPORT_PRO
|
||||||
SOURCES
|
SOURCES
|
||||||
|
HatchetHelpers.cpp
|
||||||
account/HatchetAccount.cpp
|
account/HatchetAccount.cpp
|
||||||
account/HatchetAccountConfig.cpp
|
account/HatchetAccountConfig.cpp
|
||||||
sip/WebSocket.cpp
|
sip/WebSocket.cpp
|
||||||
sip/WebSocketThreadController.cpp
|
sip/WebSocketThreadController.cpp
|
||||||
sip/HatchetSip.cpp
|
sip/HatchetSip.cpp
|
||||||
|
#sip/HatchetCredentialFetcher.cpp
|
||||||
UI
|
UI
|
||||||
account/HatchetAccountConfig.ui
|
account/HatchetAccountConfig.ui
|
||||||
LINK_LIBRARIES
|
LINK_LIBRARIES
|
||||||
|
233
src/accounts/hatchet/HatchetHelpers.cpp
Normal file
233
src/accounts/hatchet/HatchetHelpers.cpp
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
|
*
|
||||||
|
* Copyright 2014, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||||
|
*
|
||||||
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tomahawk is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "HatchetHelpers.h"
|
||||||
|
|
||||||
|
#include "utils/Closure.h"
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
#include "utils/NetworkAccessManager.h"
|
||||||
|
#include "utils/TomahawkUtils.h"
|
||||||
|
|
||||||
|
#include <qjson/parser.h>
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tomahawk
|
||||||
|
{
|
||||||
|
namespace Accounts
|
||||||
|
{
|
||||||
|
namespace Hatchet
|
||||||
|
{
|
||||||
|
namespace HatchetHelpers
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
QVariantMap
|
||||||
|
parseReply( QNetworkReply* reply, bool& okRet )
|
||||||
|
{
|
||||||
|
QVariantMap resp;
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok );
|
||||||
|
if ( reply->error() != QNetworkReply::NoError && statusCode < 400 )
|
||||||
|
{
|
||||||
|
tLog() << Q_FUNC_INFO << "Network error in command:" << reply->error() << reply->errorString();
|
||||||
|
okRet = false;
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJson::Parser p;
|
||||||
|
QByteArray replyData = reply->readAll();
|
||||||
|
resp = p.parse( replyData, &ok ).toMap();
|
||||||
|
|
||||||
|
if ( !ok )
|
||||||
|
{
|
||||||
|
tLog() << Q_FUNC_INFO << "Error parsing JSON from server" << replyData;
|
||||||
|
okRet = false;
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( statusCode >= 400 )
|
||||||
|
{
|
||||||
|
tDebug() << "Error from tomahawk server response, or in parsing from json:" << resp.value( "error" ).toString() << resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
tDebug() << Q_FUNC_INFO << "Got keys" << resp.keys();
|
||||||
|
tDebug() << Q_FUNC_INFO << "Got values" << resp.values();
|
||||||
|
okRet = true;
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HatchetCredentialFetcher::HatchetCredentialFetcher( QObject* parent )
|
||||||
|
: QObject( parent )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HatchetCredentialFetcher::~HatchetCredentialFetcher()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HatchetCredentialFetcher::fetchAccessToken( const QString& type, const MandellaInformation& mandellaInformation )
|
||||||
|
{
|
||||||
|
if ( mandellaInformation.bearerToken.isEmpty() ||
|
||||||
|
(mandellaInformation.bearerTokenExpiration < QDateTime::currentDateTime().toTime_t() &&
|
||||||
|
(mandellaInformation.refreshToken.isEmpty() ||
|
||||||
|
(mandellaInformation.refreshTokenExpiration != 0 && mandellaInformation.refreshTokenExpiration < QDateTime::currentDateTime().toTime_t()))) )
|
||||||
|
{
|
||||||
|
tLog() << "No valid combination of access/refresh tokens, not logging in";
|
||||||
|
tLog() << "Mandella access token expiration:" << mandellaInformation.bearerTokenExpiration << ", refresh token expiration:" << mandellaInformation.refreshTokenExpiration;
|
||||||
|
emit authError( "No valid credentials are stored locally, please log in again.", 401, QVariantMap() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool interceptionNeeded = mandellaInformation.bearerTokenExpiration < QDateTime::currentDateTime().toTime_t();
|
||||||
|
|
||||||
|
QNetworkRequest req( QUrl( "https://auth.hatchet.is/v1/tokens/" + (interceptionNeeded ? "refresh/" + QString::fromUtf8(mandellaInformation.bearerTokenType).toLower() : "fetch/" + type) ) );
|
||||||
|
QNetworkReply* reply;
|
||||||
|
|
||||||
|
if ( interceptionNeeded )
|
||||||
|
{
|
||||||
|
tLog() << "Intercepting; new mandella access token needed";
|
||||||
|
req.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" );
|
||||||
|
QUrl params;
|
||||||
|
TomahawkUtils::urlAddQueryItem( params, "grant_type", "refresh_token" );
|
||||||
|
TomahawkUtils::urlAddQueryItem( params, "refresh_token", mandellaInformation.refreshToken );
|
||||||
|
QByteArray data = TomahawkUtils::encodedQuery( params );
|
||||||
|
reply = Tomahawk::Utils::nam()->post( req, data );
|
||||||
|
reply->setProperty( "originalType", type );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tLog() << "Fetching token of type" << type;
|
||||||
|
req.setRawHeader( "Authorization", QString( mandellaInformation.bearerTokenType + " " + mandellaInformation.bearerToken).toUtf8() );
|
||||||
|
reply = Tomahawk::Utils::nam()->get( req );
|
||||||
|
}
|
||||||
|
|
||||||
|
NewClosure( reply, SIGNAL( finished() ), this, SLOT( onFetchAccessTokenFinished( QNetworkReply*, const QString& ) ), reply, type );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HatchetCredentialFetcher::onFetchAccessTokenFinished( QNetworkReply* reply, const QString& type )
|
||||||
|
{
|
||||||
|
tLog() << Q_FUNC_INFO;
|
||||||
|
Q_ASSERT( reply );
|
||||||
|
|
||||||
|
QString originalType;
|
||||||
|
if ( reply->property( "originalType" ).isValid() )
|
||||||
|
{
|
||||||
|
originalType = reply->property( "originalType" ).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok );
|
||||||
|
if ( !ok )
|
||||||
|
{
|
||||||
|
tLog() << Q_FUNC_INFO << "Error finding status code from auth server";
|
||||||
|
emit authError( "An error occurred getting the status code from the server", 0, QVariantMap() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QVariantMap resp = parseReply( reply, ok );
|
||||||
|
if ( !ok )
|
||||||
|
{
|
||||||
|
tLog() << Q_FUNC_INFO << "Error getting parsed reply from auth server";
|
||||||
|
emit authError( "An error occurred reading the reply from the authentication server", statusCode, resp );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( statusCode >= 500 )
|
||||||
|
{
|
||||||
|
tLog() << Q_FUNC_INFO << "Encountered internal error from auth server, cannot continue";
|
||||||
|
emit authError( "The authentication server reported an internal error, please try again later", statusCode, resp );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( statusCode >= 400 )
|
||||||
|
{
|
||||||
|
QString errString = resp.value( "error_description" ).toString();
|
||||||
|
tLog() << Q_FUNC_INFO << "An error was returned from the authentication server: " << errString;
|
||||||
|
emit authError( errString, statusCode, resp );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !originalType.isEmpty() )
|
||||||
|
{
|
||||||
|
const QByteArray bearerTokenBytes = resp.value( "access_token" ).toByteArray();
|
||||||
|
uint bearerTokenExpiration = resp.value( "expires_in" ).toUInt( &ok );
|
||||||
|
if ( bearerTokenBytes.isEmpty() || !ok )
|
||||||
|
{
|
||||||
|
tLog() << Q_FUNC_INFO << "Error reading access token or its expiration";
|
||||||
|
emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QByteArray bearerTokenTypeBytes = resp.value( "token_type" ).toByteArray();
|
||||||
|
if ( bearerTokenTypeBytes.isEmpty() )
|
||||||
|
{
|
||||||
|
tLog() << Q_FUNC_INFO << "Error reading access token type";
|
||||||
|
emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MandellaInformation newMandellaInformation;
|
||||||
|
newMandellaInformation.bearerTokenType = bearerTokenTypeBytes;
|
||||||
|
newMandellaInformation.bearerToken = bearerTokenBytes;
|
||||||
|
newMandellaInformation.bearerTokenExpiration = QDateTime::currentDateTime().toTime_t() + bearerTokenExpiration;
|
||||||
|
emit mandellaInformationUpdated( newMandellaInformation );
|
||||||
|
|
||||||
|
fetchAccessToken( originalType, newMandellaInformation );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QByteArray accessTokenBytes = resp.value( "access_token" ).toByteArray();
|
||||||
|
uint accessTokenExpiration = resp.value( "expires_in" ).toUInt( &ok );
|
||||||
|
if ( accessTokenBytes.isEmpty() || !ok )
|
||||||
|
{
|
||||||
|
tLog() << Q_FUNC_INFO << "Error reading access token or its expiration";
|
||||||
|
emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QByteArray tokenTypeBytes = resp.value( "token_type" ).toByteArray();
|
||||||
|
if ( tokenTypeBytes.isEmpty() )
|
||||||
|
{
|
||||||
|
tLog() << Q_FUNC_INFO << "Error reading access token type";
|
||||||
|
emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tLog() << Q_FUNC_INFO << "Access tokens fetched successfully";
|
||||||
|
|
||||||
|
AccessTokenInformation accessTokenInformation;
|
||||||
|
accessTokenInformation.type = tokenTypeBytes;
|
||||||
|
accessTokenInformation.token = accessTokenBytes;
|
||||||
|
accessTokenInformation.expiration = accessTokenExpiration;
|
||||||
|
|
||||||
|
emit accessTokenFetched( accessTokenInformation );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
80
src/accounts/hatchet/HatchetHelpers.h
Normal file
80
src/accounts/hatchet/HatchetHelpers.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
|
*
|
||||||
|
* Copyright 2014, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||||
|
*
|
||||||
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tomahawk is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HATCHET_HELPERS_H
|
||||||
|
#define HATCHET_HELPERS_H
|
||||||
|
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
class QNetworkReply;
|
||||||
|
|
||||||
|
namespace Tomahawk
|
||||||
|
{
|
||||||
|
namespace Accounts
|
||||||
|
{
|
||||||
|
namespace Hatchet
|
||||||
|
{
|
||||||
|
namespace HatchetHelpers
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
QVariantMap parseReply( QNetworkReply* reply, bool& ok );
|
||||||
|
|
||||||
|
|
||||||
|
struct MandellaInformation {
|
||||||
|
QByteArray bearerTokenType;
|
||||||
|
QByteArray bearerToken;
|
||||||
|
uint bearerTokenExpiration;
|
||||||
|
QByteArray refreshToken;
|
||||||
|
uint refreshTokenExpiration;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AccessTokenInformation {
|
||||||
|
QByteArray type;
|
||||||
|
QByteArray token;
|
||||||
|
uint expiration;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class HatchetCredentialFetcher : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
HatchetCredentialFetcher( QObject* parent );
|
||||||
|
virtual ~HatchetCredentialFetcher();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void accessTokenFetched( const HatchetHelpers::AccessTokenInformation& accessInfo );
|
||||||
|
void mandellaInformationUpdated( const HatchetHelpers::MandellaInformation& updatedInfo );
|
||||||
|
void authError( const QString& error, int statusCode, const QVariantMap& resp );
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void fetchAccessToken( const QString& type, const HatchetHelpers::MandellaInformation& mandellaInformation );
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onFetchAccessTokenFinished( QNetworkReply*, const QString& type );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@@ -17,8 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "HatchetAccount.h"
|
#include "HatchetAccount.h"
|
||||||
#include <QHostInfo>
|
|
||||||
|
|
||||||
|
#include "HatchetHelpers.h"
|
||||||
#include "HatchetAccountConfig.h"
|
#include "HatchetAccountConfig.h"
|
||||||
#include "sip/HatchetSip.h"
|
#include "sip/HatchetSip.h"
|
||||||
#include "utils/Closure.h"
|
#include "utils/Closure.h"
|
||||||
@@ -27,16 +27,24 @@
|
|||||||
#include "utils/Json.h"
|
#include "utils/Json.h"
|
||||||
#include "utils/TomahawkUtils.h"
|
#include "utils/TomahawkUtils.h"
|
||||||
|
|
||||||
#include <QtPlugin>
|
#include <QHostInfo>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
#include <QtPlugin>
|
||||||
|
|
||||||
using namespace Tomahawk;
|
#include <qjson/parser.h>
|
||||||
using namespace Accounts;
|
#include <qjson/serializer.h>
|
||||||
|
|
||||||
|
namespace Tomahawk
|
||||||
|
{
|
||||||
|
namespace Accounts
|
||||||
|
{
|
||||||
|
namespace Hatchet
|
||||||
|
{
|
||||||
|
|
||||||
static QPixmap* s_icon = 0;
|
static QPixmap* s_icon = 0;
|
||||||
HatchetAccount* HatchetAccount::s_instance = 0;
|
HatchetAccount* HatchetAccount::s_instance = 0;
|
||||||
@@ -53,7 +61,6 @@ HatchetAccountFactory::HatchetAccountFactory()
|
|||||||
|
|
||||||
HatchetAccountFactory::~HatchetAccountFactory()
|
HatchetAccountFactory::~HatchetAccountFactory()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -223,14 +230,14 @@ HatchetAccount::refreshTokenExpiration() const
|
|||||||
|
|
||||||
|
|
||||||
QByteArray
|
QByteArray
|
||||||
HatchetAccount::mandellaAccessToken() const
|
HatchetAccount::bearerToken() const
|
||||||
{
|
{
|
||||||
return credentials().value( "mandella_access_token" ).toByteArray();
|
return credentials().value( "mandella_access_token" ).toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint
|
uint
|
||||||
HatchetAccount::mandellaAccessTokenExpiration() const
|
HatchetAccount::bearerTokenExpiration() const
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
return credentials().value( "mandella_access_token_expiration" ).toUInt( &ok );
|
return credentials().value( "mandella_access_token_expiration" ).toUInt( &ok );
|
||||||
@@ -238,7 +245,7 @@ HatchetAccount::mandellaAccessTokenExpiration() const
|
|||||||
|
|
||||||
|
|
||||||
QByteArray
|
QByteArray
|
||||||
HatchetAccount::mandellaTokenType() const
|
HatchetAccount::bearerTokenType() const
|
||||||
{
|
{
|
||||||
return credentials().value( "mandella_token_type" ).toByteArray();
|
return credentials().value( "mandella_token_type" ).toByteArray();
|
||||||
}
|
}
|
||||||
@@ -279,68 +286,14 @@ HatchetAccount::loginWithPassword( const QString& username, const QString& passw
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
HatchetAccount::fetchAccessToken( const QString& type )
|
|
||||||
{
|
|
||||||
if ( username().isEmpty() )
|
|
||||||
{
|
|
||||||
tLog() << "No username, not logging in";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( mandellaAccessToken().isEmpty() ||
|
|
||||||
(mandellaAccessTokenExpiration() < QDateTime::currentDateTime().toTime_t() &&
|
|
||||||
(refreshToken().isEmpty() ||
|
|
||||||
(refreshTokenExpiration() != 0 && refreshTokenExpiration() < QDateTime::currentDateTime().toTime_t()))) )
|
|
||||||
{
|
|
||||||
tLog() << "No valid combination of access/refresh tokens, not logging in";
|
|
||||||
tLog() << "Mandella access token expiration:" << mandellaAccessTokenExpiration() << ", refresh token expiration:" << refreshTokenExpiration();
|
|
||||||
emit authError( "No valid credentials are stored locally, please log in again.", 401, QVariantMap() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint matExpiration = mandellaAccessTokenExpiration();
|
|
||||||
bool interceptionNeeded = false;
|
|
||||||
|
|
||||||
if ( matExpiration < QDateTime::currentDateTime().toTime_t() )
|
|
||||||
{
|
|
||||||
interceptionNeeded = true;
|
|
||||||
tLog() << "Mandella access token has expired, fetching new ones first";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tLog() << "Fetching access tokens of type" << type;
|
|
||||||
}
|
|
||||||
|
|
||||||
QNetworkRequest req( QUrl( c_accessTokenServer + "/tokens/" + (interceptionNeeded ? "refresh/" + QString::fromUtf8(mandellaTokenType()).toLower() : "fetch/" + type) ) );
|
|
||||||
QNetworkReply* reply;
|
|
||||||
|
|
||||||
if ( interceptionNeeded )
|
|
||||||
{
|
|
||||||
tLog() << "Intercepting; new mandella access token needed";
|
|
||||||
req.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" );
|
|
||||||
QUrl params;
|
|
||||||
TomahawkUtils::urlAddQueryItem( params, "grant_type", "refresh_token" );
|
|
||||||
TomahawkUtils::urlAddQueryItem( params, "refresh_token", refreshToken() );
|
|
||||||
QByteArray data = TomahawkUtils::encodedQuery( params );
|
|
||||||
reply = Tomahawk::Utils::nam()->post( req, data );
|
|
||||||
reply->setProperty( "originalType", type );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tLog() << "Fetching token of type" << type;
|
|
||||||
req.setRawHeader( "Authorization", QString( mandellaTokenType() + " " + mandellaAccessToken()).toUtf8() );
|
|
||||||
reply = Tomahawk::Utils::nam()->get( req );
|
|
||||||
}
|
|
||||||
|
|
||||||
NewClosure( reply, SIGNAL( finished() ), this, SLOT( onFetchAccessTokenFinished( QNetworkReply*, const QString& ) ), reply, type );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
HatchetAccount::onPasswordLoginFinished( QNetworkReply* reply, const QString& username )
|
HatchetAccount::onPasswordLoginFinished( QNetworkReply* reply, const QString& username )
|
||||||
{
|
{
|
||||||
tLog() << Q_FUNC_INFO;
|
tLog() << Q_FUNC_INFO;
|
||||||
Q_ASSERT( reply );
|
Q_ASSERT( reply );
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok );
|
int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok );
|
||||||
if ( !ok )
|
if ( !ok )
|
||||||
@@ -349,7 +302,7 @@ HatchetAccount::onPasswordLoginFinished( QNetworkReply* reply, const QString& us
|
|||||||
emit authError( "An error occurred getting the status code from the server", 0, QVariantMap() );
|
emit authError( "An error occurred getting the status code from the server", 0, QVariantMap() );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const QVariantMap resp = parseReply( reply, ok );
|
const QVariantMap resp = HatchetHelpers::parseReply( reply, ok );
|
||||||
if ( !ok )
|
if ( !ok )
|
||||||
{
|
{
|
||||||
tLog() << Q_FUNC_INFO << "Error getting parsed reply from auth server";
|
tLog() << Q_FUNC_INFO << "Error getting parsed reply from auth server";
|
||||||
@@ -420,139 +373,64 @@ HatchetAccount::onPasswordLoginFinished( QNetworkReply* reply, const QString& us
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
HatchetAccount::onFetchAccessTokenFinished( QNetworkReply* reply, const QString& type )
|
HatchetAccount::fetchAccessToken( const QString& type )
|
||||||
{
|
{
|
||||||
tLog() << Q_FUNC_INFO;
|
QVariantHash creds = credentials();
|
||||||
Q_ASSERT( reply );
|
HatchetHelpers::MandellaInformation mandellaInfo;
|
||||||
|
mandellaInfo.bearerToken = bearerToken();
|
||||||
|
mandellaInfo.bearerTokenExpiration = bearerTokenExpiration();
|
||||||
|
mandellaInfo.bearerTokenType = bearerTokenType();
|
||||||
|
mandellaInfo.refreshToken = refreshToken();
|
||||||
|
mandellaInfo.refreshTokenExpiration = refreshTokenExpiration();
|
||||||
|
|
||||||
QString originalType;
|
HatchetHelpers::HatchetCredentialFetcher* fetcher = new HatchetHelpers::HatchetCredentialFetcher( this );
|
||||||
if ( reply->property( "originalType" ).isValid() )
|
connect( fetcher,
|
||||||
{
|
SIGNAL( mandellaInformationUpdated( const HatchetHelpers::MandellaInformation& ) ),
|
||||||
originalType = reply->property( "originalType" ).toString();
|
SLOT( onFetcherMandellaInformationUpdated( const HatchetHelpers::MandellaInformation& ) ) );
|
||||||
}
|
connect( fetcher,
|
||||||
|
SIGNAL( authError( const QString&, int, const QVariantMap& ) ),
|
||||||
|
SLOT( onFetcherAuthError( const QString&, int, const QVariantMap& ) ) );
|
||||||
|
connect( fetcher,
|
||||||
|
SIGNAL( accessTokenFetched( const HatchetHelpers::AccessTokenInformation& ) ),
|
||||||
|
SLOT( onFetcherAccessTokenFetched( const HatchetHelpers::AccessTokenInformation& ) ) );
|
||||||
|
|
||||||
bool ok;
|
fetcher->fetchAccessToken( type, mandellaInfo );
|
||||||
int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok );
|
}
|
||||||
if ( !ok )
|
|
||||||
{
|
|
||||||
tLog() << Q_FUNC_INFO << "Error finding status code from auth server";
|
|
||||||
emit authError( "An error occurred getting the status code from the server", 0, QVariantMap() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const QVariantMap resp = parseReply( reply, ok );
|
|
||||||
if ( !ok )
|
|
||||||
{
|
|
||||||
tLog() << Q_FUNC_INFO << "Error getting parsed reply from auth server";
|
|
||||||
emit authError( "An error occurred reading the reply from the authentication server", statusCode, resp );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( statusCode >= 500 )
|
|
||||||
{
|
|
||||||
tLog() << Q_FUNC_INFO << "Encountered internal error from auth server, cannot continue";
|
|
||||||
emit authError( "The authentication server reported an internal error, please try again later", statusCode, resp );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( statusCode >= 400 )
|
|
||||||
{
|
|
||||||
QString errString = resp.value( "error_description" ).toString();
|
|
||||||
tLog() << Q_FUNC_INFO << "An error was returned from the authentication server: " << errString;
|
|
||||||
emit authError( errString, statusCode, resp );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap creds = credentials();
|
|
||||||
|
|
||||||
if ( !originalType.isEmpty() )
|
|
||||||
{
|
|
||||||
const QByteArray accessTokenBytes = resp.value( "access_token" ).toByteArray();
|
|
||||||
uint accessTokenExpiration = resp.value( "expires_in" ).toUInt( &ok );
|
|
||||||
if ( accessTokenBytes.isEmpty() || !ok )
|
|
||||||
{
|
|
||||||
tLog() << Q_FUNC_INFO << "Error reading access token or its expiration";
|
|
||||||
emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const QByteArray tokenTypeBytes = resp.value( "token_type" ).toByteArray();
|
|
||||||
if ( tokenTypeBytes.isEmpty() )
|
|
||||||
{
|
|
||||||
tLog() << Q_FUNC_INFO << "Error reading access token type";
|
|
||||||
emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
creds[ "mandella_access_token" ] = accessTokenBytes;
|
|
||||||
creds[ "mandella_access_token_expiration" ] = QDateTime::currentDateTime().toTime_t() + accessTokenExpiration;
|
|
||||||
creds[ "mandella_token_type" ] = tokenTypeBytes;
|
|
||||||
setCredentials( creds );
|
|
||||||
syncConfig();
|
|
||||||
|
|
||||||
fetchAccessToken( originalType );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QByteArray accessTokenBytes = resp.value( "access_token" ).toByteArray();
|
|
||||||
uint accessTokenExpiration = resp.value( "expires_in" ).toUInt( &ok );
|
|
||||||
if ( accessTokenBytes.isEmpty() || !ok )
|
|
||||||
{
|
|
||||||
tLog() << Q_FUNC_INFO << "Error reading access token or its expiration";
|
|
||||||
emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const QByteArray tokenTypeBytes = resp.value( "token_type" ).toByteArray();
|
|
||||||
if ( tokenTypeBytes.isEmpty() )
|
|
||||||
{
|
|
||||||
tLog() << Q_FUNC_INFO << "Error reading access token type";
|
|
||||||
emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
creds[ type + "_access_token" ] = accessTokenBytes;
|
|
||||||
|
|
||||||
tDebug() << Q_FUNC_INFO << "Creds: " << creds;
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HatchetAccount::onFetcherMandellaInformationUpdated( const HatchetHelpers::MandellaInformation& mandellaInformation )
|
||||||
|
{
|
||||||
|
QVariantHash creds = credentials();
|
||||||
|
creds[ "mandella_access_token" ] = mandellaInformation.bearerToken;
|
||||||
|
creds[ "mandella_access_token_expiration" ] = QDateTime::currentDateTime().toTime_t() + mandellaInformation.bearerTokenExpiration;
|
||||||
|
creds[ "mandella_token_type" ] = mandellaInformation.bearerTokenType;
|
||||||
setCredentials( creds );
|
setCredentials( creds );
|
||||||
syncConfig();
|
syncConfig();
|
||||||
|
|
||||||
tLog() << Q_FUNC_INFO << "Access tokens fetched successfully";
|
|
||||||
|
|
||||||
emit accessTokenFetched();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QVariantMap
|
void
|
||||||
HatchetAccount::parseReply( QNetworkReply* reply, bool& okRet ) const
|
HatchetAccount::onFetcherAuthError( const QString& error, int code, const QVariantMap& resp )
|
||||||
{
|
{
|
||||||
QVariantMap resp;
|
if ( sender() )
|
||||||
|
sender()->deleteLater();
|
||||||
reply->deleteLater();
|
emit authError( error, code, resp );
|
||||||
|
|
||||||
bool ok;
|
|
||||||
int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok );
|
|
||||||
if ( reply->error() != QNetworkReply::NoError && statusCode < 400 )
|
|
||||||
{
|
|
||||||
tLog() << Q_FUNC_INFO << "Network error in command:" << reply->error() << reply->errorString();
|
|
||||||
okRet = false;
|
|
||||||
return resp;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray replyData = reply->readAll();
|
|
||||||
resp = TomahawkUtils::parseJson( replyData, &ok ).toMap();
|
|
||||||
|
|
||||||
if ( !ok )
|
|
||||||
{
|
|
||||||
tLog() << Q_FUNC_INFO << "Error parsing JSON from server" << replyData;
|
|
||||||
okRet = false;
|
|
||||||
return resp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( statusCode >= 400 )
|
|
||||||
{
|
|
||||||
tDebug() << "Error from tomahawk server response, or in parsing from json:" << resp.value( "error" ).toString() << resp;
|
|
||||||
}
|
|
||||||
|
|
||||||
tDebug() << Q_FUNC_INFO << "Got keys" << resp.keys();
|
|
||||||
tDebug() << Q_FUNC_INFO << "Got values" << resp.values();
|
|
||||||
okRet = true;
|
|
||||||
return resp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_EXPORT_PLUGIN2( Tomahawk::Accounts::AccountFactory, Tomahawk::Accounts::HatchetAccountFactory )
|
|
||||||
|
void
|
||||||
|
HatchetAccount::onFetcherAccessTokenFetched( const HatchetHelpers::AccessTokenInformation& accessTokenInfo )
|
||||||
|
{
|
||||||
|
if ( sender() )
|
||||||
|
sender()->deleteLater();
|
||||||
|
emit accessTokenFetched( accessTokenInfo );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Q_EXPORT_PLUGIN2( Tomahawk::Accounts::AccountFactory, Tomahawk::Accounts::Hatchet::HatchetAccountFactory )
|
||||||
|
@@ -20,6 +20,8 @@
|
|||||||
#define HATCHET_ACCOUNT_H
|
#define HATCHET_ACCOUNT_H
|
||||||
|
|
||||||
#include "TomahawkPlugin.h"
|
#include "TomahawkPlugin.h"
|
||||||
|
#include "HatchetHelpers.h"
|
||||||
|
|
||||||
#include <accounts/Account.h>
|
#include <accounts/Account.h>
|
||||||
#include <accounts/AccountDllMacro.h>
|
#include <accounts/AccountDllMacro.h>
|
||||||
|
|
||||||
@@ -27,14 +29,15 @@
|
|||||||
|
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
|
|
||||||
class HatchetSipPlugin;
|
|
||||||
|
|
||||||
namespace Tomahawk
|
namespace Tomahawk
|
||||||
{
|
{
|
||||||
namespace Accounts
|
namespace Accounts
|
||||||
{
|
{
|
||||||
|
namespace Hatchet
|
||||||
|
{
|
||||||
|
|
||||||
class HatchetAccountConfig;
|
class HatchetAccountConfig;
|
||||||
|
class HatchetSipPlugin;
|
||||||
|
|
||||||
class ACCOUNTDLLEXPORT HatchetAccountFactory : public AccountFactory
|
class ACCOUNTDLLEXPORT HatchetAccountFactory : public AccountFactory
|
||||||
{
|
{
|
||||||
@@ -87,30 +90,31 @@ public:
|
|||||||
|
|
||||||
QString username() const;
|
QString username() const;
|
||||||
|
|
||||||
void fetchAccessToken( const QString& type = "dreamcatcher" );
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void authError( QString error, int statusCode, const QVariantMap );
|
void authError( const QString&, int, const QVariantMap&);
|
||||||
void deauthenticated();
|
void deauthenticated();
|
||||||
void accessTokenFetched();
|
void accessTokenFetched( const HatchetHelpers::AccessTokenInformation& );
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void fetchAccessToken( const QString& type );
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onPasswordLoginFinished( QNetworkReply*, const QString& username );
|
void onPasswordLoginFinished( QNetworkReply*, const QString& );
|
||||||
void onFetchAccessTokenFinished( QNetworkReply*, const QString& type );
|
void onFetcherMandellaInformationUpdated( const HatchetHelpers::MandellaInformation& );
|
||||||
|
void onFetcherAccessTokenFetched( const HatchetHelpers::AccessTokenInformation& );
|
||||||
|
void onFetcherAuthError( const QString&, int, const QVariantMap& );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QByteArray refreshToken() const;
|
QByteArray refreshToken() const;
|
||||||
uint refreshTokenExpiration() const;
|
uint refreshTokenExpiration() const;
|
||||||
|
|
||||||
QByteArray mandellaAccessToken() const;
|
QByteArray bearerToken() const;
|
||||||
uint mandellaAccessTokenExpiration() const;
|
uint bearerTokenExpiration() const;
|
||||||
|
|
||||||
QByteArray mandellaTokenType() const;
|
QByteArray bearerTokenType() const;
|
||||||
|
|
||||||
void loginWithPassword( const QString& username, const QString& password, const QString &otp );
|
void loginWithPassword( const QString& username, const QString& password, const QString &otp );
|
||||||
|
|
||||||
QVariantMap parseReply( QNetworkReply* reply, bool& ok ) const;
|
|
||||||
|
|
||||||
QPointer<HatchetAccountConfig> m_configWidget;
|
QPointer<HatchetAccountConfig> m_configWidget;
|
||||||
|
|
||||||
Account::ConnectionState m_state;
|
Account::ConnectionState m_state;
|
||||||
@@ -126,6 +130,7 @@ private:
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
using namespace Accounts;
|
using namespace Accounts;
|
||||||
|
using namespace Hatchet;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
enum ButtonAction {
|
enum ButtonAction {
|
||||||
|
@@ -32,6 +32,7 @@ namespace Ui {
|
|||||||
|
|
||||||
namespace Tomahawk {
|
namespace Tomahawk {
|
||||||
namespace Accounts {
|
namespace Accounts {
|
||||||
|
namespace Hatchet {
|
||||||
|
|
||||||
class HatchetAccount;
|
class HatchetAccount;
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ private:
|
|||||||
HatchetAccount* m_account;
|
HatchetAccount* m_account;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -37,6 +37,14 @@
|
|||||||
#include <QHostInfo>
|
#include <QHostInfo>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
|
namespace Tomahawk
|
||||||
|
{
|
||||||
|
namespace Accounts
|
||||||
|
{
|
||||||
|
namespace Hatchet
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
HatchetSipPlugin::HatchetSipPlugin( Tomahawk::Accounts::Account *account )
|
HatchetSipPlugin::HatchetSipPlugin( Tomahawk::Accounts::Account *account )
|
||||||
: SipPlugin( account )
|
: SipPlugin( account )
|
||||||
, m_sipState( Closed )
|
, m_sipState( Closed )
|
||||||
@@ -46,7 +54,9 @@ HatchetSipPlugin::HatchetSipPlugin( Tomahawk::Accounts::Account *account )
|
|||||||
{
|
{
|
||||||
tLog() << Q_FUNC_INFO;
|
tLog() << Q_FUNC_INFO;
|
||||||
|
|
||||||
connect( m_account, SIGNAL( accessTokenFetched() ), this, SLOT( connectWebSocket() ) );
|
connect( m_account,
|
||||||
|
SIGNAL( accessTokenFetched( const HatchetHelpers::AccessTokenInformation& ) ),
|
||||||
|
SLOT( connectWebSocket( const HatchetHelpers::AccessTokenInformation& ) ) );
|
||||||
connect( Servent::instance(), SIGNAL( dbSyncTriggered() ), this, SLOT( dbSyncTriggered() ));
|
connect( Servent::instance(), SIGNAL( dbSyncTriggered() ), this, SLOT( dbSyncTriggered() ));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -95,10 +105,10 @@ HatchetSipPlugin::isValid() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Tomahawk::Accounts::HatchetAccount*
|
HatchetAccount*
|
||||||
HatchetSipPlugin::hatchetAccount() const
|
HatchetSipPlugin::hatchetAccount() const
|
||||||
{
|
{
|
||||||
return qobject_cast< Tomahawk::Accounts::HatchetAccount* >( m_account );
|
return qobject_cast< HatchetAccount* >( m_account );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -133,7 +143,7 @@ HatchetSipPlugin::disconnectPlugin()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
HatchetSipPlugin::connectWebSocket()
|
HatchetSipPlugin::connectWebSocket( const HatchetHelpers::AccessTokenInformation& accessTokenInformation )
|
||||||
{
|
{
|
||||||
tLog() << Q_FUNC_INFO;
|
tLog() << Q_FUNC_INFO;
|
||||||
if ( m_webSocketThreadController )
|
if ( m_webSocketThreadController )
|
||||||
@@ -157,8 +167,7 @@ HatchetSipPlugin::connectWebSocket()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_token = m_account->credentials()[ "dreamcatcher_access_token" ].toString();
|
m_token = accessTokenInformation.token;
|
||||||
|
|
||||||
|
|
||||||
if ( m_token.isEmpty() )
|
if ( m_token.isEmpty() )
|
||||||
{
|
{
|
||||||
@@ -585,3 +594,6 @@ HatchetSipPlugin::oplogFetched( const QString& sinceguid, const QString& /* last
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -32,6 +32,13 @@ class WebSocketThreadController;
|
|||||||
|
|
||||||
const int VERSION = 1;
|
const int VERSION = 1;
|
||||||
|
|
||||||
|
namespace Tomahawk
|
||||||
|
{
|
||||||
|
namespace Accounts
|
||||||
|
{
|
||||||
|
namespace Hatchet
|
||||||
|
{
|
||||||
|
|
||||||
class ACCOUNTDLLEXPORT HatchetSipPlugin : public SipPlugin
|
class ACCOUNTDLLEXPORT HatchetSipPlugin : public SipPlugin
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -63,14 +70,14 @@ public slots:
|
|||||||
void webSocketDisconnected();
|
void webSocketDisconnected();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectWebSocket() const;
|
void connectWebSocket( const HatchetHelpers::AccessTokenInformation& ) const;
|
||||||
void disconnectWebSocket() const;
|
void disconnectWebSocket() const;
|
||||||
void rawBytes( QByteArray bytes ) const;
|
void rawBytes( QByteArray bytes ) const;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void dbSyncTriggered();
|
void dbSyncTriggered();
|
||||||
void messageReceived( const QByteArray& msg );
|
void messageReceived( const QByteArray& msg );
|
||||||
void connectWebSocket();
|
void connectWebSocket( const HatchetHelpers::AccessTokenInformation& );
|
||||||
void oplogFetched( const QString& sinceguid, const QString& lastguid, const QList< dbop_ptr > ops );
|
void oplogFetched( const QString& sinceguid, const QString& lastguid, const QList< dbop_ptr > ops );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -79,7 +86,7 @@ private:
|
|||||||
void newPeer( const QVariantMap& valMap );
|
void newPeer( const QVariantMap& valMap );
|
||||||
void peerAuthorization( const QVariantMap& valMap );
|
void peerAuthorization( const QVariantMap& valMap );
|
||||||
void sendOplog( const QVariantMap& valMap ) const;
|
void sendOplog( const QVariantMap& valMap ) const;
|
||||||
Tomahawk::Accounts::HatchetAccount* hatchetAccount() const;
|
HatchetAccount* hatchetAccount() const;
|
||||||
|
|
||||||
QPointer< WebSocketThreadController > m_webSocketThreadController;
|
QPointer< WebSocketThreadController > m_webSocketThreadController;
|
||||||
QString m_token;
|
QString m_token;
|
||||||
@@ -91,4 +98,8 @@ private:
|
|||||||
QHash< QString, QList< SipInfo > > m_sipInfoHash;
|
QHash< QString, QList< SipInfo > > m_sipInfoHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -68,7 +68,6 @@ WebSocketThreadController::run()
|
|||||||
if ( m_webSocket && m_sip )
|
if ( m_webSocket && m_sip )
|
||||||
{
|
{
|
||||||
tLog() << Q_FUNC_INFO << "Have a valid websocket and parent";
|
tLog() << Q_FUNC_INFO << "Have a valid websocket and parent";
|
||||||
connect( m_sip, SIGNAL( connectWebSocket() ), m_webSocket, SLOT( connectWs() ), Qt::QueuedConnection );
|
|
||||||
connect( m_sip, SIGNAL( disconnectWebSocket() ), m_webSocket, SLOT( disconnectWs() ), Qt::QueuedConnection );
|
connect( m_sip, SIGNAL( disconnectWebSocket() ), m_webSocket, SLOT( disconnectWs() ), Qt::QueuedConnection );
|
||||||
connect( m_sip, SIGNAL( rawBytes( QByteArray ) ), m_webSocket, SLOT( encodeMessage( QByteArray ) ), Qt::QueuedConnection );
|
connect( m_sip, SIGNAL( rawBytes( QByteArray ) ), m_webSocket, SLOT( encodeMessage( QByteArray ) ), Qt::QueuedConnection );
|
||||||
connect( m_webSocket, SIGNAL( connected() ), m_sip, SLOT( webSocketConnected() ), Qt::QueuedConnection );
|
connect( m_webSocket, SIGNAL( connected() ), m_sip, SLOT( webSocketConnected() ), Qt::QueuedConnection );
|
||||||
|
Reference in New Issue
Block a user