view src/protocols/gg/libgg.h @ 6371:8f94cce8faa5

[gaim-migrate @ 6876] I think I touched almost every file. Here's what happened. I started off fixing up the Makefile.am and configure.ac files to help with the core/UI split some. Then I got annoyed with the build_{allow,deny}_list() functions that everything used, and decided to core/UI split privacy. While doing that, I decided to redesign the dialog. So now, a lot has changed, but not really so much. Just that most files got affected. Oh yeah, and the UI stuff was taken out of internal.h and moved to gtkinternal.h. If you use this, please be aware of this change. committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Tue, 05 Aug 2003 10:55:04 +0000
parents 5239a3b4ab33
children a0b7039de507
line wrap: on
line source

/* $Id: libgg.h 6513 2003-07-08 06:11:49Z faceprint $ */

/*
 *  (C) Copyright 2001 Wojtek Kaniewski <wojtekka@irc.pl>,
 *                     Robert J. Woźny <speedy@ziew.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License Version 2 as
 *  published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef __GG_LIBGG_H
#define __GG_LIBGG_H

#ifdef __cplusplus
extern "C" {
#endif

#if defined(sun) && !defined(INADDR_NONE)
  #define INADDR_NONE 0xffffffff
#endif

#include <sys/types.h>

/*
 * typ zmiennej określającej numerek danej osoby.
 */
typedef unsigned long uin_t;

/*
 * struktura opisująca daną sesję. tworzona przez gg_login().
 */
struct gg_session {
        int fd;         	/* podglądany deskryptor */
        int check;      	/* sprawdzamy zapis czy odczyt */
        int state;      	/* aktualny stan maszynki */
        int error;      	/* kod błędu dla GG_STATE_ERROR */
	int type;		/* rodzaj sesji. == GG_SESSION_GG */
	
        int async;      	/* czy połączenie jest asynchroniczne */
	int pid;        	/* pid procesu resolvera */
	int port;       	/* port, z którym się łączymy */
	int seq;        	/* numer sekwencyjny ostatniej wiadomości */
	int last_pong;  	/* czas otrzymania ostatniego ping/pong */

	unsigned int server_ip;	/* adres serwera */
	unsigned int client_ip;	/* adres klienta */
	int client_port;	/* port, na którym klient słucha */

	uin_t uin;		/* numerek klienta */
	char *password;		/* i jego hasło. zwalniane automagicznie */
        
	int initial_status;	/* początkowy stan klienta */

	char *recv_buf;		/* bufor na otrzymywane pakiety */
	int recv_done;		/* ile już wczytano do bufora */
        int recv_left;		/* i ile jeszcze trzeba wczytać */
};

/*
 * ogólna struktura opisująca stan wszystkich operacji http.
 */
struct gg_http {
        int fd;                 /* podglądany deskryptor */
        int check;              /* sprawdzamy zapis czy odczyt */
        int state;              /* aktualny stan maszynki */
        int error;              /* kod błędu dla GG_STATE_ERROR */
 	int type;		/* rodzaj sesji. == GG_SESSION_HTTP */
	
        int async;              /* czy połączenie asynchroniczne */
	int pid;                /* pid procesu resolvera */
	int port;               /* port, z którym się łączymy */

        char *query;            /* bufor zapytania http */
        char *header;           /* bufor nagłówka */
        int header_size;        /* rozmiar wczytanego nagłówka */
        char *body;             /* bufor otrzymanych informacji */
        int body_size;          /* ilość informacji */

        void *data;             /* dane danej operacji http */
};

/*
 * ogólna struktura opisująca różne sesje. przydatna w klientach.
 */
struct gg_common {
        int fd;                 /* podglądany deskryptor */
        int check;              /* sprawdzamy zapis czy odczyt */
        int state;              /* aktualny stan maszynki */
        int error;              /* kod błędu dla GG_STATE_ERROR */
	int type;		/* rodzaj sesji */
};

/*
 * rodzaje sesji.
 */
enum {
	GG_SESSION_GG = 1,	/* połączenie z serwerem gg */
	GG_SESSION_HTTP,	/* ogólna sesja http */
	GG_SESSION_SEARCH,	/* szukanie */
	GG_SESSION_REGISTER	/* rejestrowanie */
};

/*
 * różne stany asynchronicznej maszynki.
 */
enum {
        /* wspólne */
        GG_STATE_IDLE = 0,		/* nie powinno wystąpić. */
        GG_STATE_RESOLVING,             /* wywołał gethostbyname() */
	GG_STATE_CONNECTING,            /* wywołał connect() */
	GG_STATE_READING_DATA,		/* czeka na dane http */
	GG_STATE_ERROR,			/* wystąpił błąd. kod w x->error */

        /* gg_session */
	GG_STATE_CONNECTING_GG,         /* wywołał connect() */
	GG_STATE_READING_KEY,           /* czeka na klucz */
	GG_STATE_READING_REPLY,         /* czeka na odpowiedź */
	GG_STATE_CONNECTED,             /* połączył się */

        /* gg_http */
	GG_STATE_READING_HEADER,	/* czeka na nagłówek http */
	GG_STATE_PARSING,               /* przetwarza dane */
	GG_STATE_DONE                  /* skończył */
};

/*
 * dla zachowania kompatybilności wstecz. w wersji 1.0 będzie usunięte. oby.
 */
#define GG_STATE_WRITING_HTTP GG_STATE_READING_DATA
#define GG_STATE_WAITING_FOR_KEY GG_STATE_READING_KEY
#define GG_STATE_SENDING_KEY GG_STATE_READING_REPLY
#define GG_STATE_FINISHED GG_STATE_DONE

/*
 * co proces klienta powinien sprawdzać w deskryptorach?
 */
enum {
	GG_CHECK_NONE = 0,		/* nic. nie powinno wystąpić */
	GG_CHECK_WRITE = 1,		/* sprawdzamy możliwość zapisu */
	GG_CHECK_READ = 2		/* sprawdzamy możliwość odczytu */
};

struct gg_session *gg_login(uin_t uin, char *password, int async);
void gg_free_session(struct gg_session *sess);
void gg_logoff(struct gg_session *sess);
int gg_change_status(struct gg_session *sess, int status);
int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, char *message);
int gg_ping(struct gg_session *sess);

struct gg_notify_reply {
	uin_t uin;			/* numerek */
	unsigned long status;		/* status danej osoby */
	unsigned long remote_ip;	/* adres ip delikwenta */
	unsigned short remote_port;	/* port, na którym słucha klient */
	unsigned long version;		/* == 0x0b */
	unsigned short dunno2;		/* znowu port? */
}
#ifdef __GNUC__
__attribute__ ((packed))
#endif
;

struct gg_status {
	uin_t uin;			/* numerek */
	unsigned long status;		/* nowy stan */
}
#ifdef __GNUC__
__attribute__ ((packed))
#endif
;

enum {
	GG_EVENT_NONE = 0,
	GG_EVENT_MSG,
	GG_EVENT_NOTIFY,
	GG_EVENT_STATUS,
	GG_EVENT_ACK,
	GG_EVENT_CONN_FAILED,
	GG_EVENT_CONN_SUCCESS
};

/*
 * niedługo się tego pozbędę na rzecz sensownej obsługi błędów. --w
 */
enum {
	GG_FAILURE_RESOLVING = 1,
	GG_FAILURE_CONNECTING,
	GG_FAILURE_INVALID,
	GG_FAILURE_READING,
	GG_FAILURE_WRITING,
	GG_FAILURE_PASSWORD,
	GG_FAILURE_404
};

/*
 * rodzaje błędów, na razie używane przez http. bez rozczulania się nad
 * powodami. klient powie, że albo nie znalazł hosta, albo nie mógł się
 * połączyć, albo nie mógł wysłać, albo nie mógł odebrac. i tyle. jak
 * ktoś będzie chciał, to będzie mógł sprawdzić errno. ale po co?
 */
enum {
	GG_ERROR_RESOLVING = 1,
	GG_ERROR_CONNECTING,
	GG_ERROR_READING,
	GG_ERROR_WRITING
};

/*
 * struktura opisująca rodzaj zdarzenia. wychodzi z gg_watch_fd()
 */
struct gg_event {
        int type;
        union {
                struct {
                        uin_t sender;
			int msgclass;
			time_t time;
                        unsigned char *message;
                } msg;
                struct gg_notify_reply *notify;
                struct gg_status status;
                struct {
                        uin_t recipient;
                        int status;
                        int seq;
                } ack;
		int failure;
        } event;
};

struct gg_event *gg_watch_fd(struct gg_session *sess);
void gg_free_event(struct gg_event *e);

int gg_notify(struct gg_session *sess, uin_t *userlist, int count);
int gg_add_notify(struct gg_session *sess, uin_t uin);
int gg_remove_notify(struct gg_session *sess, uin_t uin);


/*
 * OBSŁUGA HTTP
 */

struct gg_http *gg_http_connect(char *hostname, int port, int async, char *method, char *path, char *header);
int gg_http_watch_fd(struct gg_http *h);
void gg_http_stop(struct gg_http *h);
void gg_free_http(struct gg_http *h);

/* 
 * SZUKANIE UŻYTKOWNIKÓW
 */

/*
 * struktura opisująca kryteria wyszukiwania. argument gg_search().
 */
struct gg_search_request {
	int active;		/* czy ma szukać tylko aktywnych? */

	/* mode 0 */
	char *nickname;		/* pseudonim */
	char *first_name;	/* imię */
	char *last_name;	/* nazwisko */
	char *city;		/* miasto */
	int gender;		/* płeć */
	int min_birth;		/* urodzony od roku... */
	int max_birth;		/* urodzony do roku... */
	
	/* mode 1 */
	char *email;		/* adres e-mail */

	/* mode 2 */
	char *phone;		/* numer telefonu */
	
	/* mode 3 */
	uin_t uin;		/* numerek */
};

/*
 * struktura opisująca rezultat wyszukiwania. pole gg_http.
 */
struct gg_search {
	int count;				/* ilość znalezionych */
	struct gg_search_result *results;	/* tabelka z nimi */
};

/*
 * pojedynczy rezultat wyszukiwania.
 */
struct gg_search_result {
	uin_t uin;		/* numerek */
	char *first_name;	/* imię */
	char *last_name;	/* nazwisko */
	char *nickname;		/* pseudonim */
	int born;		/* rok urodzenia */
	int gender;		/* płeć */
	char *city;		/* miasto */
	int active;		/* czy jest aktywny */
};

#define GG_GENDER_NONE 0	/* nie podano lub bez znaczenia */
#define GG_GENDER_FEMALE 1	/* kobieta */
#define GG_GENDER_MALE 2	/* mężczyzna */

struct gg_http *gg_search(struct gg_search_request *r, int async);
int gg_search_watch_fd(struct gg_http *f);
void gg_free_search(struct gg_http *f);

struct gg_search_request *gg_search_request_mode_0(char *nickname, char *first_name, char *last_name, char *city, int gender, int min_birth, int max_birth, int active);
struct gg_search_request *gg_search_request_mode_1(char *email, int active);
struct gg_search_request *gg_search_request_mode_2(char *phone, int active);
struct gg_search_request *gg_search_request_mode_3(uin_t uin, int active);

/*
 * OPERACJE NA KATALOGU PUBLICZNYM
 */

struct gg_pubdir {
	int success;		/* czy się udało */
	uin_t uin;		/* otrzymany numerek. 0 jeśli błąd */
};

struct gg_http *gg_register(char *email, char *password, int async);
void gg_free_register(struct gg_http *f);

int gg_pubdir_watch_fd(struct gg_http *f);
#define gg_register_watch_fd gg_pubdir_watch_fd

/*
 * jeśli chcemy sobie podebugować, wystarczy ustawić `gg_debug_level'.
 * niestety w miarę przybywania wpisów `gg_debug(...)' nie chciało mi
 * się ustawiać odpowiednich leveli, więc większość szła do _MISC.
 */

extern int gg_debug_level;

#define GG_DEBUG_NET 1
#define GG_DEBUG_TRAFFIC 2
#define GG_DEBUG_DUMP 4
#define GG_DEBUG_FUNCTION 8
#define GG_DEBUG_MISC 16

void gg_debug(int level, char *format, ...);

/*
 * Pare małych zmiennych do obsługi "http proxy"
 *   
 */
 
extern int gg_http_use_proxy;
extern char *gg_http_proxy_host;
extern int gg_http_proxy_port;

/*
 * -------------------------------------------------------------------------
 * poniżej znajdują się wewnętrzne sprawy biblioteki. zwykły klient nie
 * powinien ich w ogóle ruszać, bo i nie ma po co. wszystko można załatwić
 * procedurami wyższego poziomu, których definicje znajdują się na początku
 * tego pliku.
 * -------------------------------------------------------------------------
 */

int gg_resolve(int *fd, int *pid, char *hostname);
void gg_debug(int level, char *format, ...);
char *gg_alloc_sprintf(char *format, ...);
char *gg_get_line(char **ptr);
int gg_connect(void *addr, int port, int async);
void gg_read_line(int sock, char *buf, int length);
void gg_chomp(char *line);
char *gg_urlencode(const char *str);
int gg_http_hash(const unsigned char *email, const unsigned char *password);

#define GG_APPMSG_HOST "appmsg.gadu-gadu.pl"
#define GG_APPMSG_PORT 80
#define GG_PUBDIR_HOST "pubdir.gadu-gadu.pl"
#define GG_PUBDIR_PORT 80
#define GG_REGISTER_HOST "register.gadu-gadu.pl"
#define GG_REGISTER_PORT 80
#define GG_DEFAULT_PORT 8074
#define GG_HTTPS_PORT 443
#define GG_HTTP_USERAGENT "Mozilla/4.7 [en] (Win98; I)"

struct gg_header {
	unsigned long type;		/* typ pakietu */
	unsigned long length;		/* długość reszty pakietu */
}
#ifdef __GNUC__
__attribute__ ((packed))
#endif
;

#define GG_WELCOME 0x0001

struct gg_welcome {
	unsigned long key;		/* klucz szyfrowania hasła */
}
#ifdef __GNUC__
__attribute__ ((packed))
#endif
;
	
#define GG_LOGIN 0x000c

struct gg_login {
	uin_t uin;			/* twój numerek */
	unsigned long hash;		/* hash hasła */
	unsigned long status;		/* status na dzień dobry */
	unsigned long dunno;		/* == 0x0b */
	unsigned long local_ip;		/* mój adres ip */
	unsigned short local_port;	/* port, na którym słucham */
}
#ifdef __GNUC__
__attribute__ ((packed))
#endif
;

#define GG_LOGIN_OK 0x0003

#define GG_LOGIN_FAILED 0x0009

#define GG_NEW_STATUS 0x0002

#define GG_STATUS_NOT_AVAIL 0x0001	/* rozłączony */
#define GG_STATUS_AVAIL 0x0002		/* dostępny */
#define GG_STATUS_BUSY 0x0003		/* zajęty */
#define GG_STATUS_INVISIBLE 0x0014	/* niewidoczny (GG 4.6) */

#define GG_STATUS_FRIENDS_MASK 0x8000	/* tylko dla znajomych (GG 4.6) */

struct gg_new_status {
	unsigned long status;			/* na jaki zmienić? */
}
#ifdef __GNUC__
__attribute__ ((packed))
#endif
;

#define GG_NOTIFY 0x0010
	
struct gg_notify {
	uin_t uin;		/* numerek danej osoby */
	char dunno1;		/* == 3 */
}
#ifdef __GNUC__
__attribute__ ((packed))
#endif
;
	
#define GG_NOTIFY_REPLY 0x000c	/* tak, to samo co GG_LOGIN */
	
/* struct gg_notify_reply zadeklarowane wyżej */

#define GG_ADD_NOTIFY 0x000d
#define GG_REMOVE_NOTIFY 0x000e
	
struct gg_add_remove {
	uin_t uin;		/* numerek */
	char dunno1;		/* == 3 */
}
#ifdef __GNUC__
__attribute__ ((packed))
#endif
;

#define GG_STATUS 0x0002

/* struct gg_status zadeklarowane wcześniej */
	
#define GG_SEND_MSG 0x000b

#define GG_CLASS_QUEUED 0x0001
#define GG_CLASS_OFFLINE GG_CLASS_QUEUED
#define GG_CLASS_MSG 0x0004
#define GG_CLASS_CHAT 0x0008

struct gg_send_msg {
	unsigned long recipient;
	unsigned long seq;
	unsigned long msgclass;
}
#ifdef __GNUC__
__attribute__ ((packed))
#endif
;

#define GG_SEND_MSG_ACK 0x0005

#define GG_ACK_DELIVERED 0x0002
#define GG_ACK_QUEUED 0x0003
	
struct gg_send_msg_ack {
	unsigned long status;
	unsigned long recipient;
	unsigned long seq;
}
#ifdef __GNUC__
__attribute__ ((packed))
#endif
;

#define GG_RECV_MSG 0x000a
	
struct gg_recv_msg {
	unsigned long sender;
	unsigned long seq;
	unsigned long time;
	unsigned long msgclass;
}
#ifdef __GNUC__
__attribute__ ((packed))
#endif
;

#define GG_PING 0x0008
	
#define GG_PONG 0x0007

#ifdef __cplusplus
}
#endif

#endif /* __GG_LIBGG_H */

/*
 * Local variables:
 * c-indentation-style: k&r
 * c-basic-offset: 8
 * indent-tabs-mode: notnil
 * End:
 *
 * vim: shiftwidth=8:
 */