Implementacja nowego protokołu Gadu-Gadu

1

Witam,
od paru dni zająłem się implementacją nowego protokołu GG. Dawniej z implementowałem już stary protokół GG, teraz potrzebna mi w pełni funkcjonalna nowa wersja. Wszystko pięknie fajnie, ale problem jednak w tym, że utknąłem przy pakiecie gg_login80 ( http://toxygen.net/libgadu/protocol/ ). Ogólnie sprawa wygląda tak - do połączenia użyłem winsocka oczywiście, pobieram adres IP z appmsg.gadu-gadu.pl, następnie się łączę, wszystko gra, otrzymuje GG_WELCOME, no i czas na wysłanie pakietu gg_login80, tak też przypisuje wartości pakietowi i wysyłam. W odpowiedzi otrzymuje w GG_HEADER wartość 49, więc podejrzewam, że jest to jakiś nieznany (przynajmniej w opisie owego protokołu) błąd. Stawiam, że problem leży w moim pakiecie GG_LOGIN80, źle wykodzony lub źle przypisany. Wszystko jednak dokładnie sprawdziłem i dalej otrzymuje błąd 49 i postanowiłem poprosić was o pomoc. A więc tak, moje pakiety wyglądają tak:

type
 TString64 = array[0..64]of Char;
 TString255 = array[0..255]of Char;
 TGGHeader = record
  _type,
  _length:integer;
 end;
 TGGWelcome = record
  _seed:integer;
 end;
 TGGLogin = record
  _number:integer;
  _language:array[0..2]of Char;
  _hash:shortint;
  _hash_result:TString64;
  _status,
  _flags,
  _features,
  _local_ip:integer;
  _local_port:smallint;
  _external_ip:integer;
  _external_port:smallint;
  _image_size:shortint;
  _unknown1:shortint;
  _version_len:integer;
  _version:TString255;
  _description_size:integer;
  _description:TString255;
 end;

Zaś przypisałem je o tak:

 
    GGHeader._type:=$31;
    GGHeader._length:=SizeOf(TGGLogin);
    send(Sock,GGHeader,sizeof(TGGHeader),0);
    Hash:=gg_sha_hash(GGPassword,GGWelcome._seed);
    Hash[20]:='\';
    Hash[21]:='0';
    with GGLogin do begin
     _number := GGNumber;
     _language := 'pl';
     _hash := $2;
     _hash_result:=Hash;
     _status:=$5;
     _flags:=$23;
     _features:=$7;
     _local_ip:=0;
     _local_port:=0;
     _external_ip:=0;
     _external_port:=0;
     _image_size:=$32;
     _unknown1:=$64;
     _version_len:=$26;
     _version:=GGVersion;
     _description_size:=$6;
     _description:=GGDesc;
    end;
    send(Sock,GGLogin,SizeOf(GGLogin),0);
    recv(Sock,GGHeader,SizeOf(TGGHeader),0);
    if(GGHeader._type=$35)then begin
     WriteLn('Zalogowano.');
    end else WriteLn(GGHeader._type);

Zmienne GGVersion oraz GGDesc:

 
 GGVersion:TString255 = 'Gadu-Gadu Client build 10.0.0.10450';
 GGDesc:TString255 = '!!!!!!';

Ogólnie nie ma sensu bym tutaj wklejał kod do hashowania hasła, bo gdyby hasło byłoby nieprawidłowe otrzymałbym w zwrocie kod 43.

Błagam o pomoc! :)

0

_description_size:integer;
_description:TString255;

z opisu zrozumiałem, że _description powinno być rozmiaru określonego przez _description_size, i analogicznie z version, a nie że description ma ileś-tam ile ci pasuje bajtów.
to komplikuje sprawę, bo oznacza, że nie da się pakietu przedstawić jako rekord (a bardziej jako strumień)

0
  
  _version_len:integer;
  _version:TString255;
  _description_size:integer;
  _description:TString255;

TString255 zmieniłem na string, i próbowałem wziąć to funkcją SizeOf, oraz strlen i nic. Normalnie ręce opadają. Może dynamiczne tablice char? Chociaż z tego co wiem to na jedno wyjdzie.

0
        uin: Integer;              /* numer Gadu-Gadu */
        language array [0..1] of char;     /* język: "pl" */
        hash_type: Byte; //albo Char       /* rodzaj funkcji skrótu hasła */
        hash array[0..63] of Char;        /* skrót hasła dopełniony \0 */
        status: Integer;           /* początkowy status połączenia */
        flags: Integer;            /* początkowe flagi połączenia */
        features: Integer;         /* opcje protokołu (0x00000367)*/
        local_ip: Integer;         /* lokalny adres połączeń bezpośrednich (nieużywany) */
        local_port: SmallInt;     /* lokalny port połączeń bezpośrednich (nieużywany) */
        external_ip: Integer;      /* zewnętrzny adres (nieużywany) */
        external_port: SmallInt;  /* zewnętrzny port (nieużywany) */
        image_size: Byte;      /* maksymalny rozmiar grafiki w KB */
        unknown1: Byte;        /* 0x64 */
        version_len: Integer;      /* długość ciągu z wersją (0x23) */
        version array of Char;       /* "Gadu-Gadu Client build 10.0.0.10450" (bez \0) */
        description_size: Integer; /* rozmiar opisu */
        description array of Char;   /* opis (nie musi wystąpić, bez \0) */
0
Azarien napisał(a)

nie da się pakietu przedstawić jako rekord

0

NazwaPakietu = Packed Record
...
end;
bez tego rozmiary mogą nie być takie jak chcesz

0
Azarien napisał(a)
Azarien napisał(a)

nie da się pakietu przedstawić jako rekord

da się, tylko że nie przejdzie wysłanie przez
WriteBuffer(pakiet, SizeOf(Pakiet));
a trzeba go będzie "ręcznie" zapisać do strumienia i dopiero taki wysłać

0

Uff, trochę czasu mi to zajęło jak to poprawnie napisać. Jednak udało mi się i to dzięki wam - dzięki :)
Jeśli komuś kiedyś się to przyda to oto jak to powinno wyglądać:

 TByte64 = packed array[0..63]of Byte;
 TGGHeader = packed record
  _type,
  _length:integer;
 end;
 TGGWelcome = packed record
  _seed:integer;
 end;
 TGGLogin = packed record
  _number:integer;
  _leangue:array[0..1]of Char;
  _hash:byte;
  _hash_result:TByte64;
  _status,
  _flags,
  _features,
  _local_ip:integer;
  _local_port:smallint;
  _external_ip:integer;
  _external_port:smallint;
  _image_size:byte;
  _unknown1:byte;
  _version_len:integer;
 end;
 TGGLoginOk = packed record
  _x:integer;
 end;
    GGVersion:=AnsiToUtf8(GGVersion);
    GGDesc:=AnsiToUtf8(GGDesc);
    with GGLogin do begin
     _number := GGNumber;
     _leangue := 'pl';
     _hash := $2;
     _hash_result:=Hash;
     _status:=$18;
     _flags:=$800000;
     _features:=$367 or $4000;
     _local_ip:=0;
     _local_port:=0;
     _external_ip:=0;
     _external_port:=0;
     _image_size:=$32;
     _unknown1:=$64;
     _version_len:=Length(GGVersion);
    end;
    GGHeader._type:=$31;
    GGHeader._length:=SizeOf(GGLogin)+SizeOf(I)+Length(GGVersion)+Length(GGDesc);
    send(Sock,GGHeader,sizeof(TGGHeader),0);
    send(Sock,GGLogin,SizeOf(GGLogin),0);
    send(Sock,GGVersion[1],Length(GGVersion),0);
    I:=Length(GGDesc);
    send(Sock,I,SizeOf(Integer),0);
    send(Sock,GGDesc[1],Length(GGDesc),0);
    recv(Sock,GGHeader,SizeOf(TGGHeader),0);
    if(GGHeader._type=$35)then begin
     WriteLn('Polaczono.');
     recv(Sock,GGLoginOk,SizeOf(TGGLoginOk),0);
     CreateThread(nil,0,@PingThread,nil,0,PTID);
     CreateThread(nil,0,@PackedThread,nil,0,PackedTID);
     GGHeader._type:=$12;
     GGHeader._length:=0;
     send(Sock,GGHeader,SizeOf(TGGHeader),0);

1 użytkowników online, w tym zalogowanych: 0, gości: 1