|
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 "/build/reproducible-path/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 \td-- 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 \td-- 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 \td-- 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. MultilogowanieGG_EVENT_MULTILOGON_INFO \tdevent.multilogon_infogg_event_multilogon_info \td Informacja o innych sesjach multilogowania. GG_EVENT_MULTILOGON_MSG \tdevent.multilogon_msggg_event_msg \td Wiadomość wysłana z innej sesji multilogowania. WiadomościGG_EVENT_XML_EVENT \tdevent.xml_eventgg_event_xml_event \td Otrzymano komunikat systemowy (7.7). GG_EVENT_MSG \tdevent.msggg_event_msg \td Otrzymano wiadomość. Przekazuje również wiadomości systemowe od numeru 0. GG_EVENT_ACK \tdevent.ackgg_event_ack \td Potwierdzenie doręczenia wiadomości. GG_EVENT_TYPING_NOTIFICATION \tdevent.typing_notificationgg_event_typing_notification \td Powiadomienie o pisaniu. GG_EVENT_IMAGE_REQUEST \tdevent.image_requestgg_event_image_request \td Żądanie przesłania obrazka z wiadomości. GG_EVENT_IMAGE_REPLY \tdevent.image_replygg_event_image_reply \td Przysłano obrazek z wiadomości. Lista kontaktówGG_EVENT_NOTIFY \tdevent.notify[]gg_notify_reply \td 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 \tdevent.notify_descrgg_event_notify_descr \td 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 \tdevent.statusgg_event_status \td 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 \tdevent.notify60[]gg_event_notify60 \td 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 \tdevent.status60gg_event_status60 \td Zmiana statusu osoby z listy kontaktów. GG_EVENT_USERLIST \tdevent.userlistgg_event_userlist \td Wynik importu lub eksportu listy kontaktów. GG_EVENT_USERLIST100_VERSION \tdevent.userlist100_versiongg_event_userlist100_version \td Otrzymano numer wersji listy kontaktów na serwerze (10.0). GG_EVENT_USERLIST100_REPLY \tdevent.userlist100_replygg_event_userlist100_reply \td Wynik importu lub eksportu listy kontaktów (10.0). Katalog publicznyGG_EVENT_PUBDIR50_SEARCH_REPLY \tdevent.pubdir50\ref pubdir50 gg_pubdir50_t"
</td>
<td> \ifile "/build/reproducible-path/libgadu-1.12.2/include/libgadu.h" Odpowiedź katalogu publicznego.
GG_EVENT_PUBDIR50_READ
event.pubdir50
gg_pubdir50_t Odczytano własne dane z katalogu publicznego. GG_EVENT_PUBDIR50_WRITE \tdevent.pubdir50\ref pubdir50 gg_pubdir50_t"
</td>
<td> \ifile "/build/reproducible-path/libgadu-1.12.2/include/libgadu.h" Zmieniono własne dane w katalogu publicznym.
Połączenia bezpośrednie
GG_EVENT_DCC7_NEW
event.dcc7_new
Nowe połączenie bezpośrednie (7.x).
GG_EVENT_DCC7_ACCEPT
event.dcc7_accept
Zaakceptowano połączenie bezpośrednie (7.x), nowy deskryptor.
GG_EVENT_DCC7_REJECT
event.dcc7_reject
Odrzucono połączenie bezpośrednie (7.x).
GG_EVENT_DCC7_PENDING
event.dcc7_pending
Trwa próba połączenia bezpośredniego (7.x), nowy deskryptor.
GG_EVENT_DCC7_CONNECTED
event.dcc7_connected
Zestawiono połączenie bezpośrednie (7.x), nowy deskryptor.
GG_EVENT_DCC7_DONE
event.dcc7_connected
Zakończono połączenie bezpośrednie (7.x).
GG_EVENT_DCC7_ERROR
event.dcc7_error
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