|
libgadu 1.12.2
|
Struktury danych | |
| union | gg_event_union |
Unia wszystkich zdarzeń zwracanych przez funkcje gg_watch_fd(), gg_dcc_watch_fd() i gg_dcc7_watch_fd(). Więcej... | |
| struct | gg_event |
| Opis zdarzenia. Więcej... | |
Funkcje | |
| void | gg_event_free (struct gg_event *e) |
| Zwalnia pamięć zajmowaną przez informację o zdarzeniu. | |
| struct gg_event * | gg_watch_fd (struct gg_session *sess) |
| Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze sesji. | |
Funkcje biblioteki zostały przygotowane w taki sposób, by móc z nich korzystać zarówno w trybie synchronicznym (działanie programu jest blokowane do zakończeniu operacji), jak i asynchroniczym (operacja jest rozpoczynana, a do czasu jej zakończenia program może robić inne rzeczy). Wyjątkiem są połączenia bezpośrednie, które pozwalają jedynie na połączenia asynchroniczne.
W trybie synchronicznym, po udanym zakończeniu funkcji gg_login(), należy w pętli wywoływać funkcję gg_watch_fd(), która po odebraniu informacji od serwera zwróci informację o zdarzeniu w strukturze gg_event lub NULL w przypadku błędu. Lista zdarzeń znajduje się poniżej.
Tryb asynchroniczny wymaga od programu obserwowania zmian na określonych deskryptorach za pomocą funkcji systemowych select() czy poll(), lub za pomocą mechanizmów pętli zdarzeń wbudowanych w wykorzystaną bibliotekę interfejsu użytkownika. Interesujące z punktu widzeniu połączenia asynchronicznego pola to fd określające obserwowany deskryptor, pole \ref gg_session::check check"
będące maską bitową typu \ref gg_check_t " połączyć");
exit(1);
}
for (;;) {
FD_ZERO(&rd);
FD_ZERO(&wd);
if ((sesja->check & GG_CHECK_READ))
FD_SET(sesja->fd, &rd);
if ((sesja->check & GG_CHECK_WRITE))
FD_SET(sesja->fd, &wd);
if (sesja->timeout) {
tv.tv_sec = sesja->timeout;
tv.tv_usec = 0;
}
wynik = select(sesja->fd + 1, &rd, &wd, NULL, (sesja->timeout) ? &tv : NULL);
if (!wynik) {
błąd("Przekroczono czas operacji");
gg_free_session(sesja);
exit(1);
}
if (wynik == -1) {
if (errno != EINTR) {
błąd("Błąd funkcji select()");
gg_free_session(sesja);
exit(1);
}
}
if (FD_ISSET(sesja->fd, &rd) || FD_ISSET(sesja->fd, &wd)) {
struct gg_event *zdarzenie;
zdarzenie = gg_watch_fd(sesja);
if (!zdarzenie) {
błąd("Połączenie przerwane");
gg_free_session(sesja);
exit(1);
}
switch (zdarzenie->type) {
case GG_EVENT_CONN_SUCCESS:
informacja("Połączono");
break;
case GG_EVENT_CONN_FAILED:
błąd("Nie można się połączyć");
gg_event_free(zdarzenie);
gg_free_session(sesja);
exit(1);
// ...
}
gg_event_free(zdarzenie);
}
}
\endcode
\note Przykład jest niekompletny, ponieważ powinien wysłać listę kontaktów
i co minutę wywoływać funkcję \c gg_ping().
@section events-list Zdarzenia
<table>
<tr>
<th>Typ zdarzenia</th>
<th>Pole \c gg_event</th>
<th>Typ pola</th>
<th>Opis</th>
</tr>
<tr>
<td>\c GG_EVENT_NONE</td>
<td>-</td>
<td>-</td>
<td> \ifile "/home/abuild/rpmbuild/BUILD/libgadu-1.12.2-build/libgadu-1.12.2/include/libgadu.h" Nie wydarzyło się nic wartego uwagi. gg_check_t"
, mówiącą czy obserwowana ma być możliwość odczytu i/lub zapisu oraz
\ref gg_session::timeout " siętimeout"
określające maksymalny czas wykonywania operacji. Gdy zaobserwuje
się zmianę na deskryptorze należy wywołać funkcję \c gg_watch_fd() i postępować
podobnie jak w trybie synchronicznym.
\note Po przekroczeniu czasu określonego w polu \c timeout, należy sprawdzić
wartość flagi \ref gg_session::soft_timeout " możnasoft_timeout"
. Jeśli jest równa \c 0 (tj. \c FALSE), można przerwać
połączenie i zwolnić zasoby, a jeśli jest różna (tj. \c TRUE), należy
wywołać \c gg_watch_fd() ustawiając wcześniej
\ref gg_session::timeout " połączyć");
exit(1);
}
informacja("Połączono");
gg_send_message(sesja, 23456, "Cześć!");
while ((zdarzenie = gg_watch_fd(sesja))) {
switch (zdarzenie->type) {
// ...
}
gg_event_free(zdarzenie);
}
gg_logoff(sesja);
gg_free_session(sesja);
\endcode
\note Przykład jest niekompletny, ponieważ powinien wysłać listę kontaktów
i co minutę wywoływać funkcję \c gg_ping().
@section sync-example Przykład połączenia asynchronicznego
@code
struct gg_session *sesja;
struct gg_login_params parametry;
struct timeval tv;
fd_set rd, wd;
int wynik;
memset(¶metry, 0, sizeof(parametry));
parametry.uin = 12345;
parametry.password = "hasło";
parametry.async = 1;
sesja = gg_login(¶metry);
if (!sesja) {
błąd("Nietimeout"
na \c 0, by dać szansę bibliotece zareagować na przekroczenie
czasu operacji. Za pomocą mechanizmu \c soft_timeout są realizowane próby
połączenia z innymi portami, np. gdy domyślny port 8074 jest zablokowany oraz
zwrotne połączenia bezpośrednie (7.x), gdy jedna ze stron połączenia znajduje
się za routerem NAT lub firewallem.
\note Po zerwaniu połączenia lub nieudanym logowaniu pole \ref
gg_session::state " sięstate"
przyjmuje wartość \c GG_STATE_IDLE. Przed dodaniem deskryptora \c fd do listy
obserwowanych, warto w ten sposób sprawdzić, czy dane połączenie nie jest już
nieaktywne.
\note Próba wysłania danych do zamkniętego połączenia (np. zerwanego przez
serwer) w systemach uniksowych powoduje wysłanie sygnału \c SIGPIPE, który
domyślnie powoduje unicestwienie procesu. Dlatego, aby pozwolić bibliotece
zareagować na zerwanie połączenia w sensowny sposób, należy ignorować sygnał
w aplikacji.
@section sync-example Przykład połączenia synchronicznego
@code
struct gg_session *sesja;
struct gg_login_params parametry;
struct gg_event *zdarzenie;
memset(¶metry, 0, sizeof(parametry));
parametry.uin = 12345;
parametry.password = "hasło";
sesja = gg_login(¶metry);
if (!sesja) {
błąd("Nie można
Zdarzenia związane z połączeniem
GG_EVENT_CONN_SUCCESS
-
-
Połączono z serwerem.
Pierwszą rzeczą, jaką należy zrobić jest wysłanie listy kontaktów.
GG_EVENT_CONN_FAILED
event.failure
gg_failure_t Nie udało się połączyć GG_EVENT_PONG - - Utrzymanie połączenia. Obecnie serwer nie wysyła już do klienta ramek utrzymania połączenia, polega wyłącznie na wysyłaniu ramek przez klienta. GG_EVENT_DISCONNECT - - Serwer zrywa połączenie. Zdarza się, gdy równolegle do serwera podłączy się druga sesja i trzeba zerwać połączenie z pierwszą. GG_EVENT_DISCONNECT_ACK - - Potwierdzenie zakończenia sesji. Informuje o tym, że zmiana stanu na niedostępny z opisem dotarła do serwera i można zakończyć połączenie TCP. Multilogowanie GG_EVENT_MULTILOGON_INFO event.multilogon_info gg_event_multilogon_info Informacja o innych sesjach multilogowania. GG_EVENT_MULTILOGON_MSG event.multilogon_msg gg_event_msg Wiadomość wysłana z innej sesji multilogowania. Wiadomości GG_EVENT_XML_EVENT event.xml_event gg_event_xml_event Otrzymano komunikat systemowy (7.7). GG_EVENT_MSG event.msg gg_event_msg Otrzymano wiadomość. Przekazuje również wiadomości systemowe od numeru 0. GG_EVENT_ACK event.ack gg_event_ack Potwierdzenie doręczenia wiadomości. GG_EVENT_TYPING_NOTIFICATION event.typing_notification gg_event_typing_notification Powiadomienie o pisaniu. GG_EVENT_IMAGE_REQUEST event.image_request gg_event_image_request Żądanie przesłania obrazka z wiadomości. GG_EVENT_IMAGE_REPLY event.image_reply gg_event_image_reply Przysłano obrazek z wiadomości. Lista kontaktów GG_EVENT_NOTIFY event.notify[] gg_notify_reply Informacja o statusach osób z listy kontaktów (przed 6.0). Zdarzenie należy obsługiwać, jeśli planuje się używać protokołu w wersji starszej niż domyślna. Ostatni element tablicy zawiera uin równy 0, a pozostałe pola są niezainicjowane. GG_EVENT_NOTIFY_DESCR event.notify_descr gg_event_notify_descr Informacja o statusie opisowym osoby z listy kontaktów (przed 6.0). Zdarzenie należy obsługiwać, jeśli planuje się używać protokołu w wersji starszej niż domyślna. GG_EVENT_STATUS event.status gg_event_status Zmiana statusu osoby z listy kontaktów (przed 6.0). Zdarzenie należy obsługiwać, jeśli planuje się używać protokołu w wersji starszej niż domyślna. GG_EVENT_NOTIFY60 event.notify60[] gg_event_notify60 Informacja o statusach osób z listy kontaktów. Ostatni element tablicy zawiera uin równy 0, a pozostałe pola są niezainicjowane. GG_EVENT_STATUS60 event.status60 gg_event_status60 Zmiana statusu osoby z listy kontaktów. GG_EVENT_USERLIST event.userlist gg_event_userlist Wynik importu lub eksportu listy kontaktów. GG_EVENT_USERLIST100_VERSION event.userlist100_version gg_event_userlist100_version Otrzymano numer wersji listy kontaktów na serwerze (10.0). GG_EVENT_USERLIST100_REPLY event.userlist100_reply gg_event_userlist100_reply Wynik importu lub eksportu listy kontaktów (10.0). Katalog publiczny GG_EVENT_PUBDIR50_SEARCH_REPLY event.pubdir50 \ref pubdir50 "\c gg_pubdir50_t" Odpowiedź katalogu publicznego. GG_EVENT_PUBDIR50_READ event.pubdir50 \ref pubdir50 "\c gg_pubdir50_t" Odczytano własne dane z katalogu publicznego. GG_EVENT_PUBDIR50_WRITE event.pubdir50 \ref pubdir50 "\c gg_pubdir50_t" Zmieniono własne dane w katalogu publicznym. Połączenia bezpośrednie GG_EVENT_DCC7_NEW event.dcc7_new gg_dcc7 Nowe połączenie bezpośrednie (7.x). GG_EVENT_DCC7_ACCEPT event.dcc7_accept gg_event_dcc7_accept Zaakceptowano połączenie bezpośrednie (7.x), nowy deskryptor. GG_EVENT_DCC7_REJECT event.dcc7_reject gg_event_dcc7_reject Odrzucono połączenie bezpośrednie (7.x). GG_EVENT_DCC7_PENDING event.dcc7_pending gg_event_dcc7_pending Trwa próba połączenia bezpośredniego (7.x), nowy deskryptor. GG_EVENT_DCC7_CONNECTED event.dcc7_connected gg_event_dcc7_connected Zestawiono połączenie bezpośrednie (7.x), nowy deskryptor. GG_EVENT_DCC7_DONE event.dcc7_connected gg_event_dcc7_connected Zakończono połączenie bezpośrednie (7.x). GG_EVENT_DCC7_ERROR event.dcc7_error \ref gg_error_t "\c gg_error_t" Błąd połączenia bezpośredniego (7.x).
| enum gg_check_t |
| enum gg_event_t |
Rodzaj zdarzenia.
| void gg_event_free | ( | struct gg_event * | e | ) |
Zwalnia pamięć zajmowaną przez informację o zdarzeniu.
Funkcję należy wywoływać za każdym razem gdy funkcja biblioteki zwróci strukturę gg_event.
| e | Struktura zdarzenia |
| struct gg_event * gg_watch_fd | ( | struct gg_session * | sess | ) |
Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze sesji.
Funkcja zwraca strukturę zdarzenia gg_event. Jeśli rodzaj zdarzenia to GG_EVENT_NONE, nie wydarzyło się jeszcze nic wartego odnotowania. Strukturę zdarzenia należy zwolnić funkcja gg_event_free().
| sess | Struktura sesji |
NULL jeśli wystąpił błąd