---------------------------------------------------------------------------

                         protok g*du-g*du 4.x
        (c) copyright 2001 by wojtek kaniewski <wojtekka@irc.pl>

--- 0) disclaimer ---------------------------------------------------------

wszystkie informacje bazuj na dowiadczeniach przeprowadzonych na moim
domowym komputerze. aden klient g*du-g*du nie zosta skrzywdzony podczas
przeprowadzania bada, blabla.

--- 1) transmisja, format wszystkich pakietw -----------------------------

w przeciwiestwie do zabawek typu icq, g*du-g*du korzysta z protokou tcp.
kady pakiet zawiera dwa stae pola:

        struct gg_header {
		int type;		/* typ pakietu */
		int length;		/* dugo reszty pakietu */
	};

dla uatwienia przyjmuj nastpujce dugoci zmiennych: sizeof(char) = 1,
sizeof(short) = 2, sizeof(int) = 4. oczywicie wszystkie liczby s zgodnie
z intelowym endianem. zakadam te, e wszystkie zmienne s bez znaku. nie
chce mi si wszdzie pisa `unsigned'.

pola, co do ktrych znaczenia nie mam pewnoci, lub w ogle nie mam pojcia,
skd si tam wziy, oznaczam `dunno'.

--- 2) zanim si poczymy -------------------------------------------------

eby wiedzie, z jakim serwerem mamy si poczy, naley poudawa przez
chwil Internet Explorera, poczy si z hostem `appmsg.gadu-gadu.pl'.

        GET /appsvc/appmsg.asp?fmnumber=<tutaj_numerek_gg> HTTP/1.0
	Host: appmsg.gadu-gadu.pl
	User-Agent: Mozilla/4.7 [en] (Win98; I)
	Pragma: no-cache

na co powinnimy dosta odpowied w stylu:

	HTTP/1.0 200 OK
	
	0 1 0 217.17.33.21:8074 217.17.33.21 217.17.33.21

co to oznacza? nie mam pojcia ;) wyglda na to, e cay g*du-g*du jest
przemylany i w przyszoci bdzie mona uywa rnych serwerw do rnych
rzeczy, typu szukanie, obsuga klientw itd. pki co, czy si trzeba na
pierwszy adres (tak, ten z portem).

--- 3) logowanie si -------------------------------------------------------

po poczeniu si portem 8074 serwera g*du-g*du, dostajemy pakiet typu 0x0001,
ktry na potrzeby tego dokumentu nazwiemy:

	#define GG_WELCOME 0x0001

reszta pakietu zawiera liczb, na podstawie ktrej liczony jest hash z hasa
klienta:

	struct gg_welcome {
		int key;		/* klucz szyfrowania hasa */
	};
	
kiedy mamy ju t warto moemy odesa pakiet logowania

	#define GG_LOGIN 0x000c

musimy poda kilka informacji:

	struct gg_login {
		int uin;		/* twj numerek */
		int hash;		/* hash hasa */
		int status;		/* status na dzie dobry */
		int dunno1;		/* == 0x0b */
		int local_ip;		/* mj adres ip */
		short local_port;	/* port, na ktrym sucham */
	};

jak obliczy hash hasa? hmm... nic prostszego. do kadej literki hasa
dodaje si jedynk, mnoy wszystko razem, a potem przez liczb podan przez
serwer. 

	for (hash = 1; *passwd; passwd++)
		hash *= (*passwd) + 1;

zrozumiae, racja? jeli wszystko si powiedzie, dostaniemy w odpowiedzi
pakiet typu

	#define GG_LOGIN_OK 0x0003

z polem header->length = 0, lub pakiet
	
	#define GG_LOGIN_FAILED 0x0009

--- 4) zmiana statusu -----------------------------------------------------

g*du-g*du przewiduje trzy stany klienta, ktre zmieniamy pakietem

	#define GG_NEW_STATUS 0x0002

	#define GG_STATUS_NOT_AVAIL 0x0001	/* rozczony */
	#define GG_STATUS_AVAIL 0x0002		/* dostpny */
	#define GG_STATUS_BUSY 0x0003		/* zajty */
	#define GG_STATUS_INVISIBLE 0x0014	/* niewidoczny */

	#define GG_STATUS_FRIENDS_MASK 0x8000	/* tylko dla przyjaci */
	
	struct gg_new_status {
		int status;			/* na jaki zmieni? */
	}

naley pamita, eby przed rozczeniem si z serwerem naley zmieni
stan na GG_STATUS_NOT_AVAIL. jeli ma by widoczny tylko dla przyjaci,
naley doda GG_STATUS_FRIENDS do normalnej wartoci stanu.

--- 5) ludzie przychodz, ludzie odchodz ---------------------------------

zaraz po zalogowaniu moemy wysa serwerowi list ludzikw w naszej licie
kontaktw, eby dowiedzie si, czy s w tej chwili dostpni. pakiet zawiera
dowoln ilo struktur gg_notify:

	#define GG_NOTIFY 0x0010
	
	struct gg_notify {
		int uin;		/* numerek danej osoby */
		char dunno1;		/* == 3 */
	};
	
jeli kto jest, serwer odpowie pakietem zawierajcym jedn lub wicej
struktur gg_notify_reply:

	#define GG_NOTIFY_REPLY 0x000c	/* tak, to samo co GG_LOGIN */
	
	struct gg_notify_reply {
		int uin;		/* numerek */
		int status;		/* status danej osoby */
		int remote_ip;		/* adres ip delikwenta */
		short remote_port;	/* port, na ktrym sucha klient */
		int dunno1;		/* == 0x0b */
		short dunno2;		/* znowu port? */
	};

jeli klient nie obsuguje pocze midzy klientami (np. g*du-g*du 3.x)
zamiast adresu ip jest 0, zamiast portu jest 2. niewane ;) w kadym razie,
jeli kto si pojawi w trakcie pracy, rwnie zostanie przysany ten
pakiet. proste? proste :)

eby doda kogo do listy w trakcie pracy, trzeba wysa niej opisany
pakiet. jego format jest identyczny jak przy GG_NOTIFY.

	#define GG_ADD 0x000d
	
	struct gg_add {
		int uin;		/* numerek */
		char dunno1;		/* == 3 */
	};

jeli kto opuci g*du-g*du lub zmieni stan, otrzymamy pakiet

	#define GG_STATUS 0x0002
	
	struct gg_status {
		int uin;		/* numerek */
		int status;		/* nowy stan */
	};

--- 6) wysyanie wiadomoci ------------------------------------------------
	
przejdmy do sedna sprawy ;)

	#define GG_SEND_MSG 0x000b

	#define GG_CLASS_MSG 0x0004
	#define GG_CLASS_CHAT 0x0008

	struct gg_send_msg {
		int recipient;
		int seq;
		int class;
		char message[];
	};

wiadomo, odbiorca. numer sekwencyjny, ktry wykorzystujemy potem do
potwierdzenia. nie wykluczone, e w jakis sposb odrnia si rne
rozmowy za pomoc czci bajtw, ale raczej nie ma znaczenia. klasa
wiadomoci pozwala odrni, czy wiadomo ma si pokaza w osobym
okienku czy jako kolejna linijka w okienku rozmowy. wyglda na to,
e to jaka bitmapa, wic najlepiej ola inne bity ni 0x0f. (czasem
klienty wysyaj 0x04, czasem 0x24)

serwer po otrzymaniu wiadomoci odsya informacj o tym. przy okazji
mwi, czy wiadomo dotara do odbiorcy (status == GG_ACK_DELIVERED),
czy moe jest offline i zostaa zakolejkowana (GG_ACK_QUEUED):

	#define GG_SEND_MSG_ACK 0x0005
	
	#define GG_ACK_DELIVERED 0x0002
	#define GG_ACK_QUEUED 0x0003

	struct gg_send_msg_ack {
		int status;
		int recipient;
		int seq;
	};

numer sekwencyjny i adresat ten sam, co przy wysyaniu.

--- 7) otrzymywanie wiadomoci ---------------------------------------------

zbyt wiele wyjanie chyba nie trzeba. wiadomo od kogo. nieznane pola to
co a'la numer sekwencyjny albo identyfikator okienka z rozmow albo nowe
dane dla setiathome. klasa wiadomoci taka sama jak przy wysyaniu:

	#define GG_RECV_MSG 0x000a
	
	struct gg_recv_msg {
		int sender;
		int dunno1;
		int dunno2;
		int class;
		char message[];
	};

--- 8) otrzymywanie wiadomoci ---------------------------------------------

od czasu do czasu klient wysya pakiet a'la ping do serwera i dostaje pust
odpowied. ciko stwierdzi, czy serwer wywala, jeli nie dostanie pinga
przez jaki czas, czy klient si rozcza, jeli serwer mu nie odpowie.
jako nie chce mi si sprawdza ;)

	#define GG_PING 0x0008
	
	/* nie ma niczego */
	
	#define GG_PONG 0x0007
	
	/* nie ma niczego */

--- 9) podzikowania -------------------------------------------------------

swj wkad w poznanie protokou mia Robert Wony, ktry opisa nowoci
w GG 4.6.

----------------------------------------------------------------------------

$Id: protocol.txt,v 1.1 2001/09/29 23:06:30 warmenhoven Exp $

