📄 baseclient.cpp
字号:
theApp.searchlist->ProcessSearchanswer(pachPacket,nSize,this,NULL,pszDirectory);
}
}
void CUpDownClient::SetUserHash(const uchar* pucUserHash)
{
if( pucUserHash == NULL ){
md4clr(m_achUserHash);
return;
}
md4cpy(m_achUserHash, pucUserHash);
}
void CUpDownClient::SetBuddyID(const uchar* pucBuddyID)
{
if( pucBuddyID == NULL ){
md4clr(m_achBuddyID);
m_bBuddyIDValid = false;
return;
}
m_bBuddyIDValid = true;
md4cpy(m_achBuddyID, pucBuddyID);
}
void CUpDownClient::SendPublicKeyPacket(){
///* delete this line later*/ AddDebugLogLine(false, _T("sending public key to '%s'"), GetUserName()));
// send our public key to the client who requested it
if (socket == NULL || credits == NULL || m_SecureIdentState != IS_KEYANDSIGNEEDED){
ASSERT ( false );
return;
}
if (!theApp.clientcredits->CryptoAvailable())
return;
Packet* packet = new Packet(OP_PUBLICKEY,theApp.clientcredits->GetPubKeyLen() + 1,OP_EMULEPROT);
theStats.AddUpDataOverheadOther(packet->size);
memcpy(packet->pBuffer+1,theApp.clientcredits->GetPublicKey(), theApp.clientcredits->GetPubKeyLen());
packet->pBuffer[0] = theApp.clientcredits->GetPubKeyLen();
if (thePrefs.GetDebugClientTCPLevel() > 0)
DebugSend("OP__PublicKey", this);
socket->SendPacket(packet,true,true);
m_SecureIdentState = IS_SIGNATURENEEDED;
}
void CUpDownClient::SendSignaturePacket(){
// signate the public key of this client and send it
if (socket == NULL || credits == NULL || m_SecureIdentState == 0){
ASSERT ( false );
return;
}
if (!theApp.clientcredits->CryptoAvailable())
return;
if (credits->GetSecIDKeyLen() == 0)
return; // We don't have his public key yet, will be back here later
///* delete this line later*/ AddDebugLogLine(false, _T("sending signature key to '%s'"), GetUserName()));
// do we have a challenge value received (actually we should if we are in this function)
if (credits->m_dwCryptRndChallengeFrom == 0){
if (thePrefs.GetLogSecureIdent())
AddDebugLogLine(false, _T("Want to send signature but challenge value is invalid ('%s')"), GetUserName());
return;
}
// v2
// we will use v1 as default, except if only v2 is supported
bool bUseV2;
if ( (m_bySupportSecIdent&1) == 1 )
bUseV2 = false;
else
bUseV2 = true;
uint8 byChaIPKind = 0;
uint32 ChallengeIP = 0;
if (bUseV2){
if (theApp.serverconnect->GetClientID() == 0 || theApp.serverconnect->IsLowID()){
// we cannot do not know for sure our public ip, so use the remote clients one
ChallengeIP = GetIP();
byChaIPKind = CRYPT_CIP_REMOTECLIENT;
}
else{
ChallengeIP = theApp.serverconnect->GetClientID();
byChaIPKind = CRYPT_CIP_LOCALCLIENT;
}
}
//end v2
uchar achBuffer[250];
uint8 siglen = theApp.clientcredits->CreateSignature(credits, achBuffer, 250, ChallengeIP, byChaIPKind );
if (siglen == 0){
ASSERT ( false );
return;
}
Packet* packet = new Packet(OP_SIGNATURE,siglen + 1+ ( (bUseV2)? 1:0 ),OP_EMULEPROT);
theStats.AddUpDataOverheadOther(packet->size);
memcpy(packet->pBuffer+1,achBuffer, siglen);
packet->pBuffer[0] = siglen;
if (bUseV2)
packet->pBuffer[1+siglen] = byChaIPKind;
if (thePrefs.GetDebugClientTCPLevel() > 0)
DebugSend("OP__Signature", this);
socket->SendPacket(packet,true,true);
m_SecureIdentState = IS_ALLREQUESTSSEND;
}
void CUpDownClient::ProcessPublicKeyPacket(uchar* pachPacket, uint32 nSize){
theApp.clientlist->AddTrackClient(this);
///* delete this line later*/ AddDebugLogLine(false, _T("recieving public key from '%s'"), GetUserName()));
if (socket == NULL || credits == NULL || pachPacket[0] != nSize-1
|| nSize == 0 || nSize > 250){
ASSERT ( false );
return;
}
if (!theApp.clientcredits->CryptoAvailable())
return;
// the function will handle everything (mulitple key etc)
if (credits->SetSecureIdent(pachPacket+1, pachPacket[0])){
// if this client wants a signature, now we can send him one
if (m_SecureIdentState == IS_SIGNATURENEEDED){
SendSignaturePacket();
}
else if(m_SecureIdentState == IS_KEYANDSIGNEEDED)
{
// something is wrong
if (thePrefs.GetLogSecureIdent())
AddDebugLogLine(false, _T("Invalid State error: IS_KEYANDSIGNEEDED in ProcessPublicKeyPacket"));
}
}
else
{
if (thePrefs.GetLogSecureIdent())
AddDebugLogLine(false, _T("Failed to use new received public key"));
}
}
void CUpDownClient::ProcessSignaturePacket(uchar* pachPacket, uint32 nSize){
///* delete this line later*/ AddDebugLogLine(false, _T("receiving signature from '%s'"), GetUserName()));
// here we spread the good guys from the bad ones ;)
if (socket == NULL || credits == NULL || nSize == 0 || nSize > 250){
ASSERT ( false );
return;
}
uint8 byChaIPKind;
if (pachPacket[0] == nSize-1)
byChaIPKind = 0;
else if (pachPacket[0] == nSize-2 && (m_bySupportSecIdent & 2) > 0) //v2
byChaIPKind = pachPacket[nSize-1];
else{
ASSERT ( false );
return;
}
if (!theApp.clientcredits->CryptoAvailable())
return;
// we accept only one signature per IP, to avoid floods which need a lot cpu time for cryptfunctions
if (m_dwLastSignatureIP == GetIP())
{
if (thePrefs.GetLogSecureIdent())
AddDebugLogLine(false, _T("received multiple signatures from one client"));
return;
}
// also make sure this client has a public key
if (credits->GetSecIDKeyLen() == 0)
{
if (thePrefs.GetLogSecureIdent())
AddDebugLogLine(false, _T("received signature for client without public key"));
return;
}
// and one more check: did we ask for a signature and sent a challange packet?
if (credits->m_dwCryptRndChallengeFor == 0)
{
if (thePrefs.GetLogSecureIdent())
AddDebugLogLine(false, _T("received signature for client with invalid challenge value ('%s')"), GetUserName());
return;
}
if (theApp.clientcredits->VerifyIdent(credits, pachPacket+1, pachPacket[0], GetIP(), byChaIPKind ) ){
// result is saved in function abouve
//if (thePrefs.GetLogSecureIdent())
// AddDebugLogLine(false, _T("'%s' has passed the secure identification, V2 State: %i"), GetUserName(), byChaIPKind);
}
else
{
if (thePrefs.GetLogSecureIdent())
AddDebugLogLine(false, _T("'%s' has failed the secure identification, V2 State: %i"), GetUserName(), byChaIPKind);
}
m_dwLastSignatureIP = GetIP();
}
void CUpDownClient::SendSecIdentStatePacket(){
// check if we need public key and signature
uint8 nValue = 0;
if (credits){
if (theApp.clientcredits->CryptoAvailable()){
if (credits->GetSecIDKeyLen() == 0)
nValue = IS_KEYANDSIGNEEDED;
else if (m_dwLastSignatureIP != GetIP())
nValue = IS_SIGNATURENEEDED;
}
if (nValue == 0){
//if (thePrefs.GetLogSecureIdent())
// AddDebugLogLine(false, _T("Not sending SecIdentState Packet, because State is Zero"));
return;
}
// crypt: send random data to sign
uint32 dwRandom = rand()+1;
credits->m_dwCryptRndChallengeFor = dwRandom;
Packet* packet = new Packet(OP_SECIDENTSTATE,5,OP_EMULEPROT);
theStats.AddUpDataOverheadOther(packet->size);
packet->pBuffer[0] = nValue;
PokeUInt32(packet->pBuffer+1, dwRandom);
if (thePrefs.GetDebugClientTCPLevel() > 0)
DebugSend("OP__SecIdentState", this);
socket->SendPacket(packet,true,true);
}
else
ASSERT ( false );
}
void CUpDownClient::ProcessSecIdentStatePacket(uchar* pachPacket, uint32 nSize){
if (nSize != 5)
return;
if (!credits){
ASSERT ( false );
return;
}
switch(pachPacket[0]){
case 0:
m_SecureIdentState = IS_UNAVAILABLE;
break;
case 1:
m_SecureIdentState = IS_SIGNATURENEEDED;
break;
case 2:
m_SecureIdentState = IS_KEYANDSIGNEEDED;
break;
}
credits->m_dwCryptRndChallengeFrom = PeekUInt32(pachPacket+1);
}
void CUpDownClient::InfoPacketsReceived(){
// indicates that both Information Packets has been received
// needed for actions, which process data from both packets
ASSERT ( m_byInfopacketsReceived == IP_BOTH );
m_byInfopacketsReceived = IP_NONE;
if (m_bySupportSecIdent){
SendSecIdentStatePacket();
}
}
void CUpDownClient::ResetFileStatusInfo()
{
if (m_abyPartStatus){
delete[] m_abyPartStatus;
m_abyPartStatus = NULL;
}
m_nRemoteQueueRank = 0;
m_nPartCount = 0;
m_strClientFilename.Empty();
m_bCompleteSource = false;
m_uFileRating = 0;
m_strFileComment.Empty();
if (m_pReqFileAICHHash != NULL){
delete m_pReqFileAICHHash;
m_pReqFileAICHHash = NULL;
}
}
bool CUpDownClient::IsBanned() const
{
return theApp.clientlist->IsBannedClient(GetIP());
}
void CUpDownClient::SendPreviewRequest(const CAbstractFile* pForFile)
{
if (m_fPreviewReqPending == 0){
m_fPreviewReqPending = 1;
Packet* packet = new Packet(OP_REQUESTPREVIEW,16,OP_EMULEPROT);
md4cpy(packet->pBuffer,pForFile->GetFileHash());
theStats.AddUpDataOverheadOther(packet->size);
SafeSendPacket(packet);
}
else{
//to res table - later
AddLogLine(true, GetResString(IDS_ERR_PREVIEWALREADY));
}
}
void CUpDownClient::SendPreviewAnswer(const CKnownFile* pForFile, CxImage** imgFrames, uint8 nCount)
{
m_fPreviewAnsPending = 0;
CSafeMemFile data(1024);
if (pForFile){
data.WriteHash16(pForFile->GetFileHash());
}
else{
static const uchar _aucZeroHash[16] = {0};
data.WriteHash16(_aucZeroHash);
}
data.WriteUInt8(nCount);
for (int i = 0; i != nCount; i++){
if (imgFrames == NULL){
ASSERT ( false );
return;
}
CxImage* cur_frame = imgFrames[i];
if (cur_frame == NULL){
ASSERT ( false );
return;
}
BYTE* abyResultBuffer = NULL;
long nResultSize = 0;
if (!cur_frame->Encode(abyResultBuffer, nResultSize, CXIMAGE_FORMAT_PNG)){
ASSERT ( false );
return;
}
data.WriteUInt32(nResultSize);
data.Write(abyResultBuffer, nResultSize);
free(abyResultBuffer);
}
Packet* packet = new Packet(&data, OP_EMULEPROT);
packet->opcode = OP_PREVIEWANSWER;
theStats.AddUpDataOverheadOther(packet->size);
SafeSendPacket(packet);
}
void CUpDownClient::ProcessPreviewReq(char* pachPacket, uint32 nSize){
if (nSize < 16)
throw GetResString(IDS_ERR_WRONGPACKAGESIZE);
if (m_fPreviewAnsPending || thePrefs.CanSeeShares()==vsfaNobody || (thePrefs.CanSeeShares()==vsfaFriends && !IsFriend()))
return;
m_fPreviewAnsPending = 1;
CKnownFile* previewFile = theApp.sharedfiles->GetFileByID((uchar*)pachPacket);
if (previewFile == NULL){
SendPreviewAnswer(NULL, NULL, 0);
}
else{
previewFile->GrabImage(4,0,true,450,this);
}
}
void CUpDownClient::ProcessPreviewAnswer(char* pachPacket, uint32 nSize){
if (m_fPreviewReqPending == 0)
return;
m_fPreviewReqPending = 0;
CSafeMemFile data((BYTE*)pachPacket,nSize);
uchar Hash[16];
data.ReadHash16(Hash);
uint8 nCount = data.ReadUInt8();
if (nCount == 0){
// to res table -later
AddLogLine(true, GetResString(IDS_ERR_PREVIEWFAILED),GetUserName());
return;
}
CSearchFile* sfile = theApp.searchlist->GetSearchFileByHash(Hash);
if (sfile == NULL){
//already deleted
return;
}
BYTE* pBuffer = NULL;
try{
for (int i = 0; i != nCount; i++){
uint32 nImgSize = data.ReadUInt32();
if (nImgSize > nSize)
throw CString(_T("CUpDownClient::ProcessPreviewAnswer - Provided image size exceeds limit"));
pBuffer = new BYTE[nImgSize];
data.Read(pBuffer, nImgSize);
CxImage* image = new CxImage(pBuffer, nImgSize, CXIMAGE_FORMAT_PNG);
delete[] pBuffer;
pBuffer = NULL;
if (image->IsValid()){
sfile->AddPreviewImg(image);
}
}
}
catch(...){
if (pBuffer != NULL)
delete[] pBuffer;
throw;
}
(new PreviewDlg())->SetFile(sfile);
}
// sends a packet, if needed it will establish a connection before
// options used: ignore max connections, control packet, delete packet
// !if the functions returns false that client object was deleted because the connection try failed and the object wasn't needed anymore.
bool CUpDownClient::SafeSendPacket(Packet* packet){
if (socket && socket->IsConnected()){
socket->SendPacket(packet);
return true;
}
else{
m_WaitingPackets_list.AddTail(packet);
return TryToConnect(true);
}
}
bool CUpDownClient::HasLowID() const
{
return IsLowID(m_nUserIDHybr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -