2018-11-28 18:56:22 +00:00
/**
2020-08-17 10:48:10 +01:00
* SPDX - FileCopyrightText : 2018 Erik Duisters < e . duisters1 @ gmail . com >
2018-11-28 18:56:22 +00:00
*
2020-08-17 10:48:10 +01:00
* SPDX - License - Identifier : GPL - 2.0 - only OR GPL - 3.0 - only OR LicenseRef - KDE - Accepted - GPL
2018-11-28 18:56:22 +00:00
*/
# include "compositeuploadjob.h"
# include <core_debug.h>
# include <KLocalizedString>
# include <KJobTrackerInterface>
# include "lanlinkprovider.h"
# include <daemon.h>
2019-01-26 16:43:09 +00:00
# include "plugins/share/shareplugin.h"
2019-12-09 22:14:19 +00:00
# include "qtcompat_p.h"
2018-11-28 18:56:22 +00:00
2019-10-27 19:35:18 +00:00
# ifdef HAVE_KIO
# include <kio/global.h>
# endif
CompositeUploadJob : : CompositeUploadJob ( const QString & deviceId , bool displayNotification )
2018-11-28 18:56:22 +00:00
: KCompositeJob ( )
, m_server ( new Server ( this ) )
, m_socket ( nullptr )
, m_port ( 0 )
, m_deviceId ( deviceId )
, m_running ( false )
, m_currentJobNum ( 1 )
, m_totalJobs ( 0 )
, m_currentJobSendPayloadSize ( 0 )
, m_totalSendPayloadSize ( 0 )
, m_totalPayloadSize ( 0 )
, m_currentJob ( nullptr )
2019-01-26 13:04:38 +00:00
, m_prevElapsedTime ( 0 )
2019-01-26 16:43:09 +00:00
, m_updatePacketPending ( false )
2018-11-28 18:56:22 +00:00
{
setCapabilities ( Killable ) ;
2019-10-27 19:35:18 +00:00
2018-11-28 18:56:22 +00:00
if ( displayNotification ) {
2019-10-27 19:35:18 +00:00
Daemon : : instance ( ) - > jobTracker ( ) - > registerJob ( this ) ;
2018-11-28 18:56:22 +00:00
}
}
bool CompositeUploadJob : : isRunning ( )
{
return m_running ;
}
void CompositeUploadJob : : start ( ) {
if ( m_running ) {
2018-12-11 17:23:06 +00:00
qCWarning ( KDECONNECT_CORE ) < < " CompositeUploadJob::start() - already running " ;
2018-11-28 18:56:22 +00:00
return ;
}
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
if ( ! hasSubjobs ( ) ) {
qCWarning ( KDECONNECT_CORE ) < < " CompositeUploadJob::start() - there are no subjobs to start " ;
emitResult ( ) ;
return ;
}
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
if ( ! startListening ( ) ) {
return ;
}
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
connect ( m_server , & QTcpServer : : newConnection , this , & CompositeUploadJob : : newConnection ) ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
m_running = true ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
//Give SharePlugin some time to add subjobs
QMetaObject : : invokeMethod ( this , " startNextSubJob " , Qt : : QueuedConnection ) ;
}
bool CompositeUploadJob : : startListening ( )
{
m_port = MIN_PORT ;
while ( ! m_server - > listen ( QHostAddress : : Any , m_port ) ) {
m_port + + ;
if ( m_port > MAX_PORT ) { //No ports available?
qCWarning ( KDECONNECT_CORE ) < < " CompositeUploadJob::startListening() - Error opening a port in range " < < MIN_PORT < < " - " < < MAX_PORT ;
m_port = 0 ;
setError ( NoPortAvailable ) ;
setErrorText ( i18n ( " Couldn't find an available port " ) ) ;
emitResult ( ) ;
return false ;
}
}
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
qCDebug ( KDECONNECT_CORE ) < < " CompositeUploadJob::startListening() - listening on port: " < < m_port ;
return true ;
}
void CompositeUploadJob : : startNextSubJob ( )
{
m_currentJob = qobject_cast < UploadJob * > ( subjobs ( ) . at ( 0 ) ) ;
m_currentJobSendPayloadSize = 0 ;
emitDescription ( m_currentJob - > getNetworkPacket ( ) . get < QString > ( QStringLiteral ( " filename " ) ) ) ;
2019-12-09 22:14:19 +00:00
# ifdef SAILFISHOS
connect ( m_currentJob , SIGNAL ( processedAmount ( KJob * , KJob : : Unit , qulonglong ) ) , this , SLOT ( slotProcessedAmount ( KJob * , KJob : : Unit , qulonglong ) ) ) ;
# else
2019-07-21 17:28:12 +01:00
connect ( m_currentJob , QOverload < KJob * , KJob : : Unit , qulonglong > : : of ( & UploadJob : : processedAmount ) , this , & CompositeUploadJob : : slotProcessedAmount ) ;
2019-12-09 22:14:19 +00:00
# endif
2018-11-28 18:56:22 +00:00
//Already done by KCompositeJob
//connect(m_currentJob, &KJob::result, this, &CompositeUploadJob::slotResult);
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
//TODO: Create a copy of the networkpacket that can be re-injected if sending via lan fails?
NetworkPacket np = m_currentJob - > getNetworkPacket ( ) ;
2019-12-09 22:14:19 +00:00
# if QT_VERSION < QT_VERSION_CHECK(5,8,0)
np . setPayload ( { } , np . payloadSize ( ) ) ;
# else
2018-11-28 18:56:22 +00:00
np . setPayload ( nullptr , np . payloadSize ( ) ) ;
2019-12-09 22:14:19 +00:00
# endif
2019-06-10 15:40:28 +01:00
np . setPayloadTransferInfo ( { { QStringLiteral ( " port " ) , m_port } } ) ;
2018-11-28 18:56:22 +00:00
np . set < int > ( QStringLiteral ( " numberOfFiles " ) , m_totalJobs ) ;
np . set < quint64 > ( QStringLiteral ( " totalPayloadSize " ) , m_totalPayloadSize ) ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
if ( Daemon : : instance ( ) - > getDevice ( m_deviceId ) - > sendPacket ( np ) ) {
m_server - > resumeAccepting ( ) ;
} else {
setError ( SendingNetworkPacketFailed ) ;
setErrorText ( i18n ( " Failed to send packet to %1 " , Daemon : : instance ( ) - > getDevice ( m_deviceId ) - > name ( ) ) ) ;
2018-12-16 16:16:22 +00:00
2018-11-28 18:56:22 +00:00
emitResult ( ) ;
}
}
void CompositeUploadJob : : newConnection ( )
{
m_server - > pauseAccepting ( ) ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
m_socket = m_server - > nextPendingConnection ( ) ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
if ( ! m_socket ) {
qCDebug ( KDECONNECT_CORE ) < < " CompositeUploadJob::newConnection() - m_server->nextPendingConnection() returned a nullptr " ;
return ;
}
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
m_currentJob - > setSocket ( m_socket ) ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
connect ( m_socket , & QSslSocket : : disconnected , this , & CompositeUploadJob : : socketDisconnected ) ;
2020-05-09 15:54:22 +01:00
# if QT_VERSION < QT_VERSION_CHECK(5,15,0)
2018-11-28 18:56:22 +00:00
connect ( m_socket , QOverload < QAbstractSocket : : SocketError > : : of ( & QAbstractSocket : : error ) , this , & CompositeUploadJob : : socketError ) ;
2020-05-09 15:54:22 +01:00
# else
connect ( m_socket , & QAbstractSocket : : errorOccurred , this , & CompositeUploadJob : : socketError ) ;
# endif
2018-11-28 18:56:22 +00:00
connect ( m_socket , QOverload < const QList < QSslError > & > : : of ( & QSslSocket : : sslErrors ) , this , & CompositeUploadJob : : sslError ) ;
connect ( m_socket , & QSslSocket : : encrypted , this , & CompositeUploadJob : : encrypted ) ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
LanLinkProvider : : configureSslSocket ( m_socket , m_deviceId , true ) ;
m_socket - > startServerEncryption ( ) ;
}
void CompositeUploadJob : : socketDisconnected ( )
{
m_socket - > close ( ) ;
}
void CompositeUploadJob : : socketError ( QAbstractSocket : : SocketError error )
{
Q_UNUSED ( error ) ;
2020-05-09 15:46:52 +01:00
2018-12-16 16:16:22 +00:00
//Do not close the socket because when android closes the socket (share is cancelled) closing the socket leads to a cyclic socketError and eventually a segv
2018-11-28 18:56:22 +00:00
setError ( SocketError ) ;
emitResult ( ) ;
2018-12-16 16:16:22 +00:00
2018-11-28 18:56:22 +00:00
m_running = false ;
}
void CompositeUploadJob : : sslError ( const QList < QSslError > & errors )
{
Q_UNUSED ( errors ) ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
m_socket - > close ( ) ;
setError ( SslError ) ;
emitResult ( ) ;
2018-12-16 16:16:22 +00:00
2018-11-28 18:56:22 +00:00
m_running = false ;
}
void CompositeUploadJob : : encrypted ( )
{
if ( ! m_timer . isValid ( ) ) {
m_timer . start ( ) ;
}
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
m_currentJob - > start ( ) ;
}
bool CompositeUploadJob : : addSubjob ( KJob * job )
{
if ( UploadJob * uploadJob = qobject_cast < UploadJob * > ( job ) ) {
NetworkPacket np = uploadJob - > getNetworkPacket ( ) ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
m_totalJobs + + ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
if ( np . payloadSize ( ) > = 0 ) {
m_totalPayloadSize + = np . payloadSize ( ) ;
setTotalAmount ( Bytes , m_totalPayloadSize ) ;
}
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
QString filename ;
QString filenameArg = QStringLiteral ( " filename " ) ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
if ( m_currentJob ) {
filename = m_currentJob - > getNetworkPacket ( ) . get < QString > ( filenameArg ) ;
} else {
filename = np . get < QString > ( filenameArg ) ;
}
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
emitDescription ( filename ) ;
2019-01-27 15:44:05 +00:00
if ( m_running & & m_currentJob & & ! m_updatePacketPending ) {
2019-01-26 16:43:09 +00:00
m_updatePacketPending = true ;
QMetaObject : : invokeMethod ( this , " sendUpdatePacket " , Qt : : QueuedConnection ) ;
}
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
return KCompositeJob : : addSubjob ( job ) ;
} else {
qCDebug ( KDECONNECT_CORE ) < < " CompositeUploadJob::addSubjob() - you can only add UploadJob's, ignoring " ;
return false ;
}
}
2019-01-26 16:43:09 +00:00
void CompositeUploadJob : : sendUpdatePacket ( ) {
NetworkPacket np ( PACKET_TYPE_SHARE_REQUEST_UPDATE ) ;
np . set < int > ( QStringLiteral ( " numberOfFiles " ) , m_totalJobs ) ;
np . set < quint64 > ( QStringLiteral ( " totalPayloadSize " ) , m_totalPayloadSize ) ;
2020-05-09 15:46:52 +01:00
2019-01-26 16:43:09 +00:00
Daemon : : instance ( ) - > getDevice ( m_deviceId ) - > sendPacket ( np ) ;
2020-05-09 15:46:52 +01:00
2019-01-26 16:43:09 +00:00
m_updatePacketPending = false ;
}
2018-11-28 18:56:22 +00:00
bool CompositeUploadJob : : doKill ( )
{
if ( m_running ) {
m_running = false ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
return m_currentJob - > stop ( ) ;
}
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
return true ;
}
void CompositeUploadJob : : slotProcessedAmount ( KJob * job , KJob : : Unit unit , qulonglong amount ) {
Q_UNUSED ( job ) ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
m_currentJobSendPayloadSize = amount ;
quint64 uploaded = m_totalSendPayloadSize + m_currentJobSendPayloadSize ;
2020-05-09 15:46:52 +01:00
2019-01-26 13:04:38 +00:00
if ( uploaded = = m_totalPayloadSize | | m_prevElapsedTime = = 0 | | m_timer . elapsed ( ) - m_prevElapsedTime > = 100 ) {
m_prevElapsedTime = m_timer . elapsed ( ) ;
setProcessedAmount ( unit , uploaded ) ;
2020-05-09 15:46:52 +01:00
2019-01-26 13:04:38 +00:00
const auto elapsed = m_timer . elapsed ( ) ;
if ( elapsed > 0 ) {
emitSpeed ( ( 1000 * uploaded ) / elapsed ) ;
}
2018-11-28 18:56:22 +00:00
}
}
void CompositeUploadJob : : slotResult ( KJob * job ) {
//Copies job error and errorText and emits result if job is in error otherwise removes job from subjob list
KCompositeJob : : slotResult ( job ) ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
if ( error ( ) | | ! m_running ) {
return ;
}
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
m_totalSendPayloadSize + = m_currentJobSendPayloadSize ;
2020-05-09 15:46:52 +01:00
2018-11-28 18:56:22 +00:00
if ( hasSubjobs ( ) ) {
m_currentJobNum + + ;
startNextSubJob ( ) ;
} else {
emitResult ( ) ;
}
}
void CompositeUploadJob : : emitDescription ( const QString & currentFileName ) {
2019-10-27 19:35:18 +00:00
Q_EMIT description ( this , i18n ( " Sending to %1 " , Daemon : : instance ( ) - > getDevice ( this - > m_deviceId ) - > name ( ) ) ,
2022-08-09 11:53:10 +01:00
{ i18n ( " File " ) , currentFileName } , { }
2018-11-28 18:56:22 +00:00
) ;
2022-08-09 11:53:10 +01:00
setProcessedAmount ( Files , m_currentJobNum ) ;
setTotalAmount ( Files , m_totalJobs ) ;
2018-11-28 18:56:22 +00:00
}