libgadu 1.12.2
Wczytywanie...
Szukanie...
Brak dopasowań
Połączenia bezpośrednie do wersji Gadu-Gadu 6.x

Struktury danych

struct  gg_dcc
 Połączenie bezpośrednie do wersji Gadu-Gadu 6.x. Więcej...

Funkcje

int gg_dcc_request (struct gg_session *sess, uin_t uin)
 Wysyła żądanie zwrotnego połączenia bezpośredniego.
int gg_dcc_fill_file_info (struct gg_dcc *d, const char *filename)
 Wypełnia pola struktury gg_dcc niezbędne do wysłania pliku.
int gg_dcc_fill_file_info2 (struct gg_dcc *d, const char *filename, const char *local_filename)
 Wypełnia pola struktury gg_dcc niezbędne do wysłania pliku.
struct gg_dccgg_dcc_get_file (uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
 Rozpoczyna odbieranie pliku przez zwrotne połączenie bezpośrednie.
struct gg_dccgg_dcc_send_file (uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
 Rozpoczyna wysyłanie pliku.
struct gg_dccgg_dcc_voice_chat (uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
 Rozpoczyna połączenie głosowe.
void gg_dcc_set_type (struct gg_dcc *d, int type)
 Ustawia typ przychodzącego połączenia bezpośredniego.
struct gg_dccgg_dcc_socket_create (uin_t uin, uint16_t port)
 Tworzy gniazdo nasłuchujące dla połączeń bezpośrednich.
int gg_dcc_voice_send (struct gg_dcc *d, char *buf, int length)
 Wysyła ramkę danych połączenia głosowego.
struct gg_eventgg_dcc_watch_fd (struct gg_dcc *h)
 Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
void gg_dcc_free (struct gg_dcc *d)
 Zwalnia zasoby używane przez połączenie bezpośrednie.

Opis szczegółowy

Nota
Funkcje opisane poniżej są zgodne ze starą wersją Gadu-Gadu. Nowy sposób przesyłania plików i przeprowadzania rozmów głosowych, wprowadzony w Gadu-Gadu 7.x, obsługiwany jest innymi funkcjami.

Gadu-Gadu, w przeciwieństwie do protokołów takich jak IRC, umożliwia połączenia w obie strony, bez względu na to, który klient nadaje, a który odbiera. Do tego, jeśli obie strony łączą się do serwera z tego samego publicznego adresu IP, serwer przesyła im ich adresy lokalne.

Ze względu na kierunek i sposób połączenia, wyróżniamy kilka sytuacji:

  • Mamy publiczny lub niepubliczny adres IP i chcemy wysłać plik do osoby z publicznym adresem – łączymy się z jego klientem, przedstawiamy się, mówimy czego chcemy i jeśli druga strona to zaakceptuje, zaczynam wysyłać plik. Przypomina zwykłe połączenia DCC klientów IRC.
  • Mamy publiczny adres IP i wysyłam plik do kogoś za NAT – wysyłamy na jego numer odpowiednią wiadomość przeznaczoną dla klienta (klasa GG_CLASS_CTCP). Druga strona po odebraniu takiego pakietu łączy się znaku o kodzie 0x02. druga strona, odebrawszy taki pakiet łączy się z nami, mówi, że proszono ją o połączenie i czeka na dalsze instrukcje. My wtedy wysyłamy informację, że owszem, chcemy wysłać plik, mówimy jaki i jeśli druga strona to zaakceptuje, nadajemy.
  • Mamy niepubliczny adres IP, tak samo jak i druga strona – tutaj nawiązanie połączenia jest możliwe tylko i wyłącznie, gdy oba klienty znajdują się w tej samej sieci (tj. oba łączą się z serwerem z tego samego adresu zewnętrznego) i wygląda to wtedy identycznie jak w punkcie pierwszym.

To, czy możemy się z kimś połączyć widać po porcie połączeń bezpośrednich drugiej strony, jaki dostajemy w zdarzeniach o zmianie statusu. Jeśli port jest niższy od 10, połączenie nie jest możliwe i należy wysłać specjalną wiadomość za pomocą funkcji gg_dcc_request().

Każde połączenie bezpośrednie i gniazdo nasłuchujące opisywane jest przez strukturę gg_dcc. To ostatnie możemy stworzyć za pomocą:

struct gg_dcc *gniazdo;
gniazdo = gg_dcc_socket_create(numer_gg, port_nasłuchujący);
if (!gniazdo)
błąd("Nie można utworzyć gniazda");
dodaj_do_obserwowanych(gniazdo);
struct gg_dcc * gg_dcc_socket_create(uin_t uin, uint16_t port)
Tworzy gniazdo nasłuchujące dla połączeń bezpośrednich.
Definicja dcc.c:384
Połączenie bezpośrednie do wersji Gadu-Gadu 6.x.
Definicja libgadu.h:429

Jeśli podamy port 0, libgadu spróbuje znaleźć pierwszy wolny port w okolicy domyślnego portu połączeń bezpośrednich. W przypadku powodzenia zwraca zaalokowaną strukturę gg_dcc, której najbardziej interesującym polem port zawierające numer przyznanego portu. Jeśli zwróci NULL, w zmiennej systemowej errno znajdzie się powód błędu: EINVAL to niewłaściwie parametry, ENOMEM to brak pamięci, a reszta możliwych błędów to błędy związane z gniazdami, np. EADDRINUSE gdy nie można znaleźć wolnego portu.

Następnie należy w zmiennej globalnej gg_dcc_port ustawić zaalokowany port, do zmiennej gg_dcc_ip wpisać publiczny adres IP i połączyć się z serwerem, żeby poinformować świat o swoich namiarach. Jeśli publiczny adres IP to 255.255.255.255, automatycznie jest przypisywany adres IP, z którego wychodzi połączenie do serwera. Należy pamiętać, że wartości tych zmiennych są używane przez gg_login(), więc ich wartości trzeba ustawić przez połączeniem.

Po połączeniu obserwujemy deskryptor gniazda nasłuchującego i gdy coś się pojawi, wywołujemy:

struct gg_event *zdarzenie;
zdarzenie = gg_dcc_watch_fd(gniazdo);
if (!zdarzenie) {
usuń_z_obserwowanych(gniazdo);
gg_dcc_free(gniazdo);
błąd("Poważny błąd!");
}
void gg_dcc_free(struct gg_dcc *d)
Zwalnia zasoby używane przez połączenie bezpośrednie.
Definicja dcc.c:1383
struct gg_event * gg_dcc_watch_fd(struct gg_dcc *h)
Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
Definicja dcc.c:570
Opis zdarzenia.
Definicja libgadu.h:1360

Błąd jest zwracany tylko w naprawdę krytycznych sytuacjach, gdy brakuje pamięci, lub nie powiodła się operacja na gniazdach, która nie miała się nie powieść (i przy okazji dalsza praca jest kompletnie bezcelowa).

Jeśli błędu nie będzie, dostaniemy informacje o zdarzeniu. W przypadku GG_SESSION_DCC_SOCKET mogą to być:

  • GG_EVENT_NONE – nic ciekawego się nie wydarzyło.
  • GG_EVENT_DCC_ERROR – wystąpił błąd, którego kod znajduje się w polu dcc_error struktury zdarzenia. W przypadku tego typu sesji możliwy jest tylko GG_ERROR_DCC_HANDSHAKE, który mówi, że nie udało się porozumieć z klientem, który się połączył.
  • GG_EVENT_DCC_NEW – nowe połączenie bezpośrednie. W polu dcc_new struktury zdarzenia jest struktura gg_dcc typu GG_SESSION_DCC, którą dodajemy do listy obserwowanych.

W każdym z tych wypadków należy po sprawdzeniu zdarzenia wywołać funkcję...

gg_event_free(zdarzenie);
void gg_event_free(struct gg_event *e)
Zwalnia pamięć zajmowaną przez informację o zdarzeniu.
Definicja events.c:66

...by zwolnić pamięć po zdarzeniu.

Gdy nadejdzie połączenie i dopiszemy je do listy obserwowanych, należy zwracać uwagę na następujące zdarzenia:

  • GG_EVENT_NONE – nic się nie zdarzyło.
  • GG_EVENT_DCC_CLIENT_ACCEPT – klient się przedstawił i czeka na autoryzację połączenia. Sprawdzamy w strukturze gg_dcc pole uin jest naszym numerem, a peer_uin jest na naszej liście kontaktów i czy chcemy z nim nawiązywać połączenie. Jeśli nie, to po prostu usuwamy połączenie:
    if (!połączenie_dozwolone(dcc->uin, dcc->peer_uin)) {
    usuń_z_obserwowanych(dcc);
    }
  • GG_EVENT_DCC_CALLBACK – poprosiliśmy klienta, żeby się z nami połączył za pomocą gg_dcc_request() i on teraz pyta się, czego chcemy. Zaraz po tym zdarzeniu należy wywołać funkcję:
    gg_dcc_set_type(dcc, rodzaj);
    void gg_dcc_set_type(struct gg_dcc *d, int type)
    Ustawia typ przychodzącego połączenia bezpośredniego.
    Definicja dcc.c:342
    gdzie connection_type to GG_SESSION_DCC_SEND lub GG_SESSION_DCC_VOICE. Jeśli wysyłamy plik, można od razu wywołać gg_dcc_fill_file_info(), ale nie jest to wymagane. Kiedy przyjdzie pora, biblioteka sama nas o to poprosi.
  • GG_EVENT_DCC_NEED_FILE_ACK – klient chce wysłać nam plik. W polu file_info struktury gg_dcc znajdują się wszystkie informacje na temat pliku, jak jego nazwa, rozmiar, atrybuty, data i czas utworzenia itp. Jeśli nie chcemy pliku, zamykamy połączenie w podobny sposób jak przy braku autoryzacji – zamykamy połączenie, ponieważ biblioteka nie potrafi odpowiadać negatywnie na prośby połączeń bezpośrednich. Jeśli plik nas interesuje, otwieramy lokalnie plik do zapisu i numer jego deskryptora zapisujemy do file_fd w strukturze gg_dcc. Jeśli chcemy wznowić przerwany transfer, otwieramy plik w trybie dopisywania i do pola offset wpisujemy ile bajtów już mamy. Biblioteka dalej się wszystkim zajmie.
  • GG_EVENT_DCC_NEED_FILE_INFO – wcześniej poprosiliśmy drugą stronę by się z nami połączyła, bo jest za NAT, a my chcemy wysłać plik. Możemy albo sami wypełnić strukturę file_info, którą biblioteka wyśle drugiej stronie, albo skorzystać z funkcji gg_dcc_fill_file_info().
    if (gg_dcc_fill_file_info(dcc, nazwa_pliku)) {
    błąd("Nie można otworzyć pliku");
    usuń_z_obserwowanych(dcc);
    }
    int gg_dcc_fill_file_info(struct gg_dcc *d, const char *filename)
    Wypełnia pola struktury gg_dcc niezbędne do wysłania pliku.
    Definicja dcc.c:108
  • GG_EVENT_DCC_DONE – zakończono transfer. Można przestać obserwować deskryptor i zwolnić zasoby po połączeniu.
  • GG_EVENT_DCC_ERROR – błąd. Możliwy kod błędu to GG_ERROR_DCC_HANDSHAKE, gdy nie powiodło się ustanowienie połączenia z klientem, GG_ERROR_DCC_NET kiedy nie udało się wysłać lub odczytać czegoś z gniazda, GG_ERROR_DCC_FILE gdy nie można było odczytać albo zapisać do pliku, GG_ERROR_DCC_EOF gdy plik lub połączenie zbyt wcześnie się skończy, GG_ERROR_DCC_REFUSED gdy użytkownik po drugiej stronie odmówił połączenia.

Tutaj również należy pamiętać o wywoływaniu gg_event_free().

Jeśli chcemy sami wysłać plik, sprawdzamy najpierw, czy druga strona może przyjąć połączenie, patrząc na jej port. Jeśli jest wyższy niż 10, możemy śmiało wywołać funkcję:

struct gg_dcc *dcc;
dcc = gg_dcc_send_file(adres_odbiorcy, port_odbiorcy, numer_wlasny, numer_odbiorcy);
if (!dcc)
błąd("Nie można ustanowić połączenia");
struct gg_dcc * gg_dcc_send_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
Rozpoczyna wysyłanie pliku.
Definicja dcc.c:305

Zaraz potem możemy wywołać funkcję gg_dcc_fill_file_info(), by uzupełnić informację o pliku...

gg_dcc_fill_file_info(conn, filename);

...ale jeśli tego nie zrobimy teraz, biblioteka poprosi nas o to w odpowiedniej za pomocą zdarzenia GG_EVENT_DCC_NEED_FILE_INFO.

Jeśli port jest podejrzanie niski, znaczy że połączenie jest niemożliwe i wtedy wywołujemy funkcję:

gg_dcc_request(sesja, numer_odbiorcy);
int gg_dcc_request(struct gg_session *sess, uin_t uin)
Wysyła żądanie zwrotnego połączenia bezpośredniego.
Definicja dcc.c:69

gdzie session to nasza sesja Gadu-Gadu (musi być połączona), a peer_uin to numer drugiej strony. Wiadomość spowoduje, że druga strona spróbuje się z nami połączyć, jeśli ma taką możliwość.

Gdy otrzymamy wiadomość klasy GG_CLASS_CTCP o treści składającej się z bajtu 0x02 znaczy, że ktoś chce nam coś przesłać i mamy się z nim połączyć. Wywołujemy wtedy:

struct gg_dcc *dcc;
dcc = gg_dcc_get_file(adres_nadawcy, port_nadawcy, numer_wlasny, numer_nadawcy);
if (!dcc)
błąd("Nie można ustanowić połączenia");
struct gg_dcc * gg_dcc_get_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
Rozpoczyna odbieranie pliku przez zwrotne połączenie bezpośrednie.
Definicja dcc.c:286

Dalej tak samo, jak przy zwykłym odbieraniu pliku.

Dokumentacja funkcji

◆ gg_dcc_request()

int gg_dcc_request ( struct gg_session * sess,
uin_t uin )

Wysyła żądanie zwrotnego połączenia bezpośredniego.

Funkcję wykorzystuje się, jeśli nie ma możliwości połączenia się z odbiorcą pliku lub rozmowy głosowej. Po otrzymaniu żądania druga strona spróbuje nawiązać zwrotne połączenie bezpośrednie z nadawcą. gg_dcc_request()

Parametry
sessStruktura sesji
uinNumer odbiorcy
Zwraca
Patrz gg_send_message_ctcp()

◆ gg_dcc_fill_file_info()

int gg_dcc_fill_file_info ( struct gg_dcc * d,
const char * filename )

Wypełnia pola struktury gg_dcc niezbędne do wysłania pliku.

Nota
Większą funkcjonalność zapewnia funkcja gg_dcc_fill_file_info2().
Parametry
dStruktura połączenia
filenameNazwa pliku
Zwraca
0 jeśli się powiodło, -1 w przypadku błędu

◆ gg_dcc_fill_file_info2()

int gg_dcc_fill_file_info2 ( struct gg_dcc * d,
const char * filename,
const char * local_filename )

Wypełnia pola struktury gg_dcc niezbędne do wysłania pliku.

Parametry
dStruktura połączenia
filenameNazwa pliku zapisywana w strukturze
local_filenameNazwa pliku w lokalnym systemie plików
Zwraca
0 jeśli się powiodło, -1 w przypadku błędu

◆ gg_dcc_get_file()

struct gg_dcc * gg_dcc_get_file ( uint32_t ip,
uint16_t port,
uin_t my_uin,
uin_t peer_uin )

Rozpoczyna odbieranie pliku przez zwrotne połączenie bezpośrednie.

Parametry
Konfiguracja IPAdres IP nadawcy
portPort nadawcy
my_uinWłasny numer
peer_uinNumer nadawcy
Zwraca
Struktura gg_dcc lub NULL w przypadku błędu

◆ gg_dcc_send_file()

struct gg_dcc * gg_dcc_send_file ( uint32_t ip,
uint16_t port,
uin_t my_uin,
uin_t peer_uin )

Rozpoczyna wysyłanie pliku.

Parametry
Konfiguracja IPAdres IP odbiorcy
portPort odbiorcy
my_uinWłasny numer
peer_uinNumer odbiorcy
Zwraca
Struktura gg_dcc lub NULL w przypadku błędu

◆ gg_dcc_voice_chat()

struct gg_dcc * gg_dcc_voice_chat ( uint32_t ip,
uint16_t port,
uin_t my_uin,
uin_t peer_uin )

Rozpoczyna połączenie głosowe.

Parametry
Konfiguracja IPAdres IP odbiorcy
portPort odbiorcy
my_uinWłasny numer
peer_uinNumer odbiorcy
Zwraca
Struktura gg_dcc lub NULL w przypadku błędu

◆ gg_dcc_set_type()

void gg_dcc_set_type ( struct gg_dcc * d,
int type )

Ustawia typ przychodzącego połączenia bezpośredniego.

Funkcję należy wywołać po otrzymaniu zdarzenia GG_EVENT_DCC_CALLBACK.

Parametry
dStruktura połączenia
typeRodzaj połączenia (GG_SESSION_DCC_SEND lub GG_SESSION_DCC_VOICE)

◆ gg_dcc_socket_create()

struct gg_dcc * gg_dcc_socket_create ( uin_t uin,
uint16_t port )

Tworzy gniazdo nasłuchujące dla połączeń bezpośrednich.

Funkcja przywiązuje gniazdo do pierwszego wolnego portu TCP.

Parametry
uinWłasny numer
portPreferowany port (jeśli równy 0 lub -1, próbuje się domyślnego)
Nota
Ze względu na możliwość podania wartości -1 do parametru będącego 16-bitową liczbą bez znaku, port 65535 nie jest dostępny.
Zwraca
Struktura gg_dcc lub NULL w przypadku błędu

◆ gg_dcc_voice_send()

int gg_dcc_voice_send ( struct gg_dcc * d,
char * buf,
int length )

Wysyła ramkę danych połączenia głosowego.

Parametry
dStruktura połączenia
bufBufor z danymi
lengthDługość bufora z danymi
Zwraca
0 jeśli się powiodło, -1 w przypadku błędu

◆ gg_dcc_watch_fd()

struct gg_event * gg_dcc_watch_fd ( struct gg_dcc * h)

Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.

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
hStruktura połączenia
Zwraca
Struktura zdarzenia lub NULL jeśli wystąpił błąd

◆ gg_dcc_free()

void gg_dcc_free ( struct gg_dcc * d)

Zwalnia zasoby używane przez połączenie bezpośrednie.

Parametry
dStruktura połączenia