mldonkey-users
[Top][All Lists]
Advanced

[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...    




reply via email to

[Prev in Thread] Current Thread [Next in Thread]