//
// Packet.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2005.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// CPacket represents a packet on a peer-to-peer network, and CPacketPool keeps lists of them
// http://wiki.shareaza.com/static/Developers.Code.CPacket
// Copy in the contents of these files here before compiling
#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "Network.h"
#include "Packet.h"
#include "ZLib.h"
#include "SHA.h"
#include "Buffer.h"
#include "WndMain.h"
#include "WndPacket.h"
// If we are compiling in debug mode, replace the text "THIS_FILE" in the code with the name of this file
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// Buffers that hold 128 ASCII and 128 wide characters, used so MultiByteToWideChar can convert short text quickly
CHAR CPacket::m_szSCHAR[PACKET_BUF_SCHAR + 1]; // 静态变量声明
WCHAR CPacket::m_szWCHAR[PACKET_BUF_WCHAR + 1];
//
// CPacket construction
// Takes a protocol id, like PROTOCOL_G1 for Gnutella
// Makes a new CPacket object to represent a packet
CPacket::CPacket(PROTOCOLID nProtocol)
{
// Save the given protocol id in the object
m_nProtocol = nProtocol;
// This packet isn't in a list yet, and isn't being used at all yet
m_pNext = NULL; // No packet next in a list
m_nReference = 0; // No one needs this packet yet, the reference count starts at 0
// Start out memory pointers and lengths at null and 0
m_pBuffer = NULL; // This is just a pointer to allocated bytes, not a CBuffer object that would take care of itself
m_nBuffer = 0;
m_nLength = 0;
m_nPosition = 0;
// Assume the bytes of the packet are in big endian order
m_bBigEndian = TRUE;//默认packet是bigendian的
}
// Delete this CPacket object
//删除m_pBuffer所占用的空间,m_nReference必须为0才可以删除
CPacket::~CPacket()
{
// Make sure the reference count is zero
ASSERT( m_nReference == 0 ); // If it's not, then this packet is being deleted when something still needs it
// If the packet points to some memory, delete it
if ( m_pBuffer ) //byte *
{
delete [] m_pBuffer;
}
}
//
// CPacket reset
// Clear and reset the values of this packet object to use it again, just like it came from the constructor
//注意这里没有释放buffer占用的内存,只是把各个长度变量清0了
void CPacket::Reset()
{
// Make sure Reset is only called when nothing is referencing this packet object
ASSERT( m_nReference == 0 );//m_nReference 为0才可以reset
// Reset the member variables to null and 0 defaults
m_pNext = NULL;
m_nLength = 0;
m_nPosition = 0;
m_bBigEndian = TRUE;
}
//
// CPacket position and seeking
// Takes a distance in bytes into the packet, and seekStart if that's forwards from the front, seekEnd if that's backwards from the end
// Moves the position this packet object remembers to that distance from the start or end
//设置m_nPosition为nPosition,如果nPosition位置有数据的话,nRelative指定了是从开始向后数nPosition个位置
//还是从末尾向前数nPosition个位置
void CPacket::Seek(DWORD nPosition, int nRelative)
{
// Set the position forwards from the start
if ( nRelative == seekStart ) //确保m_nPosition在有数据的区域
{
// Move the position in the object to the given position, making sure it's in the data
m_nPosition = max( DWORD(0), min( m_nLength, nPosition ) );
} // Set the position backwards from the end
else
{
// Move the position in the object to m_nLength - nPosition from the start, which is nPosition from the end
m_nPosition = max( DWORD(0), min( m_nLength, m_nLength - nPosition ) );
}
}
// Takes a number of bytes
// Shortens the packet to that length
//如果nLength比m_nLength小,则设置m_nLength为参数nLength,同样修改m_nPositon的值
void CPacket::Shorten(DWORD nLength)
{
// If the given length is within the data of the packet, shorten the packet and our position in it
m_nLength = min( m_nLength, nLength ); // Record that there are only nLength bytes of packet data written in the buffer
m_nPosition = min( m_nPosition, m_nLength ); // Make sure this doesn't move our position beyond the bytes of the packet
}
//
// CPacket strings
// Takes the number of bytes to look at from our position in the packet as ASCII text
// Reads those up to the next null terminator as text
// Returns a string
//从m_pBuffer + m_nPosition位置读取数据,转化为utf8编码,返回结果CString
CString CPacket::ReadString(DWORD nMaximum)
{
// We'll convert the ASCII text in the packet into wide characters, and return them in this string
CString strString;
// If maximum would have us read beyond the end of the packet, make it smaller to read to the end of the packet
//nMaximum最大只能是m_nLength - m_nPosition,也就是剩余的空间那么多
nMaximum = min( nMaximum, m_nLength - m_nPosition );
if ( ! nMaximum )
{
return strString; // If that would have us read nothing, return the new blank string
}
// Setup pointers to look at bytes in the packet
LPCSTR pszInput = (LPCSTR)m_pBuffer + m_nPosition; // Point pszInput at our position inside the buffer
LPCSTR pszScan = pszInput; // Start out pszScan at the same spot, it will find the next null terminator
// Loop for each byte in the packet at and beyond our position in it, searching for a null terminator
DWORD nLength = 0; // When this loop is done, nLength will be the number of ASCII bytes we moved over before finding the null terminator
//计算出pszScan中的ascii字节的数目,下面要用到
for ( ; nLength < nMaximum ; nLength++ )
{
// Move the position pointer in this CPacket object to the next byte
m_nPosition++;
// If pszScan points to a 0 byte, exit the loop, otherwise move the pointer forward and keep going
if ( ! *pszScan++ )
{
break;
}
}
// Find out how many wide characters the ASCII bytes will become when converted
//算出需要多大的空间来存放pszInput的数据
int nWide = MultiByteToWideChar(
CP_ACP, // Use the code page for ASCII
0, // No character type options
pszInput, // Pointer to ASCII text in the packet
nLength, // Number of bytes to read there, the number of bytes before we found the null terminator
NULL, // No output buffer, we just want to know how many wide characters one would need to hold
0 );
// Convert the ASCII bytes into wide characters
//转化为utf8编码,保存到strString中
MultiByteToWideChar(
CP_ACP, // Use the UTF8 code page
0, // No character type options
pszInput, // Pointer to ASCII text
nLength, // Number of bytes to read there, the number of bytes before we found the null terminator
strString.GetBuffer( nWide ), // Get access to the string's buffer, telling it we will write in nWide wide characters
nWide ); // Tell MultiByteToWideChar it can write nWide characters in the buffer
// Close the string and return it
strString.ReleaseBuffer( nWide );
return strString;
}
// Takes text, and true to also write a null terminator
// Converts the text into ASCII bytes using the ASCII code page, and writes them into the end of the packet
//使用ASCII码表将参数pszString转化为multibytes,也就是ascii字符
void CPacket::WriteString(LPCTSTR pszString, BOOL bNull)
{
// Find out how many ASCII bytes the wide characters will become when converted
//计算出转化为multibytes后所需空间
int nByte = WideCharToMultiByte(
CP_ACP, // Use the ASCII code page
0, // No special flags
pszString, // Wide characters to convert
-1, // The wide character text is null terminated, and the null terminator will be converted into a wide null terminator
NULL, // No buffer given, we just want to know how big one would need to be
0, // No buffer size given
NULL, // No special options for unmappable characters
NULL );
// If our buffer of 128 ASCII characters is big enough, use it, otherwise allocate a new bigger buffer
//如果小于127字节,则保存到 m_szSCHAR中,否则创建新的内存空间
LPSTR pszByte = nByte <= PACKET_BUF_SCHAR ? m_szSCHAR : new CHAR[ nByte ];
// Convert the wide characters into bytes of ASCII text
//将参数pszString写入到pszBytes中
WideCharToMultiByte(
CP_ACP, // Use the ASCII code page
0, // No special flags
pszString, // Wide characters to convert
-1, // The wide character text is null terminated
pszByte, // Have WideCharToMultiByte write the ASCII bytes in our static or just allocated buffer
nByte, // This is how much space it has
NULL, // No special options for unmappable characters
NULL );
// Write the ASCII text into the end of the packet
//写入到buffer中,如果bNull为真,则在最后写入/0,否则不写
Write( pszByte, nByte - ( bNull ? 0 : 1 ) ); // If bNull is true, also write the null terminator which got converted
// If we needed a bigger buffer and allocated one, we have to remember to delete it
if ( pszByte != m_szSCHAR ) // 如果是新分配的内存,则释放之
{
delete [] pszByte;
}
}
// Takes text
// Determines how many bytes of ASCII text it would turn into when converted
// Returns the number, 5 for "hello", that does not include a null terminator
//返回将参数LPCTSTR pszString转化为multibytes ascii编码 字符串后的长度
int CPacket::GetStringLen(LPCTSTR pszString) const
{
// If the text is blank, the length is 0
if ( *pszString == 0 )
{
return 0;
}
// Find the number of characters in the text下面WideCharToMultiByte要用到
int nLength = _tcslen( pszString ); // Same as lstrlen, doesn't include null terminator
// Find out how many ASCII bytes the text would convert into, and return that number
nLength = WideCharToMultiByte( CP_ACP, 0, pszString, nLength, NULL, 0, NULL, NULL );
return nLength;
}
//
// CPacket UTF-8 strings
// Takes the number of bytes to look at from our position in the packet as ASCII text
// Converts those up to the next null terminator into wide characters using the UTF8 code page
// Returns the string of converted Unicode wide characters
//将m_pBuffer + m_nPosition位置开始的数据转化为utf8编码的CString unicode widechar
CString CPacket::ReadStringUTF8(DWORD nMaximum)
{
// We'll convert the ASCII text in the packet into wide characters using the UTF8 code page, and return them in this string
CString strString;
// If maximum would have us read beyond the end of the packet, make it smaller to read to the end of the packet
nMaximum = min( nMaximum, m_nLength - m_nPosition );
if ( ! nMaximum )
{
return strString; // If that would have us read nothing, return the new blank string
}
// Setup pointers to look at bytes in the packet
LPCSTR pszInput = (LPCSTR)m_pBuffer + m_nPosition; // Point pszInput at our position inside the buffer
LPCSTR pszScan = pszInput; // Start out pszScan at the same spot, it will find the next null terminator
// Loop for each byte in the packet at and beyond our position in it, searching for a null terminator
DWORD nLength = 0; // When this loop is done, nLength will be the number of ASCII bytes we moved over before finding the null terminator
for ( ; nLength < nMaximum ; nLength++ )
{
// Move the position pointer in this CPacket object to the next byte
m_nPosition++;
// If pszScan points to a 0 byte, exit the loop, otherwise move the pointer forward and keep going
if ( ! *pszScan++ )
{
break;
}
}
// Find out how many wide characters the ASCII bytes will become when converted
int nWide = MultiByteToWideChar(
CP_UTF8, // Use the UTF8 code page
0, // No character type options
pszInput, // Pointer to ASCII text in the packet
nLength, // Number of bytes to read there, the number of bytes before we found the null terminator
NULL, // No output buffer, we just want to know how many wide characters one would need to hold
0 );
// Convert the ASCII bytes into wide characters
MultiByteToWideChar(
CP_UTF8, // Use the UTF8 code page
0, // No character type options
pszInput, // Pointer to ASCII text
nLength, // Number of bytes to read there, the number of bytes before we found the null terminator
strString.GetBuffer( nWide ), // Get access to the string's buffer, telling it we will write in nWide wide characters
nWide ); // Tell MultiByteToWideChar it can write nWide characters in the buffer
// Close the string and return it
strString.ReleaseBuffer( nWide );
return strString;
}
// Takes Unicode text, and true to also write a null terminator into the packet
// Converts it into ASCII bytes using the UTF8 code page, and writes them into the end of the packet
//将参数utf8编码的pszString转化为ascii编码的字符串,写入到buffer中
void CPacket::WriteStringUTF8(LPCTSTR pszString, BOOL bNull)
{
// Find out how many bytes of ASCII text the wide characters will become when converted with the UTF8 code page
int nByte = WideCharToMultiByte(
CP_UTF8, // Use the UTF8 code page
0, // No special performance and mapping flags
pszString, // Wide characters to convert
-1, // The given text in null terminated, and we want the text and the null terminator converted
NULL, // No buffer given, we just want to know how many bytes the converted ASCII text will take up
0,
NULL, // No special options for unmappable characters
NULL );
// If our buffer of 128 ASCII characters is big enough, use it, otherwise allocate a new bigger buffer
LPSTR pszByte = nByte <= PACKET_BUF_SCHAR ? m_szSCHAR : new CHAR[ nByte ];
// Convert the wide characters into bytes of ASCII text
WideCharToMultiByte(
CP_UTF8, // Use the UTF8 code page
0, // No special performance and mapping flags
pszString, // Wide characters to convert
-1, // The given text in null terminated, and we want the text and the null terminator converted
pszByte, // Have WideCharToMultiByte write the ASCII bytes in our static or just allocated buffer
nByte, // This is how much space it has
NULL, // No special options for unmappable characters
NULL );
// Write the ASCII text into the end of the packet
Write( pszByte, nByte - ( bNull ? 0 : 1 ) ); // If bNull is true, also write the null terminator which got converted
// If we needed a bigger buffer and allocated one, we have to remember to delete it
if ( pszByte != m_szSCHAR )
{
delete [] pszByte;
}
}
// Takes text
// Determines how many bytes of ASCII text it would turn into when converted with the UTF8 code page
// Returns the number, which does not include a null terminator
//计算出如果将字符串pszString转化为utf8编码后需要多少个字节
int CPacket::GetStringLenUTF8(LPCTSTR pszString) const
{
// If the text is blank, the length is 0
if ( *pszString == 0 )
{
return 0;
}
// Find the number of characters in the text
int nLength = _tcslen( pszString ); // Same as lstrlen, doesn't include null terminator
// Find out how many ASCII bytes the text would convert into using the UTF8 code page, and return that number
nLength = WideCharToMultiByte( CP_UTF8, 0, pszString, nLength, NULL, 0, NULL, NULL );
return nLength;
}
//
// CPacket ZLIB
// Takes a length of compressed data, access to a DWORD to write a size, and a guess as to how big the data will be decompressed
// Uses zlib to decompress the next nLength bytes of data from our current position in the packet
// Returns a pointer to the decompressed memory that CZLib allocated
//将当前buffer中的压缩过的数据解压缩,返回结果unsigned char *
LPBYTE CPacket::ReadZLib(DWORD nLength, DWORD* pnOutput, DWORD nSuggest)
{
// The packet has m_nLength bytes, and we are at m_nPosition in it, make sure nLength can fit in the part afterwards
if ( m_nLength - m_nPosition < nLength ) // 从m_nPosition开始nLength长度的数据解压缩
{
return NULL;
}
// Decompress the data 解压缩数据,pnOutput保存了解压缩后的长度
*pnOutput = 0; // CZLib will write the size of the memory block it's returning here
LPBYTE pOutput = CZLib::Decompress( // Use zlib, return a pointer to memory CZLib allocated
m_pBuffer + m_nPosition, // The compressed data starts here
nLength, // And is this long
(DWORD*)pnOutput, // CZLib::Decompress will write the size of the memory it returns a pointer to here
nSuggest ); // Tell zlib how big we expect the data to be when decompressed
// Move the position in the packet past the memory we just decompressed
m_nPosition += nLength;// 指向压缩数据后面的数据
// Return a pointer to the memory that CZLib allocated
return pOutput;
}
// Takes a pointer to memory, and the number of bytes we can read there
// Compresses that data, and writes it into the packet
//将参数pData压缩,结果写入到当前buffer中
void CPacket::WriteZLib(LPCVOID pData, DWORD nLength)
{
// Compress the given data
DWORD nOutput = 0; // CZLib will write the size of the memory it returns here
BYTE* pOutput = CZLib::Compress( // Compress the data, getting a pointer to the memory CZLib allocated
pData, // Compress the data at pData
(DWORD)nLength, // Where there are nLength bytes
&nOutput ); // CZLib will write the size of the memory it returns in nOutput
// Write the compressed bytes into the packet
Write( pOutput, nOutput );
// Remember to delete the memory the CZLib allocated and returned
delete [] pOutput;
}
//
// CPacket pointer access
// Takes the number of bytes to write, nLength, and where we want to write them, nOffset
// Increases the size of the buffer and makes a gap to hold that many bytes there
// Returns a pointer to the gap where the caller can insert the new data
//返回可写入的位置,m_pBuffer + nOffset,将原来的数据后移nLength个位置
BYTE* CPacket::WriteGetPointer(DWORD nLength, DWORD nOffset)
{
// If the caller didn't specify an nOffset, the method's default is -1, make nOffset the end of the packet
if ( nOffset == 0xFFFFFFFF )// 没有指定noffset,默认是全部的长度m_nLength
{
nOffset = m_nLength;
}
// If adding nLength would go beyond the buffer, we need to make it bigger
if ( m_nLength + nLength > m_nBuffer ) // 原来buffer的长度不够了,增大这个长度
{
// Increase the size of the buffer by the needed length, or 128 bytes, whichever is bigger
m_nBuffer += max( nLength, DWORD(PACKET_GROW) ); // Packet grow is 128 bytes
LPBYTE pNew = new BYTE[ m_nBuffer ]; // Allocate a new buffer of that size
CopyMemory( pNew, m_pBuffer, m_nLength ); // Copy all the memory of the old buffer into the new bigger one
if ( m_pBuffer )
{
delete [] m_pBuffer; // Free the old buffer
}
m_pBuffer = pNew; // Point this packet object at its new, bigger buffer
}
// If the offset isn't at the very end of the buffer
if ( nOffset != m_nLength ) // 指定了长度,则首先将m_pBuffer + nOffset位置的数据移动到m_pBuffer + nOffset + nLength位置
{
// Shift the fragment beyond the offset into the buffer further to make a gap m_nLength big to hold the new data
MoveMemory(
m_pBuffer + nOffset + nLength, // Destination is beyond the offset and the length of what we're going to insert
m_pBuffer + nOffset, // Source is at the offset
m_nLength - nOffset ); // Size is the number of bytes written in the buffer beyond the offset
}
// Record there are going to be nLength more bytes stored in the buffer
m_nLength += nLength;
// Return a pointer to where the caller can write the nLength bytes
return m_pBuffer + nOffset;
}
//
// CPacket string conversion
// Ask this packet what type it is
// Returns text
LPCTSTR CPacket::GetType() const // Saying const indicates this method doesn't change the values of any member variables
{
// This is just a CPacket, not a G1Packet which would have a type
return NULL; // Return blank
}
// Express all the bytes of the packet as base 16 digits separated by spaces, like "08 C0 12 AF"
// Returns a string
//将原来的内容m_pBuffer的所有内容转化为16进制形式返回,例如0X12 0X34转化为:“12 34”
CString CPacket::ToHex() const
{
// Setup the alphabet to use when endoing each byte in two hexadecimal characters, 0-9 and A-F
LPCTSTR pszHex = _T("0123456789ABCDEF");
// Make a string and open it to write the characters in it directly, for speed
CString strDump; // 结果数据空间,长度变为3倍,例如变为数字0XFF变为“空格FF”
LPTSTR pszDump = strDump.GetBuffer( m_nLength * 3 ); // Each byte will become 3 characters
// Loop i down each byte in the packet
for ( DWORD i = 0 ; i < m_nLength ; i++ )
{
// Copy the byte at i into an integer called nChar
int nChar = m_pBuffer[i];
// If this isn't the very start, write a space into the text
if ( i ) // 第一个数字没有空格,后面的都有空格,类似于:12 34 46 48 98
{
*pszDump++ = ' '; // Write a space at pszDump, then move the pszDump pointer forward to the next character
}
// Express the byte as two characters in the text, "00" through "FF"
*pszDump++ = pszHex[ nChar >> 4 ];
*pszDump++ = pszHex[ nChar & 0x0F ];
}
// Write a null terminator beyond the characters we wrote, close direct memory access to the string, and return it
*pszDump = 0;//最后了,写入/0
strDump.ReleaseBuffer();
return strDump;
}
// Read the bytes of the packet as though they are ASCII characters, placing periods for those that aren't
// Returns a string like "abc..fgh.i"
//将m_pBuffer的所有内容转化为ascii,如果是小于32的字符则显示为.
CString CPacket::ToASCII() const
{
// Make a string and get direct access to its memory buffer
CString strDump;
LPTSTR pszDump = strDump.GetBuffer( m_nLength + 1 ); // We'll write a character for each byte, and 1 more for the null terminator
// Loop i down each byte in the packet
for ( DWORD i = 0 ; i < m_nLength ; i++ )
{
// Copy the byte at i into an integer called nChar
int nChar = m_pBuffer[i];
// If the byte is 32 or greater, read it as an ASCII character and copy that character into the string
*pszDump++ = ( nChar >= 32 ? nChar : '.' ); // If it's 0-31, copy in a period instead
}
// Write a null terminator beyond the characters we wrote, close direct memory access to the string, and return it
*pszDump = 0;
strDump.ReleaseBuffer();
return strDump;
}
//
// CPacket debugging
// Classes that inherit from CPacket override this with their own Debug methods that record debugging information
// Takes text that describes what happened
//Debug用,显示当前buffer的真实内容
void CPacket::Debug(LPCTSTR pszReason) const
{
// Only include these lines in the program if it is being compiled in debug mode
#ifdef _DEBUG
theApp.Message( MSG_DEBUG, pszReason );
CString strOutput;
// Loop the index i down each byte in the packet buffer
for ( DWORD i = 0 ; i < m_nLength ; i++ )
{
// Read the byte there as an int called nChar
int nChar = m_pBuffer[i];
// Encode it as two base 16 characters followed by an ASCII character, like "00(.) " or "41(A) "
// avoid % in order to avoid trouble with format functions
CString strTmp;
strTmp.Format( _T("%.2X(%c) "), nChar, ( nChar >= 32 && nChar != '%' ? nChar : '.' ) );
strOutput += strTmp;
}
theApp.Message( MSG_DEBUG, LPCTSTR( strOutput ) );
// Go back to including all the lines in the program
#endif
}
//
// CPacket smart dumping
// Takes a CNeighbour object, an IP address without a port number, and true if we are sending the packet, false if we received it
// Gives this packet and related objects to each window in the tab bar for them to process it
//调用所有CPacketWnd类的窗口都处理包含当前对象的,参数为参数列表的消息,调用Process方法
void CPacket::SmartDump(CNeighbour* pNeighbour,
IN_ADDR* pUDP, BOOL bOutgoing) const
{
// Get exclusive access to the program's critical section while this method runs
CSingleLock pLock( &theApp.m_pSection ); // When the method exits, pLock will go out of scope, be destructed, and release the lock
if ( pLock.Lock( 50 ) ) // If we wait more than 1/20th of a second for access, Lock will return false so we can just give up
{
// Get a pointer to the main Shareaza window 找到主Shareaza窗口
if ( CMainWnd* pMainWnd = (CMainWnd*)theApp.m_pSafeWnd )
{
// Get pointers to the window manager, and null a pointer to a packet window
CWindowManager* pWindows = &pMainWnd->m_pWindows;
CPacketWnd* pWnd = NULL;
// Loop through all the windows, pointing pWnd at each one 遍历搜索和调用Process
while ( pWnd = (CPacketWnd*)pWindows->Find( RUNTIME_CLASS(CPacketWnd), pWnd ) )
{
// Give each window this packet to process, along with the related CNeighbour object, IP address, and travel direction
pWnd->Process( pNeighbour, pUDP, bOutgoing, this );
}
}
}
}
//
// CPacket RAZA signatures
// Takes the number of bytes in this packet to hash
// Computs the SHA hash of those bytes
// Writes the hash under the given pointer and returns true, or false on error
//获得当前packet对应的sha1 hash
BOOL CPacket::GetRazaHash(SHA1* pHash, DWORD nLength) const
{
// If the caller didn't specify a length, we'll hash all the bytes in the packet
if ( nLength == 0xFFFFFFFF ) // 用户没有指定nLength,默认为m_nLength
{
nLength = m_nLength;
}
// Make sure the caller didn't ask to hash more bytes than the packet contains
if ( (DWORD)m_nLength < nLength ) // nLength只能比m_nLength要小
{
return FALSE;
}
// Make a new local CSHA object to use to hash the data
//将m_pBuffer的hash结果写入参数pHash中
CSHA pSHA;
pSHA.Add( m_pBuffer, nLength ); // Add the bytes of the packet to those it needs to hash
pSHA.Finish(); // Tell it that's all we have
pSHA.GetHash( pHash ); // Ask it to write the hash under the pHash pointer
return TRUE; // Report success
}
// Does nothing, and is not overriden by any inheritng class (do)
void CPacket::RazaSign()
{
// Do nothing (do)
}
// Does nothing, and is not overriden by any inheritng class (do)
BOOL CPacket::RazaVerify() const
{
// Always return false (do)
return FALSE;
}
//
// CPacketPool construction
// Make a new packet pool
CPacketPool::CPacketPool()
{
// Set member variables to null and 0 defaults
m_pFree = NULL; // No pointer to a CPacket object
m_nFree = 0; // Start the count at 0 (do)
}
// Delete this packet pool
CPacketPool::~CPacketPool()
{
// Free all the packets in this pool before the destructor frees this packet pool object itself
Clear();
}
//
// CPacketPool clear
// Delete all the packet objects that this packet pool points to, and return the member variables to defaults
//释放m_pPools的所有空间
void CPacketPool::Clear()
{
//删除m_pPools数组中所有的CPacket pPool,调用FreePoolImpl来释放内存
// Loop from the end of the pointer array back to the start
for (
int nIndex = m_pPools.GetSize() - 1; // GetSize returns the number of pointers in the array, start nIndex on the last one
nIndex >= 0; // If nIndex reaches 0, loop one more time, when it's -1, don't do the loop anymore
nIndex-- ) // Move back one index in the pointer array
{
// Point pPool at the packet pool at that position in the array
CPacket* pPool = (CPacket*)m_pPools.GetAt( nIndex );
// Delete the packet pool, freeing the memory of the 256 packets in it
FreePoolImpl( pPool ); // Calls up higher on the inheritance tree
}
// Clear all the member variables of this packet pool object,清空m_pPools
m_pPools.RemoveAll(); // Remove all the pointers from the MFC CPtrArray structure
m_pFree = NULL; // There are no packets to point to anymore
m_nFree = 0; // This packet pool has 0 packets now
}
//
// CPacketPool new pool setup
// Create a new array of 256 packets, called a packet pool, and add it to this CPacketPool object's list of them
//加入一个CPacket* Pool到m_pPools中
void CPacketPool::NewPool()
{
// Allocate an array of 256 packets, this is a new packet pool
CPacket* pPool = NULL;
int nPitch = 0, nSize = 256;
//分配一个256个packet的array,结果保存在pPool中
NewPoolImpl( // NewPoolImpl allocates an array of packets for this packet pool object
nSize, // The number of packets the array will hold, we want 256
pPool, // NewPoolImpl will save a pointer to the allocated array here
nPitch ); // NewPoolImpl will save the size in bytes of each packet in the array here
// Add the new packet pool to m_pPools, this CPacketPool object's list of them
//将新的pPool加入到m_pPools的最后
m_pPools.Add( pPool );
// Link the packets in the new pool so m_pFree points at the last one, they each point to the one before, and the first points to what m_pFree used to
//将参数pPool的所有CPacket加入到m_pFree链表的开始位置
BYTE* pBytes = (BYTE*)pPool; // Start the pBytes pointer at the start of our new packet pool
while ( nSize-- > 0 ) // Loop 256 times, once for each packet in the new pool
{
// Link this packet to the one before it
pPool = (CPacket*)pBytes; // Point pPool at the new packet pool we just created and added to the list
pBytes += nPitch; // Move pBytes to the next packet in the pool
pPool->m_pNext = m_pFree; // Set the next pointer in the first packet in the pool
m_pFree = pPool; // Point m_pFree at the next packet
m_nFree++; // Record one more packet is linked into the list
}
}