Protokół PolChat

1

Witam. Szukam juz troche po sieci i jakos dziwnie cicho. :-) Nie moge znalzc protokolu polchata, wie ktos moze skad go wziac ? W koncu troche botow czy innych programow powstalo, nie wierze ze ich autorzy siedzieli ze snifferem :-/

0

Istnieje pewien komponent do delphi który umożliwia komunikację z serwerem polchata, ale już go chyba nigdzie nie ma...

Autor ICeQ rzeczywiście siedział ze snifferem... reszta chyba także. Sam poszukuję protokołu. Jak znajdziesz jakiś artykuł, to chętnie bym poczytał.

0

Sam usiadlem ze snifferem a pozniej chyba mi sie znudzilo, teraz juz prawie nic nie pamietam ale to nie jest skomplikowane. Pamietam ze pomoglo mi jak zdekompilowalem zrodlo apletu polchatu. To byla oczywiscie masakra bo wszystkie zdefiniowane obiekty mialy nadane losowe nazwy.

Jesli chodzi o protokol to pakiety zbudowane sa nastepujaco:
naglowek - LLLLIISS
  LLLL (4 bajty) - dlugosc calego pakietu lacznie z naglowkiem
  II (2 bajty) - ilosc liczb w ciele
  SS (2 bajty) - ilosc stringow w ciele
cialo - liczby, stringi
  liczby - kazda po 2 bajty bez przerwy zgodnie z iloscia podana w naglowku
  stringi - kazdy string ma postac LL...0
    LL - dlugosc stringa ale nie znakow tylko bajtow
    ... - czesc wlasciwa stringa w UTF-8
    0 - bajt zerowy nieuwzgledniony w LL
0

A jak by to zaimplementować w delphi?

czy może być coś takiego?:

type TPolchatPackage = class(TObject)
        head : record
                LLLL : array[1..4] of byte; // dlugosc calego pakietu z naglowkiem
                II : array[1..2] of byte;   // ilosc liczb w ciele
                SS : array[1..2] of byte;   // ilosc lancychów w ciele
        end;
        body : record
                numbers : string; // kazda po 2 bajty
                strings : string{unknown};
                LL : integer; // dlugosc stringa (bajty)
                UTF : string; // czesc wlasciwa w UTF-8
                zero : byte;
        end;
end;

nie jestem tylko pewny ciała...

0

szczerze mowiac to nie wiem ale zostaly mi szkice procedur do wysylania i odbierania pakietow, moze Ci cos pomoga, wiem ze dzialaja, mozna sie za ich pomoca na pewno zalogowac:

uses SimpleTcp;

type
  TArString = array of string;
  TArWord = array of Word;

const
  SOI = SizeOf(Integer);
  SOW = SizeOf(Word);
  SOB = SizeOf(Byte);

procedure Rvrs(var Buf; Count: Integer);
var
  S: string;
  I: Integer;
begin
  SetLength(S, Count);
  Move(Buf, Pointer(S)^, Count);
  for I := 0 to Count - 1 do
    (PChar(@Buf) + I)^ := S[Count - I];
end;

function PolchatWrite(Sock: TTcpSocket; ArW: array of Word;
  ArS: array of string): Boolean;
var
  Bt: Byte;
  Count: Word;
  SoPck, I: Integer;
begin
  for I := 0 to High(ArS) do 
    ArS[I] := AnsiToUTF8(ArS[I]);
  Count := Length(ArW);
  SoPck := SOI + (2 * SOW) + (Count * SOW);
  for I := 0 to High(ArS) do
    Inc(SoPck, SOW + Length(ArS[I]) + SOB);
  I := SoPck;
  Rvrs(I, SOI);
  Dec(SoPck, Sock.Write(I, SOI));
  Rvrs(Count, SOW);
  Dec(SoPck, Sock.Write(Count, SOW));
  Count := Length(ArS);
  Rvrs(Count, SOW);
  Dec(SoPck, Sock.Write(Count, SOW));
  for I := 0 to High(ArW) do
  begin
    Rvrs(ArW[I], SOW);
    Dec(SoPck, Sock.Write(ArW[I], SOW));
  end;
  Bt := 0;
  for I := 0 to High(ArS) do
  begin
    Count := Length(ArS[I]);
    Rvrs(Count, SOW);
    Dec(SoPck, Sock.Write(Count, SOW));
    Dec(SoPck, Sock.Write(ArS[I][1], Length(ArS[I])));
    Dec(SoPck, Sock.Write(Bt, SOB));
  end;
  Result := SoPck = 0;
end;

function PolchatRead(Sock: TTcpSocket; var ArW: TArWord;
  var ArS: TArString): Boolean;
var
  Bt: Byte;
  Count: Word;
  SoPck, I: Integer;
begin
  I := Sock.ReadAll(SoPck, SOI);
  Rvrs(SoPck, SOI);
  Result := (I = SOI) and (SoPck >= SOI + (2 * SOW));
  if not Result then Exit;
  Dec(SoPck, I);
  Dec(SoPck, Sock.ReadAll(Count, SOW));
  Rvrs(Count, SOW);
  SetLength(ArW, Count);
  Dec(SoPck, Sock.ReadAll(Count, SOW));
  Rvrs(Count, SOW);
  SetLength(ArS, Count);
  for I := 0 to High(ArW) do
  begin
    Dec(SoPck, Sock.ReadAll(Count, SOW));
    Rvrs(Count, SOW);
    ArW[I] := Count;
  end;
  for I := 0 to High(ArS) do
  begin
    Dec(SoPck, Sock.ReadAll(Count, SOW));
    Rvrs(Count, SOW);
    SetLength(ArS[I], Count);
    Dec(SoPck, Sock.ReadAll(ArS[I][1], Length(ArS[I])));
    Dec(SoPck, Sock.Read(Bt, SOB));
  end;
  Result := SoPck = 0;
  for I := 0 to High(ArS) do
     ArS[I] := UTF8ToAnsi(ArS[I]);
end;

modul SimpleTCP mozna pobrac ponizej:
http://piechnat.w.interia.pl/SimpleTcp.pas
ale ja juz nie pamietam czy on jest skonczony :-D

0

A nie dało by się tego jakoś przedstawić w IdTcpClient albo zwykłym TCPClientSocket z D6? Z tym SimpleTCP jakoś się nie łapię.

W sumie to nawet w tym przypadku udało mi się nawiązać połączenie, ale miałem już lekki kłopot z tymi tablicami, oraz odbieraniem i wysyłaniem pakietów :(

0

Dobra, troche czasu minęło. Oto podpowiedź dla kolejnych ktorzy by szukali pomocy z budowa pakietow:

type TPolchatPacket = record
        pDD : longword;
        pII : word;
        pSI : word;
        PacketType : word;
        INTs : TStringList;
        STRs : TStringList;
end;

Albo krótko, na dobry początek budowa pakietu logującego (nie na podstawie TPolchatPacket):

// BEGIN //
DD DD DD DD 00 01  00 08  05  78 UU UU [string USER] 00 PP PP [string PASS] 00 00 00 00 00 RR RR [string ROOM] 00 AA AA [string AUTHLINK] 00 S1 S1 [string SERVER] 00 S2 S2 [string SERVER-STRING] 00 CC CC [string CLIENT] 00
// END //

DD DD DD DD - Długość pakietu ( w zupelnosci moze byc tez 00 00 DD DD)
PP - Długość nicka
RR - Długość pokoju
AA - Dlugosc linka
S1 - Długość nazwy hosta
S2 - Długość stringu z opcjami zaawansowanymi
CC - Informacja o kliencie

Dzięki temu możecie smiało się zalogować na polchat za pomoca zwyklego socketa poprzez Sendtext().

===
Natomiast budowa właściwego protokołu polchata wygląda następująco:

DD DD DD DD II II IS IS [INTs] [STRINGs]

STRING: DS DS STRING 00

Lub następująco z przykladem jednego inta i jednego stringa:
DD DD DD DD II II IS IS TP TP [INT] (...) [DS DS STRING 00] (...)

DD - Dlugosc pakietu
II - Ilosc Intow
IS - Ilosc Stringow
TP - Typ pakietu (pierwszy int)
INT - Dane liczbowe
DS - Dlugosc stringa
STRING - wartosc ciągu

Podstawowe typy pakietow (dla odbioru) to:

610: [display na czacie]
614: powitanie #1, param-string
615: JOIN
616: LEAVE
617: GUEST/UNGUEST & OP/UNOP
618: BUDDY/UNBUDDY
619: USERLIST
625: ROOM INFO
626: (Na wejsciu) kolory, conv-table, pokoje, etc.
630: Wchodzisz do pokoju

Hmm... brakuje czegos? Tak... nie ma procedure budujacych i rozkladajacych pakiety... no cóż. Odrobina myślenia Wam nie zaszkodzi ;)


Znacznie wiecej informacji o budowie i zastosowaniu protokolu znajdziecie pod adresem http://eter.sytes.net/polchatproto/
0

Jak to podlaczyc z tym modulem TCP

function PolchatWrite(Sock: TTcpSocket; ArW: array of Word;
  ArS: array of string): Boolean;

to co za zmienna dac w Sock ? podczas wykonywania tej procedury. ma ktos przykladowya procedure po
wcosnieciu buttona zeby sie zalogowac do tego polchatu ?

0

Za ciosem.
Udalo mi sie polaczyc z polchatem uzylem dokladnie tych funkcji wyzej z kompnentami Socket.
Kiedy odbieram dane w OnRead wpisalem:

var
  Bt: Byte;
  Count: Word;
  SoPck, I: Integer;
  ArW: TArWord;
  ArS: TArString
begin
  I := Sock.ReadAll(SoPck, SOI);
  Rvrs(SoPck, SOI);
  Result := (I = SOI) and (SoPck >= SOI + (2 * SOW));
  if not Result then Exit;
  Dec(SoPck, I);
  Dec(SoPck, Sock.ReadAll(Count, SOW));
  Rvrs(Count, SOW);
  SetLength(ArW, Count);
  Dec(SoPck, Sock.ReadAll(Count, SOW));
  Rvrs(Count, SOW);
  SetLength(ArS, Count);
  for I := 0 to High(ArW) do
  begin
    Dec(SoPck, Sock.ReadAll(Count, SOW));
    Rvrs(Count, SOW);
    ArW[I] := Count;
  end;
  for I := 0 to High(ArS) do
  begin
    Dec(SoPck, Sock.ReadAll(Count, SOW));
    Rvrs(Count, SOW);
    SetLength(ArS[I], Count);
    Dec(SoPck, Sock.ReadAll(ArS[I][1], Length(ArS[I])));
    Dec(SoPck, Sock.Read(Bt, SOB));
  end;
  Result := SoPck = 0;
  for I := 0 to High(ArS) do
     ArS[I] := UTF8ToAnsi(ArS[I]);

Teraz jest tak ze kiedy juz odczyta sie porcja danych W tablicy ArS i ArW w tablicy sa dane z pakietu. Wiec nizej wpisalem sobie tak:

For D := 0 to High(ArW) do Begin
  memo1.lines.add('ArW'+inttostr(D)+': ' + IntToStr(ArW[D]));
  ArrOfInts[D] := ArW[D];
  End;

  For D := 0 to High(ArS) do Begin
  memo1.lines.add('TSr'+inttostr(D)+': ' + ArS[D]);
  ArrOfString[D] := ArS[D];

Kiedy uzywam Memo1 i wyswietlam dane co tam sie odbiera jest OK
Kiedy jej nie ma wywala blad access violation
A takze kiedy wchodze na kanal gdzie jest malo osob jest ok
a jak wejde na kanal gdzie dostaje dluuuga liste USERLISt
wyskakuje mi blad Access violation.

Czy wiecie moze jak to rozwiazac by nie bylo problemow z odbieraniem tych danych?

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