libgadu
1.12.2
|
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. Więcej... | |
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. Więcej... | |
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. Więcej... | |
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. Więcej... | |
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. Więcej... | |
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. Więcej... | |
void | gg_dcc_set_type (struct gg_dcc *d, int type) |
Ustawia typ przychodzącego połączenia bezpośredniego. Więcej... | |
struct gg_dcc * | gg_dcc_socket_create (uin_t uin, uint16_t port) |
Tworzy gniazdo nasłuchujące dla połączeń bezpośrednich. Więcej... | |
int | gg_dcc_voice_send (struct gg_dcc *d, char *buf, int length) |
Wysyła ramkę danych połączenia głosowego. Więcej... | |
struct gg_event * | gg_dcc_watch_fd (struct gg_dcc *h) |
Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia. Więcej... | |
void | gg_dcc_free (struct gg_dcc *d) |
Zwalnia zasoby używane przez połączenie bezpośrednie. Więcej... | |
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:
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.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ą:
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:
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ę...
...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: 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ę: 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()
. 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ę:
Zaraz potem możemy wywołać funkcję gg_dcc_fill_file_info()
, by uzupełnić informację o pliku...
...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ę:
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:
Dalej tak samo, jak przy zwykłym odbieraniu pliku.
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()
sess | Struktura sesji |
uin | Numer odbiorcy |
gg_send_message_ctcp()
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.
gg_dcc_fill_file_info2()
.d | Struktura połączenia |
filename | Nazwa 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.
d | Struktura połączenia |
filename | Nazwa pliku zapisywana w strukturze |
local_filename | Nazwa pliku w lokalnym systemie plików |
Rozpoczyna odbieranie pliku przez zwrotne połączenie bezpośrednie.
ip | Adres IP nadawcy |
port | Port nadawcy |
my_uin | Własny numer |
peer_uin | Numer nadawcy |
gg_dcc
lub NULL
w przypadku błędu Rozpoczyna wysyłanie pliku.
ip | Adres IP odbiorcy |
port | Port odbiorcy |
my_uin | Własny numer |
peer_uin | Numer odbiorcy |
gg_dcc
lub NULL
w przypadku błędu Rozpoczyna połączenie głosowe.
ip | Adres IP odbiorcy |
port | Port odbiorcy |
my_uin | Własny numer |
peer_uin | Numer odbiorcy |
gg_dcc
lub NULL
w przypadku błędu 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
.
d | Struktura połączenia |
type | Rodzaj połączenia (GG_SESSION_DCC_SEND lub GG_SESSION_DCC_VOICE ) |
Tworzy gniazdo nasłuchujące dla połączeń bezpośrednich.
Funkcja przywiązuje gniazdo do pierwszego wolnego portu TCP.
uin | Własny numer |
port | Preferowany port (jeśli równy 0 lub -1, próbuje się domyślnego) |
gg_dcc
lub NULL
w przypadku błędu int gg_dcc_voice_send | ( | struct gg_dcc * | d, |
char * | buf, | ||
int | length | ||
) |
Wysyła ramkę danych połączenia głosowego.
d | Struktura połączenia |
buf | Bufor z danymi |
length | Długość bufora z danymi |
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
.
h | Struktura połączenia |
NULL
jeśli wystąpił błąd void gg_dcc_free | ( | struct gg_dcc * | d | ) |
Zwalnia zasoby używane przez połączenie bezpośrednie.
d | Struktura połączenia |