[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Mldonkey-users] Emule Extended Protocol guesswork
From: |
Jorfen |
Subject: |
[Mldonkey-users] Emule Extended Protocol guesswork |
Date: |
Sat, 28 Dec 2002 00:10:54 +0100 |
User-agent: |
KMail/1.4.3 |
This is pure guesswork and was only collected by looking at the sourcecode.
Never used Emule, never will.
EMULE_PACKET
------------
uint8 edonkey_id = EMULE_PROT =0xc5
unint32 packet length
unit8 command
OP_EMULEINFO(0x01) / OP_EMULEINFOANSER (0x02) (Baseclient.cpp:226)
--------------------------------
guesswork : send to emule and tell them that we understand their protocoll and
get answer OP_EMULEINFOANSWER.
may also work, if mld gets an OP_EMULEINFO and we only send them an
OP_EMULEINFOANSWER.
----
uint8 clientversion
uint8 emule_prot_version (0x01)
uint32 number of tags (2) (NOT) (look at packets.cpp:195) following (hardcoded
to 2)
NOT*type3
all of the tags are type3 tags (if you look at the source)
format :
type3
{
uint8 tagtype (should be 3)
uint16 taglen (should be 1)
uint8 specialtag (thats what the tag really means (compression,etc))
uint32 value
}
one tag will be ET_COMPRESSION (0x20, as specialtag) which is either value=0
or value=1.
the other will be ET_UDPPORT (0x21), which seems the port of the
EMULE_UDP_PROTO.
these seem to be the only tags used in the protocol
OP_QUEUERANKING (0x60) (send UploadClient.cpp:397, receive
ListenSocket.cpp:360)
(emule checks for fixed size of 12 bytes)
-----------------------------------
uint16 rank
10*uint8 NULL (nada, 0, 0x00, null, nichts)
dunno why that is filled up with zeroes, look at the source yourself, could
not make any sense out of it
OP_ANSWERSOURCES (0x82) (Knownfile.cpp:420,ListenSocket.cpp:382)
----------------
char[16] filehash
uint16 NULL (0x00) (source names this nCount... may mean something someday
later?)
X*CI (the current source send 20 or less sources (thats the X))
CI
{
uint32 IP
uint16 PORT
uint32 Serverip
uint16 serverport
}
OP_REQUESTSOURCES (0x81) (Knownfile.cpp:420,ListenSOcket.cpp:368)
(emule checks for fixed size of 16 bytes)
-----------------
has the same format like OP_ANSWERSOURCES, but WE fill it with sources we know
and get other data back...
OP_FILEDESC (0x61) (BaseClient.cpp:316)
(emule only processes 50 bytes of the packet (BaseClient.cpp:323)
-----------
int8 rate (dunno what it means)
sizeof(int) length (is sizeof(int) different on linux/win32?)
char[length+1] comment
OP_COMPRESSEDPART (0x40)
-------------------
what is compress comes from the supplied zlib package from emule.
This packet should have the same format as a standart packet except it uses
the extend protocol and the data is compressed.
void CUpDownClient::CreatePackedPackets(byte* data,uint32 togo,
Requested_Block_Struct* currentblock){
BYTE* output = new BYTE[togo+300];
uLongf newsize = togo+300;
uint16 result = compress2(output,&newsize,data,togo,9);
if (result != Z_OK || togo <= newsize){
delete[] output;
CreateStandartPackets(data,togo,currentblock);
return;
}
m_bUsedComprUp = true;
CMemFile memfile(output,newsize);
togo = newsize;
uint32 nPacketSize;
if (togo > 10240)
nPacketSize = togo/(uint32)(togo/10240);
else
nPacketSize = togo;
while (togo){
if (togo < nPacketSize*2)
nPacketSize = togo;
togo -= nPacketSize;
Packet* packet = new
Packet(OP_COMPRESSEDPART,nPacketSize+24,OP_EMULEPROT);
memcpy(&packet->pBuffer[0],reqfileid,16);
uint32 statpos = currentblock->StartOffset;
memcpy(&packet->pBuffer[16],&statpos,4);
memcpy(&packet->pBuffer[20],&newsize,4);
memfile.Read(&packet->pBuffer[24],nPacketSize);
m_BlockSend_queue.AddTail(packet);
}
delete[] output;
}
void CUpDownClient::ProcessBlockPacket(char* packet, uint32 size, bool
packed){
if (!(GetDownloadState() == DS_DOWNLOADING || GetDownloadState() ==
DS_NONEEDEDPARTS))
return;
theApp.UpdateReceivedBytes(size);
m_dwLastBlockReceived = ::GetTickCount();
CSafeMemFile* data = new CSafeMemFile((BYTE*)packet,size);
uchar fileid[16];
data->Read(fileid,16);
if ( (!reqfile) || memcmp(packet,reqfile->GetFileHash(),16)){
delete data; //mf
throw CString(GetResString(IDS_ERR_WRONGFILEID)+"
(ProcessBlockPacket)");
}
uint32 nStartPos;
uint32 nEndPos;
uint32 nBlockSize = 0;
data->Read(&nStartPos,4);
if (packed){
data->Read(&nBlockSize,4);
nEndPos = nStartPos + (size-24);
usedcompressiondown = true;
}
else
data->Read(&nEndPos,4);
if ( size != (nEndPos-nStartPos)+24){
delete data; //mf
throw CString(GetResString(IDS_ERR_BADDATABLOCK)+"
(ProcessBlockPacket)");
}
downdataratems += nEndPos-nStartPos;
m_nTransferedDown += nEndPos-nStartPos;
credits->AddDownloaded(nEndPos-nStartPos);
nEndPos--;
delete data;
for (POSITION pos = m_PendingBlocks_list.GetHeadPosition();pos !=
0;m_PendingBlocks_list.GetNext(pos)){
Pending_Block_Struct* cur_block =
m_PendingBlocks_list.GetAt(pos);
if (cur_block->block->StartOffset <= nStartPos &&
cur_block->block->EndOffset >= nEndPos){
cur_block->buffer->Write(packet+24,size-24);
m_nLastBlockOffset = nStartPos; // [Cax2]
if (!packed){
if (nEndPos == cur_block->block->EndOffset){
if
((cur_block->block->EndOffset-cur_block->block->StartOffset)+1 !=
cur_block->buffer->GetLength()){
theApp.emuledlg->AddLogLine(false,GetResString(IDS_ERR_PACKAGEERROR),reqfile->GetFileName());
}
else{
char* blockbuffer =
(char*)cur_block->buffer->Detach();
reqfile->BlockReceived(cur_block->block->StartOffset,cur_block->block->EndOffset,blockbuffer);
free(blockbuffer);
}
delete cur_block->block;
delete cur_block->buffer;
delete cur_block;
m_PendingBlocks_list.RemoveAt(pos);
SendBlockRequests();
}
}
else{
if (nBlockSize ==
cur_block->buffer->GetLength()){
BYTE* blockbuffer =
cur_block->buffer->Detach();
BYTE* unpack = new BYTE[BLOCKSIZE+300];
uLongf unpackedsize = BLOCKSIZE+300;
uint16 result =
uncompress(unpack,&unpackedsize,blockbuffer,nBlockSize);
if (result == Z_OK){
reqfile->BlockReceived(cur_block->block->StartOffset,cur_block->block->StartOffset
+ (unpackedsize-1),(char*)unpack, nBlockSize);
}
else{
theApp.emuledlg->AddLogLine(false,GetResString(IDS_ERR_CORRUPTCOMPRPKG),reqfile->GetFileName(),result);
reqfile->RemoveBlockFromList(cur_block->block->StartOffset,cur_block->block->StartOffset+1);
}
delete[] unpack;
delete cur_block->block;
delete cur_block->buffer;
delete cur_block;
free(blockbuffer);
m_PendingBlocks_list.RemoveAt(pos);
SendBlockRequests();
}
}
return;
}
}
}
------------------------------------------------
there is also an opcode 0xD4 for edonkey_id in the header for a purely
compressed protocol.
uses these funtions :
void Packet::PackPacket(){
ASSERT (!m_bSplitted);
BYTE* output = new BYTE[size+300];
uLongf newsize = size+300;
uint16 result = compress2(output,&newsize,(BYTE*)pBuffer,size,9);
if (result != Z_OK || size <= newsize){
delete[] output;
return;
}
prot = OP_PACKEDPROT;
memcpy(pBuffer,output,newsize);
delete[] output;
m_bPacked = true;
}
bool Packet::UnPackPacket(){
ASSERT ( prot == OP_PACKEDPROT);
uint32 nNewSize = size*10+300;
if (nNewSize > 50000)
nNewSize = 50000;
BYTE* unpack = new BYTE[nNewSize];
uLongf unpackedsize = nNewSize;
uint16 result = uncompress(unpack,&unpackedsize,(BYTE*)pBuffer,size);
if (result == Z_OK){
ASSERT ( completebuffer == NULL );
ASSERT ( pBuffer != NULL );
size = unpackedsize;
delete[] pBuffer;
pBuffer = (char*)unpack;
prot = OP_EMULEPROT;
return true;
}
delete[] unpack;
return false;
}
but it is not used by emule (see Listensocket.cpp:464) or look at this :
void CClientReqSocket::PacketReceived(Packet* packet){
switch (packet->prot){
case OP_EDONKEYPROT:
ProcessPacket(packet->pBuffer,packet->size,packet->opcode);
break;
case OP_PACKEDPROT:
if (!packet->UnPackPacket()){
ASSERT ( false );
break;
}
case OP_EMULEPROT:
ProcessExtPacket(packet->pBuffer,packet->size,packet->opcode);
break;
default:;
}
}
---
OP_VERIFYUPSREQ (0x71) and OP_VERIFYUPSANSWER(0x72) are unused.
tear and feather me if something is wrong...
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Mldonkey-users] Emule Extended Protocol guesswork,
Jorfen <=