From 3734f3c4129429668dacd016759edec932d975fb Mon Sep 17 00:00:00 2001 From: TheReign Date: Mon, 7 Dec 2015 12:41:49 -0500 Subject: Added 64-bit ack option to DCC receive. --- src/kvirc/kernel/KviOptions.cpp | 3 +- src/kvirc/kernel/KviOptions.h | 3 +- src/modules/dcc/DccFileTransfer.cpp | 60 ++++++++++++++----------------- src/modules/dcc/DccFileTransfer.h | 21 +++++------ src/modules/options/OptionsWidget_dcc.cpp | 5 +++ 5 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/kvirc/kernel/KviOptions.cpp b/src/kvirc/kernel/KviOptions.cpp index 0c71f7a7b..d9064be43 100644 --- a/src/kvirc/kernel/KviOptions.cpp +++ b/src/kvirc/kernel/KviOptions.cpp @@ -340,7 +340,8 @@ KviBoolOption g_boolOptionsTable[KVI_NUM_BOOL_OPTIONS]= BOOL_OPTION("ShowUserFlagForChannelsInWindowList",true,KviOption_sectFlagWindowList | KviOption_resetUpdateGui), BOOL_OPTION("EnableCustomCursorWidth",false,KviOption_sectFlagGui | KviOption_resetUpdateGui), BOOL_OPTION("ShowFavoriteServersOnly",false,KviOption_sectFlagFrame), - BOOL_OPTION("RequireControlToCopy",false,KviOption_sectFlagIrcView) + BOOL_OPTION("RequireControlToCopy",false,KviOption_sectFlagIrcView), + BOOL_OPTION("Send64BitAckInDccRecv",false,KviOption_sectFlagDcc) }; #define STRING_OPTION(_txt,_val,_flags) KviStringOption(KVI_STRING_OPTIONS_PREFIX _txt,_val,_flags) diff --git a/src/kvirc/kernel/KviOptions.h b/src/kvirc/kernel/KviOptions.h index f230df05a..ab72e60b3 100644 --- a/src/kvirc/kernel/KviOptions.h +++ b/src/kvirc/kernel/KviOptions.h @@ -356,8 +356,9 @@ DECLARE_OPTION_STRUCT(KviStringListOption,QStringList) #define KviOption_boolEnableCustomCursorWidth 261 /* interface */ #define KviOption_boolShowFavoriteServersOnly 262 /* connection::ircservers */ #define KviOption_boolRequireControlToCopy 263 /* interface::ircview */ +#define KviOption_boolSend64BitAckInDccRecv 264 /* dcc::send */ -#define KVI_NUM_BOOL_OPTIONS 264 +#define KVI_NUM_BOOL_OPTIONS 265 #define KVI_STRING_OPTIONS_PREFIX "string" diff --git a/src/modules/dcc/DccFileTransfer.cpp b/src/modules/dcc/DccFileTransfer.cpp index d404f85a7..536c8d7cd 100644 --- a/src/modules/dcc/DccFileTransfer.cpp +++ b/src/modules/dcc/DccFileTransfer.cpp @@ -68,6 +68,7 @@ #include #include #include +#include #define INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_MSECS 3000 #define INSTANT_BANDWIDTH_CHECK_INTERVAL_IN_SECS 3 @@ -112,22 +113,29 @@ DccRecvThread::~DccRecvThread() delete m_pTimeInterval; } -bool DccRecvThread::sendAck(int filePos,bool bTolerateErrors) +bool DccRecvThread::sendAck(qint64 filePos, bool bUse64BitAck) { - quint32 size = htonl(filePos & 0xffffffff); + quint32 ack32 = htonl(filePos & 0xffffffff); + quint64 ack64 = qToBigEndian(filePos); + + char * ack = (char*) &ack32; + int ackSize = 4; + + if(bUse64BitAck) + { + ackSize = 8; + ack = (char*) &ack64; + } + int iRet=0; #ifdef COMPILE_SSL_SUPPORT if(m_pSSL) - { - iRet = m_pSSL->write((char*)(&size),4); - } else { -#endif //COMPILE_SSL_SUPPORT - iRet = kvi_socket_send(m_fd,(void *)(&size),4); -#ifdef COMPILE_SSL_SUPPORT - } + iRet = m_pSSL->write(ack,ackSize); + else #endif //COMPILE_SSL_SUPPORT + iRet = kvi_socket_send(m_fd,(void *)(ack),ackSize); - if(iRet == 4) + if(iRet == ackSize) return true; // everything sent // When downloading from a fast server using send-ahead via an asymmetric link (such as the @@ -147,9 +155,6 @@ bool DccRecvThread::sendAck(int filePos,bool bTolerateErrors) if(iRet < 0) { - if(bTolerateErrors) - return true; // ignore at all - // Reported error. If it's EAGAIN or EINTR then no data has been sent. #ifdef COMPILE_SSL_SUPPORT if(m_pSSL) @@ -196,24 +201,17 @@ bool DccRecvThread::sendAck(int filePos,bool bTolerateErrors) // This will probably throttle the bandwidth usage a bit too. msleep(10); - int iMissingPart = 4 - iRet; + int iMissingPart = ackSize - iRet; #ifdef COMPILE_SSL_SUPPORT if(m_pSSL) - { - iRet = m_pSSL->write(((char*)(&size)) + iRet,iMissingPart); - } else { -#endif //COMPILE_SSL_SUPPORT - iRet = kvi_socket_send(m_fd,(void *)(((char *)(&size)) + iRet),iMissingPart); -#ifdef COMPILE_SSL_SUPPORT - } + iRet = m_pSSL->write(ack + iRet,iMissingPart); + else #endif //COMPILE_SSL_SUPPORT + iRet = kvi_socket_send(m_fd,(void *)(ack + iRet),iMissingPart); if(iRet != iMissingPart) { - if(bTolerateErrors) - return true; // ignore at all - // Crap.. couldn't send the missing part of the ack :/ postErrorEvent(KviError::AcknowledgeError); return false; @@ -290,6 +288,8 @@ void DccRecvThread::run() m_pFile = new QFile(QString::fromUtf8(m_pOpt->szFileName.ptr())); + bool bSend64BitAck = m_pOpt->bSend64BitAck && (m_pOpt->uTotalFileSize >> 32); + if(m_pOpt->bResume) { if(!m_pFile->open(QIODevice::WriteOnly | QIODevice::Append)) @@ -307,7 +307,7 @@ void DccRecvThread::run() if(m_pOpt->bSendZeroAck && (!m_pOpt->bNoAcks)) { - if(!sendAck(m_pFile->pos(),false)) + if(!sendAck(m_pFile->pos(),bSend64BitAck)) goto exit_dcc; } @@ -407,14 +407,7 @@ void DccRecvThread::run() } else { // Must send the ack... the peer must close the connection - // We tolerate ack errors if we're in the last 90% of the file. - // It might be that we're slow with receiving data but the server - // has already closed the connection (buggy server though). - - bool bTolerateErrors = (m_pOpt->uTotalFileSize > 0) && - (((quint64)m_pFile->pos()) >= (m_pOpt->uTotalFileSize - (m_pOpt->uTotalFileSize / 10))); - - if(!sendAck(m_pFile->pos(),bTolerateErrors)) + if(!sendAck(m_pFile->pos(),bSend64BitAck)) break; } @@ -2119,6 +2112,7 @@ void DccFileTransfer::connected() o->iIdleStepLengthInMSec = KVI_OPTION_BOOL(KviOption_boolDccSendForceIdleStep) ? KVI_OPTION_UINT(KviOption_uintDccSendIdleStepInMSec) : 0; o->bIsTdcc = m_pDescriptor->bIsTdcc; o->bSendZeroAck = KVI_OPTION_BOOL(KviOption_boolSendZeroAckInDccRecv); + o->bSend64BitAck = KVI_OPTION_BOOL(KviOption_boolSend64BitAckInDccRecv); o->bNoAcks = m_pDescriptor->bNoAcks; o->uMaxBandwidth = m_uMaxBandwidth; m_pSlaveRecvThread = new DccRecvThread(this,m_pMarshal->releaseSocket(),o); diff --git a/src/modules/dcc/DccFileTransfer.h b/src/modules/dcc/DccFileTransfer.h index fea2d6467..d8f9cb11d 100644 --- a/src/modules/dcc/DccFileTransfer.h +++ b/src/modules/dcc/DccFileTransfer.h @@ -53,7 +53,7 @@ class QMenu; typedef struct _KviDccSendThreadOptions { - KviCString szFileName; + KviCString szFileName; quint64 uStartPosition; int iPacketSize; int iIdleStepLengthInMSec; @@ -101,10 +101,11 @@ protected: typedef struct _KviDccRecvThreadOptions { bool bResume; - KviCString szFileName; + KviCString szFileName; quint64 uTotalFileSize; int iIdleStepLengthInMSec; bool bSendZeroAck; + bool bSend64BitAck; bool bNoAcks; bool bIsTdcc; unsigned int uMaxBandwidth; @@ -127,7 +128,7 @@ protected: // internal unsigned long m_uStartTime; KviMSecTimeInterval * m_pTimeInterval; // used for computing the instant bandwidth - quint64 m_uInstantReceivedBytes; + quint64 m_uInstantReceivedBytes; quint64 m_uInstantSpeedInterval; QFile * m_pFile; public: @@ -143,7 +144,7 @@ public: protected: void postMessageEvent(const char * msg); void updateStats(); - bool sendAck(int filePos,bool bTolerateErrors = false); + bool sendAck(qint64 filePos, bool bUse64BitAck = false); virtual void run(); }; @@ -174,13 +175,13 @@ public: DccFileTransfer(DccDescriptor * dcc); ~DccFileTransfer(); private: - DccSendThread * m_pSlaveSendThread; - DccRecvThread * m_pSlaveRecvThread; - DccDescriptor * m_pDescriptor; - DccMarshal * m_pMarshal; + DccSendThread * m_pSlaveSendThread; + DccRecvThread * m_pSlaveRecvThread; + DccDescriptor * m_pDescriptor; + DccMarshal * m_pMarshal; - KviCString m_szTarget; - KviCString m_szDccType; + KviCString m_szTarget; + KviCString m_szDccType; QString m_szTransferIdString; QString m_szStatusString; diff --git a/src/modules/options/OptionsWidget_dcc.cpp b/src/modules/options/OptionsWidget_dcc.cpp index 28564cb24..9674351ee 100644 --- a/src/modules/options/OptionsWidget_dcc.cpp +++ b/src/modules/options/OptionsWidget_dcc.cpp @@ -235,6 +235,11 @@ OptionsWidget_dccSendAdvanced::OptionsWidget_dccSendAdvanced(QWidget * parent) __tr2qs_ctx("
This option causes KVIrc to replace spaces with underscores in filenames " \ "for all the outgoing file transfers. This will fix filename handling with some buggy clients (e.g. some versions of mIRC).","options")); + b = addBoolSelector(g,__tr2qs_ctx("Send 64-bit ACKs for files larger than 4GiB","options"),KviOption_boolSend64BitAckInDccRecv); + mergeTip(b, + __tr2qs_ctx("
This option causes KVIrc to send ACKs as 64-bit integers instead of 32-bit integers
" \ + "Use this to fix DCC RECEIVE transfers where the other client is using the mIRC ACK standard.
","options")); + g = addGroupBox(0,1,0,1,Qt::Horizontal,__tr2qs_ctx("Limits","options")); KviTalHBox * hb = new KviTalHBox(g); -- cgit v1.3.1-10-gc9f91