00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "Network.h"
00026 #include "Statistics.h"
00027 #include "Neighbours.h"
00028 #include "EDNeighbour.h"
00029 #include "EDPacket.h"
00030 #include "Security.h"
00031 #include "GProfile.h"
00032 #include "HostCache.h"
00033 #include "EDClients.h"
00034
00035 #include "Library.h"
00036 #include "SharedFile.h"
00037 #include "Transfers.h"
00038 #include "Downloads.h"
00039 #include "Download.h"
00040 #include "QuerySearch.h"
00041 #include "QueryHit.h"
00042
00043 #include "UploadQueues.h"
00044 #include "Schema.h"
00045 #include "XML.h"
00046
00047 #ifdef _DEBUG
00048 #undef THIS_FILE
00049 static char THIS_FILE[]=__FILE__;
00050 #define new DEBUG_NEW
00051 #endif
00052
00053
00055
00056
00057 CEDNeighbour::CEDNeighbour() : CNeighbour( PROTOCOL_ED2K )
00058 {
00059 m_nNodeType = ntHub;
00060 m_nClientID = 0;
00061 m_nUserCount = 0;
00062 m_nUserLimit = 0;
00063 m_nFileLimit = 1000;
00064 m_nTCPFlags = 0;
00065 m_nUDPFlags = 0;
00066 m_nFilesSent = 0;
00067 m_pMoreResultsGUID = NULL;
00068 }
00069
00070 CEDNeighbour::~CEDNeighbour()
00071 {
00072 for ( POSITION pos = m_pQueries.GetHeadPosition() ; pos ; )
00073 {
00074 delete (GGUID*)m_pQueries.GetNext( pos );
00075 }
00076
00077 if ( m_pMoreResultsGUID != NULL ) delete m_pMoreResultsGUID;
00078 }
00079
00081
00082
00083 BOOL CEDNeighbour::ConnectTo(IN_ADDR* pAddress, WORD nPort, BOOL bAutomatic)
00084 {
00085 if ( CConnection::ConnectTo( pAddress, nPort ) )
00086 {
00087 WSAEventSelect( m_hSocket, Network.m_pWakeup, FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE );
00088
00089 theApp.Message( MSG_DEFAULT, IDS_ED2K_SERVER_CONNECTING,
00090 (LPCTSTR)m_sAddress, htons( m_pHost.sin_port ) );
00091 }
00092 else
00093 {
00094 theApp.Message( MSG_ERROR, IDS_CONNECTION_CONNECT_FAIL,
00095 (LPCTSTR)CString( inet_ntoa( m_pHost.sin_addr ) ) );
00096 return FALSE;
00097 }
00098
00099 m_nState = nrsConnecting;
00100 m_bAutomatic = bAutomatic;
00101
00102 Neighbours.Add( this );
00103
00104 return TRUE;
00105 }
00106
00108
00109
00110 BOOL CEDNeighbour::Send(CPacket* pPacket, BOOL bRelease, BOOL bBuffered)
00111 {
00112 BOOL bSuccess = FALSE;
00113
00114 if ( ( m_nState == nrsHandshake1 || m_nState >= nrsConnected ) &&
00115 pPacket->m_nProtocol == PROTOCOL_ED2K )
00116 {
00117 m_nOutputCount++;
00118 Statistics.Current.eDonkey.Outgoing++;
00119
00120 pPacket->ToBuffer( m_pZOutput ? m_pZOutput : m_pOutput );
00121 QueueRun();
00122
00123 pPacket->SmartDump( this, NULL, TRUE );
00124
00125 bSuccess = TRUE;
00126 }
00127
00128 if ( bRelease ) pPacket->Release();
00129
00130 return bSuccess;
00131 }
00132
00134
00135
00136 BOOL CEDNeighbour::OnRun()
00137 {
00138 DWORD tNow = GetTickCount();
00139
00140 if ( m_nState != nrsConnected )
00141 {
00142 if ( tNow - m_tConnected > Settings.Connection.TimeoutConnect )
00143 {
00144 Close( IDS_CONNECTION_TIMEOUT_CONNECT );
00145 return FALSE;
00146 }
00147 }
00148 else if ( m_nClientID == 0 )
00149 {
00150 if ( tNow - m_tConnected > Settings.Connection.TimeoutHandshake )
00151 {
00152 Close( IDS_HANDSHAKE_TIMEOUT );
00153 return FALSE;
00154 }
00155 }
00156 else
00157 {
00158 if ( tNow - m_tLastPacket > 20 * 60 * 1000 )
00159 {
00160 Close( IDS_CONNECTION_TIMEOUT_TRAFFIC );
00161 return FALSE;
00162 }
00163 }
00164
00165 return TRUE;
00166 }
00167
00169
00170
00171 BOOL CEDNeighbour::OnConnected()
00172 {
00173 DWORD nVersion = ( ( ( ED2K_COMPATIBLECLIENT_ID & 0xFF ) << 24 ) |
00174 ( ( theApp.m_nVersion[0] & 0x7F ) << 17 ) |
00175 ( ( theApp.m_nVersion[1] & 0x7F ) << 10 ) |
00176 ( ( theApp.m_nVersion[2] & 0x07 ) << 7 ) |
00177 ( ( theApp.m_nVersion[3] & 0x7F ) ) );
00178
00179 theApp.Message( MSG_DEFAULT, IDS_ED2K_SERVER_CONNECTED, (LPCTSTR)m_sAddress );
00180
00181 CEDPacket* pPacket = CEDPacket::New( ED2K_C2S_LOGINREQUEST );
00182
00183 GGUID pGUID = MyProfile.GUID;
00184 pGUID.n[5] = 14;
00185 pGUID.n[14] = 111;
00186 pPacket->Write( &pGUID, 16 );
00187
00188 pPacket->WriteLongLE( m_nClientID );
00189 pPacket->WriteShortLE( htons( Network.m_pHost.sin_port ) );
00190
00191 pPacket->WriteLongLE( 5 );
00192
00193
00194
00195
00196 CEDTag( ED2K_CT_NAME, MyProfile.GetNick().Left( 255 ) ).Write( pPacket, 0 );
00197
00198 CEDTag( ED2K_CT_VERSION, ED2K_VERSION ).Write( pPacket, 0 );
00199
00200 CEDTag( ED2K_CT_PORT, htons( Network.m_pHost.sin_port ) ).Write( pPacket, 0 );
00201
00202 CEDTag( ED2K_CT_SOFTWAREVERSION, nVersion ).Write( pPacket, 0 );
00203
00204 CEDTag( ED2K_CT_FLAGS, ED2K_SERVER_TCP_DEFLATE | ED2K_SERVER_TCP_SMALLTAGS | ED2K_SERVER_TCP_UNICODE ).Write( pPacket, 0 );
00205
00206 m_nState = nrsHandshake1;
00207 Send( pPacket );
00208
00209 return TRUE;
00210 }
00211
00212 void CEDNeighbour::OnDropped(BOOL bError)
00213 {
00214 if ( m_nState < nrsConnected )
00215 {
00216 HostCache.OnFailure( &m_pHost.sin_addr, htons( m_pHost.sin_port ) );
00217 }
00218
00219 if ( m_nState == nrsConnecting )
00220 {
00221 Close( IDS_CONNECTION_REFUSED );
00222 }
00223 else
00224 {
00225 Close( IDS_CONNECTION_DROPPED );
00226 }
00227 }
00228
00230
00231
00232 BOOL CEDNeighbour::OnRead()
00233 {
00234 BOOL bSuccess = TRUE;
00235 CEDPacket* pPacket;
00236
00237 CNeighbour::OnRead();
00238
00239 while ( pPacket = CEDPacket::ReadBuffer( m_pZInput ? m_pZInput : m_pInput, ED2K_PROTOCOL_EDONKEY ) )
00240 {
00241 try
00242 {
00243 bSuccess = OnPacket( pPacket );
00244 }
00245 catch ( CException* pException )
00246 {
00247 pException->Delete();
00248 }
00249
00250 pPacket->Release();
00251 if ( ! bSuccess ) break;
00252 }
00253
00254 return bSuccess;
00255 }
00256
00258
00259
00260 BOOL CEDNeighbour::OnPacket(CEDPacket* pPacket)
00261 {
00262 pPacket->SmartDump( this, NULL, FALSE );
00263
00264
00265 m_nInputCount++;
00266 Statistics.Current.eDonkey.Incoming++;
00267 m_tLastPacket = GetTickCount();
00268
00269 switch ( pPacket->m_nType )
00270 {
00271 case ED2K_S2C_REJECTED:
00272 return OnRejected( pPacket );
00273 case ED2K_S2C_SERVERMESSAGE:
00274 return OnServerMessage( pPacket );
00275 case ED2K_S2C_IDCHANGE:
00276 return OnIdChange( pPacket );
00277 case ED2K_S2C_SERVERLIST:
00278 return OnServerList( pPacket );
00279 case ED2K_S2C_SERVERSTATUS:
00280 return OnServerStatus( pPacket );
00281 case ED2K_S2C_SERVERIDENT:
00282 return OnServerIdent( pPacket );
00283 case ED2K_S2C_CALLBACKREQUESTED:
00284 return OnCallbackRequest( pPacket );
00285 case ED2K_S2C_SEARCHRESULTS:
00286 return OnSearchResults( pPacket );
00287 case ED2K_S2C_FOUNDSOURCES:
00288 return OnFoundSources( pPacket );
00289 default:
00290 {
00291 pPacket->Debug( _T("Unknown") );
00292 break;
00293 }
00294 }
00295
00296 return TRUE;
00297 }
00298
00300
00301
00302 BOOL CEDNeighbour::OnRejected(CEDPacket* pPacket)
00303 {
00304 Close( IDS_ED2K_SERVER_REJECTED );
00305 return FALSE;
00306 }
00307
00308 BOOL CEDNeighbour::OnServerMessage(CEDPacket* pPacket)
00309 {
00310 if ( pPacket->GetRemaining() < 4 ) return TRUE;
00311
00312 CString strMessage = pPacket->ReadEDString( m_nTCPFlags );
00313
00314 while ( strMessage.GetLength() > 0 )
00315 {
00316 CString strLine = strMessage.SpanExcluding( _T("\r\n") );
00317
00318 if ( strLine.GetLength() > 0 )
00319 {
00320 strMessage = strMessage.Mid( strLine.GetLength() );
00321 theApp.Message( MSG_SYSTEM, IDS_ED2K_SERVER_MESSAGE,
00322 (LPCTSTR)m_sAddress, (LPCTSTR)strLine );
00323 }
00324
00325 if ( strMessage.GetLength() > 0 ) strMessage = strMessage.Mid( 1 );
00326 }
00327
00328 return TRUE;
00329 }
00330
00331 BOOL CEDNeighbour::OnIdChange(CEDPacket* pPacket)
00332 {
00333 if ( pPacket->GetRemaining() < 4 ) return TRUE;
00334
00335 DWORD nClientID = pPacket->ReadLongLE();
00336
00337 if ( nClientID == 0 )
00338 {
00339 Close( IDS_ED2K_SERVER_REFUSED );
00340 return FALSE;
00341 }
00342
00343 if ( pPacket->GetRemaining() >= 4 )
00344 {
00345 m_nTCPFlags = pPacket->ReadLongLE();
00346 }
00347
00348 if ( m_nClientID == 0 )
00349 {
00350 theApp.Message( MSG_DEFAULT, IDS_ED2K_SERVER_ONLINE, (LPCTSTR)m_sAddress, nClientID );
00351 SendSharedFiles();
00352 Send( CEDPacket::New( ED2K_C2S_GETSERVERLIST ) );
00353 HostCache.eDonkey.Add( &m_pHost.sin_addr, htons( m_pHost.sin_port ) );
00354 }
00355 else
00356 {
00357 theApp.Message( MSG_DEFAULT, IDS_ED2K_SERVER_IDCHANGE, (LPCTSTR)m_sAddress, m_nClientID, nClientID );
00358 }
00359
00360 m_nState = nrsConnected;
00361 m_nClientID = nClientID;
00362
00363 if ( ! CEDPacket::IsLowID( m_nClientID ) )
00364 {
00365 if ( Settings.Connection.InHost.IsEmpty() )
00366 {
00367 Network.m_pHost.sin_addr.S_un.S_addr = m_nClientID;
00368 }
00369 }
00370
00371 CString strServerFlags;
00372 strServerFlags.Format(
00373 _T( "Server Flags: Zlib: %d Short Tags: %d Unicode: %d GetSources2: %d (64): %d (128): %d" ),
00374 m_nTCPFlags & ED2K_SERVER_TCP_DEFLATE,
00375 m_nTCPFlags & ED2K_SERVER_TCP_SMALLTAGS,
00376 m_nTCPFlags & ED2K_SERVER_TCP_UNICODE,
00377 m_nTCPFlags & ED2K_SERVER_TCP_GETSOURCES2,
00378 m_nTCPFlags & 0x00000040,
00379 m_nTCPFlags & 0x00000080 );
00380 theApp.Message( MSG_DEBUG, strServerFlags );
00381
00382
00383 return TRUE;
00384 }
00385
00386 BOOL CEDNeighbour::OnServerList(CEDPacket* pPacket)
00387 {
00388 if ( pPacket->GetRemaining() < 1 ) return TRUE;
00389
00390 int nCount = pPacket->ReadByte();
00391 if ( pPacket->GetRemaining() < nCount * 6 ) return TRUE;
00392
00393 while ( nCount-- > 0 )
00394 {
00395 DWORD nAddress = pPacket->ReadLongLE();
00396 WORD nPort = pPacket->ReadShortLE();
00397
00398 theApp.Message( MSG_DEBUG, _T("CEDNeighbour::OnServerList(): %s: %s:%i"),
00399 (LPCTSTR)m_sAddress,
00400 (LPCTSTR)CString( inet_ntoa( (IN_ADDR&)nAddress ) ), nPort );
00401
00402 if ( Settings.eDonkey.LearnNewServers )
00403 {
00404 HostCache.eDonkey.Add( (IN_ADDR*)&nAddress, nPort );
00405 }
00406 }
00407
00408 HostCache.eDonkey.Add( &m_pHost.sin_addr, htons( m_pHost.sin_port ) );
00409
00410 return TRUE;
00411 }
00412
00413 BOOL CEDNeighbour::OnServerStatus(CEDPacket* pPacket)
00414 {
00415 if ( pPacket->GetRemaining() < 8 ) return TRUE;
00416
00417 m_nUserCount = pPacket->ReadLongLE();
00418 m_nFileCount = pPacket->ReadLongLE();
00419
00420 if ( CHostCacheHost* pHost = HostCache.eDonkey.Add( &m_pHost.sin_addr, htons( m_pHost.sin_port ) ) )
00421 {
00422
00423 pHost->m_nUserCount = m_nUserCount;
00424 pHost->m_nUserLimit = max( pHost->m_nUserLimit, m_nUserCount );
00425 }
00426
00427 return TRUE;
00428 }
00429
00430 BOOL CEDNeighbour::OnServerIdent(CEDPacket* pPacket)
00431 {
00432 if ( pPacket->GetRemaining() < sizeof(GGUID) + 6 + 4 ) return TRUE;
00433
00434 m_bGUID = TRUE;
00435 pPacket->Read( &m_pGUID, sizeof(GGUID) );
00436
00437 pPacket->ReadLongLE();
00438 pPacket->ReadShortLE();
00439
00440 DWORD nTags = pPacket->ReadLongLE();
00441 CString strDescription;
00442
00443 while ( nTags-- > 0 && pPacket->GetRemaining() > 1 )
00444 {
00445 CEDTag pTag;
00446 if ( ! pTag.Read( pPacket, m_nTCPFlags ) ) break;
00447
00448 switch ( pTag.m_nKey )
00449 {
00450 case ED2K_ST_SERVERNAME:
00451
00452 m_sServerName = pTag.m_sValue;
00453 break;
00454 case ED2K_ST_DESCRIPTION:
00455 strDescription = pTag.m_sValue;
00456 break;
00457 case ED2K_ST_MAXUSERS:
00458 m_nUserLimit = pTag.m_nValue;
00459 break;
00460
00461
00462
00463
00464
00465
00466
00467
00468 default:
00469 CString str;
00470 str.Format( _T("Unrecognised packet - IP: %s - opcode: 0x%x - in CEDNeighbour::OnServerIdent"),
00471 LPCTSTR( m_sAddress ), int( pTag.m_nKey ) );
00472 theApp.Message( MSG_DEBUG, LPCTSTR( str ) );
00473 }
00474 }
00475
00476 if ( (DWORD&)m_pGUID == 0x2A2A2A2A )
00477 m_sUserAgent = _T("eFarm Server");
00478 else
00479 m_sUserAgent = _T("eDonkey2000 Server");
00480
00481 if ( CHostCacheHost* pHost = HostCache.eDonkey.Add( &m_pHost.sin_addr, htons( m_pHost.sin_port ) ) )
00482 {
00483 pHost->m_sName = m_sServerName;
00484 pHost->m_sDescription = strDescription;
00485 pHost->m_nUserLimit = m_nUserLimit;
00486 pHost->m_nTCPFlags = m_nTCPFlags;
00487
00488
00489 if ( m_nTCPFlags & ED2K_SERVER_TCP_DEFLATE )
00490 {
00491 pHost->m_nUDPFlags |= ED2K_SERVER_UDP_GETSOURCES;
00492 pHost->m_nUDPFlags |= ED2K_SERVER_UDP_GETFILES;
00493 }
00494 if ( m_nTCPFlags & ED2K_SERVER_TCP_UNICODE )
00495 pHost->m_nUDPFlags |= ED2K_SERVER_UDP_UNICODE;
00496 if ( m_nTCPFlags & ED2K_SERVER_TCP_GETSOURCES2 )
00497 pHost->m_nUDPFlags |= ED2K_SERVER_UDP_GETSOURCES2;
00498
00499 }
00500
00501 theApp.Message( MSG_DEFAULT, IDS_ED2K_SERVER_IDENT, (LPCTSTR)m_sAddress, (LPCTSTR)m_sServerName );
00502
00503 return TRUE;
00504 }
00505
00506 BOOL CEDNeighbour::OnCallbackRequest(CEDPacket* pPacket)
00507 {
00508 if ( pPacket->GetRemaining() < 6 ) return TRUE;
00509
00510 DWORD nAddress = pPacket->ReadLongLE();
00511 WORD nPort = pPacket->ReadShortLE();
00512
00513 if ( Network.IsFirewalledAddress( &nAddress ) ) return TRUE;
00514
00515 EDClients.PushTo( nAddress, nPort );
00516
00517 return TRUE;
00518 }
00519
00520 BOOL CEDNeighbour::OnSearchResults(CEDPacket* pPacket)
00521 {
00522 if ( m_pQueries.GetCount() == 0 )
00523 {
00524 Statistics.Current.eDonkey.Dropped++;
00525 m_nDropCount++;
00526 return TRUE;
00527 }
00528
00529 GGUID* pGUID = (GGUID*)m_pQueries.RemoveHead();
00530 CQueryHit* pHits = CQueryHit::FromPacket( pPacket, &m_pHost, m_nTCPFlags, pGUID );
00531
00532 if ( pHits == NULL )
00533 {
00534 delete pGUID;
00535
00536 if ( pPacket->m_nLength != 17 && pPacket->m_nLength != 5 )
00537 {
00538 pPacket->Debug( _T("BadSearchResult") );
00539 theApp.Message( MSG_ERROR, IDS_PROTOCOL_BAD_HIT, (LPCTSTR)m_sAddress );
00540 Statistics.Current.eDonkey.Dropped++;
00541 m_nDropCount++;
00542 }
00543
00544 return TRUE;
00545 }
00546
00547
00548 if ( pPacket->m_nType == ED2K_S2C_SEARCHRESULTS && pPacket->GetRemaining() == 1 && m_pQueries.IsEmpty() )
00549 {
00550 if ( pPacket->ReadByte() == TRUE )
00551 {
00552 m_pMoreResultsGUID = pGUID;
00553 pGUID = NULL;
00554 theApp.Message( MSG_DEBUG, _T("Additional results packet received.") );
00555 }
00556 }
00557
00558 Network.OnQueryHits( pHits );
00559
00560 if ( pGUID != NULL ) delete pGUID;
00561
00562 return TRUE;
00563 }
00564
00565 BOOL CEDNeighbour::OnFoundSources(CEDPacket* pPacket)
00566 {
00567 CQueryHit* pHits = CQueryHit::FromPacket( pPacket, &m_pHost, m_nTCPFlags );
00568
00569 if ( pHits == NULL )
00570 {
00571
00572 if ( pPacket->m_nLength != 17 && pPacket->m_nLength != 5 )
00573 {
00574 pPacket->Debug( _T("BadSearchResult") );
00575 theApp.Message( MSG_ERROR, IDS_PROTOCOL_BAD_HIT, (LPCTSTR)m_sAddress );
00576 Statistics.Current.eDonkey.Dropped++;
00577 m_nDropCount++;
00578 }
00579
00580 return TRUE;
00581 }
00582
00583 Network.OnQueryHits( pHits );
00584
00585 return TRUE;
00586 }
00587
00589
00590
00591
00592
00593
00594
00595 void CEDNeighbour::SendSharedFiles()
00596 {
00597
00598 m_nFileLimit = max( Settings.eDonkey.MaxShareCount, ( (DWORD)25 ) );
00599
00600 CHostCacheHost *pServer = HostCache.eDonkey.Find( &m_pHost.sin_addr );
00601 if ( pServer && ( pServer->m_nFileLimit > 10 ) )
00602 {
00603 m_nFileLimit = min( m_nFileLimit, pServer->m_nFileLimit );
00604 }
00605
00606 CEDPacket* pPacket = CEDPacket::New( ED2K_C2S_OFFERFILES );
00607 POSITION pos;
00608
00609 m_nFilesSent = 0;
00610
00611 pPacket->WriteLongLE( m_nFilesSent );
00612
00613
00614 CSingleLock pTransfersLock( &Transfers.m_pSection );
00615 CSingleLock pLibraryLock( &Library.m_pSection );
00616
00617
00618 pTransfersLock.Lock();
00619 for ( pos = Downloads.GetIterator() ; pos != NULL && ( m_nFilesSent < m_nFileLimit ) ; )
00620 {
00621 CDownload* pDownload = Downloads.GetNext( pos );
00622
00623
00624 if ( ( pDownload->m_bED2K ) && ( pDownload->IsStarted() ) && ( pDownload->m_nSize != SIZE_UNKNOWN ) &&
00625 ( pDownload->NeedHashset() == FALSE ) && ( ! pDownload->IsMoving() ) )
00626 {
00627
00628 pPacket->Write( &pDownload->m_pED2K, sizeof(MD4) );
00629
00630
00631 if ( m_nTCPFlags & ED2K_SERVER_TCP_DEFLATE )
00632 {
00633
00634 pPacket->WriteLongLE( 0xFCFCFCFC );
00635 pPacket->WriteShortLE ( 0xFCFC );
00636 }
00637 else
00638 {
00639 if ( CEDPacket::IsLowID( m_nClientID ) )
00640 {
00641 pPacket->WriteLongLE( 0 );
00642 pPacket->WriteShortLE ( 0 );
00643 }
00644 else
00645 {
00646 pPacket->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00647 pPacket->WriteShortLE ( Network.m_pHost.sin_port );
00648 }
00649 }
00650
00651
00652 pPacket->WriteLongLE( 2 );
00653
00654
00655 CEDTag( ED2K_FT_FILENAME, pDownload->m_sRemoteName ).Write( pPacket, m_nTCPFlags );
00656
00657 CEDTag( ED2K_FT_FILESIZE, (DWORD)pDownload->m_nSize ).Write( pPacket, m_nTCPFlags );
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 m_nFilesSent++;
00668 }
00669 }
00670 pTransfersLock.Unlock();
00671
00672
00673 pLibraryLock.Lock();
00674 for ( pos = LibraryMaps.GetFileIterator() ; pos != NULL && ( m_nFilesSent < m_nFileLimit ) ; )
00675 {
00676 CLibraryFile* pFile = LibraryMaps.GetNextFile( pos );
00677
00678 if ( pFile->IsShared() && pFile->m_bED2K )
00679 {
00680 if ( ( Settings.eDonkey.MinServerFileSize == 0 ) || ( pFile->GetSize() > Settings.eDonkey.MinServerFileSize * 1024 * 1024 ) )
00681 {
00682 if ( UploadQueues.CanUpload( PROTOCOL_ED2K, pFile ) )
00683 {
00684
00685 DWORD nTags;
00686 CString strType(_T("")), strCodec(_T(""));
00687 DWORD nBitrate = 0, nLength = 0;
00688 BYTE nRating = 0;
00689
00690
00691 pPacket->Write( &pFile->m_pED2K, sizeof(MD4) );
00692
00693
00694 if ( m_nTCPFlags & ED2K_SERVER_TCP_DEFLATE )
00695 {
00696
00697 pPacket->WriteLongLE( 0xFBFBFBFB );
00698 pPacket->WriteShortLE ( 0xFBFB );
00699 }
00700 else
00701 {
00702 if ( CEDPacket::IsLowID( m_nClientID ) )
00703 {
00704 pPacket->WriteLongLE( 0 );
00705 pPacket->WriteShortLE ( 0 );
00706 }
00707 else
00708 {
00709 pPacket->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00710 pPacket->WriteShortLE ( Network.m_pHost.sin_port );
00711 }
00712 }
00713
00715
00716
00717 nTags = 2;
00718 if ( pFile->m_pSchema != NULL )
00719 {
00720
00721 if ( pFile->m_pSchema->m_sDonkeyType.GetLength() )
00722 {
00723 strType = pFile->m_pSchema->m_sDonkeyType;
00724 nTags ++;
00725 }
00726
00727
00728 if ( m_nTCPFlags & ED2K_SERVER_TCP_SMALLTAGS )
00729 {
00730 if ( pFile->IsSchemaURI( CSchema::uriAudio ) )
00731 {
00732
00733 if ( pFile->m_pMetadata->GetAttributeValue( _T("bitrate") ).GetLength() )
00734 {
00735 _stscanf( pFile->m_pMetadata->GetAttributeValue( _T("bitrate") ), _T("%i"), &nBitrate );
00736 if ( nBitrate ) nTags ++;
00737 }
00738
00739
00740 if ( pFile->m_pMetadata->GetAttributeValue( _T("seconds") ).GetLength() )
00741 {
00742 _stscanf( pFile->m_pMetadata->GetAttributeValue( _T("seconds") ), _T("%i"), &nLength );
00743 if ( nLength ) nTags ++;
00744 }
00745 }
00746
00747
00748 if ( pFile->IsSchemaURI( CSchema::uriVideo ) )
00749 {
00750
00751 if ( pFile->m_pMetadata->GetAttributeValue( _T("codec") ).GetLength() )
00752 {
00753 strCodec = pFile->m_pMetadata->GetAttributeValue( _T("codec") );
00754 if ( strCodec.GetLength() ) nTags ++;
00755 }
00756
00757
00758 if ( pFile->m_pMetadata->GetAttributeValue( _T("minutes") ).GetLength() )
00759 {
00760 double nMins;
00761
00762 _stscanf( pFile->m_pMetadata->GetAttributeValue( _T("minutes") ), _T("%.3lf"), &nMins );
00763 nLength = (DWORD)( nMins * (double)60 );
00764 if ( nLength ) nTags ++;
00765 }
00766 }
00767 }
00768 }
00769
00770
00771 if ( ( m_nTCPFlags & ED2K_SERVER_TCP_SMALLTAGS ) && ( pFile->m_nRating ) )
00772 {
00773 nRating = min ( pFile->m_nRating, 5 );
00774 nTags ++;
00775 }
00776
00778
00779
00780 pPacket->WriteLongLE( nTags );
00781
00782
00783 CEDTag( ED2K_FT_FILENAME, pFile->m_sName ).Write( pPacket, m_nTCPFlags );
00784
00785 CEDTag( ED2K_FT_FILESIZE, (DWORD)pFile->GetSize() ).Write( pPacket, m_nTCPFlags );
00786
00787 if ( strType.GetLength() ) CEDTag( ED2K_FT_FILETYPE, strType ).Write( pPacket, m_nTCPFlags );
00788
00789 if ( nBitrate ) CEDTag( ED2K_FT_BITRATE, nBitrate ).Write( pPacket, m_nTCPFlags );
00790
00791 if ( nLength ) CEDTag( ED2K_FT_LENGTH, nLength ).Write( pPacket, m_nTCPFlags );
00792
00793 if ( strCodec.GetLength() ) CEDTag( ED2K_FT_CODEC, strCodec ).Write( pPacket, m_nTCPFlags );
00794
00795 if ( nRating ) CEDTag( ED2K_FT_FILERATING, nRating ).Write( pPacket, m_nTCPFlags );
00796
00797
00798 m_nFilesSent++;
00799 }
00800 }
00801 }
00802 }
00803 pLibraryLock.Unlock();
00804
00805 *(DWORD*)pPacket->m_pBuffer = m_nFilesSent;
00806
00807 if ( m_nTCPFlags & ED2K_SERVER_TCP_DEFLATE ) pPacket->Deflate();
00808
00809 Send( pPacket );
00810 }
00811
00812
00813 BOOL CEDNeighbour::SendSharedDownload(CDownload* pDownload)
00814 {
00815
00816
00817 if ( m_nState < nrsConnected ) return FALSE;
00818 if ( ! pDownload->m_bED2K || pDownload->NeedHashset() ) return FALSE;
00819 if ( pDownload->m_nSize == SIZE_UNKNOWN ) return FALSE;
00820 if ( m_nFilesSent >= m_nFileLimit ) return FALSE;
00821
00822
00823 CEDPacket* pPacket = CEDPacket::New( ED2K_C2S_OFFERFILES );
00824 pPacket->WriteLongLE( 1 );
00825
00826
00827 pPacket->Write( &pDownload->m_pED2K, sizeof(MD4) );
00828
00829
00830 if ( m_nTCPFlags & ED2K_SERVER_TCP_DEFLATE )
00831 {
00832
00833 pPacket->WriteLongLE( 0xFCFCFCFC );
00834 pPacket->WriteShortLE ( 0xFCFC );
00835 }
00836 else
00837 {
00838 if ( CEDPacket::IsLowID( m_nClientID ) )
00839 {
00840 pPacket->WriteLongLE( 0 );
00841 pPacket->WriteShortLE ( 0 );
00842 }
00843 else
00844 {
00845 pPacket->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00846 pPacket->WriteShortLE ( Network.m_pHost.sin_port );
00847 }
00848 }
00849
00850
00851 pPacket->WriteLongLE( 2 );
00852
00853
00854 CEDTag( ED2K_FT_FILENAME, pDownload->m_sRemoteName ).Write( pPacket, m_nTCPFlags );
00855
00856 CEDTag( ED2K_FT_FILESIZE, (DWORD)pDownload->m_nSize ).Write( pPacket, m_nTCPFlags );
00857
00858
00859 if ( m_nTCPFlags & ED2K_SERVER_TCP_DEFLATE ) pPacket->Deflate();
00860 Send( pPacket );
00861
00862
00863 m_nFilesSent ++;
00864
00865 return TRUE;
00866 }
00867
00869
00870
00871 BOOL CEDNeighbour::SendQuery(CQuerySearch* pSearch, CPacket* pPacket, BOOL bLocal)
00872 {
00873 if ( m_nState != nrsConnected || m_nClientID == 0 )
00874 {
00875 return FALSE;
00876 }
00877 else if ( pPacket == NULL || pPacket->m_nProtocol != PROTOCOL_ED2K || ! bLocal )
00878 {
00879 return FALSE;
00880 }
00881
00882
00883 if ( ( ! pSearch->m_bED2K ) || ( pSearch->m_bWantDN && Settings.eDonkey.MagnetSearch ) )
00884 m_pQueries.AddTail( new GGUID( pSearch->m_pGUID ) );
00885
00886 Send( pPacket, FALSE, FALSE );
00887
00888 return TRUE;
00889 }