comparison src/protocols/gg/protocol.txt @ 2393:a7ecfd3f7714

[gaim-migrate @ 2406] Arkadiusz Miskiewicz\'s Gadu-Gadu plugin. I was able to figure out enough polish to be able to download Gadu-Gadu, create an account, and test the plugin. Imagine my shock when I got my info and it said I was a woman. Whoops. Also splitting plugins.c so that non-gtk stuff is in modules.c. gaim-core is almost ready for protocol implantaion. Also fixing an IRC bug. Also patiently waiting for anoncvs_gaim's lock in /cvsroot/gaim/gaim/pixmaps committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sat, 29 Sep 2001 23:06:30 +0000
parents
children 1ffac7cf4e94
comparison
equal deleted inserted replaced
2392:9965c0bbdb7c 2393:a7ecfd3f7714
1 ---------------------------------------------------------------------------
2
3 protokół g*du-g*du 4.x
4 (c) copyright 2001 by wojtek kaniewski <wojtekka@irc.pl>
5
6 --- 0) disclaimer ---------------------------------------------------------
7
8 wszystkie informacje bazują na doświadczeniach przeprowadzonych na moim
9 domowym komputerze. żaden klient g*du-g*du nie został skrzywdzony podczas
10 przeprowadzania badań, blabla.
11
12 --- 1) transmisja, format wszystkich pakietów -----------------------------
13
14 w przeciwieństwie do zabawek typu icq, g*du-g*du korzysta z protokołu tcp.
15 każdy pakiet zawiera dwa stałe pola:
16
17 struct gg_header {
18 int type; /* typ pakietu */
19 int length; /* długość reszty pakietu */
20 };
21
22 dla ułatwienia przyjmuję następujące długości zmiennych: sizeof(char) = 1,
23 sizeof(short) = 2, sizeof(int) = 4. oczywiście wszystkie liczby są zgodnie
24 z intelowym endianem. zakładam też, że wszystkie zmienne są bez znaku. nie
25 chce mi się wszędzie pisać `unsigned'.
26
27 pola, co do których znaczenia nie mam pewności, lub w ogóle nie mam pojęcia,
28 skąd się tam wzięły, oznaczam `dunno'.
29
30 --- 2) zanim się połączymy -------------------------------------------------
31
32 żeby wiedzieć, z jakim serwerem mamy się połączyć, należy poudawać przez
33 chwilę Internet Explorera, połączyć się z hostem `appmsg.gadu-gadu.pl'.
34
35 GET /appsvc/appmsg.asp?fmnumber=<tutaj_numerek_gg> HTTP/1.0
36 Host: appmsg.gadu-gadu.pl
37 User-Agent: Mozilla/4.7 [en] (Win98; I)
38 Pragma: no-cache
39
40 na co powinniśmy dostać odpowiedź w stylu:
41
42 HTTP/1.0 200 OK
43
44 0 1 0 217.17.33.21:8074 217.17.33.21 217.17.33.21
45
46 co to oznacza? nie mam pojęcia ;) wygląda na to, że cały g*du-g*du jest
47 przemyślany i w przyszłości będzie można używać różnych serwerów do różnych
48 rzeczy, typu szukanie, obsługa klientów itd. póki co, łączyć się trzeba na
49 pierwszy adres (tak, ten z portem).
50
51 --- 3) logowanie się -------------------------------------------------------
52
53 po połączeniu się portem 8074 serwera g*du-g*du, dostajemy pakiet typu 0x0001,
54 który na potrzeby tego dokumentu nazwiemy:
55
56 #define GG_WELCOME 0x0001
57
58 reszta pakietu zawiera liczbę, na podstawie której liczony jest hash z hasła
59 klienta:
60
61 struct gg_welcome {
62 int key; /* klucz szyfrowania hasła */
63 };
64
65 kiedy mamy już tą wartość możemy odesłać pakiet logowania
66
67 #define GG_LOGIN 0x000c
68
69 musimy podać kilka informacji:
70
71 struct gg_login {
72 int uin; /* twój numerek */
73 int hash; /* hash hasła */
74 int status; /* status na dzień dobry */
75 int dunno1; /* == 0x0b */
76 int local_ip; /* mój adres ip */
77 short local_port; /* port, na którym słucham */
78 };
79
80 jak obliczyć hash hasła? hmm... nic prostszego. do każdej literki hasła
81 dodaje się jedynkę, mnoży wszystko razem, a potem przez liczbę podaną przez
82 serwer.
83
84 for (hash = 1; *passwd; passwd++)
85 hash *= (*passwd) + 1;
86
87 zrozumiałe, racja? jeśli wszystko się powiedzie, dostaniemy w odpowiedzi
88 pakiet typu
89
90 #define GG_LOGIN_OK 0x0003
91
92 z polem header->length = 0, lub pakiet
93
94 #define GG_LOGIN_FAILED 0x0009
95
96 --- 4) zmiana statusu -----------------------------------------------------
97
98 g*du-g*du przewiduje trzy stany klienta, które zmieniamy pakietem
99
100 #define GG_NEW_STATUS 0x0002
101
102 #define GG_STATUS_NOT_AVAIL 0x0001 /* rozłączony */
103 #define GG_STATUS_AVAIL 0x0002 /* dostępny */
104 #define GG_STATUS_BUSY 0x0003 /* zajęty */
105 #define GG_STATUS_INVISIBLE 0x0014 /* niewidoczny */
106
107 #define GG_STATUS_FRIENDS_MASK 0x8000 /* tylko dla przyjaciół */
108
109 struct gg_new_status {
110 int status; /* na jaki zmienić? */
111 }
112
113 należy pamiętać, żeby przed rozłączeniem się z serwerem należy zmienić
114 stan na GG_STATUS_NOT_AVAIL. jeśli ma być widoczny tylko dla przyjaciół,
115 należy dodać GG_STATUS_FRIENDS do normalnej wartości stanu.
116
117 --- 5) ludzie przychodzą, ludzie odchodzą ---------------------------------
118
119 zaraz po zalogowaniu możemy wysłać serwerowi listę ludzików w naszej liście
120 kontaktów, żeby dowiedzieć się, czy są w tej chwili dostępni. pakiet zawiera
121 dowolną ilość struktur gg_notify:
122
123 #define GG_NOTIFY 0x0010
124
125 struct gg_notify {
126 int uin; /* numerek danej osoby */
127 char dunno1; /* == 3 */
128 };
129
130 jeśli ktoś jest, serwer odpowie pakietem zawierającym jedną lub więcej
131 struktur gg_notify_reply:
132
133 #define GG_NOTIFY_REPLY 0x000c /* tak, to samo co GG_LOGIN */
134
135 struct gg_notify_reply {
136 int uin; /* numerek */
137 int status; /* status danej osoby */
138 int remote_ip; /* adres ip delikwenta */
139 short remote_port; /* port, na którym słucha klient */
140 int dunno1; /* == 0x0b */
141 short dunno2; /* znowu port? */
142 };
143
144 jeśli klient nie obsługuje połączeń między klientami (np. g*du-g*du 3.x)
145 zamiast adresu ip jest 0, zamiast portu jest 2. nieważne ;) w każdym razie,
146 jeśli ktoś się pojawi w trakcie pracy, również zostanie przysłany ten
147 pakiet. proste? proste :)
148
149 żeby dodać kogoś do listy w trakcie pracy, trzeba wysłać niżej opisany
150 pakiet. jego format jest identyczny jak przy GG_NOTIFY.
151
152 #define GG_ADD 0x000d
153
154 struct gg_add {
155 int uin; /* numerek */
156 char dunno1; /* == 3 */
157 };
158
159 jeśli ktoś opuści g*du-g*du lub zmieni stan, otrzymamy pakiet
160
161 #define GG_STATUS 0x0002
162
163 struct gg_status {
164 int uin; /* numerek */
165 int status; /* nowy stan */
166 };
167
168 --- 6) wysyłanie wiadomości ------------------------------------------------
169
170 przejdźmy do sedna sprawy ;)
171
172 #define GG_SEND_MSG 0x000b
173
174 #define GG_CLASS_MSG 0x0004
175 #define GG_CLASS_CHAT 0x0008
176
177 struct gg_send_msg {
178 int recipient;
179 int seq;
180 int class;
181 char message[];
182 };
183
184 wiadomo, odbiorca. numer sekwencyjny, który wykorzystujemy potem do
185 potwierdzenia. nie wykluczone, że w jakis sposób odróżnia się różne
186 rozmowy za pomocą części bajtów, ale raczej nie ma znaczenia. klasa
187 wiadomości pozwala odróżnić, czy wiadomość ma się pokazać w osobym
188 okienku czy jako kolejna linijka w okienku rozmowy. wygląda na to,
189 że to jakaś bitmapa, więc najlepiej olać inne bity niż 0x0f. (czasem
190 klienty wysyłają 0x04, czasem 0x24)
191
192 serwer po otrzymaniu wiadomości odsyła informację o tym. przy okazji
193 mówi, czy wiadomość dotarła do odbiorcy (status == GG_ACK_DELIVERED),
194 czy może jest offline i została zakolejkowana (GG_ACK_QUEUED):
195
196 #define GG_SEND_MSG_ACK 0x0005
197
198 #define GG_ACK_DELIVERED 0x0002
199 #define GG_ACK_QUEUED 0x0003
200
201 struct gg_send_msg_ack {
202 int status;
203 int recipient;
204 int seq;
205 };
206
207 numer sekwencyjny i adresat ten sam, co przy wysyłaniu.
208
209 --- 7) otrzymywanie wiadomości ---------------------------------------------
210
211 zbyt wiele wyjaśnień chyba nie trzeba. wiadomo od kogo. nieznane pola to
212 coś a'la numer sekwencyjny albo identyfikator okienka z rozmową albo nowe
213 dane dla setiathome. klasa wiadomości taka sama jak przy wysyłaniu:
214
215 #define GG_RECV_MSG 0x000a
216
217 struct gg_recv_msg {
218 int sender;
219 int dunno1;
220 int dunno2;
221 int class;
222 char message[];
223 };
224
225 --- 8) otrzymywanie wiadomości ---------------------------------------------
226
227 od czasu do czasu klient wysyła pakiet a'la ping do serwera i dostaje pustą
228 odpowiedź. ciężko stwierdzić, czy serwer wywala, jeśli nie dostanie pinga
229 przez jakiś czas, czy klient się rozłącza, jeśli serwer mu nie odpowie.
230 jakoś nie chce mi się sprawdzać ;)
231
232 #define GG_PING 0x0008
233
234 /* nie ma niczego */
235
236 #define GG_PONG 0x0007
237
238 /* nie ma niczego */
239
240 --- 9) podziękowania -------------------------------------------------------
241
242 swój wkład w poznanie protokołu miał Robert Woźny, który opisał nowości
243 w GG 4.6.
244
245 ----------------------------------------------------------------------------
246
247 $Id: protocol.txt 2406 2001-09-29 23:06:30Z warmenhoven $
248