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 "lanlinkprovider.h"
2019-01-26 16:43:09 +00:00
# include "plugins/share/shareplugin.h"
2022-09-10 22:23:52 +01:00
# include <KJobTrackerInterface>
# include <KLocalizedString>
# include <core_debug.h>
# include <daemon.h>
2024-06-03 12:52:44 +01:00
# include <device.h>
2018-11-28 18:56:22 +00:00
2024-06-03 12:52:44 +01:00
CompositeUploadJob : : CompositeUploadJob ( Device * device , bool displayNotification )
: KCompositeJob ( device )
2018-11-28 18:56:22 +00:00
, m_server ( new Server ( this ) )
, m_socket ( nullptr )
, m_port ( 0 )
2024-06-03 12:52:44 +01:00
, m_device ( device )
2018-11-28 18:56:22 +00:00
, 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 ;
}
2022-09-10 22:23:52 +01:00
void CompositeUploadJob : : start ( )
{
2018-11-28 18:56:22 +00:00
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
2022-09-10 22:23:52 +01:00
// Give SharePlugin some time to add subjobs
2018-11-28 18:56:22 +00:00
QMetaObject : : invokeMethod ( this , " startNextSubJob " , Qt : : QueuedConnection ) ;
}
bool CompositeUploadJob : : startListening ( )
{
m_port = MIN_PORT ;
while ( ! m_server - > listen ( QHostAddress : : Any , m_port ) ) {
m_port + + ;
2022-09-10 22:23:52 +01:00
if ( m_port > MAX_PORT ) { // No ports available?
2018-11-28 18:56:22 +00:00
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 ( )
{
2022-09-10 22:23:52 +01:00
m_currentJob = qobject_cast < UploadJob * > ( subjobs ( ) . at ( 0 ) ) ;
2018-11-28 18:56:22 +00:00
m_currentJobSendPayloadSize = 0 ;
emitDescription ( m_currentJob - > getNetworkPacket ( ) . get < QString > ( QStringLiteral ( " filename " ) ) ) ;
2023-04-19 20:21:05 +01:00
connect ( m_currentJob , & UploadJob : : processedAmountChanged , this , & CompositeUploadJob : : slotProcessedAmount ) ;
2023-07-18 21:13:27 +01:00
2022-09-10 22:23:52 +01:00
// Already done by KCompositeJob
// connect(m_currentJob, &KJob::result, this, &CompositeUploadJob::slotResult);
2020-05-09 15:46:52 +01:00
2022-09-10 22:23:52 +01:00
// TODO: Create a copy of the networkpacket that can be re-injected if sending via lan fails?
2018-11-28 18:56:22 +00:00
NetworkPacket np = m_currentJob - > getNetworkPacket ( ) ;
np . setPayload ( nullptr , np . payloadSize ( ) ) ;
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
2024-06-03 12:52:44 +01:00
if ( m_device - > sendPacket ( np ) ) {
2018-11-28 18:56:22 +00:00
m_server - > resumeAccepting ( ) ;
} else {
setError ( SendingNetworkPacketFailed ) ;
2024-06-03 12:52:44 +01:00
setErrorText ( i18n ( " Failed to send packet to %1 " , m_device - > 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
2023-08-04 15:46:12 +01:00
connect ( m_socket , & QSslSocket : : disconnected , this , [ this ] ( ) {
m_socket - > close ( ) ;
} ) ;
connect ( m_socket , & QAbstractSocket : : errorOccurred , this , [ this ] ( QAbstractSocket : : SocketError error ) {
qCDebug ( KDECONNECT_CORE ) < < " Error in socket occurred " < < error ;
// 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
setError ( SocketError ) ;
emitResult ( ) ;
2018-12-16 16:16:22 +00:00
2023-08-04 15:46:12 +01:00
m_running = false ;
} ) ;
connect ( m_socket , & QSslSocket : : sslErrors , this , [ this ] ( const QList < QSslError > & errors ) {
qCDebug ( KDECONNECT_CORE ) < < " Received ssl errors " < < errors ;
m_socket - > close ( ) ;
setError ( SslError ) ;
emitResult ( ) ;
2018-11-28 18:56:22 +00:00
2023-08-04 15:46:12 +01:00
m_running = false ;
} ) ;
connect ( m_socket , & QSslSocket : : encrypted , this , [ this ] ( ) {
if ( ! m_timer . isValid ( ) ) {
m_timer . start ( ) ;
}
2018-12-16 16:16:22 +00:00
2023-08-04 15:46:12 +01:00
m_currentJob - > start ( ) ;
} ) ;
2018-11-28 18:56:22 +00:00
2024-06-03 12:52:44 +01:00
LanLinkProvider : : configureSslSocket ( m_socket , m_device - > id ( ) , true ) ;
2020-05-09 15:46:52 +01:00
2023-08-04 15:46:12 +01:00
m_socket - > startServerEncryption ( ) ;
2018-11-28 18:56:22 +00:00
}
2022-09-10 22:23:52 +01:00
bool CompositeUploadJob : : addSubjob ( KJob * job )
2018-11-28 18:56:22 +00:00
{
2022-09-10 22:23:52 +01:00
if ( UploadJob * uploadJob = qobject_cast < UploadJob * > ( job ) ) {
2018-11-28 18:56:22 +00:00
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
2022-09-10 22:23:52 +01:00
if ( np . payloadSize ( ) > = 0 ) {
2018-11-28 18:56:22 +00:00
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 ;
}
}
2022-09-10 22:23:52 +01:00
void CompositeUploadJob : : sendUpdatePacket ( )
{
2023-07-16 14:01:04 +01:00
m_updatePacketPending = false ;
2019-01-26 16:43:09 +00:00
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
2024-06-03 12:52:44 +01:00
m_device - > sendPacket ( np ) ;
2019-01-26 16:43:09 +00:00
}
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 ;
}
2023-07-28 08:11:43 +01:00
void CompositeUploadJob : : slotProcessedAmount ( KJob * /*job*/ , KJob : : Unit unit , qulonglong amount )
2022-09-10 22:23: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
}
}
2022-09-10 22:23:52 +01: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
2018-11-28 18:56:22 +00:00
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 ( ) ;
}
}
2022-09-10 22:23:52 +01:00
void CompositeUploadJob : : emitDescription ( const QString & currentFileName )
{
2024-06-03 12:52:44 +01:00
Q_EMIT description ( this , i18n ( " Sending to %1 " , m_device - > name ( ) ) , { i18n ( " File " ) , currentFileName } , { } ) ;
2022-08-09 11:53:10 +01:00
setProcessedAmount ( Files , m_currentJobNum ) ;
setTotalAmount ( Files , m_totalJobs ) ;
2018-11-28 18:56:22 +00:00
}
2023-07-26 09:15:11 +01:00
# include "moc_compositeuploadjob.cpp"