Traduire deserializeAs_ProtocolRequired [NOOB]

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#21
deja "Corps du buffer remis sur une syntaxe correcte: <Buffer 00 00 08 00 00 06 b5 00>" , c'est forcement pas bon
les 2 1ers 00 viennent de l'espace (surement un coup des illuminatis) , le 08 a rien a faire dans le corps , c'est la taille du corps (tu sais les 2 x 4 octets , 8 octets qu'il faudrait convertir en 2 integers (de 4 octets chacun)) et il manque a la fin 00 06 bb qui ont disparus , on ne sais pas pourquoi

ca devrait etre ca : 00 00 06 b5 00 00 06 bb (y'en a bien 8 , tu sais le 08 que tu as en trop dans le corps ou ton "messageLen: 8")
avec le bon corps et
let currentVersion = buf.readInt32BE(4)
ca devrait etre correct mais il va falloir que tu revois comment arriver a avoir 00 00 06 b5 00 00 06 bb avec 00 05 08 00 00 06 b5 00 00 06 bb (en gros pourquoi il faut virer les 3 1ers octets sans ajouter des 00 de l'espace , et pourquoi dans ce cas c'est 3 octets alors que ca pourrait parfois etre 2 ou 4 , indice , ca un rapporte avec ton "typeLen: 1")
 
Dernière édition:
Inscrit
4 Aout 2016
Messages
166
Reactions
0
#22
Wooh! Merci beaucoup pour ce commentaire ultra précis toons, je suis super content, y'a juste un truc qu'il faudrait que tu m'explique :p

La méthode que je pensais être la bonne:

Le code:
JavaScript:
let buff = packetsData.get(1) // J'obtiens les données du packet protocolID = 1
let header = packetManager.handleHeader(buff) // J'extrait les infos des deux premiers bytes
let body =  buff.slice(2, Buffer.byteLength(buff) ) // D'après openDofus, la têtes = 16 bits == 2 bytes

console.log('Buffer:\n', buff);
console.log('Tête du buffer:\n', header);
console.log('Corps du buffer:\n', body);

console.log('\n[METHODE 1] Infos tête du buffer:', header);
console.log('Infos corps du buffer', deserializeAsProtocolRequired(body) );

function deserializeAsProtocolRequired(buf) {
    let reader = new bufferReader(buf)
    let requiredVersion = buf.readInt32BE(0, 4) // Je recopie le fichier.as :p
    if ( requiredVersion < 0 ) throw new Error('Invalid version !')
    let currentVersion = buf.readInt32BE(4, 8)
    if ( currentVersion < 0 ) throw new Error('An Error occurred in game version parsing ! :(')

    return { requiredVersion: requiredVersion, currentVersion: currentVersion }
}
Méthode 1:
JavaScript:
function handleHeader(packet) {
    let header = packet.readInt16BE(0) // On lis les 16 premiers bytes pour avoir notre header.
    let id = header >> 2               // On décale l'header de 2 bits pour avoir l'id.
    let typeLen = header & 3           // BIN -> 1 = 0001, 2 -> 0010, 3 -> 0011
    let messageLen = getBodySize( typeLen, packet )

    return {id: id, typeLen: typeLen, messageLen: messageLen }
}
OUTPUT ( en retirant les throw new Error ):
Code:
> node test.js
Buffer:
<Buffer 00 05 08 00 00 06 b5 00 00 06 bb>
Tête du buffer:
{ id: 1, typeLen: 1, messageLen: 8 }
Corps du buffer:
<Buffer 08 00 00 06 b5 00 00 06 bb>

[METHODE 1] Infos tête du buffer: { id: 1, typeLen: 1, messageLen: 8 }
On peux clairement voir que ça merde ! :x

Avec l'explication de ToOns :
Le code reste inchangé sauf :
JavaScript:
let body =  buff.slice(3, Buffer.byteLength(buff) ) // D'après openDofus, la têtes = 16 bits == 2 bytes
En effet, je pensais que le header ne faisait que 2 bytes !

[CORRIGEZ MOI SI JE ME TROMPE]
Mais après réflexion, en regardant le schema sur openD,

(PacketID >> MessageLenghtType >> LenghtMessage >> Message)

Je me rend compte, que ce que je prenais pour header n'était que PacketID et MessageLengthType, sauf qu'il manque LengthMessage que je décode avec cette fonction :

JavaScript:
function getBodySize (typeLen, buffer) {
    let local5
    let local6
    let bLocal5
    let bLocal6

    switch ( typeLen ) {
        case 1:
            return buffer.readUInt8(2)
            break;
        case 2:
            return buffer.readUInt16BE(2)
            break;
        case 3:
            local5 = ( Buffer.byteLength( buffer, 'utf8' ) >> 16 ) & 0xFF // HEX -> 0xFF = BIN -> 1111 1111 = DECIMAL -> 255
            local6 =  Buffer.byteLength( buffer, 'utf8' ) & 0xFFFF        // HEX -> OxFFFF = BIN -> 1111 1111 1111 1111 = DECIMAL -> 65 535
            break;
        default:
            console.error(typeLen, 'is not a valid typeLen !');
            return undefined
    }
}
Faites pas attention à la case 3, c'est un échec de reverse enge. ^^

Du coup j'ai gardé 1 byte en plus, ce que m'a fucké tout le parsage de mon corps ! ^^'

Voilà voilà ! :)

[/CORRIGEZ MOI SI JE ME TROMPE]

Donc, maintenant si on exclut le troisième byte du corps, et que l'on utilise le même chemin qu'avant :

Output:
Code:
Infos corps du buffer { requiredVersion: 1717, currentVersion: 1723 }

OUIIIII OOOOOOOOOOOOUUUUUUUUUUUUIIIIIIIIIIII PUTAIN JE SUIS CHAUD LAA JE SUIS CHAAUD J'AI PARSE LE BUFFER PROTOCOLREQUIRED YA QUOOI ?!!!

Humm ! Désolé !

Bon bah voilà mon premier packet parsé que j'aurais jamais pus faire sans votre aide, @ToOnS et @dampenfr31 , c'est vraiment cool qu'il y est des gens comme vous qui prennent du temps pour aider les noobs comme moi vous ne pouvez pas imaginez la satisfaction que l'on à quand on à enfin compris le truc ! :)

Merci ! ;)
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#23
deja , ca :
let body = buff.slice(3, Buffer.byteLength(buff) ) // D'après openDofus, la têtes = 16 bits == 2 bytes

en fait le 3 , c'est les 2 octets que tu pensais etre le header (a "cause" de openDofus ?) + ton typeLen: 1 (qui en realité est le nombre d'octets qui vont servir a compter la taille du corps avec ton getBodySize) mais qui peut changer , il y'a des paquets tres gros dont la taille du corps depasse 256 octets (FF en hexa) , comme ca depasse FF il faut l'ecrire sur 2 octets ou 3 pour les vraiment enormes

ce serait mieux de le changer par :
let body = buff.slice(2+typeLen, Buffer.byteLength(buff) ) // D'après openDofus, la têtes = 16 bits == 2 bytes + le nombre d'octets qui vont servir a en deduire LengthMessage avec getBodySize

comme ca il va t'ejecter toujours le bon nombre d'octets que ca soit
2 si typelen = 0 (ca arrive meme si c'est etrange de recevoir un message sans corps) ou
3 si typelen = 1 (corps de 256 octets max) ou
4 si typelen = 2 (corps entre 256 octets et 256 x 256 octets) ou
5 si typelen = 3 (corps entre 256 x 256 octets et 256 x 256 x 256 octets au max)

du coup tu as compris que dans ton getBodySize , tu geres les 3 derniers cas mais tu ne geres pas le cas typelen = 0
pendant que j'y suis pour case 3 , il y'a plus simple :
return buffer.readUInt8(2)*256*256 + buffer.readUInt8(3)*256 + buffer.readUInt8(4)





bien plus tard tu vas t'apercevoir qu"il peut y avoir plusieurs messages (enfin plusieurs ID) dans un seul paquet , donc il faudra que tu regarde si ton buffer de corps est plus grand que LengthMessage c'est que derriere tu as un autre ID dans le meme paquet

parfois aussi il peut n'y avoir dans un paquet qu'un bout du message , si ton buffer (de corps) est plus petit que LengthMessage alors tu auras la suite du message dans le paquet suivant
 
Dernière édition:
Inscrit
4 Aout 2016
Messages
166
Reactions
0
#24
Super infos ! Merci je vais adapter mon code des que je sors de cours ! :)

Mais comment savoir si c'est un headers ? Ça pourrait être un corps :/ ( dans le cas ou deux buffers se suivent )

PS: ( je ne rejette pas la faute sur open Dofus, j'ai seulement mal compris ^^)
 
Inscrit
15 Aout 2016
Messages
20
Reactions
0
#25
Tu sais qu'un message commence forcément par 2 octets, ton header.

En l'interprétant, tu apprends le typeLen (compris entre 0 et 3). Grâce au typeLen, tu sais de combien d'octets ton paquet est composé.

Tu sais donc que, si ton paquet est plus long que désiré, les données "en trop", sont tout simplement un, voire plusieurs nouveaux paquets (commençant aussi à leur tour par un header, etc, etc).
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#26
tu compares la taille de ton "let body" avec LengthMessage ,
_si les 2 sont egaux alors tout va bien
_si la taille de "body" est plus grande que LengthMessage alors il y'a un nouveau header juste apres (et donc un nouveau corps) dans ce cas tu "slice" body (au bon endroit , donc de LengthMessage pour le 1er argument pour virer les octets de body que tu as deserialisé) dans Buffer et tu recommences comme si c'est un nouveau Buffer
_si la taille de "body" est plus petite que LengthMessage alors tu t'arretes la , tu deserialises pas , tu sauvegardes Buffer (pas body) dans un buffer temporaire et quand le prochain packet arrive tu ajoutes ton buffer temporaire au depart du Buffer du nouveau packet avant de passer Buffer a la moulinette
 
Dernière édition:
Inscrit
4 Aout 2016
Messages
166
Reactions
0
#27
Ah ouais !

Genre:
Si bufferLen > bufferBody alors prochainBufferBody = suite de bufferBody

?
 
Inscrit
15 Aout 2016
Messages
20
Reactions
0
#28
C'est exact. Les trames TCP ayant une taille maximale.
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#29
Ah ouais !

Genre:
Si bufferLen > bufferBody alors prochainBufferBody = suite de bufferBody

?
presque ,
Si bufferLen > bufferBody alors prochainBuffer = suite de Buffer
parceque faut garder le header pour simplifier , comme ca apres comme tu as le header tu le geres comme si c'est un packet normal et pas comme une suite de corps
 
Haut Bas