00001 // 00002 // G1Packet.h 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 // Make the compiler only include the lines here once, this is the same thing as pragma once 00026 #if !defined(AFX_G1PACKET_H__6B611C29_56C1_4E2A_AA72_249AB7BD76D0__INCLUDED_) 00027 #define AFX_G1PACKET_H__6B611C29_56C1_4E2A_AA72_249AB7BD76D0__INCLUDED_ 00028 00029 // Only include the lines beneath this one once 00030 #pragma once 00031 00032 // Copy in the contents of these files here before compiling 00033 #include "Packet.h" 00034 00035 // Instruct the compiler to align bytes and DWORDs in a structure on a 1 byte boundary 00036 #pragma pack(1) // This means, don't put any space between anything 00037 00038 // We can cast a pointer as a GNUTELLAPACKET structure to easily read the parts of the Gnutella packet header 00039 typedef struct 00040 { 00041 // These are the parts of a Gnutella packet header, in the right order, with each part the right size 00042 GGUID m_pGUID; // At 0, length 16, the globally unique identifier of this packet 00043 BYTE m_nType; // At 16, the byte that identifies what kind of packet this is, like ping or pong 00044 BYTE m_nTTL; // At 17, the number of hops this packet can travel across the Internet from here 00045 BYTE m_nHops; // At 18, the number of hops this packet has traveled across the Internet to get here 00046 LONG m_nLength; // At 19, length 4, for a total size 23 bytes, the length of the packet payload 00047 00048 } GNUTELLAPACKET; 00049 00050 // Each CG1Packet object represents a received or preparing to send Gnutella packet 00051 class CG1Packet : public CPacket // Inherit from CPacket to get memory management, and methods to read and write ASCII text, bytes, and DWORDs 00052 { 00053 00054 protected: 00055 00056 // Make a new CG1Packet object, and delete this one 00057 CG1Packet(); 00058 virtual ~CG1Packet(); // Why is this virtual, it's at the top of the inheritance tree (do) 00059 00060 public: 00061 00062 // Data in the packet 00063 GGUID m_pGUID; // The globally unique identifier of this packet 00064 BYTE m_nType; // The type of this packet, like ping or pong 00065 BYTE m_nTTL; // The number of hops this packet can travel across the Internet from here 00066 BYTE m_nHops; // The number of hops this packet has travelled across the Internet to get here 00067 00068 // Data about the packet 00069 int m_nTypeIndex; // Packet type like ping or pong, except as an enumeration this program defines instead of the byte code used by the packet itself 00070 DWORD m_nHash; // Used by CacheHash, but doesn't seem to ever get a hash written into it (do) 00071 00072 public: 00073 00074 // Change the packet's TTL and hop counts 00075 BOOL Hop(); // Make sure the TTL is 2 or more, and then make it one less and the hops count one more 00076 00077 // Hash the packet 00078 void CacheHash(); // Calculate a simple hash of the packet payload in m_nHash 00079 virtual BOOL GetRazaHash(SHA1* pHash, DWORD nLength = 0) const; // Compute the SHA hash of the packet GUID, type byte, and payload 00080 00081 // Get the packet's type, GUID, and all its bytes 00082 virtual LPCTSTR GetType() const; // Returns a pointer to a text literal like "Ping" or "Pong" 00083 CString GetGUID() const; // Returns the packet's GUID encoded into text in base 16 00084 virtual void ToBuffer(CBuffer* pBuffer) const; // Adds the Gnutella packet header and payload into the given CBuffer object 00085 00086 // Record information about the packet for debugging purposes 00087 virtual void Debug(LPCTSTR pszReason) const; // Writes debug information about the packet into the Shareaza.log file 00088 00089 public: 00090 00091 // Convert between the various ways the program expresses packet types, like ping and pong 00092 static int GnutellaTypeToIndex(BYTE nType); // Turn a type byte, like 0x30, into index 4, both describe a query route packet 00093 static LPCTSTR m_pszPackets[9]; // Turn a type index, like 4, into text like "QRP" for query route packet 00094 00095 protected: 00096 00097 // Create a nested class, CG1PacketPool, that holds arrays of Gnutella packets we can use quickly 00098 class CG1PacketPool : public CPacketPool // Inherit from CPacketPool to get methods to create arrays of packets and break them off for speedy use 00099 { 00100 00101 public: 00102 00103 // Delete this CG1PacketPool object 00104 virtual ~CG1PacketPool() { Clear(); } // Call the Clear method to free all the arrays of packets 00105 00106 protected: 00107 00108 // Create a new array of packets, and free one 00109 virtual void NewPoolImpl(int nSize, CPacket*& pPool, int& nPitch); // Allocate a new array of 256 packets 00110 virtual void FreePoolImpl(CPacket* pPool); // Free an array of 256 packets 00111 }; 00112 00113 // Separate from objects made from this CG1Packet class, allow a single CG1PacketPool called POOL to be made 00114 static CG1PacketPool POOL; 00115 00116 public: 00117 00118 // Get a new packet from the global packet pool called POOL, fill it with these values, and return a pointer to it 00119 static CG1Packet* New(int nType = 0, DWORD nTTL = 0, GGUID* pGUID = NULL); 00120 00121 // Takes a Gnutella packet header structure 00122 // Gets a new packet from the pool and fills it with values from the header structure 00123 // Returns a pointer to the prepared packet in the pool 00124 inline static CG1Packet* New(GNUTELLAPACKET* pSource) 00125 { 00126 // Get a blank packet from the pool 00127 CG1Packet* pPacket = (CG1Packet*)POOL.New(); 00128 00129 // Fill it with information from the given Gnutella packet header structure 00130 pPacket->m_pGUID = pSource->m_pGUID; 00131 pPacket->m_nType = pSource->m_nType; 00132 pPacket->m_nTTL = pSource->m_nTTL; 00133 pPacket->m_nHops = pSource->m_nHops; 00134 00135 // Also record the type as an index 00136 pPacket->m_nTypeIndex = GnutellaTypeToIndex( pPacket->m_nType ); 00137 00138 // Copy the bytes of the payload from beyond the gnutella packet structure into the buffer of the packet object 00139 pPacket->Write( // Have the packet write these bytes into its buffer for the packet payload 00140 &pSource[1], // The 1 moves forward 1 structure size, to the bytes beyond the structure 00141 (DWORD)pSource->m_nLength ); // The number of bytes there is the payload size according to the header structure 00142 00143 // Return a pointer to the packet, sitting in the pool, filled with the given header values and payload 00144 return pPacket; 00145 } 00146 00147 // Delete this packet 00148 inline virtual void Delete() 00149 { 00150 // Tell the pool to delete this packet 00151 POOL.Delete( this ); // All it will really do is link it back into the list of packets we can use later 00152 } 00153 00154 // Let the nested CG1PacketPool class access the private members of this CG1Packet class 00155 friend class CG1Packet::CG1PacketPool; 00156 }; 00157 00158 // Takes nSize, the number of CG1Packet objects we want 00159 // Sets nPitch to the size of each one, and points pPool at a new array of that many of them 00160 inline void CG1Packet::CG1PacketPool::NewPoolImpl(int nSize, CPacket*& pPool, int& nPitch) 00161 { 00162 // Set nPitch to the size in bytes of each CG1Packet object 00163 nPitch = sizeof(CG1Packet); 00164 00165 // Allocate a new array of nSize CG1Packet objects, and point pPool at it 00166 pPool = new CG1Packet[ nSize ]; 00167 } 00168 00169 // Takes a pointer to an array of packets, which is called a packet pool 00170 // Deletes the packet pool, freeing the memory of all the packets in it 00171 inline void CG1Packet::CG1PacketPool::FreePoolImpl(CPacket* pPacket) 00172 { 00173 // Delete the array of packets 00174 delete [] (CG1Packet*)pPacket; 00175 } 00176 00177 // Those are all the structures we need special alignment for 00178 #pragma pack() // Same as pragma pack(pop) 00179 00180 // Gnutella packet type codes, m_nType in the header will be one of these values to show the type 00181 #define G1_PACKET_PING 0x00 // Ping packet 00182 #define G1_PACKET_PONG 0x01 // Pong packet, response to a ping 00183 #define G1_PACKET_BYE 0x02 // Goodbye packet, the remote computer telling us why it's disconnecting 00184 #define G1_PACKET_QUERY_ROUTE 0x30 // Packet about query routing table (do) 00185 #define G1_PACKET_VENDOR 0x31 // Vendor-specific packets (do) 00186 #define G1_PACKET_VENDOR_APP 0x32 00187 #define G1_PACKET_PUSH 0x40 // Packet asking that we push open a connection to a remote computer that can't connect directly to us 00188 #define G1_PACKET_QUERY 0x80 // Search query 00189 #define G1_PACKET_HIT 0x81 // Response to search query, a hit 00190 00191 // Packet type indices, another enumeration for Gnutella packets, GnutellaTypeToIndex translates from the byte code to this number 00192 #define G1_PACKTYPE_UNKNOWN 0 00193 #define G1_PACKTYPE_PING 1 00194 #define G1_PACKTYPE_PONG 2 00195 #define G1_PACKTYPE_BYE 3 00196 #define G1_PACKTYPE_QUERY_ROUTE 4 00197 #define G1_PACKTYPE_VENDOR 5 00198 #define G1_PACKTYPE_PUSH 6 00199 #define G1_PACKTYPE_QUERY 7 00200 #define G1_PACKTYPE_HIT 8 00201 #define G1_PACKTYPE_MAX 9 // There are 9 packet type indices, with values 0 through 8 00202 00203 // MinSpeed Flags (do) 00204 #define G1_QF_TAG 0x8000 00205 #define G1_QF_FIREWALLED 0x4000 00206 #define G1_QF_XML 0x2000 00207 #define G1_QF_DYNAMIC 0x1000 00208 #define G1_QF_BIN_HASH 0x800 00209 #define G1_QF_OOB 0x400 00210 00211 // QHD Flags (do) 00212 #define G1_QHD_PUSH 0x01 00213 #define G1_QHD_BAD 0x02 00214 #define G1_QHD_BUSY 0x04 00215 #define G1_QHD_STABLE 0x08 00216 #define G1_QHD_SPEED 0x10 00217 #define G1_QHD_GGEP 0x20 00218 #define G1_QHD_MASK 0x3D 00219 00220 // The byte that tells that a GGEP block follows 00221 #define GGEP_MAGIC 0xC3 00222 00223 // End the group of lines to only include once, pragma once doesn't require an endif at the bottom 00224 #endif // !defined(AFX_G1PACKET_H__6B611C29_56C1_4E2A_AA72_249AB7BD76D0__INCLUDED_)