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

Neighbour.cpp

Go to the documentation of this file.
00001 //
00002 // Neighbour.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 // CNeighbour is in the middle of the CConnection inheritance tree, adding compression and a bunch of member variables
00023 // http://wiki.shareaza.com/static/Developers.Code.CNeighbour
00024 
00025 // Copy in the contents of these files here before compiling
00026 #include "StdAfx.h"
00027 #include "Shareaza.h"
00028 #include "Settings.h"
00029 #include "Network.h"
00030 #include "Neighbours.h"
00031 #include "Neighbour.h"
00032 #include "Security.h"
00033 #include "RouteCache.h"
00034 #include "Library.h"
00035 #include "Buffer.h"
00036 #include "Packet.h"
00037 #include "G1Packet.h"
00038 #include "G2Packet.h"
00039 #include "SearchManager.h"
00040 #include "QueryHashTable.h"
00041 #include "QueryHashGroup.h"
00042 #include "QueryHashMaster.h"
00043 #include "QueryHit.h"
00044 #include "GProfile.h"
00045 #include "Statistics.h"
00046 #include <zlib.h>
00047 
00048 // If we are compiling in debug mode, replace the text "THIS_FILE" in the code with the name of this file
00049 #ifdef _DEBUG
00050 #undef THIS_FILE
00051 static char THIS_FILE[]=__FILE__;
00052 #define new DEBUG_NEW
00053 #endif
00054 
00055 // Set Z_TIMER to 1/5th of a second
00056 #define Z_TIMER 200
00057 
00059 // CNeighbour construction
00060 
00061 // Make a new CNeighbour object for a certain network
00062 // Takes a protocol ID, like PROTOCOL_G1
00063 CNeighbour::CNeighbour(PROTOCOLID nProtocol)
00064 {
00065         // Copy the given network protocol into this new object
00066         m_nProtocol = nProtocol; // nProtocol is like PROTOCOL_ED2K
00067 
00068         // Set null and default values for connection state, software vendor, guid, and user profile
00069         m_nState   = nrsNull; // No state now, soon we'll connect and do the handshake
00070         m_pVendor  = NULL;    // We don't know what brand software the remote computer is running yet
00071         m_bGUID    = FALSE;   // There is no GUID stored here yet
00072         m_pProfile = NULL;    // No profile on the person running the remote computer yet
00073 
00074         // Set handshake values to defaults
00075         m_bAutomatic    = FALSE;  // Automatic setting used to maintain the connection
00076         m_bShareaza     = FALSE;  // Expect the remote computer to not be running Shareaza
00077         m_nNodeType     = ntNode; // Start out assuming that we and the remote computer are both hubs
00078         m_bQueryRouting = FALSE;  // Don't start query routing or pong caching yet
00079         m_bPongCaching  = FALSE;
00080         m_bVendorMsg    = FALSE;  // The remote computer hasn't told us it supports the vendor-specific messages yet
00081         m_bGGEP         = FALSE;  // The remote computer hasn't told us it supports the GGEP block yet
00082         m_bObsoleteClient= FALSE; //
00083         m_bBadClient    = FALSE;  //
00084 
00085         // Start out time variables as 0
00086         m_tLastQuery  = 0; // We'll set these to the current tick or seconds count when we get a query or packet
00087         m_tLastPacket = 0;
00088 
00089         // Zero packet and file counts
00090         m_nInputCount = m_nOutputCount = 0;
00091         m_nDropCount  = 0;
00092         m_nLostCount  = 0;
00093         m_nOutbound   = 0;
00094         m_nFileCount  = 0;
00095         m_nFileVolume = 0;
00096 
00097         // The local and remote query tables aren't set up yet, make the pointers to them start out null
00098         m_pQueryTableLocal  = NULL;
00099         m_pQueryTableRemote = NULL;
00100 
00101         // Null pointers and zero counts for zlib compression
00102         m_pZInput   = NULL;
00103         m_pZOutput  = NULL;
00104         m_nZInput   = 0;
00105         m_nZOutput  = 0;
00106         m_pZSInput  = NULL;
00107         m_pZSOutput = NULL;
00108         m_bZFlush   = FALSE;
00109         m_tZOutput  = 0;
00110 
00111         // This guid of the last search will be used to get more results, but we don't have one at the start
00112         m_pMoreResultsGUID = NULL;
00113 }
00114 
00115 // Make a new CNeighbour object, copying values from a base one
00116 // Takes a protocol ID and a base neighbour to copy information from
00117 CNeighbour::CNeighbour(PROTOCOLID nProtocol, CNeighbour* pBase)
00118 {
00119         // Calls CConection::AttachTo, treating CNeighbour* pBase as class* CConnection
00120         AttachTo( pBase );
00121 
00122         // Copy the values from pBase into this CNeighbour object
00123         CopyMemory( &m_zStart, &pBase->m_zStart, (LPBYTE)&m_zEnd - (LPBYTE)&m_zStart );
00124 
00125         // Set some custom values for the new CNeighbour object
00126         m_nState                = nrsConnected;         // Set the state of this neighbour to connected
00127         m_nProtocol             = nProtocol;            // Store the given protocol in the object
00128         m_tConnected    = GetTickCount();       // Set Connected and LastPacket with the current time
00129         m_tLastPacket   = m_tConnected;
00130 
00131         // If this connected computer is sending and receiving Gnutella2 packets, it will also support query routing
00132         if ( m_bQueryRouting )
00133         {
00134                 // Make two new QueryHashTable objects, one for the local table, and one for the remote one for
00135                 m_pQueryTableLocal      = new CQueryHashTable();
00136                 m_pQueryTableRemote     = new CQueryHashTable();
00137         }
00138 
00139         // Call CNeighboursBase::Add to keep track of this newly created CNeighbours object
00140         Neighbours.Add( this, FALSE );
00141 }
00142 
00143 // Delete this CNeighbour object
00144 CNeighbour::~CNeighbour()
00145 {
00146         // If m_pZSOutput isn't NULL, we are probably in the middle of a zlib compression operation
00147         if ( z_streamp pStream = (z_streamp)m_pZSOutput ) // This is correctly assignment, not comparison, in an if statement
00148         {
00149                 // End the compression and delete the pStream object
00150                 deflateEnd( pStream );
00151                 delete pStream;
00152         }
00153 
00154         // Same thing, except for decompressing input
00155         if ( z_streamp pStream = (z_streamp)m_pZSInput )
00156         {
00157                 // End the decompression and delete the pStream object
00158                 inflateEnd( pStream );
00159                 delete pStream;
00160         }
00161 
00162         // If any of these objects exist, delete them
00163         if ( m_pProfile )                       delete m_pProfile;
00164         if ( m_pZOutput )                       delete m_pZOutput;
00165         if ( m_pZInput )                        delete m_pZInput;
00166         if ( m_pQueryTableRemote )      delete m_pQueryTableRemote;
00167         if ( m_pQueryTableLocal )       delete m_pQueryTableLocal;
00168 }
00169 
00171 // CNeighbour close
00172 
00173 // Close the connection to the remote computer
00174 // Takes the reason we're closing the connection, IDS_CONNECTION_CLOSED by default
00175 void CNeighbour::Close(UINT nError)
00176 {
00177         // Make sure that the socket stored in this CNeighbour object is valid
00178         ASSERT( m_hSocket != INVALID_SOCKET );
00179 
00180         // If nError is the default closed or a result of peer pruning, we're closing the connection voluntarily
00181         BOOL bVoluntary = ( nError == IDS_CONNECTION_CLOSED || nError == IDS_CONNECTION_PEERPRUNE );
00182 
00183         // Remove this neighbour from the list of them
00184         Neighbours.Remove( this );
00185 
00186         // Actually close the socket connection to the remote computer
00187         CConnection::Close();
00188 
00189         // If this Close method was called with an error, among which IDS_CONNECTION_CLOSED counts
00190         if ( nError )
00191         {
00192                 // Report a voluntary default close, or an error
00193                 theApp.Message( bVoluntary ? MSG_DEFAULT : MSG_ERROR, nError, (LPCTSTR)m_sAddress );
00194         }
00195 
00196         // Delete this CNeighbour object, calling its destructor right now
00197         delete this;
00198 }
00199 
00200 // Close the connection, but not until we've written the buffered outgoing data first
00201 // Takes the reason we're closing the connection, or 0 by default
00202 void CNeighbour::DelayClose(UINT nError)
00203 {
00204         // If this method got passed a close reason error, report it
00205         if ( nError ) theApp.Message( MSG_ERROR, nError, (LPCTSTR)m_sAddress );
00206 
00207         // Change this object's state to closing
00208         m_nState = nrsClosing;
00209 
00210         // Have the connection object write all the outgoing data soon
00211         QueueRun();
00212 }
00213 
00215 // CNeighbour send
00216 
00217 // Send a packet to the remote computer (do)
00218 // Takes the packet, bRelease to release it, and bBuffered
00219 BOOL CNeighbour::Send(CPacket* pPacket, BOOL bRelease, BOOL bBuffered)
00220 {
00221         // If we should release the packet, call its release method (do)
00222         if ( bRelease ) pPacket->Release();
00223 
00224         // Always return false (do)
00225         return FALSE;
00226 }
00227 
00228 // CG1Neighbour, which inherits from CNeighbour, overrides this method with its own version that does something
00229 BOOL CNeighbour::SendQuery(CQuerySearch* pSearch, CPacket* pPacket, BOOL bLocal)
00230 {
00231         // Always return false (do)
00232         return FALSE;
00233 }
00234 
00236 // CNeighbour run event handler
00237 
00238 // Check the connection hasn't gone silent too long, and send a query patch table if necessary
00239 // Returns true if the connection is still open and there was no error sending the patch table
00240 BOOL CNeighbour::OnRun()
00241 {
00242         // Get the tick count right now
00243         DWORD tNow = GetTickCount();
00244 
00245         // If it's been awhile since the last packet came in through this connection
00246         if ( tNow - m_tLastPacket > Settings.Connection.TimeoutTraffic * 3 )
00247         {
00248                 // Close the connection, citing traffic timeout as the reason, and return false
00249                 Close( IDS_CONNECTION_TIMEOUT_TRAFFIC );
00250                 return FALSE;
00251         }
00252 
00253         // If this connection is to a hub above us, or to a Gnutella2 hub like us
00254         if ( m_nNodeType == ntHub || ( m_nNodeType == ntNode && m_nProtocol == PROTOCOL_G2 ) )
00255         {
00256                 // And if we have a local query table for this neighbour and its cookie isn't the master cookie (do)
00257                 if ( m_pQueryTableLocal != NULL && m_pQueryTableLocal->m_nCookie != QueryHashMaster.m_nCookie )
00258                 {
00259                         // And (do)
00260                         if ( tNow - QueryHashMaster.m_nCookie > 30000 ||                                                        // It's been more than 3 seconds since the master cookie (do)
00261                                  QueryHashMaster.m_nCookie - m_pQueryTableLocal->m_nCookie > 60000 ||   // Or, the master cookie is a minute older than the local one (do)
00262                                  m_pQueryTableLocal->m_bLive == FALSE )                                                                 // Or, the local query table is not live (do)
00263                         {
00264                                 // Then send the connected computer a query hash table patch
00265                                 if ( m_pQueryTableLocal->PatchTo( &QueryHashMaster, this ) )
00266                                 {
00267                                         // There was an error, record it
00268                                         theApp.Message( MSG_SYSTEM, IDS_PROTOCOL_QRP_SENT, (LPCTSTR)m_sAddress,
00269                                                 m_pQueryTableLocal->m_nBits, m_pQueryTableLocal->m_nHash,
00270                                                 m_pQueryTableLocal->m_nInfinity, m_pQueryTableLocal->GetPercent() );
00271                                 }
00272                         }
00273                 }
00274         }
00275 
00276         // Report success
00277         return TRUE;
00278 }
00279 
00281 // CNeighbour close event handler
00282 
00283 // Call when the connection has been dropped
00284 // Logs the error with some statistics about how long it was quiet
00285 void CNeighbour::OnDropped(BOOL bError)
00286 {
00287         // Find out how many seconds it's been since this neighbour connected, and since it received the last packet
00288         DWORD nTime1 = ( GetTickCount() - m_tConnected ) / 1000;        // Time since connected in seconds
00289         DWORD nTime2 = ( GetTickCount() - m_tLastPacket ) / 1000;       // Time since last packet received in seconds
00290 
00291         // Report these times in a message about the connection being dropped
00292         theApp.Message( MSG_DEBUG, _T("Dropped neighbour %s (%s), conn: %.2i:%.2i, packet: %.2i:%.2i"),
00293                 (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent,
00294                 nTime1 / 60, nTime1 % 60, nTime2 / 60, nTime2 % 60 );
00295 
00296         // Close the connection, citing the reason as dropped
00297         Close( IDS_CONNECTION_DROPPED );
00298 }
00299 
00301 // CNeighbour compressed read and write handlerss
00302 
00303 // Read data waiting in the socket into the input buffer, and decompress it into the zlib input buffer
00304 // Return false if error
00305 BOOL CNeighbour::OnRead()
00306 {
00307         // Read the bytes waiting in our end of the socket into the input buffer
00308         CConnection::OnRead();
00309 
00310         // If compression is off, we're done, return true now
00311         // Otherwise, compression is on, the bytes we read into the input buffer are compressed, and we have to decompress them
00312         if ( m_pZInput == NULL || m_pInput->m_nLength == 0 ) return TRUE;
00313 
00314         // Start or continue using zlib with m_pZSInput and pStream pointers
00315         BOOL bNew = ( m_pZSInput == NULL );                     // If the zlib input pointer is null, make bNew true, otherwise it's false
00316         if ( bNew ) m_pZSInput = new z_stream;          // If the zlib input pointer is null, make a new z_stream
00317         z_streamp pStream = (z_streamp)m_pZSInput;      // Cast the pointer as a z_streamp and call that pStream
00318 
00319         // If we are starting to use zlib now
00320         if ( bNew )
00321         {
00322                 // Zero the z_stream structure and set it up for decompression
00323                 ZeroMemory( pStream, sizeof(z_stream) );
00324                 if ( inflateInit( pStream ) != Z_OK )
00325                 {
00326                         // There was an error setting up zlib, clean up and leave now
00327                         delete pStream;
00328                         delete m_pZInput;
00329                         m_pZInput = NULL;
00330                         m_pZSInput = NULL;
00331                         return TRUE; // Report success anyway
00332                 }
00333         }
00334 
00335         // Loop until there is no more data for zlib to decompress
00336         while ( m_pInput->m_nLength ||                                                  // While the input buffer has data in it
00337                         m_pZInput->m_nLength == m_pZInput->m_nBuffer || // Or the zlib buffer length is the same as the buffer (do)
00338                         pStream->avail_out == 0 )                                               // Or there is no more data availiable for zlib to decompress
00339         {
00340                 // Make sure the zlib buffer holds at least 1 KB (do)
00341                 m_pZInput->EnsureBuffer( 1024 );
00342 
00343                 // Tell zlib where the compressed data is, how much is there, where it can output bytes, and how much space it has there
00344                 pStream->next_in        = m_pInput->m_pBuffer;                                                  // Point zlib at the start of the input buffer
00345                 pStream->avail_in       = m_pInput->m_nLength;                                                  // Give it the entire block there
00346                 pStream->next_out       = m_pZInput->m_pBuffer + m_pZInput->m_nLength;  // Have it put decompressed bytes in the empty space of the ZInput buffer
00347                 pStream->avail_out      = m_pZInput->m_nBuffer - m_pZInput->m_nLength;  // This is how much space is left there
00348 
00349                 // Call zlib inflate to decompress the contents of m_pInput into the end of m_pZInput
00350                 inflate( pStream, Z_SYNC_FLUSH ); // Zlib adjusts next in, avail in, next out, and avail out to record what it did
00351 
00352                 // Zlib decompressed something
00353                 if ( pStream->avail_in >= 0 && pStream->avail_in < m_pInput->m_nLength ) // We set avail_in to nLength, but zlib shrunk it smaller
00354                 {
00355                         // Remove the portion in the start of the input buffer that zlib decompressed
00356                         m_pInput->Remove( m_pInput->m_nLength - pStream->avail_in ); // nLength - avail_in is the size of the block that zlib decompressed
00357                 }
00358 
00359                 // Calculate the size of nBlock, the block of data in ZInput that Zlib just decompressed
00360                 DWORD nBlock = ( m_pZInput->m_nBuffer - m_pZInput->m_nLength ) - pStream->avail_out; // Buffer size minus previous length and current empty space
00361 
00362                 // Record tha this many more bytes are stored in the ZInput buffer
00363                 m_pZInput->m_nLength += nBlock;
00364 
00365                 // Add this number of bytes to the zlib count
00366                 m_nZInput += nBlock;
00367 
00368                 // If Zlib didn't decompress anything, leave the loop
00369                 if ( ! nBlock ) break;
00370         }
00371 
00372         // Report success
00373         return TRUE;
00374 }
00375 
00376 // Compress data and send it to the connected computer
00377 // Return false if error
00378 BOOL CNeighbour::OnWrite()
00379 {
00380         // If we're not sending compressed data to the remote computer, just call CConnection::OnWrite to send the output buffer
00381         if ( m_pZOutput == NULL ) return CConnection::OnWrite(); // Return the result and leave now
00382 
00383         // Start or continue using zlib with m_pZSInput and pStream pointers
00384         BOOL bNew = ( m_pZSOutput == NULL );            // Make bNew true if zlib compression isn't setup yet
00385         if ( bNew ) m_pZSOutput = new z_stream;         // Create a new z_stream structure and point m_pZSOutput and pStream at it
00386         z_streamp pStream = (z_streamp)m_pZSOutput;
00387         
00388         // If we are starting to use zlib now
00389         if ( bNew )
00390         {
00391                 // Zero the z_stream structure and set it up for compression
00392                 ZeroMemory( pStream, sizeof(z_stream) );
00393                 if ( deflateInit( pStream, 6 ) != Z_OK )
00394                 {
00395                         // There was an error setting up zlib, clean up and leave now
00396                         delete pStream;
00397                         delete m_pZOutput;
00398                         m_pZOutput = NULL;
00399                         m_pZSOutput = NULL;
00400                         return TRUE; // Report success anyway
00401                 }
00402         }
00403 
00404         // If there is data in the output buffer already
00405         if ( m_pOutput->m_nLength ) 
00406         {
00407                 // Send it to the other computer
00408                 CConnection::OnWrite();
00409                 if ( m_pOutput->m_nLength ) return TRUE; // Return true if there is still more to send after this (do)
00410         }
00411 
00412         // If it's been more than 2 seconds since we've flushed the compressed output buffer to the remote computer, set the flag to do it next
00413         DWORD tNow = GetTickCount();
00414         if ( tNow - m_tZOutput >= Z_TIMER ) m_bZFlush = TRUE;
00415 
00416         // Loop until all the data in ZOutput has been compressed into Output
00417         while ( ( m_pZOutput->m_nLength && ! m_pOutput->m_nLength )     // ZOutput has data to compress and Output is empty
00418                 || pStream->avail_out == 0 )                                                    // Or, zlib says it has no more room left (do)
00419         {
00420                 // Make sure the output buffer is 1 KB (do)
00421                 m_pOutput->EnsureBuffer( 1024 );
00422 
00423                 // Tell zlib where the data to compress is, and where it should put the compressed data
00424                 pStream->next_in        = m_pZOutput->m_pBuffer; // Start next_in and avail_in on the data in ZOutput
00425                 pStream->avail_in       = m_pZOutput->m_nLength;
00426                 pStream->next_out       = m_pOutput->m_pBuffer + m_pOutput->m_nLength; // Start next_out and avail_out on the empty space in Output
00427                 pStream->avail_out      = m_pOutput->m_nBuffer - m_pOutput->m_nLength;
00428 
00429                 // Call zlib inflate to decompress the contents of m_pInput into the end of m_pZInput
00430                 deflate( pStream, m_bZFlush ? Z_SYNC_FLUSH : 0 ); // Zlib adjusts next in, avail in, next out, and avail out to record what it did
00431 
00432                 // Add the number of uncompressed bytes that zlib compressed to the m_nZOutput count
00433                 m_nZOutput += m_pZOutput->m_nLength - pStream->avail_in;
00434 
00435                 // Remove the chunk that zlib compressed from the start of ZOutput
00436                 m_pZOutput->Remove( m_pZOutput->m_nLength - pStream->avail_in );
00437 
00438                 // Set nOutput to the size of the new compressed block in the output buffer between the data already there, and the empty space afterwards
00439                 int nOutput = ( m_pOutput->m_nBuffer - m_pOutput->m_nLength ) - pStream->avail_out;
00440 
00441                 // Zlib compressed something
00442                 if ( nOutput )
00443                 {
00444                         // Add the new block to the length, and record when this happened
00445                         m_pOutput->m_nLength += nOutput;
00446                         m_tZOutput = tNow;
00447 
00448                 // Zlib didn't compress anything, and the flush flag is true
00449                 }
00450                 else if ( m_bZFlush )
00451                 {
00452                         // Make the flush flag false
00453                         m_bZFlush = FALSE;
00454                 }
00455 
00456                 // Send the contents of the output buffer to the remote computer
00457                 CConnection::OnWrite();
00458         }
00459 
00460         // Report success
00461         return TRUE;
00462 }
00463 
00465 // CNeighbour common hit routing code
00466 
00467 BOOL CNeighbour::OnCommonHit(CPacket* pPacket)
00468 {
00469         CQueryHit* pHits = NULL;
00470         int nHops = 0;
00471 
00472         if ( pPacket->m_nProtocol == PROTOCOL_G1 )
00473         {
00474                 pHits = CQueryHit::FromPacket( (CG1Packet*)pPacket, &nHops );
00475         }
00476         else if ( pPacket->m_nProtocol == PROTOCOL_G2 )
00477         {
00478                 pHits = CQueryHit::FromPacket( (CG2Packet*)pPacket, &nHops );
00479         }
00480         else
00481         {
00482                 ASSERT( FALSE );
00483         }
00484         
00485         if ( pHits == NULL )
00486         {
00487                 pPacket->Debug( _T("BadHit") );
00488                 theApp.Message( MSG_ERROR, IDS_PROTOCOL_BAD_HIT, (LPCTSTR)m_sAddress );
00489                 m_nDropCount++;
00490                 if ( m_nProtocol == PROTOCOL_G1 )
00491                         Statistics.Current.Gnutella1.Dropped++;
00492                 else if ( m_nProtocol == PROTOCOL_G2 )
00493                         Statistics.Current.Gnutella2.Dropped++;
00494                 return TRUE;
00495         }
00496         
00497         if ( Security.IsDenied( &pHits->m_pAddress ) || nHops > (int)Settings.Gnutella1.MaximumTTL )
00498         {
00499                 pHits->Delete();
00500                 m_nDropCount++;
00501                 if ( m_nProtocol == PROTOCOL_G1 )
00502                         Statistics.Current.Gnutella1.Dropped++;
00503                 else if ( m_nProtocol == PROTOCOL_G2 )
00504                         Statistics.Current.Gnutella2.Dropped++;
00505                 return TRUE;
00506         }
00507         
00508         Network.NodeRoute->Add( &pHits->m_pClientID, this );
00509         
00510         if ( SearchManager.OnQueryHits( pHits ) )
00511         {
00512                 Network.RouteHits( pHits, pPacket );
00513         }
00514         
00515         Network.OnQueryHits( pHits );
00516         
00517         return TRUE;
00518 }
00519 
00521 // CNeighbour common query hash table
00522 
00523 BOOL CNeighbour::OnCommonQueryHash(CPacket* pPacket)
00524 {
00525         if ( m_pQueryTableRemote == NULL )
00526         {
00527                 m_pQueryTableRemote = new CQueryHashTable();
00528                 theApp.Message( MSG_DEFAULT, IDS_PROTOCOL_QRP_UNEXPECTED, (LPCTSTR)m_sAddress );
00529         }
00530         
00531         BOOL bLive = m_pQueryTableRemote->m_bLive;
00532         
00533         if ( ! m_pQueryTableRemote->OnPacket( pPacket ) )
00534         {
00535                 theApp.Message( MSG_ERROR, IDS_PROTOCOL_QRP_FAILED, (LPCTSTR)m_sAddress );
00536                 return FALSE;
00537         }
00538         
00539         if ( m_pQueryTableRemote->m_bLive && ! bLive )
00540         {
00541                 theApp.Message( MSG_DEFAULT, IDS_PROTOCOL_QRP_UPDATED, (LPCTSTR)m_sAddress,
00542                         m_pQueryTableRemote->m_nBits, m_pQueryTableRemote->m_nHash,
00543                         m_pQueryTableRemote->m_nInfinity, m_pQueryTableRemote->GetPercent() );
00544         }
00545         
00546         if ( m_nNodeType == ntLeaf && m_pQueryTableRemote->m_pGroup == NULL )
00547         {
00548                 QueryHashMaster.Add( m_pQueryTableRemote );
00549         }
00550         
00551         return TRUE;
00552 }
00553 
00555 // CNeighbour compression statistics
00556 
00557 // Calculate the average compression rate in either direction for this connection
00558 // Takes pointers to numbers to write the answers in
00559 void CNeighbour::GetCompression(float* pnInRate, float* pnOutRate)
00560 {
00561         // Set the compression ratios to -1 to indicate that compression is off
00562         *pnInRate = -1; *pnOutRate = -1;
00563 
00564         // If there is a buffer for decompressing read data and a count of bytes have been decompressed
00565         if ( m_pZInput != NULL && m_nZInput > 0.)
00566         {
00567                 // Calculate the compression rate of the data coming in
00568                 *pnInRate = 1.0f                                // 1 minus, so if there were 80 compressed bytes that inflated to 100, its 1 - (80 / 100) = .2
00569                         - (float)m_mInput.nTotal        // The total number of compressed bytes the bandwidth meter has counted come in from the socket
00570                         / (float)m_nZInput;                     // Divided by the total number of not compressed bytes that OnRead has decompressed into the m_nZInput buffer
00571 
00572                 // Keep the rate between 0 and 1
00573                 if ( *pnInRate < 0 ) *pnInRate = 0;
00574                 else if ( *pnInRate > 1 ) *pnInRate = 1;
00575         }
00576 
00577         // If there is a buffer for compressing data to write and a count of bytes have been compressed
00578         if ( m_pZOutput != NULL && m_mOutput.nTotal > 0.)
00579         {
00580                 // Calculate the compressing rate of the data going out
00581                 *pnOutRate = 1.0f                               // 1 minus, so if there were 100 bytes that deflated down to 70, its 1 - (70 / 100) = .3
00582                         - (float)m_mOutput.nTotal       // The total number of compressed bytes the bandwidth meter has counted go out through the socket
00583                         / (float)m_nZOutput;            // Divided by the total number of not compressed bytes that OnWrite has compressed from the m_nZOutput buffer
00584 
00585                 // Keep the rate between 0 and 1
00586                 if ( *pnOutRate < 0 ) *pnOutRate = 0;
00587                 else if ( *pnOutRate > 1 ) *pnOutRate = 1;
00588         }
00589 }

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