libgadu 1.12.2

- Strona główna
- Dodatkowe strony
- Moduły
- Struktury Danych
- Pliki

Struktury danych | Wyliczenia | Funkcje
Obsługa zdarzeń
Połączenie z serwerem

Więcej...

## 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...

## Wyliczenia
enum | gg_check_t { GG_CHECK_NONE = 0, GG_CHECK_WRITE = 1, GG_CHECK_READ = 2 }
| Informacja o tym, czy biblioteka chce zapisywać i/lub czytać z deskryptora. Więcej...
enum | gg_event_t { GG_EVENT_NONE = 0, GG_EVENT_MSG, GG_EVENT_NOTIFY, GG_EVENT_NOTIFY_DESCR, GG_EVENT_STATUS, GG_EVENT_ACK, GG_EVENT_PONG, GG_EVENT_CONN_FAILED, GG_EVENT_CONN_SUCCESS, GG_EVENT_DISCONNECT, GG_EVENT_DCC_NEW, GG_EVENT_DCC_ERROR, GG_EVENT_DCC_DONE, GG_EVENT_DCC_CLIENT_ACCEPT, GG_EVENT_DCC_CALLBACK, GG_EVENT_DCC_NEED_FILE_INFO, GG_EVENT_DCC_NEED_FILE_ACK, GG_EVENT_DCC_NEED_VOICE_ACK, GG_EVENT_DCC_VOICE_DATA, GG_EVENT_PUBDIR50_SEARCH_REPLY, GG_EVENT_PUBDIR50_READ, GG_EVENT_PUBDIR50_WRITE, GG_EVENT_STATUS60, GG_EVENT_NOTIFY60, GG_EVENT_USERLIST, GG_EVENT_IMAGE_REQUEST, GG_EVENT_IMAGE_REPLY, GG_EVENT_DCC_ACK, GG_EVENT_DCC7_NEW, GG_EVENT_DCC7_ACCEPT, GG_EVENT_DCC7_REJECT, GG_EVENT_DCC7_CONNECTED, GG_EVENT_DCC7_ERROR, GG_EVENT_DCC7_DONE, GG_EVENT_DCC7_PENDING, GG_EVENT_XML_EVENT, GG_EVENT_DISCONNECT_ACK, GG_EVENT_TYPING_NOTIFICATION, GG_EVENT_USER_DATA, GG_EVENT_MULTILOGON_MSG, GG_EVENT_MULTILOGON_INFO, GG_EVENT_USERLIST100_VERSION, GG_EVENT_USERLIST100_REPLY, GG_EVENT_IMTOKEN, GG_EVENT_PONG110, GG_EVENT_JSON_EVENT, GG_EVENT_ACK110, GG_EVENT_CHAT_INFO, GG_EVENT_CHAT_INFO_GOT_ALL, GG_EVENT_CHAT_INFO_UPDATE, GG_EVENT_CHAT_CREATED, GG_EVENT_CHAT_INVITE_ACK }
| Rodzaj zdarzenia. Więcej...

## Funkcje
void | gg_event_free (struct gg_event *e)
| Zwalnia pamięć zajmowaną przez informację o zdarzeniu. Więcej...
struct gg_event * | gg_watch_fd (struct gg_session *sess)
| Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze sesji. Więcej...

## Opis szczegółowy

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 `check` będące maską bitową typu `gg_check_t` , mówiącą czy obserwowana ma być możliwość odczytu i/lub zapisu oraz `timeout` określające maksymalny czas wykonywania operacji. Gdy zaobserwuje się zmianę na deskryptorze należy wywołać funkcję `gg_watch_fd()` i postępować podobnie jak w trybie synchronicznym.

Nota
  Po przekroczeniu czasu określonego w polu `timeout`, należy sprawdzić wartość flagi `soft_timeout` . Jeśli jest równa `0` (tj. `FALSE`), można przerwać połączenie i zwolnić zasoby, a jeśli jest różna (tj. `TRUE`), należy wywołać `gg_watch_fd()` ustawiając wcześniej `timeout` na `0`, by dać szansę bibliotece zareagować na przekroczenie czasu operacji. Za pomocą mechanizmu `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.
  Po zerwaniu połączenia lub nieudanym logowaniu pole `state` przyjmuje wartość `GG_STATE_IDLE`. Przed dodaniem deskryptora `fd` do listy obserwowanych, warto w ten sposób sprawdzić, czy dane połączenie nie jest już nieaktywne.
  Próba wysłania danych do zamkniętego połączenia (np. zerwanego przez serwer) w systemach uniksowych powoduje wysłanie sygnału `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.

# Przykład połączenia synchronicznego

struct gg_session *sesja;
struct gg_login_params parametry;
struct gg_event *zdarzenie;
memset(&parametry, 0, sizeof(parametry));
parametry.uin = 12345;
parametry.password = "hasło";
sesja = gg_login(&parametry);
if (!sesja) {
błąd("Nie można się 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);

Nota
  Przykład jest niekompletny, ponieważ powinien wysłać listę kontaktów i co minutę wywoływać funkcję `gg_ping()`.

# Przykład połączenia synchronicznego

struct gg_session *sesja;
struct gg_login_params parametry;
struct timeval tv;
fd_set rd, wd;
int wynik;
memset(&parametry, 0, sizeof(parametry));
parametry.uin = 12345;
parametry.password = "hasło";
parametry.async = 1;
sesja = gg_login(&parametry);
if (!sesja) {
błąd("Nie można się 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);
}
}

Nota
  Przykład jest niekompletny, ponieważ powinien wysłać listę kontaktów i co minutę wywoływać funkcję `gg_ping()`.

# Zdarzenia

Typ zdarzenia | Pole `gg_event` | Typ pola | Opis
--- | --- | --- | ---
`GG_EVENT_NONE` | - | - |
Zdarzenia związane z połączeniem
`GG_EVENT_CONN_SUCCESS` | - | - |
`GG_EVENT_CONN_FAILED` | `event.failure` | `gg_failure_t` |
`GG_EVENT_PONG` | - | - |
`GG_EVENT_DISCONNECT` | - | - |
`GG_EVENT_DISCONNECT_ACK` | - | - |
Multilogowanie
`GG_EVENT_MULTILOGON_INFO` | `event.multilogon_info` | `gg_event_multilogon_info` |
`GG_EVENT_MULTILOGON_MSG` | `event.multilogon_msg` | `gg_event_msg` |
Wiadomości
`GG_EVENT_XML_EVENT` | `event.xml_event` | `gg_event_xml_event` |
`GG_EVENT_MSG` | `event.msg` | `gg_event_msg` |
`GG_EVENT_ACK` | `event.ack` | `gg_event_ack` |
`GG_EVENT_TYPING_NOTIFICATION` | `event.typing_notification` | `gg_event_typing_notification` |
`GG_EVENT_IMAGE_REQUEST` | `event.image_request` | `gg_event_image_request` |
`GG_EVENT_IMAGE_REPLY` | `event.image_reply` | `gg_event_image_reply` |
Lista kontaktów
`GG_EVENT_NOTIFY` | `event.notify`[] | `gg_notify_reply` |
`GG_EVENT_NOTIFY_DESCR` | `event.notify_descr` | `gg_event_notify_descr` |
`GG_EVENT_STATUS` | `event.status` | `gg_event_status` |
`GG_EVENT_NOTIFY60` | `event.notify60`[] | `gg_event_notify60` |
`GG_EVENT_STATUS60` | `event.status60` | `gg_event_status60` |
`GG_EVENT_USERLIST` | `event.userlist` | `gg_event_userlist` |
`GG_EVENT_USERLIST100_VERSION` | `event.userlist100_version` | `gg_event_userlist100_version` |
`GG_EVENT_USERLIST100_REPLY` | `event.userlist100_reply` | `gg_event_userlist100_reply` |
Katalog publiczny
`GG_EVENT_PUBDIR50_SEARCH_REPLY` | `event.pubdir50` | `gg_pubdir50_t` |
`GG_EVENT_PUBDIR50_READ` | `event.pubdir50` | `gg_pubdir50_t` |
`GG_EVENT_PUBDIR50_WRITE` | `event.pubdir50` | `gg_pubdir50_t` |
Połączenia bezpośrednie
`GG_EVENT_DCC7_NEW` | `event.dcc7_new` | `gg_dcc7` |
`GG_EVENT_DCC7_ACCEPT` | `event.dcc7_accept` | `gg_event_dcc7_accept` |
`GG_EVENT_DCC7_REJECT` | `event.dcc7_reject` | `gg_event_dcc7_reject` |
`GG_EVENT_DCC7_PENDING` | `event.dcc7_pending` | `gg_event_dcc7_pending` |
`GG_EVENT_DCC7_CONNECTED` | `event.dcc7_connected` | `gg_event_dcc7_connected` |
`GG_EVENT_DCC7_DONE` | `event.dcc7_connected` | `gg_event_dcc7_connected` |
`GG_EVENT_DCC7_ERROR` | `event.dcc7_error` | `gg_error_t` |

## Dokumentacja typów wyliczanych

enum gg_check_t

Informacja o tym, czy biblioteka chce zapisywać i/lub czytać z deskryptora.

Maska bitowa.

Wartości wyliczeń
GG_CHECK_NONE | Nie sprawdzaj niczego.
GG_CHECK_WRITE | Sprawdź możliwość zapisu.
GG_CHECK_READ | Sprawdź możliwość odczytu.

enum gg_event_t

Rodzaj zdarzenia.

Wartości wyliczeń
GG_EVENT_NONE | Nie wydarzyło się nic wartego uwagi.
GG_EVENT_MSG | Otrzymano wiadomość. Przekazuje również wiadomości systemowe od numeru 0.
GG_EVENT_NOTIFY | 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 | 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 | 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_ACK | Potwierdzenie doręczenia wiadomości.
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_CONN_FAILED | Nie udało się połączyć
GG_EVENT_CONN_SUCCESS | Połączono z serwerem. Pierwszą rzeczą, jaką należy zrobić jest wysłanie listy kontaktów.
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_DCC_NEW | Nowe połączenie bezpośrednie (6.x)
GG_EVENT_DCC_ERROR | Błąd połączenia bezpośredniego (6.x)
GG_EVENT_DCC_DONE | Zakończono połączenie bezpośrednie (6.x)
GG_EVENT_DCC_CLIENT_ACCEPT | Moment akceptacji klienta w połączeniu bezpośrednim (6.x)
GG_EVENT_DCC_CALLBACK | Zwrotne połączenie bezpośrednie (6.x)
GG_EVENT_DCC_NEED_FILE_INFO | Należy wypełnić `file_info` dla połączenia bezpośredniego (6.x)
GG_EVENT_DCC_NEED_FILE_ACK | Czeka na potwierdzenie pliku w połączeniu bezpośrednim (6.x)
GG_EVENT_DCC_NEED_VOICE_ACK | Czeka na potwierdzenie rozmowy w połączeniu bezpośrednim (6.x)
GG_EVENT_DCC_VOICE_DATA | Dane bezpośredniego połączenia głosowego (6.x)
GG_EVENT_PUBDIR50_SEARCH_REPLY | Odpowiedź katalogu publicznego.
GG_EVENT_PUBDIR50_READ | Odczytano własne dane z katalogu publicznego.
GG_EVENT_PUBDIR50_WRITE | Zmieniono własne dane w katalogu publicznym.
GG_EVENT_STATUS60 | Zmiana statusu osoby z listy kontaktów.
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_USERLIST | Wynik importu lub eksportu listy kontaktów.
GG_EVENT_IMAGE_REQUEST | Żądanie przesłania obrazka z wiadomości.
GG_EVENT_IMAGE_REPLY | Przysłano obrazek z wiadomości.
GG_EVENT_DCC_ACK | Potwierdzenie transmisji w połączeniu bezpośrednim (6.x)
GG_EVENT_DCC7_NEW | Nowe połączenie bezpośrednie (7.x)
GG_EVENT_DCC7_ACCEPT | Zaakceptowano połączenie bezpośrednie (7.x), nowy deskryptor.
GG_EVENT_DCC7_REJECT | Odrzucono połączenie bezpośrednie (7.x)
GG_EVENT_DCC7_CONNECTED | Zestawiono połączenie bezpośrednie (7.x), nowy deskryptor.
GG_EVENT_DCC7_ERROR | Błąd połączenia bezpośredniego (7.x)
GG_EVENT_DCC7_DONE | Zakończono połączenie bezpośrednie (7.x)
GG_EVENT_DCC7_PENDING | Trwa próba połączenia bezpośredniego (7.x), nowy deskryptor.
GG_EVENT_XML_EVENT | Otrzymano komunikat systemowy (7.7)
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.
GG_EVENT_TYPING_NOTIFICATION | Powiadomienie o pisaniu.
GG_EVENT_USER_DATA | Informacja o kontaktach.
GG_EVENT_MULTILOGON_MSG | Wiadomość wysłana z innej sesji multilogowania.
GG_EVENT_MULTILOGON_INFO | Informacja o innych sesjach multilogowania.
GG_EVENT_USERLIST100_VERSION | Otrzymano numer wersji listy kontaktów na serwerze (10.0)
GG_EVENT_USERLIST100_REPLY | Wynik importu lub eksportu listy kontaktów (10.0)
GG_EVENT_IMTOKEN | Otrzymano ciąg IMTOKEN (11.0)
GG_EVENT_PONG110 | Utrzymanie połączenia (11.0). Może służyć do synchronizacji czasu z serwerem.
GG_EVENT_JSON_EVENT | Otrzymano komunikat systemowy (11.0)
GG_EVENT_ACK110 | Potwierdzenie wysłania wiadomości (11.0)
GG_EVENT_CHAT_INFO | Otrzymano informację o konferencji (11.0).
GG_EVENT_CHAT_INFO_GOT_ALL | Informacje o wszystkich konferencjach zostały już wysłane (11.0). Otrzymywany po ostatnim pakiecie `GG_EVENT_CHAT_INFO`
GG_EVENT_CHAT_INFO_UPDATE | Aktualizacja informacji o konferencji (11.0). Dodanie, usunięcie jednego z uczestników.
GG_EVENT_CHAT_CREATED | Potwierdzenie utworzenia konferencji (11.0)
GG_EVENT_CHAT_INVITE_ACK | Potwierdzenie wysłania zaproszenia do konferencji (11.0)

## Dokumentacja funkcji

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`.

Parametry

  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()`.

Parametry

  sess | Struktura sesji

Zwraca
  Struktura zdarzenia lub `NULL` jeśli wystąpił błąd