Hey hey ! C'est moi que v'là, bon j'ai pas chômé (Enfin peut-être un peu mais.. bon, c'est ouf ce que j'ai fais pour moi)
Bref voilà, j'ai un tout petit soucis, vraiment pas grand chose, enfin.. si c'était si peu je serais pas là à écrire ces lignes.
Donc j'vais balancer mon code (Il est commenté)
Traitement du Paquet TCP :
var Packet = PacketDotNet.Packet.ParsePacket(e.GetPacket().LinkLayerType, e.GetPacket().Data);
var ip = Packet.Extract<PacketDotNet.IPPacket>();
if(ip != null)
{
var tcp = Packet.Extract<PacketDotNet.TcpPacket>();
if(tcp != null)
{
//Tout ce qui est au dessus est un peu useless, c'est juste la partie sniff du paquet
byte[] buffer = Packet.PayloadPacket.PayloadPacket.PayloadData;
if (buffer.Length > 0)
{
BigEndianBinaryReader reader = new BigEndianBinaryReader(new MemoryStream(buffer)); //Créer un stream des datas du paquet
Int16 hiheader = reader.ReadInt16(); //Récupère le Hi Header du paquet
short packetID = (short)(hiheader >> 2); //Récupère l'ID du paquet (Enfin, du protocol contenu dans le paquet)
short lenType = (short)(hiheader & 3); //Récupère le lentype
uint length = 0;
switch (lenType)
{
case 0:
length = 0;
break;
case 1:
length = reader.ReadByte();
break;
case 2:
length = reader.ReadUInt16();
break;
case 3:
length = (uint)(((reader.ReadByte() & 255) << 16) + ((reader.ReadByte() & 255) << 8) + (reader.ReadByte() & 255));
break;
default:
length = 0;
break;
}
TreatPacket(reader, packetID, length, buffer); //Appel la fonction TreatPacket
//reader.Close();
}
}
}
Paquet Traitement :
private void TreatPacket(BigEndianBinaryReader Reader, short packetID, uint Lenght, byte[] Buffer)
{
switch(packetID)
{
case 5855: //Protocol ID correpondant à la classe 'com.ankamagames.dofus.network.messages.game.chat.ChatServerMessage
new ServerMessageManager(Reader, Lenght, richTextBox1, Buffer); //Créer un nouveau ServerMessageManager en lui passant, le stream des datas, la taille du contenu du paquet, (Le log de la lecture du packet), le buffer (Dont je ne me sers que pour analyser les bytes des paquets erronés)
break;
}
}
Gestion du paquet 'ChatServerMessage' :
public class ServerMessageManager
{
private uint _Length = 0; //La taille du contenu
private BigEndianBinaryReader _Reader; //Le stream des datas (Sans le Hi Header)
private RichTextBox _LogBox; //Le log des paquets
private byte[] _Buffer; //Le buffer pour read les bytes des paquets éronés, si paquet éronés il y'a
private double _SenderID = 0; //SenderID (Information du contenu du paquet)
private string _SenderName = ""; //SenderName (Information du contenu du paquet (Qui represent l'emetteur du message))
private uint _Channel = 0; //Le canal sur lequel à été envoyé le message
private string _Content = ""; //Le contenu du message (Le message en somme)
private uint _TimeStamp = 0; //Un truc dont je ne me sers pas
private string _FingerPrint = ""; //Un autre truc dont je ne me sers pas
// Dans cette classe je reproduis le plus fidelement possible les sources du jeu
public ServerMessageManager(BigEndianBinaryReader Reader, uint Length, RichTextBox LogBox, byte[] Buffer = null)
{
_Reader = Reader;
_Length = Length;
_LogBox = LogBox;
_Buffer = Buffer;
DeserializeChatServerMessage();
_Reader.Close(); //Ferme le stream une fois qu'il a disséquer le paquet
}
public void DeserializeChatServerMessage()
{
DeserializeChatAbstractServerMessage(); //Lecture du premier "paquet"
try //Préviens en cas d'eventuel erreur
{
_SenderID = _Reader.ReadDouble();
_Reader.BaseStream.Position = _Reader.BaseStream.Position + 1;
_SenderName = _Reader.ReadString();
LogMessage();
}
catch (Exception ex)
{
ErrorLogMessage("La fonction DeserializeChatServerMessage à retourner : " + ex.Message + " erreur");
}
}
public void DeserializeChatAbstractServerMessage()
{
try
{
_Channel = _Reader.ReadByte(); //Récupère l'ID du chan sur lequel le message à été envoyé
_Reader.BaseStream.Position = _Reader.BaseStream.Position + 1; //Se déplace de 1 dans le stream (Parce que je ne sais pas pourquoi mais entre le ChannelID et le contenu du message, il y'a un byte (Si vous avez une idée))
_Content = _Reader.ReadString(); //Récupère le contenu du message
_TimeStamp = _Reader.ReadUInt32(); //Récupère le timestamp (Contenu dans le contenu du paquet)
_Reader.BaseStream.Position = _Reader.BaseStream.Position + 1; //On se redéplace de 1 pour pouvoir lire le FingerPrint
_FingerPrint = _Reader.ReadString(); //Recupère le FingerPrint
}
catch (Exception ex)
{
ErrorLogMessage("La fonction DeserializeChatAbstractServerManager à retourner : " + ex.Message + " erreur"); //Si il y'a une erreur quelconque on le notifie dans les logs et on affiche un messageBox, qui contient entre autre le _Buffer (Ou la structure complète du paquet erronée)
}
}
private void LogMessage()
{
string Message = "(" + Enum.GetName(typeof(Utils.Channels), (uint)_Channel) + ") " + _SenderName + " : " + _Content + "\n"; //Cast le contenu du paquet pour le rendre lisible (Format Dofus en somme)
_LogBox.Invoke(new MethodInvoker(() => _LogBox.AppendText(Message)));
}
private void ErrorLogMessage(string ErrorMessage)
{
if (_Buffer != null) //Si j'ai passé le Buffer en argument dans le constructeur, alors il va afficher les bytes du paquet
ErrorMessage += "\n" + Utils.GetBytes(_Buffer);
_LogBox.Invoke(new MethodInvoker(() => _LogBox.AppendText(ErrorMessage + "\n"))); //Affichage du message d'erreur dans les logs
}
}
Donc, le chat Dofus correspondant :
![img]()
Et maintenant la sortie sur mon programme :

En gros la plupart des messages sont bien lu, mais pour une raison que je ne connais pas (Peut-être que si le message est trop long, la trame change pour récuperer le contenu du message ailleurs sur la trame ou je sais pas trop)
Et donc le message de Piicola est complétement bugué, je récupère une partie de son message là où j'aurai du récuperer son Nom.
Edit : Je viens de comprendre un truc en regardant les sources. (Plus j'avance, plus je m'y retrouve, ça fait vraiment plaisir)
En fait le byte que je devais sauter dans mon code (Pour read le contenu du paquet) bah c'est l'instance ID ! C'est vrai que j'avais lu quelque part que les paquets contenait ce truc là, mais j'y avais pas prêter attention, c'est en regardant writePacket (Dans la classe Network message) que j'ai pigé..
En gros le paquet est codé comme ça :
Type len est défini à partir de la taille du contenu du paquet
On écrit dans le flux un short qui contient "MsgID" décaler de 2 bits vers la gauche, on | avec le type len, et en fait dans mon code je lis un short >> 2 pour décaller les bits de 2 pour récupérer simplement le MsgID et ensuite je lis un autre short & 3 pour dissocier le type len du tout (3 étant le BITMASK qui est utilisé dans la classe ServerConnection d'ailleurs)
Alors j'ai pas l'habitude de faire des compliments, et je suis du genre à approuver le développement d'Ankama, et vu que je suis novice dans le domaine du réseau.. je trouve que c'est du p***** de génie.