Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

DownloadTransferED2K.cpp

Go to the documentation of this file.
00001 //
00002 // DownloadTransferED2K.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include <limits>
00024 #include "Shareaza.h"
00025 #include "Settings.h"
00026 #include "Download.h"
00027 #include "Downloads.h"
00028 #include "DownloadSource.h"
00029 #include "DownloadTransfer.h"
00030 #include "DownloadTransferED2K.h"
00031 #include "FragmentedFile.h"
00032 #include "Datagrams.h"
00033 #include "EDClients.h"
00034 #include "EDClient.h"
00035 #include "EDPacket.h"
00036 #include "Network.h"
00037 #include "Buffer.h"
00038 #include "ED2K.h"
00039 
00040 #include <zlib.h>
00041 
00042 #ifdef _DEBUG
00043 #undef THIS_FILE
00044 static char THIS_FILE[]=__FILE__;
00045 #define new DEBUG_NEW
00046 #endif
00047 
00048 #define BUFFER_SIZE             8192
00049 
00050 
00052 // CDownloadTransferED2K construction
00053 
00054 CDownloadTransferED2K::CDownloadTransferED2K(CDownloadSource* pSource) : CDownloadTransfer( pSource, PROTOCOL_ED2K )
00055 {
00056         m_pClient               = NULL;
00057         m_bHashset              = FALSE;
00058         m_tRequest              = 0;
00059         m_tSources              = 0;
00060         m_tRanking              = 0;
00061         m_pAvailable    = NULL;
00062         m_bUDP                  = FALSE;
00063         
00064         m_pInflatePtr           = NULL;
00065         m_pInflateBuffer        = new CBuffer();
00066         
00067         ASSERT( m_pDownload->m_bED2K );
00068 }
00069 
00070 CDownloadTransferED2K::~CDownloadTransferED2K()
00071 {
00072         ClearRequests();
00073         delete m_pInflateBuffer;
00074         
00075         if ( m_pAvailable != NULL ) delete [] m_pAvailable;
00076         
00077 #ifdef _DEBUG
00078         ASSERT( m_pClient == NULL );
00079         
00080         for ( CEDClient* pClient = EDClients.GetFirst() ; pClient ; pClient = pClient->m_pEdNext )
00081         {
00082                 ASSERT( pClient->m_pDownload != this );
00083         }
00084 #endif
00085 }
00086 
00088 // CDownloadTransferED2K initiate
00089 
00090 BOOL CDownloadTransferED2K::Initiate()
00091 {
00092         ASSERT( m_pClient == NULL );
00093         ASSERT( m_nState == dtsNull );
00094         
00095         if ( ! m_pDownload->m_bED2K || m_pDownload->m_nSize == SIZE_UNKNOWN )
00096         {
00097                 Close( TS_FALSE );
00098                 return FALSE;
00099         }
00100         
00101         m_pClient = EDClients.Connect(
00102                 m_pSource->m_pAddress.S_un.S_addr,
00103                 m_pSource->m_nPort,
00104                 m_pSource->m_nServerPort ? &m_pSource->m_pServerAddress : NULL,
00105                 m_pSource->m_nServerPort,
00106                 m_pSource->m_bGUID ? &m_pSource->m_pGUID : NULL );
00107         
00108         if ( m_pClient == NULL )
00109         {
00110                 Close( EDClients.IsFull() ? TS_TRUE : TS_FALSE );
00111                 return FALSE;
00112         }
00113         
00114         SetState( dtsConnecting );
00115         m_tConnected = GetTickCount();
00116         
00117         if ( ! m_pClient->AttachDownload( this ) )
00118         {
00119                 SetState( dtsNull );
00120                 m_pClient = NULL;
00121                 Close( TS_TRUE );
00122                 return FALSE;
00123         }
00124         
00125         m_pHost                 = m_pClient->m_pHost;
00126         m_sAddress              = m_pClient->m_sAddress;
00127         
00128         m_pClient->m_mInput.pLimit = &Downloads.m_nLimitDonkey;
00129         
00130         return TRUE;
00131 }
00132 
00134 // CDownloadTransferED2K close
00135 
00136 void CDownloadTransferED2K::Close(TRISTATE bKeepSource)
00137 {
00138         SetState( dtsNull );
00139 
00140         if ( m_pClient != NULL )
00141         {
00142                 m_pClient->OnDownloadClose();
00143                 m_pClient = NULL;
00144         }
00145         
00146         CDownloadTransfer::Close( bKeepSource );
00147 }
00148 
00150 // CDownloadTransferED2K bandwidth control
00151 
00152 void CDownloadTransferED2K::Boost()
00153 {
00154         if ( m_pClient == NULL ) return;
00155         m_pClient->m_mInput.pLimit = NULL;
00156 }
00157 
00158 DWORD CDownloadTransferED2K::GetAverageSpeed()
00159 {
00160         return m_pSource->m_nSpeed = GetMeasuredSpeed();
00161 }
00162 
00163 DWORD CDownloadTransferED2K::GetMeasuredSpeed()
00164 {
00165         if ( m_pClient == NULL ) return 0;
00166         m_pClient->Measure();
00167         return m_pClient->m_mInput.nMeasure;
00168 }
00169 
00171 // CDownloadTransferED2K run event
00172 
00173 BOOL CDownloadTransferED2K::OnRun()
00174 {
00175         return OnRunEx( GetTickCount() );
00176 }
00177 
00178 BOOL CDownloadTransferED2K::OnRunEx(DWORD tNow)
00179 {
00180         switch ( m_nState )
00181         {
00182         case dtsConnecting:
00183                 if ( tNow > m_tConnected && tNow - m_tConnected > Settings.Connection.TimeoutConnect * 2 )
00184                 {
00185                         theApp.Message( MSG_ERROR, IDS_CONNECTION_TIMEOUT_CONNECT, (LPCTSTR)m_sAddress );
00186                         Close( TS_TRUE );
00187                         return FALSE;
00188                 }
00189                 break;
00190         case dtsRequesting:
00191         case dtsEnqueue:
00192                 if ( tNow > m_tRequest && tNow - m_tRequest > Settings.Connection.TimeoutHandshake * 2 )
00193                 {
00194                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_REQUEST_TIMEOUT, (LPCTSTR)m_sAddress );
00195                         Close( TS_UNKNOWN );
00196                         return FALSE;
00197                 }
00198                 break;
00199         case dtsQueued:
00200                 return RunQueued( tNow );
00201         case dtsDownloading:
00202         case dtsHashset:
00203                 if ( tNow > m_pClient->m_mInput.tLast &&
00204                          tNow - m_pClient->m_mInput.tLast > Settings.Connection.TimeoutTraffic * 2 )
00205                 {
00206                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_TRAFFIC_TIMEOUT, (LPCTSTR)m_sAddress );
00207                         Close( TS_TRUE );
00208                         return FALSE;
00209                 }
00210                 break;
00211         }
00212         
00213         return TRUE;
00214 }
00215 
00217 // CDownloadTransferED2K connection established event
00218 
00219 BOOL CDownloadTransferED2K::OnConnected()
00220 {
00221         ASSERT( m_pClient != NULL );
00222         ASSERT( m_pSource != NULL );
00223 
00224         m_pHost         = m_pClient->m_pHost;
00225         m_sAddress      = m_pClient->m_sAddress;
00226         
00227         m_pSource->m_bGUID              = TRUE;
00228         m_pSource->m_pGUID              = m_pClient->m_pGUID;
00229         m_pSource->m_sServer    = m_sUserAgent = m_pClient->m_sUserAgent;
00230         m_pSource->m_sNick              = m_pClient->m_sNick;
00231         m_pSource->SetLastSeen();
00232         
00233         theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_CONNECTED, (LPCTSTR)m_sAddress );
00234         
00235         return SendPrimaryRequest();
00236 }
00237 
00239 // CDownloadTransferED2K connection dropped event
00240 
00241 void CDownloadTransferED2K::OnDropped(BOOL bError)
00242 {
00243         if ( m_nState == dtsQueued )
00244         {
00245                 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_QUEUE_DROP,
00246                         (LPCTSTR)m_pDownload->GetDisplayName() );
00247         }
00248         else
00249         {
00250                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_DROPPED, (LPCTSTR)m_sAddress );
00251                 Close( TS_UNKNOWN );
00252         }
00253 }
00254 
00256 // CDownloadTransferED2K packet handlers
00257 
00258 BOOL CDownloadTransferED2K::OnFileReqAnswer(CEDPacket* pPacket)
00259 {
00260         if ( m_pDownload->m_nSize <= ED2K_PART_SIZE )
00261         {
00262                 if ( m_pAvailable ) delete [] m_pAvailable;
00263                 m_pAvailable = new BYTE[ 1 ];
00264                 m_pAvailable[ 0 ] = TRUE;
00265                 m_pSource->m_oAvailable.insert( m_pSource->m_oAvailable.end(),
00266                         FF::SimpleFragment( 0, m_pDownload->m_nSize ) );
00267                 SendSecondaryRequest();
00268         }
00269         // Not really interested
00270         return TRUE;
00271 }
00272 
00273 BOOL CDownloadTransferED2K::OnFileNotFound(CEDPacket* pPacket)
00274 {
00275         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_FILENOTFOUND,
00276                 (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
00277         
00278         Close( TS_FALSE );
00279         return FALSE;
00280 }
00281 
00282 BOOL CDownloadTransferED2K::OnFileStatus(CEDPacket* pPacket)
00283 {
00284         if ( m_nState <= dtsConnecting ) return TRUE;
00285         
00286         if ( pPacket->GetRemaining() < sizeof(MD4) + 2 )
00287         {
00288                 theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
00289                 Close( TS_FALSE );
00290                 return FALSE;
00291         }
00292         
00293         MD4 pMD4;
00294         pPacket->Read( &pMD4, sizeof(MD4) );
00295         
00296         if ( pMD4 != m_pDownload->m_pED2K )
00297         {
00298                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_HASH,
00299                         (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
00300                 return TRUE;
00301         }
00302         
00303         DWORD nBlocks = pPacket->ReadShortLE();
00304         
00305         if ( nBlocks == (DWORD)( ( m_pDownload->m_nSize + ED2K_PART_SIZE - 1 ) / ED2K_PART_SIZE ) )
00306         {
00307         m_pSource->m_oAvailable.clear();
00308                 
00309                 if ( m_pAvailable != NULL ) delete [] m_pAvailable;
00310                 m_pAvailable = new BYTE[ nBlocks ];
00311                 ZeroMemory( m_pAvailable, nBlocks );
00312                 
00313                 for ( DWORD nBlock = 0 ; nBlock < nBlocks && pPacket->GetRemaining() ; )
00314                 {
00315                         BYTE nByte = pPacket->ReadByte();
00316                         
00317                         for ( int nBit = 0 ; nBit < 8 && nBlock < nBlocks ; nBit++, nBlock++ )
00318                         {
00319                                 if ( nByte & ( 1 << nBit ) )
00320                                 {
00321                                         QWORD nFrom = ED2K_PART_SIZE * nBlock;
00322                                         QWORD nTo = nFrom + ED2K_PART_SIZE;
00323                                         nTo = min( nTo, m_pDownload->m_nSize );
00324                                         
00325                     m_pSource->m_oAvailable.insert( m_pSource->m_oAvailable.end(),
00326                         FF::SimpleFragment( nFrom, nTo ) );
00327                                         m_pAvailable[ nBlock ] = TRUE;
00328                                 }
00329                         }
00330                 }
00331         }
00332         else if ( nBlocks == 0 )
00333         {
00334                 m_pSource->m_oAvailable.clear();
00335                 
00336                 if ( m_pAvailable != NULL ) delete [] m_pAvailable;
00337                 m_pAvailable = NULL;
00338         }
00339         else
00340         {
00341                 theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
00342                 Close( TS_FALSE );
00343                 return FALSE;
00344         }
00345         
00346         SendSecondaryRequest();
00347         
00348         return TRUE;
00349 }
00350 
00351 BOOL CDownloadTransferED2K::OnHashsetAnswer(CEDPacket* pPacket)
00352 {
00353         if ( m_nState != dtsHashset ) return TRUE;
00354         
00355         if ( pPacket->GetRemaining() < sizeof(MD4) + 2 )
00356         {
00357                 theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
00358                 Close( TS_FALSE );
00359                 return FALSE;
00360         }
00361         
00362         MD4 pMD4;
00363         pPacket->Read( &pMD4, sizeof(MD4) );
00364         
00365         if ( pMD4 != m_pDownload->m_pED2K )
00366         {
00367                 return TRUE;    // Hack
00368                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HASHSET_ERROR, (LPCTSTR)m_sAddress );
00369                 Close( TS_FALSE );
00370                 return FALSE;
00371         }
00372         
00373         m_bHashset = TRUE;
00374         
00375         DWORD nBlocks = pPacket->ReadShortLE();
00376         
00377         if ( nBlocks == 0 ) nBlocks = 1;
00378         
00379         if ( nBlocks != (DWORD)( ( m_pDownload->m_nSize + ED2K_PART_SIZE - 1 ) / ED2K_PART_SIZE ) )
00380         {
00381                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HASHSET_ERROR, (LPCTSTR)m_sAddress );
00382         }
00383         else if ( m_pDownload->SetHashset(      pPacket->m_pBuffer + pPacket->m_nPosition,
00384                                                                                 pPacket->GetRemaining() ) )
00385         {
00386                 return SendSecondaryRequest();
00387         }
00388         
00389         Close( TS_FALSE );
00390         return FALSE;
00391 }
00392 
00393 BOOL CDownloadTransferED2K::OnQueueRank(CEDPacket* pPacket)
00394 {
00395         if ( m_nState <= dtsConnecting ) return TRUE;
00396         
00397         if ( pPacket->GetRemaining() < 4 )
00398         {
00399                 theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
00400                 Close( TS_FALSE );
00401                 return FALSE;
00402         }
00403         
00404         m_nQueuePos     = pPacket->ReadLongLE();
00405         
00406         if ( m_nQueuePos > 0 )
00407         {
00408                 SetQueueRank( m_nQueuePos );
00409         }
00410         else
00411         {
00412                 m_pSource->m_tAttempt = GetTickCount() + Settings.eDonkey.ReAskTime * 1000;
00413                 Close( TS_UNKNOWN );
00414         }
00415         
00416         return TRUE;
00417 }
00418 
00419 BOOL CDownloadTransferED2K::OnRankingInfo(CEDPacket* pPacket)
00420 {
00421         if ( m_nState <= dtsConnecting ) return TRUE;
00422         
00423         if ( pPacket->GetRemaining() < 12 )
00424         {
00425                 theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
00426                 Close( TS_FALSE );
00427                 return FALSE;
00428         }
00429         
00430         m_nQueuePos     = pPacket->ReadShortLE();
00431         m_nQueueLen     = pPacket->ReadShortLE();
00432         
00433         SetQueueRank( m_nQueuePos );
00434         
00435         return TRUE;
00436 }
00437 
00438 BOOL CDownloadTransferED2K::OnFileComment(CEDPacket* pPacket)
00439 {
00440         BYTE nFileRating;
00441         DWORD nLength;
00442         CString sFileComment;
00443 
00444         // Read in the file rating
00445         nFileRating = pPacket->ReadByte();
00446 
00447         nLength = pPacket->ReadLongLE();
00448         if ( nLength > 0 ) 
00449         {
00450                 if ( nLength > ED2K_COMMENT_MAX ) nLength = ED2K_COMMENT_MAX;
00451 
00452                 // Read in comment
00453                 if ( m_pClient && m_pClient->m_bEmUnicode )
00454                         sFileComment = pPacket->ReadStringUTF8( nLength );
00455                 else
00456                         sFileComment = pPacket->ReadString( nLength );
00457         }
00458 
00459         if ( m_pDownload && m_pClient )
00460         {
00461                 return m_pDownload->AddReview( &m_pClient->m_pHost.sin_addr, 3, nFileRating, m_pClient->m_sNick, sFileComment );
00462         }
00463 
00464         return FALSE;
00465 }
00466 
00467 BOOL CDownloadTransferED2K::OnStartUpload(CEDPacket* pPacket)
00468 {
00469         SetState( dtsDownloading );
00470         m_pClient->m_mInput.tLast = GetTickCount();
00471         
00472         ClearRequests();
00473         
00474         return SendFragmentRequests();
00475 }
00476 
00477 BOOL CDownloadTransferED2K::OnFinishUpload(CEDPacket* pPacket)
00478 {
00479         return SendPrimaryRequest();
00480 }
00481 
00482 BOOL CDownloadTransferED2K::OnSendingPart(CEDPacket* pPacket)
00483 {
00484         if ( m_nState != dtsDownloading ) return TRUE;
00485         
00486         if ( pPacket->GetRemaining() <= sizeof(MD4) + 8 )
00487         {
00488                 theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
00489                 Close( TS_FALSE );
00490                 return FALSE;
00491         }
00492         
00493         MD4 pMD4;
00494         pPacket->Read( &pMD4, sizeof(MD4) );
00495 
00496         if ( pMD4 != m_pDownload->m_pED2K )
00497         {
00498                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_HASH,
00499                         (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
00500                 // Close( TS_FALSE );
00501                 // return FALSE;
00502                 return TRUE;
00503         }
00504         
00505         QWORD nOffset = pPacket->ReadLongLE();
00506         QWORD nLength = pPacket->ReadLongLE();
00507         
00508         if ( nLength <= nOffset )
00509         {
00510                 if ( nLength == nOffset ) return TRUE;
00511                 theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
00512                 Close( TS_FALSE );
00513                 return FALSE;
00514         }
00515         
00516         nLength -= nOffset;
00517         
00518         if ( nLength > (QWORD)pPacket->GetRemaining() )
00519         {
00520                 theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
00521                 Close( TS_FALSE );
00522                 return FALSE;
00523         }
00524         
00525         BOOL bUseful = m_pDownload->SubmitData( nOffset,
00526                 pPacket->m_pBuffer + pPacket->m_nPosition, nLength );
00527         
00528     m_oRequested.erase( FF::SimpleFragment( nOffset, nOffset + nLength ) );
00529         
00530         m_pSource->AddFragment( nOffset, nLength,
00531                 ( nOffset % ED2K_PART_SIZE ) ? TRUE : FALSE );
00532         
00533         m_nDownloaded += nLength;
00534         
00535         m_pSource->SetValid();
00536         
00537         return SendFragmentRequests();
00538 }
00539 
00540 BOOL CDownloadTransferED2K::OnCompressedPart(CEDPacket* pPacket)
00541 {
00542         if ( m_nState != dtsDownloading ) return TRUE;
00543         
00544         if ( pPacket->GetRemaining() <= sizeof(MD4) + 8 )
00545         {
00546                 theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
00547                 Close( TS_FALSE );
00548                 return FALSE;
00549         }
00550         
00551         MD4 pMD4;
00552         pPacket->Read( &pMD4, sizeof(MD4) );
00553         
00554         if ( pMD4 != m_pDownload->m_pED2K )
00555         {
00556                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_HASH,
00557                         (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
00558                 // Close( TS_FALSE );
00559                 // return FALSE;
00560                 return TRUE;
00561         }
00562         
00563         QWORD nBaseOffset = pPacket->ReadLongLE();
00564         QWORD nBaseLength = pPacket->ReadLongLE();
00565         
00566         z_streamp pStream = (z_streamp)m_pInflatePtr;
00567         
00568         if ( m_pInflatePtr == NULL || m_nInflateOffset != nBaseOffset || m_nInflateLength != nBaseLength )
00569         {
00570                 if ( pStream != NULL )
00571                 {
00572                         inflateEnd( pStream );
00573                         delete pStream;
00574                 }
00575                 
00576                 m_nInflateOffset        = nBaseOffset;
00577                 m_nInflateLength        = nBaseLength;
00578                 m_nInflateRead          = 0;
00579                 m_nInflateWritten       = 0;
00580                 m_pInflateBuffer->Clear();
00581                 
00582                 m_pInflatePtr = new z_stream;
00583                 pStream = (z_streamp)m_pInflatePtr;
00584                 ZeroMemory( pStream, sizeof(z_stream) );
00585                 
00586                 if ( inflateInit( pStream ) != Z_OK )
00587                 {
00588                         delete pStream;
00589                         m_pInflatePtr = NULL;
00590                         
00591                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_INFLATE_ERROR,
00592                                 (LPCTSTR)m_pDownload->GetDisplayName() );
00593                         
00594                         Close( TS_FALSE );
00595                         return FALSE;
00596                 }
00597         }
00598         
00599         m_pInflateBuffer->Add( pPacket->m_pBuffer + pPacket->m_nPosition, pPacket->GetRemaining() );
00600         
00601         BYTE pBuffer[ BUFFER_SIZE ];
00602         
00603         if ( m_pInflateBuffer->m_nLength > 0 && m_nInflateRead < m_nInflateLength )
00604         {
00605                 pStream->next_in        = m_pInflateBuffer->m_pBuffer;
00606                 pStream->avail_in       = m_pInflateBuffer->m_nLength;
00607                 
00608                 do
00609                 {
00610                         pStream->next_out       = pBuffer;
00611                         pStream->avail_out      = BUFFER_SIZE;
00612                         
00613                         inflate( pStream, Z_SYNC_FLUSH );
00614                         
00615                         if ( pStream->avail_out < BUFFER_SIZE )
00616                         {
00617                                 QWORD nOffset = m_nInflateOffset + m_nInflateWritten;
00618                                 QWORD nLength = BUFFER_SIZE - pStream->avail_out;
00619                                 
00620                                 BOOL bUseful = m_pDownload->SubmitData( nOffset, pBuffer, nLength );
00621                                 
00622                 m_oRequested.erase( FF::SimpleFragment( nOffset, nOffset + nLength ) );
00623                                 
00624                                 m_pSource->AddFragment( nOffset, nLength,
00625                                         ( nOffset % ED2K_PART_SIZE ) ? TRUE : FALSE );
00626                                 
00627                                 m_nDownloaded += nLength;
00628                                 m_nInflateWritten += nLength;
00629                         }
00630                 }
00631                 while ( pStream->avail_out == 0 );
00632                 
00633                 if ( pStream->avail_in >= 0 && pStream->avail_in < m_pInflateBuffer->m_nLength )
00634                 {
00635                         m_nInflateRead += ( m_pInflateBuffer->m_nLength - pStream->avail_in );
00636                         m_pInflateBuffer->Remove( m_pInflateBuffer->m_nLength - pStream->avail_in );
00637                 }
00638         }
00639         
00640         if ( m_nInflateRead >= m_nInflateLength )
00641         {
00642                 inflateEnd( pStream );
00643                 delete pStream;
00644                 m_pInflatePtr = NULL;
00645                 m_pInflateBuffer->Clear();
00646         }
00647         
00648         m_pSource->SetValid();
00649         
00650         return SendFragmentRequests();
00651 }
00652 
00654 // CDownloadTransferED2K send
00655 
00656 void CDownloadTransferED2K::Send(CEDPacket* pPacket, BOOL bRelease)
00657 {
00658         ASSERT( m_nState > dtsConnecting );
00659         ASSERT( m_pClient != NULL );
00660         m_pClient->Send( pPacket, bRelease );
00661 }
00662 
00664 // CDownloadTransferED2K file requestors
00665 
00666 BOOL CDownloadTransferED2K::SendPrimaryRequest()
00667 {
00668         ASSERT( m_pClient != NULL );
00669         DWORD tNow = GetTickCount();
00670         
00671         /*
00672         if ( m_pDownload->GetVolumeRemaining() == 0 )
00673         {
00674                 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress );
00675                 Close( TS_TRUE );
00676                 return FALSE;
00677         }
00678         */
00679 
00680         //This source is current requesting
00681         SetState( dtsRequesting );
00682 
00683         //Set the 'last requested' time
00684         m_tRequest      = tNow;         
00685 
00686         ClearRequests();
00687         
00688         //Send ed2k file request
00689         CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_FILEREQUEST );
00690         pPacket->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
00691 
00692         if ( Settings.eDonkey.ExtendedRequest && m_pClient->m_bEmRequest >= 1 )
00693         {
00694                 m_pClient->WritePartStatus( pPacket, m_pDownload );
00695         }
00696         /*
00697         //We don't have any need to do this- it's not very useful (or accurate). Raza only offers extended request V1
00698         if ( Settings.eDonkey.ExtendedRequest && m_pClient->m_bEmRequest >= 2 ) 
00699         {
00700                 pPacket->WriteShortLE( m_pDownload->GetED2KCompleteSourceCount() );
00701         }
00702         */
00703         Send( pPacket );
00704         
00705         if ( m_pDownload->m_nSize <= ED2K_PART_SIZE )
00706         {
00707                 // Don't ask for status - if the client answers we know the file is complete anyway
00708         }
00709         else
00710         {
00711                 //Send ed2k status request
00712                 pPacket = CEDPacket::New( ED2K_C2C_FILESTATUSREQUEST );
00713                 pPacket->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
00714                 Send( pPacket );
00715         }
00716         
00717         if ( ( m_pDownload->GetSourceCount() < Settings.Downloads.SourcesWanted ) &&//We want more sources
00718                  ( tNow > m_tSources ) && ( tNow - m_tSources > 30 * 60 * 1000 ) &&             //We have not asked for at least 30 minutes
00719                  ( m_pClient->m_bEmule ) && ( Network.IsListening() ) )                                 //Remote client is eMule compatible and we are accepting packets
00720         {
00721                 //Set 'last asked for sources' time
00722                 m_tSources = tNow;
00723                 //Send ed2k request for sources packet
00724                 pPacket = CEDPacket::New( ED2K_C2C_REQUESTSOURCES, ED2K_PROTOCOL_EMULE );
00725                 pPacket->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
00726                 Send( pPacket );
00727         }
00728         
00729         return TRUE;
00730 }
00731 
00732 BOOL CDownloadTransferED2K::SendSecondaryRequest()
00733 {
00734         ASSERT( m_pClient != NULL );
00735         ASSERT( m_nState > dtsConnecting );
00736         // ASSERT( m_nState == dtsRequesting || m_nState == dtsHashset );
00737         
00738         if ( ! m_pDownload->PrepareFile() )
00739         {
00740                 Close( TS_TRUE );
00741                 return FALSE;
00742         }
00743         
00744         if ( m_bHashset == FALSE && m_pDownload->NeedHashset() )
00745         {
00746                 CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_HASHSETREQUEST );
00747                 pPacket->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
00748                 Send( pPacket );
00749                 
00750                 SetState( dtsHashset );
00751                 m_pClient->m_mInput.tLast = GetTickCount();
00752         }
00753         else if ( m_pSource->HasUsefulRanges() )
00754         {
00755                 CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_QUEUEREQUEST );
00756                 pPacket->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
00757                 Send( pPacket );
00758                 
00759                 SetState( dtsEnqueue );
00760                 m_tRequest = GetTickCount();
00761         }
00762         else
00763         {
00764                 m_pSource->m_tAttempt = GetTickCount() + Settings.eDonkey.ReAskTime * 500;
00765                 m_pSource->SetAvailableRanges( NULL );
00766                 theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress );
00767                 Close( TS_TRUE );
00768                 return FALSE;
00769         }
00770         
00771         ClearRequests();
00772         
00773         return TRUE;
00774 }
00775 
00777 // CDownloadTransferED2K fragment request manager
00778 
00779 BOOL CDownloadTransferED2K::SendFragmentRequests()
00780 {
00781         ASSERT( m_nState == dtsDownloading );
00782         ASSERT( m_pClient != NULL );
00783         
00784         if ( m_oRequested.size() >= (int)Settings.eDonkey.RequestPipe ) return TRUE;
00785         
00786     FF::SimpleFragmentList oPossible( m_pDownload->GetEmptyFragmentList() );
00787         
00788         if ( ! m_pDownload->m_bTorrentEndgame )
00789         {
00790                 for ( CDownloadTransfer* pTransfer = m_pDownload->GetFirstTransfer() ; pTransfer && !oPossible.empty() ; pTransfer = pTransfer->m_pDlNext )
00791                 {
00792                         pTransfer->SubtractRequested( oPossible );
00793                 }
00794         }
00795         
00796         while ( m_oRequested.size() < (int)Settings.eDonkey.RequestPipe )
00797         {
00798                 QWORD nOffset, nLength;
00799                 
00800                 if ( SelectFragment( oPossible, nOffset, nLength ) )
00801                 {
00802                         ChunkifyRequest( &nOffset, &nLength, Settings.eDonkey.RequestSize, FALSE );
00803                         
00804             FF::SimpleFragment Selected( nOffset, nOffset + nLength );
00805             oPossible.erase( Selected );
00806                         
00807             m_oRequested.pushBack( Selected );
00808 
00809                         CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_REQUESTPARTS );
00810                         pPacket->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
00811                         pPacket->WriteLongLE( (DWORD)nOffset );
00812                         pPacket->WriteLongLE( 0 );
00813                         pPacket->WriteLongLE( 0 );
00814                         pPacket->WriteLongLE( (DWORD)( nOffset + nLength ) );
00815                         pPacket->WriteLongLE( 0 );
00816                         pPacket->WriteLongLE( 0 );
00817                         Send( pPacket );
00818                         
00819                         int nType = ( m_nDownloaded == 0 || ( nOffset % ED2K_PART_SIZE ) == 0 )
00820                                 ? MSG_DEFAULT : MSG_DEBUG;
00821                         
00822                         theApp.Message( nType, IDS_DOWNLOAD_FRAGMENT_REQUEST,
00823                                 nOffset, nOffset + nLength - 1,
00824                                 (LPCTSTR)m_pDownload->GetDisplayName(), (LPCTSTR)m_sAddress );
00825                 }
00826                 else
00827                 {
00828                         break;
00829                 }
00830         }
00831 
00832         // If there are no more possible chunks to request, and endgame is available but not active
00833         if ( oPossible.empty() && Settings.eDonkey.Endgame && ! m_pDownload->m_bTorrentEndgame )
00834         {
00835                 // And the file is at least 100MB, with less than 1MB to go
00836                 if ( ( m_pDownload->GetVolumeComplete() > 100*1024*1024 ) && 
00837                          ( m_pDownload->GetVolumeRemaining() <  1*1024*1024 ) )
00838                 {
00839                         // Then activate endgame
00840                         m_pDownload->m_bTorrentEndgame = TRUE;
00841                         theApp.Message( MSG_DEBUG, _T("Activating endgame for ed2k transfer %s"), m_pDownload->m_sLocalName );
00842                 }
00843         }
00844 
00845         if ( !m_oRequested.empty() ) return TRUE;
00846         
00847         Send( CEDPacket::New( ED2K_C2C_QUEUERELEASE ) );
00848         
00849         theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress );
00850         Close( TS_TRUE );
00851         
00852         return FALSE;
00853 }
00854 
00855 void CDownloadTransferED2K::ClearRequests()
00856 {
00857         m_oRequested.clear();
00858         
00859         if ( z_streamp pStream = (z_streamp)m_pInflatePtr )
00860         {
00861                 inflateEnd( pStream );
00862                 delete pStream;
00863                 m_pInflatePtr = NULL;
00864                 m_pInflateBuffer->Clear();
00865         }
00866 }
00867 
00869 // CDownloadTransferED2K fragment selector
00870 
00871 BOOL CDownloadTransferED2K::SelectFragment(const FF::SimpleFragmentList& oPossible, QWORD& nOffset, QWORD& nLength)
00872 {
00873     FF::SimpleFragment oSelection( selectBlock( oPossible,
00874         ED2K_PART_SIZE, m_pAvailable ) );
00875 
00876     if ( oSelection.end() == ::std::numeric_limits< FF::SimpleFragment::SizeType >::max() ) return FALSE;
00877 
00878     nOffset = oSelection.begin();
00879     nLength = oSelection.length();
00880 
00881     return TRUE;
00882 }
00883 
00885 // CDownloadTransferED2K subtract requested fragments
00886 
00887 BOOL CDownloadTransferED2K::SubtractRequested(FF::SimpleFragmentList& ppFragments)
00888 {
00889         if ( m_nState != dtsDownloading ) return FALSE;
00890         ppFragments.erase( m_oRequested.begin(), m_oRequested.end() );
00891         return TRUE;
00892 }
00893 
00895 // CDownloadTransferED2K run queued state
00896 
00897 BOOL CDownloadTransferED2K::RunQueued(DWORD tNow)
00898 {
00899         ASSERT( m_pClient != NULL );
00900         ASSERT( m_nState == dtsQueued );
00901         
00902         if ( Settings.Downloads.QueueLimit > 0 && m_nQueuePos > Settings.Downloads.QueueLimit )
00903         {
00904                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_QUEUE_HUGE,
00905                         (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName(), m_nQueuePos );
00906                 Close( TS_FALSE );
00907                 return FALSE;
00908         }
00909         else if ( m_pClient->m_bConnected == FALSE && tNow > m_tRanking && tNow - m_tRanking > Settings.eDonkey.ReAskTime * 1000 + 20000 )
00910         {
00911                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_QUEUE_TIMEOUT,
00912                         (LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
00913                 Close( TS_UNKNOWN );
00914                 return FALSE;
00915         }
00916         else if ( m_pClient->m_nUDP > 0 && ! m_bUDP && tNow > m_tRequest && tNow - m_tRequest > Settings.eDonkey.ReAskTime * 1000 - 20000 )
00917         {
00918                 CEDPacket* pPing = CEDPacket::New( ED2K_C2C_UDP_REASKFILEPING, ED2K_PROTOCOL_EMULE );
00919                 pPing->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
00920                 Datagrams.Send( &m_pClient->m_pHost.sin_addr, m_pClient->m_nUDP, pPing );
00921                 m_bUDP = TRUE;
00922         }
00923         else if ( tNow > m_tRequest && tNow - m_tRequest > Settings.eDonkey.ReAskTime * 1000 )
00924         {
00925                 m_tRequest = GetTickCount();
00926                 
00927                 if ( m_pClient->IsOnline() )
00928                 {
00929                         return OnConnected();
00930                 }
00931                 else
00932                 {
00933                         m_pClient->Connect();
00934                 }
00935         }
00936         
00937         return TRUE;
00938 }
00939 
00941 // CDownloadTransferED2K queue rank update
00942 
00943 void CDownloadTransferED2K::SetQueueRank(int nRank)
00944 {
00945         SetState( dtsQueued );
00946 
00947         m_tRequest      = m_tRanking = GetTickCount();
00948         m_nQueuePos     = nRank;
00949         m_bUDP          = FALSE;
00950         
00951         ClearRequests();
00952         
00953         theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_QUEUED,
00954                 (LPCTSTR)m_sAddress, m_nQueuePos, m_nQueueLen, _T("eDonkey2000") );
00955 }

Generated on Thu Dec 15 10:39:40 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2