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

G1Packet.cpp

Go to the documentation of this file.
00001 //
00002 // G1Packet.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 // CG1Packet represents a Gnutella packet, and CG1PacketPool keeps lists of them
00023 // http://wiki.shareaza.com/static/Developers.Code.CG1Packet
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 "G1Packet.h"
00030 #include "Network.h"
00031 #include "Buffer.h"
00032 #include "SHA.h"
00033 
00034 // If we are compiling in debug mode, replace the text "THIS_FILE" in the code with the name of this file
00035 #ifdef _DEBUG
00036 #undef THIS_FILE
00037 static char THIS_FILE[]=__FILE__;
00038 #define new DEBUG_NEW
00039 #endif
00040 
00041 // When the program runs, create a single, global CG1PacketPool called POOL to hold a bunch of Gnutella packets
00042 CG1Packet::CG1PacketPool CG1Packet::POOL;
00043 
00045 // CG1Packet construction
00046 
00047 // Make a new CG1Packet object
00048 CG1Packet::CG1Packet() : CPacket( PROTOCOL_G1 ) // Before running the code here, call the CPacket constructor, giving it Gnutella as the protocol
00049 {
00050         // Start out with the type and type index 0, later they will be set to ping or pong
00051         m_nType      = 0;
00052         m_nTypeIndex = 0;
00053 
00054         // Set the time to live and hops counts to 0
00055         m_nTTL = m_nHops = 0;
00056 
00057         // No hash yet
00058         m_nHash = 0;
00059 }
00060 
00061 // Delete this CG1Packet object
00062 CG1Packet::~CG1Packet()
00063 {
00064         // The CPacket destructor will take care of freeing memory, so there is nothing to do here (do)
00065 }
00066 
00068 // CG1Packet new
00069 
00070 // Takes a packet type like ping, a TTL number, and a GUID for the packet
00071 // Makes a new packet with these values
00072 // Returns a pointer to it
00073 CG1Packet* CG1Packet::New(int nType, DWORD nTTL, GGUID* pGUID)
00074 {
00075         // Get a pointer to a packet in the single global Gnutella packet pool
00076         CG1Packet* pPacket = (CG1Packet*)POOL.New(); // Calls CPacketPool::New, defined in Packet.h
00077 
00078         // Copy the given type and corresponding type index into it
00079         pPacket->m_nType      = (BYTE)nType;
00080         pPacket->m_nTypeIndex = GnutellaTypeToIndex( pPacket->m_nType );
00081 
00082         // Set the TTL and hops counts
00083         pPacket->m_nTTL  = (BYTE)( nTTL > 0 ? nTTL : Settings.Gnutella1.DefaultTTL ); // If the given TTL is 0, use the default instead
00084         pPacket->m_nHops = 0; // This packet hasn't travelled across the Internet at all yet
00085 
00086         // No hash yet
00087         pPacket->m_nHash = 0;
00088 
00089         // If the caller has given us a GUID to use in the packet
00090         if ( pGUID )
00091         {
00092                 // Copy the GUID into the packet
00093                 pPacket->m_pGUID = *pGUID;
00094 
00095         } // If the caller didn't give us a GUID to use
00096         else
00097         {
00098                 // Create a GUID for this packet
00099                 Network.CreateID( pPacket->m_pGUID );
00100         }
00101 
00102         // Return a pointer to the packet
00103         return pPacket;
00104 }
00105 
00107 // CG1Packet type conversion
00108 
00109 // Takes the byte in a Gnutella packet that describes what type it is, like ping or pong
00110 // Returns the corresponding enumerantion index number, like 0, 1, 2, the program uses to mean the same thing
00111 int CG1Packet::GnutellaTypeToIndex(BYTE nType)
00112 {
00113         // Sort by the type byte, and return the corresponding index number which means the same thing
00114         switch ( nType )
00115         {
00116         case G1_PACKET_PING:        return G1_PACKTYPE_PING;        // Byte 0x00 is index 1, ping
00117         case G1_PACKET_PONG:        return G1_PACKTYPE_PONG;        // Byte 0x01 is index 2, pong
00118         case G1_PACKET_BYE:         return G1_PACKTYPE_BYE;         // Byte 0x02 is index 3, bye
00119         case G1_PACKET_QUERY_ROUTE: return G1_PACKTYPE_QUERY_ROUTE; // Byte 0x30 is index 4, query route
00120         case G1_PACKET_VENDOR:                                      // Bytes 0x31 and 0x32 are index 5, vendor
00121         case G1_PACKET_VENDOR_APP:  return G1_PACKTYPE_VENDOR;
00122         case G1_PACKET_PUSH:        return G1_PACKTYPE_PUSH;        // Byte 0x40 is index 6, push
00123         case G1_PACKET_QUERY:       return G1_PACKTYPE_QUERY;       // Byte 0x80 is index 7, query
00124         case G1_PACKET_HIT:         return G1_PACKTYPE_HIT;         // Byte 0x81 is index 8, hit
00125         default:                    return G1_PACKTYPE_UNKNOWN;     // All other bytes are index 0, unknown
00126         }
00127 }
00128 
00130 // CG1Packet hopping
00131 
00132 // Adjusts the TTL and hops counts of this packet to record a trip across the Internet
00133 // If the packet's TTL starts out less than 2, returns false without changing the numbers (do)
00134 BOOL CG1Packet::Hop()
00135 {
00136         // Make sure the packet's TTL is 2 or more
00137         if ( m_nTTL < 2 ) return FALSE;
00138 
00139         // Record a trip across the Internet
00140         m_nTTL--;  // One less trip to live
00141         m_nHops++; // One more hop made
00142 
00143         // Report that we checked and changed the numbers
00144         return TRUE;
00145 }
00146 
00148 // CG1Packet hashing
00149 
00150 // Calculate a simple hash of the bytes of the packet, and store it in the member DWORD m_nHash
00151 void CG1Packet::CacheHash()
00152 {
00153         // Point pInput at the packet's buffer, where the bytes of the packet are stored
00154         BYTE* pInput = m_pBuffer;
00155 
00156         // Start out with the packet's hash set to 0
00157         m_nHash = 0;
00158 
00159         // Loop once for every byte in the packet
00160         for ( DWORD nPosition = m_nLength ; nPosition ; nPosition-- ) // If there are 10 bytes in the packet, loops 10 times, the loop doesn't use this index
00161         {
00162                 // Use the byte under pInput to adjust a simple 4 byte hash of the packet
00163                 m_nHash = ( m_nHash << 8 ) | ( ( m_nHash >> 24 ) ^ *pInput++ ); // After reading the byte under pInput, move to the next one
00164         }
00165 
00166         // If the last bit in the hash is 0, make it a 1
00167         m_nHash |= 1;
00168 }
00169 
00170 // Takes the number of bytes in the packet to hash, or leave that blank to hash all of them
00171 // Computes the SHA hash of the packet
00172 // Returns true and writes the hash under pHash, or returns false on error
00173 BOOL CG1Packet::GetRazaHash(SHA1* pHash, DWORD nLength) const
00174 {
00175         // If the caller didn't specify a length, use the length of the packet
00176         if ( nLength == 0xFFFFFFFF ) nLength = m_nLength;
00177         if ( (DWORD)m_nLength < nLength ) return FALSE; // Make sure the caller didn't ask for more than that
00178 
00179         // Hash the data, writing the hash under pHash, and report success
00180         CSHA pSHA;                             // Make a local CSHA object which will compute the hash
00181         pSHA.Add( &m_pGUID, sizeof(m_pGUID) ); // Start by hashing the GUID of the packet
00182         pSHA.Add( &m_nType, sizeof(m_nType) ); // Then throw in the type byte
00183         pSHA.Add( m_pBuffer, nLength );        // After that, hash the bytes of the packet
00184         pSHA.Finish();                         // Tell the object that is all
00185         pSHA.GetHash( pHash );                 // Have the object write the hash under pHash
00186         return TRUE;                           // Report success
00187 }
00188 
00190 // CG1Packet string conversion
00191 
00192 // Use this array to lookup a packet index and get title text, like CG1Packet::m_pszPackets[ 1 ] resolves to "Ping"
00193 LPCTSTR CG1Packet::m_pszPackets[ G1_PACKTYPE_MAX ] = // There are 9 packet types, with values 0 through 8
00194 {
00195         // 0 is unknown, 1 Ping, 2 Pong, and so on
00196         _T("Unknown"), _T("Ping"), _T("Pong"), _T("Bye"), _T("QRP"), _T("Vendor"), _T("Push"), _T("Query"), _T("Hit")
00197 };
00198 
00199 // Uses the packet type index in this packet to look up text that describes that type
00200 // Returns text like "Ping" or "Pong"
00201 LPCTSTR CG1Packet::GetType() const
00202 {
00203         // Return the pointer to the text literal defined above this method
00204         return m_pszPackets[ m_nTypeIndex ];
00205 }
00206 
00207 // Describes the GUID of this packet as text using base 16 notation
00208 // Returns a string
00209 CString CG1Packet::GetGUID() const
00210 {
00211         // Compose a string like "0001020304050607080910111213141516" with two characters to describe each of the 16 bytes of the GUID
00212         CString strOut;
00213         strOut.Format( _T("%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X"),
00214                 m_pGUID.n[0],  m_pGUID.n[1],  m_pGUID.n[2],  m_pGUID.n[3],
00215                 m_pGUID.n[4],  m_pGUID.n[5],  m_pGUID.n[6],  m_pGUID.n[7],
00216                 m_pGUID.n[8],  m_pGUID.n[9],  m_pGUID.n[10], m_pGUID.n[11],
00217                 m_pGUID.n[12], m_pGUID.n[13], m_pGUID.n[14], m_pGUID.n[15] );
00218 
00219         // Return it
00220         return strOut;
00221 }
00222 
00224 // CG1Packet buffer output
00225 
00226 // Takes a pointer to a buffer
00227 // Writes this Gnutella packet into it, composing a Gnutella packet header and then adding the payload from the packet's buffer
00228 void CG1Packet::ToBuffer(CBuffer* pBuffer) const
00229 {
00230         // Compose a Gnutella packet header with values from this CG1Packet object
00231         GNUTELLAPACKET pHeader;              // Make a local GNUTELLAPACKET structure called pHeader
00232         pHeader.m_pGUID   = m_pGUID;         // Copy in the GUID
00233         pHeader.m_nType   = m_nType;         // Copy in the type byte
00234         pHeader.m_nTTL    = m_nTTL;          // Copy in the TTL and hops counts
00235         pHeader.m_nHops   = m_nHops;
00236         pHeader.m_nLength = (LONG)m_nLength; // Copy in the payload length number of bytes
00237 
00238         // Add the Gnutella packet header and packet payload to the buffer
00239         pBuffer->Add( &pHeader, sizeof(pHeader) ); // First, copy the bytes of the Gnutella packet header structure we made right here
00240         pBuffer->Add( m_pBuffer, m_nLength );      // This packet object's buffer is the payload, copy that in after the header
00241 }
00242 
00244 // CG1Packet debug
00245 
00246 // Takes text that describes something that happened when debugging the program
00247 // Writes it into a line at the bottom of the file Shareaza.log
00248 void CG1Packet::Debug(LPCTSTR pszReason) const
00249 {
00250 
00251 // Only include these lines in the program if it is being compiled in debug mode
00252 #ifdef _DEBUG
00253 
00254         // Local objects
00255         CString strOutput; // We'll compose text that describes what happened here
00256         strOutput.Format( L"[G1]: '%s' %s [%i/%i] %s", pszReason, GetType(), m_nTTL, m_nHops, (LPCTSTR)ToASCII() );
00257         CPacket::Debug( strOutput );
00258 
00259 // Go back to including all the lines in the program
00260 #endif
00261 
00262 }

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