comparison libpurple/protocols/gg/lib/libgadu.c @ 29538:6359fde67f4c

Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows. Refs #10542. The Windows build errors are the only reason this isn't on `im.pidgin.pidgin` already.
author John Bailey <rekkanoryo@rekkanoryo.org>
date Sun, 21 Feb 2010 16:52:42 +0000
parents 259bbfb423d4
children db6735e579f8
comparison
equal deleted inserted replaced
29474:551253814063 29538:6359fde67f4c
1 /* $Id: libgadu.c 16856 2006-08-19 01:13:25Z evands $ */ 1 /* $Id: libgadu.c 878 2009-11-16 23:48:19Z wojtekka $ */
2 2
3 /* 3 /*
4 * (C) Copyright 2001-2003 Wojtek Kaniewski <wojtekka@irc.pl> 4 * (C) Copyright 2001-2009 Wojtek Kaniewski <wojtekka@irc.pl>
5 * Robert J. Wo糿y <speedy@ziew.org> 5 * Robert J. Wo藕ny <speedy@ziew.org>
6 * Arkadiusz Mi秌iewicz <arekm@pld-linux.org> 6 * Arkadiusz Mi艣kiewicz <arekm@pld-linux.org>
7 * Tomasz Chili駍ki <chilek@chilan.com> 7 * Tomasz Chili艅ski <chilek@chilan.com>
8 * Adam Wysocki <gophi@ekg.chmurka.net>
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License Version 11 * it under the terms of the GNU Lesser General Public License Version
11 * 2.1 as published by the Free Software Foundation. 12 * 2.1 as published by the Free Software Foundation.
12 * 13 *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details. 17 * GNU Lesser General Public License for more details.
17 * 18 *
18 * You should have received a copy of the GNU Lesser General Public 19 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program; if not, write to the Free Software 20 * License along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
21 * USA. 22 * USA.
22 */ 23 */
23 24
24 #include "libgadu.h" 25 /**
26 * \file libgadu.c
27 *
28 * \brief G艂贸wny modu艂 biblioteki
29 */
25 30
26 #include <sys/types.h> 31 #include <sys/types.h>
27 #ifndef _WIN32
28 #include <sys/wait.h>
29 #include <sys/socket.h> 32 #include <sys/socket.h>
30 #include <netinet/in.h> 33 #include <netinet/in.h>
31 #include <arpa/inet.h> 34 #include <arpa/inet.h>
32 #ifdef sun 35 #ifdef sun
33 # include <sys/filio.h> 36 # include <sys/filio.h>
34 #endif 37 #endif
35 #else 38
36 #include <io.h> 39 #include "compat.h"
37 #include <fcntl.h> 40 #include "libgadu.h"
41 #include "protocol.h"
42 #include "resolver.h"
43 #include "libgadu-internal.h"
44
38 #include <errno.h> 45 #include <errno.h>
39 #define SHUT_RDWR SD_BOTH
40 #endif
41
42 #include "libgadu-config.h"
43
44 #include <errno.h>
45 #ifndef _WIN32
46 #include <netdb.h> 46 #include <netdb.h>
47 #endif
48 #ifdef __GG_LIBGADU_HAVE_PTHREAD
49 # include <pthread.h>
50 #endif
51 #include <stdarg.h> 47 #include <stdarg.h>
52 #include <stdio.h> 48 #include <stdio.h>
53 #include <stdlib.h> 49 #include <stdlib.h>
54 #include <string.h> 50 #include <string.h>
51 #include <signal.h>
52 #include <time.h>
55 #include <unistd.h> 53 #include <unistd.h>
56 #ifdef __GG_LIBGADU_HAVE_OPENSSL 54 #ifdef GG_CONFIG_HAVE_OPENSSL
57 # include <openssl/err.h> 55 # include <openssl/err.h>
58 # include <openssl/rand.h> 56 # include <openssl/rand.h>
59 #endif 57 #endif
60 58
61 #include "compat.h" 59 #define GG_LIBGADU_VERSION "1.9.0-rc2"
62 60
61 /**
62 * Poziom rejestracji informacji odpluskwiaj膮cych. Zmienna jest mask膮 bitow膮
63 * sk艂adaj膮c膮 si臋 ze sta艂ych \c GG_DEBUG_...
64 *
65 * \ingroup debug
66 */
63 int gg_debug_level = 0; 67 int gg_debug_level = 0;
68
69 /**
70 * Funkcja, do kt贸rej s膮 przekazywane informacje odpluskwiaj膮ce. Je艣li zar贸wno
71 * ten \c gg_debug_handler, jak i \c gg_debug_handler_session, s膮 r贸wne
72 * \c NULL, informacje s膮 wysy艂ane do standardowego wyj艣cia b艂臋du (\c stderr).
73 *
74 * \param level Poziom rejestracji
75 * \param format Format wiadomo艣ci (zgodny z \c printf)
76 * \param ap Lista argument贸w (zgodna z \c printf)
77 *
78 * \note Funkcja jest przes艂aniana przez \c gg_debug_handler_session.
79 *
80 * \ingroup debug
81 */
64 void (*gg_debug_handler)(int level, const char *format, va_list ap) = NULL; 82 void (*gg_debug_handler)(int level, const char *format, va_list ap) = NULL;
65 83
84 /**
85 * Funkcja, do kt贸rej s膮 przekazywane informacje odpluskwiaj膮ce. Je艣li zar贸wno
86 * ten \c gg_debug_handler, jak i \c gg_debug_handler_session, s膮 r贸wne
87 * \c NULL, informacje s膮 wysy艂ane do standardowego wyj艣cia b艂臋du.
88 *
89 * \param sess Sesja kt贸rej dotyczy informacja lub \c NULL
90 * \param level Poziom rejestracji
91 * \param format Format wiadomo艣ci (zgodny z \c printf)
92 * \param ap Lista argument贸w (zgodna z \c printf)
93 *
94 * \note Funkcja przes艂ania przez \c gg_debug_handler_session.
95 *
96 * \ingroup debug
97 */
98 void (*gg_debug_handler_session)(struct gg_session *sess, int level, const char *format, va_list ap) = NULL;
99
100 /**
101 * Port gniazda nas艂uchuj膮cego dla po艂膮cze艅 bezpo艣rednich.
102 *
103 * \ingroup ip
104 */
66 int gg_dcc_port = 0; 105 int gg_dcc_port = 0;
106
107 /**
108 * Adres IP gniazda nas艂uchuj膮cego dla po艂膮cze艅 bezpo艣rednich.
109 *
110 * \ingroup ip
111 */
67 unsigned long gg_dcc_ip = 0; 112 unsigned long gg_dcc_ip = 0;
68 113
114 /**
115 * Adres lokalnego interfejsu IP, z kt贸rego wywo艂ywane s膮 wszystkie po艂膮czenia.
116 *
117 * \ingroup ip
118 */
69 unsigned long gg_local_ip = 0; 119 unsigned long gg_local_ip = 0;
70 /* 120
71 * zmienne opisuj眂e parametry proxy http. 121 /**
122 * Flaga w艂膮czenia po艂膮cze艅 przez serwer po艣rednicz膮cy.
123 *
124 * \ingroup proxy
125 */
126 int gg_proxy_enabled = 0;
127
128 /**
129 * Adres serwera po艣rednicz膮cego.
130 *
131 * \ingroup proxy
72 */ 132 */
73 char *gg_proxy_host = NULL; 133 char *gg_proxy_host = NULL;
134
135 /**
136 * Port serwera po艣rednicz膮cego.
137 *
138 * \ingroup proxy
139 */
74 int gg_proxy_port = 0; 140 int gg_proxy_port = 0;
75 int gg_proxy_enabled = 0; 141
142 /**
143 * Flaga u偶ywania serwera po艣rednicz膮cego jedynie dla us艂ug HTTP.
144 *
145 * \ingroup proxy
146 */
76 int gg_proxy_http_only = 0; 147 int gg_proxy_http_only = 0;
148
149 /**
150 * Nazwa u偶ytkownika do autoryzacji serwera po艣rednicz膮cego.
151 *
152 * \ingroup proxy
153 */
77 char *gg_proxy_username = NULL; 154 char *gg_proxy_username = NULL;
155
156 /**
157 * Has艂o u偶ytkownika do autoryzacji serwera po艣rednicz膮cego.
158 *
159 * \ingroup proxy
160 */
78 char *gg_proxy_password = NULL; 161 char *gg_proxy_password = NULL;
79 162
80 #ifndef lint 163 #ifndef DOXYGEN
164
165 #ifndef lint
81 static char rcsid[] 166 static char rcsid[]
82 #ifdef __GNUC__ 167 #ifdef __GNUC__
83 __attribute__ ((unused)) 168 __attribute__ ((unused))
84 #endif 169 #endif
85 = "$Id: libgadu.c 16856 2006-08-19 01:13:25Z evands $"; 170 = "$Id: libgadu.c 878 2009-11-16 23:48:19Z wojtekka $";
86 #endif
87
88 #ifdef _WIN32
89 /**
90 * Deal with the fact that you can't select() on a win32 file fd.
91 * This makes it practically impossible to tie into purple's event loop.
92 *
93 * -This is thanks to Tor Lillqvist.
94 * XXX - Move this to where the rest of the the win32 compatiblity stuff goes when we push the changes back to libgadu.
95 */
96 static int
97 socket_pipe (int *fds)
98 {
99 SOCKET temp, socket1 = -1, socket2 = -1;
100 struct sockaddr_in saddr;
101 int len;
102 u_long arg;
103 fd_set read_set, write_set;
104 struct timeval tv;
105
106 temp = socket(AF_INET, SOCK_STREAM, 0);
107
108 if (temp == INVALID_SOCKET) {
109 goto out0;
110 }
111
112 arg = 1;
113 if (ioctlsocket(temp, FIONBIO, &arg) == SOCKET_ERROR) {
114 goto out0;
115 }
116
117 memset(&saddr, 0, sizeof(saddr));
118 saddr.sin_family = AF_INET;
119 saddr.sin_port = 0;
120 saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
121
122 if (bind(temp, (struct sockaddr *)&saddr, sizeof (saddr))) {
123 goto out0;
124 }
125
126 if (listen(temp, 1) == SOCKET_ERROR) {
127 goto out0;
128 }
129
130 len = sizeof(saddr);
131 if (getsockname(temp, (struct sockaddr *)&saddr, &len)) {
132 goto out0;
133 }
134
135 socket1 = socket(AF_INET, SOCK_STREAM, 0);
136
137 if (socket1 == INVALID_SOCKET) {
138 goto out0;
139 }
140
141 arg = 1;
142 if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
143 goto out1;
144 }
145
146 if (connect(socket1, (struct sockaddr *)&saddr, len) != SOCKET_ERROR ||
147 WSAGetLastError() != WSAEWOULDBLOCK) {
148 goto out1;
149 }
150
151 FD_ZERO(&read_set);
152 FD_SET(temp, &read_set);
153
154 tv.tv_sec = 0;
155 tv.tv_usec = 0;
156
157 if (select(0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR) {
158 goto out1;
159 }
160
161 if (!FD_ISSET(temp, &read_set)) {
162 goto out1;
163 }
164
165 socket2 = accept(temp, (struct sockaddr *) &saddr, &len);
166 if (socket2 == INVALID_SOCKET) {
167 goto out1;
168 }
169
170 FD_ZERO(&write_set);
171 FD_SET(socket1, &write_set);
172
173 tv.tv_sec = 0;
174 tv.tv_usec = 0;
175
176 if (select(0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR) {
177 goto out2;
178 }
179
180 if (!FD_ISSET(socket1, &write_set)) {
181 goto out2;
182 }
183
184 arg = 0;
185 if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
186 goto out2;
187 }
188
189 arg = 0;
190 if (ioctlsocket(socket2, FIONBIO, &arg) == SOCKET_ERROR) {
191 goto out2;
192 }
193
194 fds[0] = socket1;
195 fds[1] = socket2;
196
197 closesocket (temp);
198
199 return 0;
200
201 out2:
202 closesocket (socket2);
203 out1:
204 closesocket (socket1);
205 out0:
206 closesocket (temp);
207 errno = EIO; /* XXX */
208
209 return -1;
210 }
211 #endif 171 #endif
212 172
213 /* 173 #endif /* DOXYGEN */
214 * gg_libgadu_version() 174
215 * 175 /**
216 * zwraca wersj libgadu. 176 * Zwraca wersj臋 biblioteki.
217 * 177 *
218 * - brak 178 * \return Wska藕nik na statyczny bufor z wersj膮 biblioteki.
219 * 179 *
220 * wersja libgadu. 180 * \ingroup version
221 */ 181 */
222 const char *gg_libgadu_version() 182 const char *gg_libgadu_version()
223 { 183 {
224 return GG_LIBGADU_VERSION; 184 return GG_LIBGADU_VERSION;
225 } 185 }
226 186
227 /* 187 /**
228 * gg_fix32() 188 * \internal Zamienia kolejno艣膰 bajt贸w w 32-bitowym s艂owie.
229 * 189 *
230 * zamienia kolejno舵 bajt體 w liczbie 32-bitowej tak, by odpowiada砤 190 * Ze wzgl臋du na little-endianowo艣膰 protoko艂u Gadu-Gadu, na maszynach
231 * kolejno禼i bajt體 w protokole GG. ze wzgl阣u na LE-owo舵 serwera, 191 * big-endianowych odwraca kolejno艣膰 bajt贸w w s艂owie.
232 * zamienia tylko na maszynach BE-wych. 192 *
233 * 193 * \param x Liczba do zamiany
234 * - x - liczba do zamiany 194 *
235 * 195 * \return Liczba z odpowiedni膮 kolejno艣ci膮 bajt贸w
236 * liczba z odpowiedni kolejno禼i bajt體. 196 *
197 * \ingroup helper
237 */ 198 */
238 uint32_t gg_fix32(uint32_t x) 199 uint32_t gg_fix32(uint32_t x)
239 { 200 {
240 #ifndef __GG_LIBGADU_BIGENDIAN 201 #ifndef GG_CONFIG_BIGENDIAN
241 return x; 202 return x;
242 #else 203 #else
243 return (uint32_t) 204 return (uint32_t)
244 (((x & (uint32_t) 0x000000ffU) << 24) | 205 (((x & (uint32_t) 0x000000ffU) << 24) |
245 ((x & (uint32_t) 0x0000ff00U) << 8) | 206 ((x & (uint32_t) 0x0000ff00U) << 8) |
246 ((x & (uint32_t) 0x00ff0000U) >> 8) | 207 ((x & (uint32_t) 0x00ff0000U) >> 8) |
247 ((x & (uint32_t) 0xff000000U) >> 24)); 208 ((x & (uint32_t) 0xff000000U) >> 24));
248 #endif 209 #endif
249 } 210 }
250 211
251 /* 212 /**
252 * gg_fix16() 213 * \internal Zamienia kolejno艣膰 bajt贸w w 16-bitowym s艂owie.
253 * 214 *
254 * zamienia kolejno舵 bajt體 w liczbie 16-bitowej tak, by odpowiada砤 215 * Ze wzgl臋du na little-endianowo艣膰 protoko艂u Gadu-Gadu, na maszynach
255 * kolejno禼i bajt體 w protokole GG. ze wzgl阣u na LE-owo舵 serwera, 216 * big-endianowych zamienia kolejno艣膰 bajt贸w w s艂owie.
256 * zamienia tylko na maszynach BE-wych. 217 *
257 * 218 * \param x Liczba do zamiany
258 * - x - liczba do zamiany 219 *
259 * 220 * \return Liczba z odpowiedni膮 kolejno艣ci膮 bajt贸w
260 * liczba z odpowiedni kolejno禼i bajt體. 221 *
222 * \ingroup helper
261 */ 223 */
262 uint16_t gg_fix16(uint16_t x) 224 uint16_t gg_fix16(uint16_t x)
263 { 225 {
264 #ifndef __GG_LIBGADU_BIGENDIAN 226 #ifndef GG_CONFIG_BIGENDIAN
265 return x; 227 return x;
266 #else 228 #else
267 return (uint16_t) 229 return (uint16_t)
268 (((x & (uint16_t) 0x00ffU) << 8) | 230 (((x & (uint16_t) 0x00ffU) << 8) |
269 ((x & (uint16_t) 0xff00U) >> 8)); 231 ((x & (uint16_t) 0xff00U) >> 8));
270 #endif 232 #endif
271 } 233 }
272 234
273 /* 235 /**
274 * gg_login_hash() // funkcja wewn阾rzna 236 * \internal Liczy skr贸t z has艂a i ziarna.
275 * 237 *
276 * liczy hash z has砤 i danego seeda. 238 * \param password Has艂o
277 * 239 * \param seed Ziarno podane przez serwer
278 * - password - has硂 do hashowania 240 *
279 * - seed - warto舵 podana przez serwer 241 * \return Warto艣膰 skr贸tu
280 *
281 * hash.
282 */ 242 */
283 unsigned int gg_login_hash(const unsigned char *password, unsigned int seed) 243 unsigned int gg_login_hash(const unsigned char *password, unsigned int seed)
284 { 244 {
285 unsigned int x, y, z; 245 unsigned int x, y, z;
286 246
302 } 262 }
303 263
304 return y; 264 return y;
305 } 265 }
306 266
307 #ifndef _WIN32 267 /**
308 268 * \internal Odbiera od serwera dane binarne.
309 /* 269 *
310 * gg_resolve() // funkcja wewn阾rzna 270 * Funkcja odbiera dane od serwera zajmuj膮c si臋 TLS w razie konieczno艣ci.
311 * 271 *
312 * tworzy potok, forkuje si i w drugim procesie zaczyna resolvowa 272 * \param sess Struktura sesji
313 * podanego hosta. zapisuje w sesji deskryptor potoku. je秎i co tam 273 * \param buf Bufor na danymi
314 * b阣zie gotowego, znaczy, 縠 mo縩a wczyta struct in_addr. je秎i 274 * \param length D艂ugo艣膰 bufora
315 * nie znajdzie, zwraca INADDR_NONE. 275 *
316 * 276 * \return To samo co funkcja systemowa \c read
317 * - fd - wska糿ik gdzie wrzuci deskryptor
318 * - pid - gdzie wrzuci pid procesu potomnego
319 * - hostname - nazwa hosta do zresolvowania
320 *
321 * 0, -1.
322 */
323 int gg_resolve(int *fd, int *pid, const char *hostname)
324 {
325 int pipes[2], res;
326 struct in_addr a;
327 int errno2;
328
329 gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve(%p, %p, \"%s\");\n", fd, pid, hostname);
330
331 if (!fd || !pid) {
332 errno = EFAULT;
333 return -1;
334 }
335
336 if (pipe(pipes) == -1)
337 return -1;
338
339 if ((res = fork()) == -1) {
340 errno2 = errno;
341 close(pipes[0]);
342 close(pipes[1]);
343 errno = errno2;
344 return -1;
345 }
346
347 if (!res) {
348 if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) {
349 struct in_addr *hn;
350
351 if (!(hn = gg_gethostbyname(hostname)))
352 a.s_addr = INADDR_NONE;
353 else {
354 a.s_addr = hn->s_addr;
355 free(hn);
356 }
357 }
358
359 write(pipes[1], &a, sizeof(a));
360
361 _exit(0);
362 }
363
364 close(pipes[1]);
365
366 *fd = pipes[0];
367 *pid = res;
368
369 return 0;
370 }
371 #endif
372
373 #ifdef __GG_LIBGADU_HAVE_PTHREAD
374
375 struct gg_resolve_pthread_data {
376 char *hostname;
377 int fd;
378 };
379
380 static void *gg_resolve_pthread_thread(void *arg)
381 {
382 struct gg_resolve_pthread_data *d = arg;
383 struct in_addr a;
384
385 pthread_detach(pthread_self());
386
387 if ((a.s_addr = inet_addr(d->hostname)) == INADDR_NONE) {
388 struct in_addr *hn;
389
390 if (!(hn = gg_gethostbyname(d->hostname)))
391 a.s_addr = INADDR_NONE;
392 else {
393 a.s_addr = hn->s_addr;
394 free(hn);
395 }
396 }
397
398 write(d->fd, &a, sizeof(a));
399 close(d->fd);
400
401 free(d->hostname);
402 d->hostname = NULL;
403
404 free(d);
405
406 pthread_exit(NULL);
407
408 return NULL; /* 縠by kompilator nie marudzi */
409 }
410
411 /*
412 * gg_resolve_pthread() // funkcja wewn阾rzna
413 *
414 * tworzy potok, nowy w眛ek i w nim zaczyna resolvowa podanego hosta.
415 * zapisuje w sesji deskryptor potoku. je秎i co tam b阣zie gotowego,
416 * znaczy, 縠 mo縩a wczyta struct in_addr. je秎i nie znajdzie, zwraca
417 * INADDR_NONE.
418 *
419 * - fd - wska糿ik do zmiennej przechowuj眂ej desktyptor resolvera
420 * - resolver - wska糿ik do wska糿ika resolvera
421 * - hostname - nazwa hosta do zresolvowania
422 *
423 * 0, -1.
424 */
425 int gg_resolve_pthread(int *fd, void **resolver, const char *hostname)
426 {
427 struct gg_resolve_pthread_data *d = NULL;
428 pthread_t *tmp;
429 int pipes[2], new_errno;
430
431 gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_pthread(%p, %p, \"%s\");\n", fd, resolver, hostname);
432
433 if (!resolver || !fd || !hostname) {
434 gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() invalid arguments\n");
435 errno = EFAULT;
436 return -1;
437 }
438
439 if (!(tmp = malloc(sizeof(pthread_t)))) {
440 gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory for pthread id\n");
441 return -1;
442 }
443
444 if (pipe(pipes) == -1) {
445 gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno));
446 free(tmp);
447 return -1;
448 }
449
450 if (!(d = malloc(sizeof(*d)))) {
451 gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n");
452 new_errno = errno;
453 goto cleanup;
454 }
455
456 d->hostname = NULL;
457
458 if (!(d->hostname = strdup(hostname))) {
459 gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n");
460 new_errno = errno;
461 goto cleanup;
462 }
463
464 d->fd = pipes[1];
465
466 if (pthread_create(tmp, NULL, gg_resolve_pthread_thread, d)) {
467 gg_debug(GG_DEBUG_MISC, "// gg_resolve_phread() unable to create thread\n");
468 new_errno = errno;
469 goto cleanup;
470 }
471
472 gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() %p\n", tmp);
473
474 *resolver = tmp;
475
476 *fd = pipes[0];
477
478 return 0;
479
480 cleanup:
481 if (d) {
482 free(d->hostname);
483 free(d);
484 }
485
486 close(pipes[0]);
487 close(pipes[1]);
488
489 free(tmp);
490
491 errno = new_errno;
492
493 return -1;
494 }
495
496 #elif defined _WIN32
497
498 struct gg_resolve_win32thread_data {
499 char *hostname;
500 int fd;
501 };
502
503 static DWORD WINAPI gg_resolve_win32thread_thread(LPVOID arg)
504 {
505 struct gg_resolve_win32thread_data *d = arg;
506 struct in_addr a;
507
508 if ((a.s_addr = inet_addr(d->hostname)) == INADDR_NONE) {
509 struct in_addr *hn;
510
511 if (!(hn = gg_gethostbyname(d->hostname)))
512 a.s_addr = INADDR_NONE;
513 else {
514 a.s_addr = hn->s_addr;
515 free(hn);
516 }
517 }
518
519 write(d->fd, &a, sizeof(a));
520 close(d->fd);
521
522 free(d->hostname);
523 d->hostname = NULL;
524
525 free(d);
526
527 return 0;
528 }
529
530
531 int gg_resolve_win32thread(int *fd, void **resolver, const char *hostname)
532 {
533 struct gg_resolve_win32thread_data *d = NULL;
534 HANDLE h;
535 DWORD dwTId;
536 int pipes[2], new_errno;
537
538 gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_win32thread(%p, %p, \"%s\");\n", fd, resolver, hostname);
539
540 if (!resolver || !fd || !hostname) {
541 gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() invalid arguments\n");
542 errno = EFAULT;
543 return -1;
544 }
545
546 if (socket_pipe(pipes) == -1) {
547 gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno));
548 return -1;
549 }
550
551 if (!(d = malloc(sizeof(*d)))) {
552 gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n");
553 new_errno = GetLastError();
554 goto cleanup;
555 }
556
557 d->hostname = NULL;
558
559 if (!(d->hostname = strdup(hostname))) {
560 gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n");
561 new_errno = GetLastError();
562 goto cleanup;
563 }
564
565 d->fd = pipes[1];
566
567 h = CreateThread(NULL, 0, gg_resolve_win32thread_thread,
568 d, 0, &dwTId);
569
570 if (h == NULL) {
571 gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create thread\n");
572 new_errno = GetLastError();
573 goto cleanup;
574 }
575
576 *resolver = h;
577 *fd = pipes[0];
578
579 return 0;
580
581 cleanup:
582 if (d) {
583 free(d->hostname);
584 free(d);
585 }
586
587 close(pipes[0]);
588 close(pipes[1]);
589
590 errno = new_errno;
591
592 return -1;
593
594 }
595 #endif
596
597 /*
598 * gg_read() // funkcja pomocnicza
599 *
600 * czyta z gniazda okre秎on ilo舵 bajt體. bierze pod uwag, czy mamy
601 * po潮czenie zwyk砮 czy TLS.
602 *
603 * - sess - sesja,
604 * - buf - bufor,
605 * - length - ilo舵 bajt體,
606 *
607 * takie same warto禼i jak read().
608 */ 277 */
609 int gg_read(struct gg_session *sess, char *buf, int length) 278 int gg_read(struct gg_session *sess, char *buf, int length)
610 { 279 {
611 int res; 280 int res;
612 281
613 #ifdef __GG_LIBGADU_HAVE_OPENSSL 282 #ifdef GG_CONFIG_HAVE_OPENSSL
614 if (sess->ssl) { 283 if (sess->ssl) {
615 int err; 284 int err;
616 285
617 res = SSL_read(sess->ssl, buf, length); 286 res = SSL_read(sess->ssl, buf, length);
618 287
629 res = read(sess->fd, buf, length); 298 res = read(sess->fd, buf, length);
630 299
631 return res; 300 return res;
632 } 301 }
633 302
634 /* 303 /**
635 * gg_write() // funkcja pomocnicza 304 * \internal Wysy艂a do serwera dane binarne.
636 * 305 *
637 * zapisuje do gniazda okre秎on ilo舵 bajt體. bierze pod uwag, czy mamy 306 * Funkcja wysy艂a dane do serwera zajmuj膮c si臋 TLS w razie konieczno艣ci.
638 * po潮czenie zwyk砮 czy TLS. 307 *
639 * 308 * \param sess Struktura sesji
640 * - sess - sesja, 309 * \param buf Bufor z danymi
641 * - buf - bufor, 310 * \param length D艂ugo艣膰 bufora
642 * - length - ilo舵 bajt體, 311 *
643 * 312 * \return To samo co funkcja systemowa \c write
644 * takie same warto禼i jak write().
645 */ 313 */
646 int gg_write(struct gg_session *sess, const char *buf, int length) 314 int gg_write(struct gg_session *sess, const char *buf, int length)
647 { 315 {
648 int res = 0; 316 int res = 0;
649 317
650 #ifdef __GG_LIBGADU_HAVE_OPENSSL 318 #ifdef GG_CONFIG_HAVE_OPENSSL
651 if (sess->ssl) { 319 if (sess->ssl) {
652 int err; 320 int err;
653 321
654 res = SSL_write(sess->ssl, buf, length); 322 res = SSL_write(sess->ssl, buf, length);
655 323
662 return -1; 330 return -1;
663 } 331 }
664 } else 332 } else
665 #endif 333 #endif
666 { 334 {
667 int written = 0; 335 if (!sess->async) {
668 336 int written = 0;
669 while (written < length) { 337
670 res = write(sess->fd, buf + written, length - written); 338 while (written < length) {
671 339 res = write(sess->fd, buf + written, length - written);
672 if (res == -1) { 340
673 if (errno == EAGAIN) 341 if (res == -1) {
342 if (errno != EINTR)
343 break;
344
674 continue; 345 continue;
675 else 346 }
676 break; 347
677 } else {
678 written += res; 348 written += res;
679 res = written; 349 res = written;
680 } 350 }
351 } else {
352 if (!sess->send_buf)
353 res = write(sess->fd, buf, length);
354 else
355 res = 0;
356
357 if (res == -1) {
358 if (errno != EAGAIN)
359 return res;
360
361 res = 0;
362 }
363
364 if (res < length) {
365 char *tmp;
366
367 if (!(tmp = realloc(sess->send_buf, sess->send_left + length - res))) {
368 errno = ENOMEM;
369 return -1;
370 }
371
372 sess->send_buf = tmp;
373
374 memcpy(sess->send_buf + sess->send_left, buf + res, length - res);
375
376 sess->send_left += length - res;
377 }
681 } 378 }
682 } 379 }
683 380
684 return res; 381 return res;
685 } 382 }
686 383
687 /* 384 /**
688 * gg_recv_packet() // funkcja wewn阾rzna 385 * \internal Odbiera pakiet od serwera.
689 * 386 *
690 * odbiera jeden pakiet i zwraca wska糿ik do niego. pami赕 po nim 387 * Funkcja odczytuje nag艂贸wek pakietu, a nast臋pnie jego zawarto艣膰 i zwraca
691 * nale縴 zwolni za pomoc free(). 388 * w zaalokowanym buforze.
692 * 389 *
693 * - sess - opis sesji 390 * Przy po艂膮czeniach asynchronicznych, funkcja mo偶e nie by膰 w stanie
694 * 391 * skompletowa膰 ca艂ego pakietu -- w takim przypadku zwr贸ci -1, a kodem b艂臋du
695 * w przypadku b酬du NULL, kod b酬du w errno. nale縴 zwr骳i uwag, 縠 gdy 392 * b臋dzie \c EAGAIN.
696 * po潮czenie jest nieblokuj眂e, a kod b酬du wynosi EAGAIN, nie uda硂 si 393 *
697 * odczyta ca砮go pakietu i nie nale縴 tego traktowa jako b潮d. 394 * \param sess Struktura sesji
395 *
396 * \return Wska藕nik do zaalokowanego bufora
698 */ 397 */
699 void *gg_recv_packet(struct gg_session *sess) 398 void *gg_recv_packet(struct gg_session *sess)
700 { 399 {
701 struct gg_header h; 400 struct gg_header h;
702 char *buf = NULL; 401 char *buf = NULL;
703 int ret = 0, offset, size = 0; 402 int ret = 0;
704 403 unsigned int offset, size = 0;
705 gg_debug(GG_DEBUG_FUNCTION, "** gg_recv_packet(%p);\n", sess); 404
706 405 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_recv_packet(%p);\n", sess);
406
707 if (!sess) { 407 if (!sess) {
708 errno = EFAULT; 408 errno = EFAULT;
709 return NULL; 409 return NULL;
710 } 410 }
711 411
712 if (sess->recv_left < 1) { 412 if (sess->recv_left < 1) {
713 if (sess->header_buf) { 413 if (sess->header_buf) {
714 memcpy(&h, sess->header_buf, sess->header_done); 414 memcpy(&h, sess->header_buf, sess->header_done);
715 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv: resuming last read (%d bytes left)\n", sizeof(h) - sess->header_done); 415 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv: resuming last read (%d bytes left)\n", sizeof(h) - sess->header_done);
716 free(sess->header_buf); 416 free(sess->header_buf);
717 sess->header_buf = NULL; 417 sess->header_buf = NULL;
718 } else 418 } else
719 sess->header_done = 0; 419 sess->header_done = 0;
720 420
721 while (sess->header_done < sizeof(h)) { 421 while (sess->header_done < sizeof(h)) {
722 ret = gg_read(sess, (char*) &h + sess->header_done, sizeof(h) - sess->header_done); 422 ret = gg_read(sess, (char*) &h + sess->header_done, sizeof(h) - sess->header_done);
723 423
724 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv(%d,%p,%d) = %d\n", sess->fd, &h + sess->header_done, sizeof(h) - sess->header_done, ret); 424 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv(%d,%p,%d) = %d\n", sess->fd, &h + sess->header_done, sizeof(h) - sess->header_done, ret);
725 425
726 if (!ret) { 426 if (!ret) {
727 errno = ECONNRESET; 427 errno = ECONNRESET;
728 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: connection broken\n"); 428 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: connection broken\n");
729 return NULL; 429 return NULL;
730 } 430 }
731 431
732 if (ret == -1) { 432 if (ret == -1) {
733 if (errno == EINTR) { 433 if (errno == EINTR) {
734 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() interrupted system call, resuming\n"); 434 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() interrupted system call, resuming\n");
735 continue; 435 continue;
736 } 436 }
737 437
738 if (errno == EAGAIN) { 438 if (errno == EAGAIN) {
739 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() incomplete header received\n"); 439 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() incomplete header received\n");
740 440
741 if (!(sess->header_buf = malloc(sess->header_done))) { 441 if (!(sess->header_buf = malloc(sess->header_done))) {
742 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() not enough memory\n"); 442 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() not enough memory\n");
743 return NULL; 443 return NULL;
744 } 444 }
745 445
746 memcpy(sess->header_buf, &h, sess->header_done); 446 memcpy(sess->header_buf, &h, sess->header_done);
747 447
448 errno = EAGAIN;
449
748 return NULL; 450 return NULL;
749 } 451 }
750 452
751 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: errno=%d, %s\n", errno, strerror(errno)); 453 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: errno=%d, %s\n", errno, strerror(errno));
752 454
753 return NULL; 455 return NULL;
754 } 456 }
755 457
756 sess->header_done += ret; 458 sess->header_done += ret;
759 461
760 h.type = gg_fix32(h.type); 462 h.type = gg_fix32(h.type);
761 h.length = gg_fix32(h.length); 463 h.length = gg_fix32(h.length);
762 } else 464 } else
763 memcpy(&h, sess->recv_buf, sizeof(h)); 465 memcpy(&h, sess->recv_buf, sizeof(h));
764 466
765 /* jakie sensowne limity na rozmiar pakietu */ 467 /* jakie艣 sensowne limity na rozmiar pakietu */
766 if (h.length > 65535) { 468 if (h.length > 65535) {
767 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() invalid packet length (%d)\n", h.length); 469 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() invalid packet length (%d)\n", h.length);
768 errno = ERANGE; 470 errno = ERANGE;
769 return NULL; 471 return NULL;
770 } 472 }
771 473
772 if (sess->recv_left > 0) { 474 if (sess->recv_left > 0) {
773 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() resuming last gg_recv_packet()\n"); 475 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() resuming last gg_recv_packet()\n");
774 size = sess->recv_left; 476 size = sess->recv_left;
775 offset = sess->recv_done; 477 offset = sess->recv_done;
776 buf = sess->recv_buf; 478 buf = sess->recv_buf;
777 } else { 479 } else {
778 if (!(buf = malloc(sizeof(h) + h.length + 1))) { 480 if (!(buf = malloc(sizeof(h) + h.length + 1))) {
779 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() not enough memory for packet data\n"); 481 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() not enough memory for packet data\n");
780 return NULL; 482 return NULL;
781 } 483 }
782 484
783 memcpy(buf, &h, sizeof(h)); 485 memcpy(buf, &h, sizeof(h));
784 486
786 size = h.length; 488 size = h.length;
787 } 489 }
788 490
789 while (size > 0) { 491 while (size > 0) {
790 ret = gg_read(sess, buf + sizeof(h) + offset, size); 492 ret = gg_read(sess, buf + sizeof(h) + offset, size);
791 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv(%d,%p,%d) = %d\n", sess->fd, buf + sizeof(h) + offset, size, ret); 493 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() body recv(%d,%p,%d) = %d\n", sess->fd, buf + sizeof(h) + offset, size, ret);
792 if (!ret) { 494 if (!ret) {
793 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed: connection broken\n"); 495 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed: connection broken\n");
794 free(buf);
795 errno = ECONNRESET; 496 errno = ECONNRESET;
796 return NULL; 497 return NULL;
797 } 498 }
798 if (ret > -1 && ret <= size) { 499 if (ret > -1 && ret <= size) {
799 offset += ret; 500 offset += ret;
800 size -= ret; 501 size -= ret;
801 } else if (ret == -1) { 502 } else if (ret == -1) {
802 int errno2 = errno; 503 int errno2 = errno;
803 504
804 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed (errno=%d, %s)\n", errno, strerror(errno)); 505 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed (errno=%d, %s)\n", errno, strerror(errno));
805 errno = errno2; 506 errno = errno2;
806 507
807 if (errno == EAGAIN) { 508 if (errno == EAGAIN) {
808 gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() %d bytes received, %d left\n", offset, size); 509 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() %d bytes received, %d left\n", offset, size);
809 sess->recv_buf = buf; 510 sess->recv_buf = buf;
810 sess->recv_left = size; 511 sess->recv_left = size;
811 sess->recv_done = offset; 512 sess->recv_done = offset;
812 return NULL; 513 return NULL;
813 } 514 }
821 sess->recv_left = 0; 522 sess->recv_left = 0;
822 523
823 if ((gg_debug_level & GG_DEBUG_DUMP)) { 524 if ((gg_debug_level & GG_DEBUG_DUMP)) {
824 unsigned int i; 525 unsigned int i;
825 526
826 gg_debug(GG_DEBUG_DUMP, "// gg_recv_packet(%.2x)", h.type); 527 gg_debug_session(sess, GG_DEBUG_DUMP, "// gg_recv_packet(%.2x)", h.type);
827 for (i = 0; i < sizeof(h) + h.length; i++) 528 for (i = 0; i < sizeof(h) + h.length; i++)
828 gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) buf[i]); 529 gg_debug_session(sess, GG_DEBUG_DUMP, " %.2x", (unsigned char) buf[i]);
829 gg_debug(GG_DEBUG_DUMP, "\n"); 530 gg_debug_session(sess, GG_DEBUG_DUMP, "\n");
830 } 531 }
831 532
832 return buf; 533 return buf;
833 } 534 }
834 535
835 /* 536 /**
836 * gg_send_packet() // funkcja wewn阾rzna 537 * \internal Wysy艂a pakiet do serwera.
837 * 538 *
838 * konstruuje pakiet i wysy砤 go do serwera. 539 * Funkcja konstruuje pakiet do wys艂ania z dowolnej liczby fragment贸w. Je艣li
839 * 540 * rozmiar pakietu jest za du偶y, by m贸c go wys艂a膰 za jednym razem, pozosta艂a
840 * - sock - deskryptor gniazda 541 * cz臋艣膰 zostanie zakolejkowana i wys艂ana, gdy b臋dzie to mo偶liwe.
841 * - type - typ pakietu 542 *
842 * - payload_1 - pierwsza cz甓 pakietu 543 * \param sess Struktura sesji
843 * - payload_length_1 - d硊go舵 pierwszej cz甓ci 544 * \param type Rodzaj pakietu
844 * - payload_2 - druga cz甓 pakietu 545 * \param ... Lista kolejnych cz臋艣ci pakietu (wska藕nik na bufor i d艂ugo艣膰
845 * - payload_length_2 - d硊go舵 drugiej cz甓ci 546 * typu \c int) zako艅czona \c NULL
846 * - ... - kolejne cz甓ci pakietu i ich d硊go禼i 547 *
847 * - NULL - ko馽owym parametr (konieczny!) 548 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
848 *
849 * je秎i si powiod硂, zwraca 0, w przypadku b酬du -1. je秎i errno == ENOMEM,
850 * zabrak硂 pami阠i. inaczej by b潮d przy wysy砤niu pakietu. dla errno == 0
851 * nie wys砤no ca砮go pakietu.
852 */ 549 */
853 int gg_send_packet(struct gg_session *sess, int type, ...) 550 int gg_send_packet(struct gg_session *sess, int type, ...)
854 { 551 {
855 struct gg_header *h; 552 struct gg_header *h;
856 char *tmp; 553 char *tmp;
857 int tmp_length; 554 unsigned int tmp_length;
858 void *payload; 555 void *payload;
859 unsigned int payload_length; 556 unsigned int payload_length;
860 va_list ap; 557 va_list ap;
861 int res; 558 int res;
862 559
863 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_packet(%p, 0x%.2x, ...)\n", sess, type); 560 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_packet(%p, 0x%.2x, ...);\n", sess, type);
864 561
865 tmp_length = sizeof(struct gg_header); 562 tmp_length = sizeof(struct gg_header);
866 563
867 if (!(tmp = malloc(tmp_length))) { 564 if (!(tmp = malloc(tmp_length))) {
868 gg_debug(GG_DEBUG_MISC, "// gg_send_packet() not enough memory for packet header\n"); 565 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet() not enough memory for packet header\n");
869 return -1; 566 return -1;
870 } 567 }
871 568
872 va_start(ap, type); 569 va_start(ap, type);
873 570
877 char *tmp2; 574 char *tmp2;
878 575
879 payload_length = va_arg(ap, unsigned int); 576 payload_length = va_arg(ap, unsigned int);
880 577
881 if (!(tmp2 = realloc(tmp, tmp_length + payload_length))) { 578 if (!(tmp2 = realloc(tmp, tmp_length + payload_length))) {
882 gg_debug(GG_DEBUG_MISC, "// gg_send_packet() not enough memory for payload\n"); 579 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet() not enough memory for payload\n");
883 free(tmp); 580 free(tmp);
884 va_end(ap); 581 va_end(ap);
885 return -1; 582 return -1;
886 } 583 }
887 584
888 tmp = tmp2; 585 tmp = tmp2;
889 586
890 memcpy(tmp + tmp_length, payload, payload_length); 587 memcpy(tmp + tmp_length, payload, payload_length);
891 tmp_length += payload_length; 588 tmp_length += payload_length;
892 589
893 payload = va_arg(ap, void *); 590 payload = va_arg(ap, void *);
894 } 591 }
898 h = (struct gg_header*) tmp; 595 h = (struct gg_header*) tmp;
899 h->type = gg_fix32(type); 596 h->type = gg_fix32(type);
900 h->length = gg_fix32(tmp_length - sizeof(struct gg_header)); 597 h->length = gg_fix32(tmp_length - sizeof(struct gg_header));
901 598
902 if ((gg_debug_level & GG_DEBUG_DUMP)) { 599 if ((gg_debug_level & GG_DEBUG_DUMP)) {
903 int i; 600 unsigned int i;
904 601
905 gg_debug(GG_DEBUG_DUMP, "// gg_send_packet(0x%.2x)", gg_fix32(h->type)); 602 gg_debug_session(sess, GG_DEBUG_DUMP, "// gg_send_packet(0x%.2x)", gg_fix32(h->type));
906 for (i = 0; i < tmp_length; ++i) 603 for (i = 0; i < tmp_length; ++i)
907 gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) tmp[i]); 604 gg_debug_session(sess, GG_DEBUG_DUMP, " %.2x", (unsigned char) tmp[i]);
908 gg_debug(GG_DEBUG_DUMP, "\n"); 605 gg_debug_session(sess, GG_DEBUG_DUMP, "\n");
909 } 606 }
910 607
911 if ((res = gg_write(sess, tmp, tmp_length)) < tmp_length) { 608 res = gg_write(sess, tmp, tmp_length);
912 gg_debug(GG_DEBUG_MISC, "// gg_send_packet() write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno)); 609
913 free(tmp); 610 free(tmp);
914 return -1; 611
915 } 612 if (res == -1) {
916 613 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet() write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno));
917 free(tmp); 614 return -1;
615 }
616
617 if (sess->async)
618 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet() partial write(), %d sent, %d left, %d total left\n", res, tmp_length - res, sess->send_left);
619
620 if (sess->send_buf)
621 sess->check |= GG_CHECK_WRITE;
622
918 return 0; 623 return 0;
919 } 624 }
920 625
921 /* 626 /**
922 * gg_session_callback() // funkcja wewn阾rzna 627 * \internal Funkcja zwrotna sesji.
923 * 628 *
924 * wywo硑wany z gg_session->callback, wykonuje gg_watch_fd() i pakuje 629 * Pole \c callback struktury \c gg_session zawiera wska藕nik do tej funkcji.
925 * do gg_session->event jego wynik. 630 * Wywo艂uje ona \c gg_watch_fd i zachowuje wynik w polu \c event.
926 */ 631 *
927 static int gg_session_callback(struct gg_session *s) 632 * \note Korzystanie z tej funkcjonalno艣ci nie jest ju偶 zalecane.
928 { 633 *
929 if (!s) { 634 * \param sess Struktura sesji
635 *
636 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
637 */
638 static int gg_session_callback(struct gg_session *sess)
639 {
640 if (!sess) {
930 errno = EFAULT; 641 errno = EFAULT;
931 return -1; 642 return -1;
932 } 643 }
933 644
934 return ((s->event = gg_watch_fd(s)) != NULL) ? 0 : -1; 645 return ((sess->event = gg_watch_fd(sess)) != NULL) ? 0 : -1;
935 } 646 }
936 647
937 /* 648 /**
938 * gg_login() 649 * 艁膮czy si臋 z serwerem Gadu-Gadu.
939 * 650 *
940 * rozpoczyna procedur 潮czenia si z serwerem. reszt obs硊guje si przez 651 * Przy po艂膮czeniu synchronicznym funkcja zako艅czy dzia艂anie po nawi膮zaniu
941 * gg_watch_fd(). 652 * po艂膮czenia lub gdy wyst膮pi b艂膮d. Po udanym po艂膮czeniu nale偶y wywo艂ywa膰
942 * 653 * funkcj臋 \c gg_watch_fd(), kt贸ra odbiera informacje od serwera i zwraca
943 * UWAGA! program musi obs硊縴 SIGCHLD, je秎i 潮czy si asynchronicznie, 654 * informacje o zdarzeniach.
944 * 縠by poprawnie zamkn辨 proces resolvera. 655 *
945 * 656 * Przy po艂膮czeniu asynchronicznym funkcja rozpocznie procedur臋 po艂膮czenia
946 * - p - struktura opisuj眂a pocz眛kowy stan. wymagane pola: uin, 657 * i zwr贸ci zaalokowan膮 struktur臋. Pole \c fd struktury \c gg_session zawiera
947 * password 658 * deskryptor, kt贸ry nale偶y obserwowa膰 funkcj膮 \c select, \c poll lub za
948 * 659 * pomoc膮 mechanizm贸w u偶ytej p臋tli zdarze艅 (Glib, Qt itp.). Pole \c check
949 * w przypadku b酬du NULL, je秎i idzie dobrze (async) albo posz硂 660 * jest mask膮 bitow膮 m贸wi膮c膮, czy biblioteka chce by膰 informowana o mo偶liwo艣ci
950 * dobrze (sync), zwr骳i wska糿ik do zaalokowanej struct gg_session. 661 * odczytu danych (\c GG_CHECK_READ) czy zapisu danych (\c GG_CHECK_WRITE).
662 * Po zaobserwowaniu zmian na deskryptorze nale偶y wywo艂a膰 funkcj臋
663 * \c gg_watch_fd(). Podczas korzystania z po艂膮cze艅 asynchronicznych, w trakcie
664 * po艂膮czenia mo偶e zosta膰 stworzony dodatkowy proces rozwi膮zuj膮cy nazw臋
665 * serwera -- z tego powodu program musi poprawnie obs艂u偶y膰 sygna艂 SIGCHLD.
666 *
667 * \note Po nawi膮zaniu po艂膮czenia z serwerem nale偶y wys艂a膰 list臋 kontakt贸w
668 * za pomoc膮 funkcji \c gg_notify() lub \c gg_notify_ex().
669 *
670 * \param p Struktura opisuj膮ca parametry po艂膮czenia. Wymagane pola: uin,
671 * password, async.
672 *
673 * \return Wska藕nik do zaalokowanej struktury sesji \c gg_session lub NULL
674 * w przypadku b艂臋du.
675 *
676 * \ingroup login
951 */ 677 */
952 struct gg_session *gg_login(const struct gg_login_params *p) 678 struct gg_session *gg_login(const struct gg_login_params *p)
953 { 679 {
954 struct gg_session *sess = NULL; 680 struct gg_session *sess = NULL;
955 char *hostname; 681 char *hostname;
979 if (!(sess->password = strdup(p->password))) { 705 if (!(sess->password = strdup(p->password))) {
980 gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for password\n"); 706 gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for password\n");
981 goto fail; 707 goto fail;
982 } 708 }
983 709
984 if (p->status_descr && !(sess->initial_descr = strdup(p->status_descr))) { 710 if (p->hash_type < 0 || p->hash_type > GG_LOGIN_HASH_SHA1) {
985 gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for status\n"); 711 gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. unknown hash type (%d)\n", p->hash_type);
712 errno = EFAULT;
986 goto fail; 713 goto fail;
987 } 714 }
988 715
989 sess->uin = p->uin; 716 sess->uin = p->uin;
990 sess->state = GG_STATE_RESOLVING; 717 sess->state = GG_STATE_RESOLVING;
997 sess->destroy = gg_free_session; 724 sess->destroy = gg_free_session;
998 sess->port = (p->server_port) ? p->server_port : ((gg_proxy_enabled) ? GG_HTTPS_PORT : GG_DEFAULT_PORT); 725 sess->port = (p->server_port) ? p->server_port : ((gg_proxy_enabled) ? GG_HTTPS_PORT : GG_DEFAULT_PORT);
999 sess->server_addr = p->server_addr; 726 sess->server_addr = p->server_addr;
1000 sess->external_port = p->external_port; 727 sess->external_port = p->external_port;
1001 sess->external_addr = p->external_addr; 728 sess->external_addr = p->external_addr;
729
730 sess->protocol_features = (p->protocol_features & ~(GG_FEATURE_STATUS77 | GG_FEATURE_MSG77));
731
732 if (!(p->protocol_features & GG_FEATURE_STATUS77))
733 sess->protocol_features |= GG_FEATURE_STATUS80;
734
735 if (!(p->protocol_features & GG_FEATURE_MSG77))
736 sess->protocol_features |= GG_FEATURE_MSG80;
737
1002 sess->protocol_version = (p->protocol_version) ? p->protocol_version : GG_DEFAULT_PROTOCOL_VERSION; 738 sess->protocol_version = (p->protocol_version) ? p->protocol_version : GG_DEFAULT_PROTOCOL_VERSION;
739
1003 if (p->era_omnix) 740 if (p->era_omnix)
1004 sess->protocol_version |= GG_ERA_OMNIX_MASK; 741 sess->protocol_flags |= GG_ERA_OMNIX_MASK;
1005 if (p->has_audio) 742 if (p->has_audio)
1006 sess->protocol_version |= GG_HAS_AUDIO_MASK; 743 sess->protocol_flags |= GG_HAS_AUDIO_MASK;
1007 sess->client_version = (p->client_version) ? strdup(p->client_version) : NULL; 744 sess->client_version = (p->client_version) ? strdup(p->client_version) : NULL;
1008 sess->last_sysmsg = p->last_sysmsg; 745 sess->last_sysmsg = p->last_sysmsg;
1009 sess->image_size = p->image_size; 746 sess->image_size = p->image_size;
1010 sess->pid = -1; 747 sess->pid = -1;
748 sess->encoding = p->encoding;
749
750 if (gg_session_set_resolver(sess, p->resolver) == -1) {
751 gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. unsupported resolver type (%d)\n", p->resolver);
752 errno = EFAULT;
753 goto fail;
754 }
755
756 if (p->status_descr) {
757 int max_length;
758
759 if (sess->protocol_version >= 0x2d)
760 max_length = GG_STATUS_DESCR_MAXSIZE;
761 else
762 max_length = GG_STATUS_DESCR_MAXSIZE_PRE_8_0;
763
764 if (sess->protocol_version >= 0x2d && p->encoding != GG_ENCODING_UTF8)
765 sess->initial_descr = gg_cp_to_utf8(p->status_descr);
766 else
767 sess->initial_descr = strdup(p->status_descr);
768
769 if (!sess->initial_descr) {
770 gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for status\n");
771 goto fail;
772 }
773
774 // XXX pami臋ta膰, 偶eby nie ci膮膰 w 艣rodku znaku utf-8
775
776 if (strlen(sess->initial_descr) > max_length)
777 sess->initial_descr[max_length] = 0;
778 }
1011 779
1012 if (p->tls == 1) { 780 if (p->tls == 1) {
1013 #ifdef __GG_LIBGADU_HAVE_OPENSSL 781 #ifdef GG_CONFIG_HAVE_OPENSSL
1014 char buf[1024]; 782 char buf[1024];
1015 783
1016 OpenSSL_add_ssl_algorithms(); 784 OpenSSL_add_ssl_algorithms();
1017 785
1018 if (!RAND_status()) { 786 if (!RAND_status()) {
1021 time_t time; 789 time_t time;
1022 void *ptr; 790 void *ptr;
1023 } rstruct; 791 } rstruct;
1024 792
1025 time(&rstruct.time); 793 time(&rstruct.time);
1026 rstruct.ptr = (void *) &rstruct; 794 rstruct.ptr = (void *) &rstruct;
1027 795
1028 RAND_seed((void *) rdata, sizeof(rdata)); 796 RAND_seed((void *) rdata, sizeof(rdata));
1029 RAND_seed((void *) &rstruct, sizeof(rstruct)); 797 RAND_seed((void *) &rstruct, sizeof(rstruct));
1030 } 798 }
1031 799
1048 } 816 }
1049 #else 817 #else
1050 gg_debug(GG_DEBUG_MISC, "// gg_login() client requested TLS but no support compiled in\n"); 818 gg_debug(GG_DEBUG_MISC, "// gg_login() client requested TLS but no support compiled in\n");
1051 #endif 819 #endif
1052 } 820 }
1053 821
1054 if (gg_proxy_enabled) { 822 if (gg_proxy_enabled) {
1055 hostname = gg_proxy_host; 823 hostname = gg_proxy_host;
1056 sess->proxy_port = port = gg_proxy_port; 824 sess->proxy_port = port = gg_proxy_port;
1057 } else { 825 } else {
1058 hostname = GG_APPMSG_HOST; 826 hostname = GG_APPMSG_HOST;
1059 port = GG_APPMSG_PORT; 827 port = GG_APPMSG_PORT;
1060 } 828 }
1061 829
830 if (p->hash_type)
831 sess->hash_type = p->hash_type;
832 else
833 sess->hash_type = GG_LOGIN_HASH_SHA1;
834
1062 if (!p->async) { 835 if (!p->async) {
1063 struct in_addr a; 836 struct in_addr addr;
1064 837
1065 if (!p->server_addr || !p->server_port) { 838 if (!sess->server_addr) {
1066 if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { 839 if ((addr.s_addr = inet_addr(hostname)) == INADDR_NONE) {
1067 struct in_addr *hn; 840 if (gg_gethostbyname_real(hostname, &addr, 0) == -1) {
1068
1069 if (!(hn = gg_gethostbyname(hostname))) {
1070 gg_debug(GG_DEBUG_MISC, "// gg_login() host \"%s\" not found\n", hostname); 841 gg_debug(GG_DEBUG_MISC, "// gg_login() host \"%s\" not found\n", hostname);
1071 goto fail; 842 goto fail;
1072 } else {
1073 a.s_addr = hn->s_addr;
1074 free(hn);
1075 } 843 }
1076 } 844 }
1077 } else { 845 } else {
1078 a.s_addr = p->server_addr; 846 addr.s_addr = sess->server_addr;
1079 port = p->server_port; 847 port = sess->port;
1080 } 848 }
1081 849
1082 sess->hub_addr = a.s_addr; 850 sess->hub_addr = addr.s_addr;
1083 851
1084 if (gg_proxy_enabled) 852 if (gg_proxy_enabled)
1085 sess->proxy_addr = a.s_addr; 853 sess->proxy_addr = addr.s_addr;
1086 854
1087 if ((sess->fd = gg_connect(&a, port, 0)) == -1) { 855 if ((sess->fd = gg_connect(&addr, port, 0)) == -1) {
1088 gg_debug(GG_DEBUG_MISC, "// gg_login() connection failed (errno=%d, %s)\n", errno, strerror(errno)); 856 gg_debug(GG_DEBUG_MISC, "// gg_login() connection failed (errno=%d, %s)\n", errno, strerror(errno));
1089 goto fail; 857
1090 } 858 /* nie wysz艂o? pr贸bujemy portu 443. */
1091 859 if (sess->server_addr) {
1092 if (p->server_addr && p->server_port) 860 sess->port = GG_HTTPS_PORT;
861
862 if ((sess->fd = gg_connect(&addr, GG_HTTPS_PORT, 0)) == -1) {
863 /* ostatnia deska ratunku zawiod艂a?
864 * w takim razie zwijamy manatki. */
865 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_login() connection failed (errno=%d, %s)\n", errno, strerror(errno));
866 goto fail;
867 }
868 } else {
869 goto fail;
870 }
871 }
872
873 if (sess->server_addr)
1093 sess->state = GG_STATE_CONNECTING_GG; 874 sess->state = GG_STATE_CONNECTING_GG;
1094 else 875 else
1095 sess->state = GG_STATE_CONNECTING_HUB; 876 sess->state = GG_STATE_CONNECTING_HUB;
1096 877
1097 while (sess->state != GG_STATE_CONNECTED) { 878 while (sess->state != GG_STATE_CONNECTED) {
1112 gg_event_free(e); 893 gg_event_free(e);
1113 } 894 }
1114 895
1115 return sess; 896 return sess;
1116 } 897 }
1117 898
1118 if (!sess->server_addr || gg_proxy_enabled) { 899 if (!sess->server_addr || gg_proxy_enabled) {
1119 #ifdef __GG_LIBGADU_HAVE_PTHREAD 900 if (sess->resolver_start(&sess->fd, &sess->resolver, hostname) == -1) {
1120 if (gg_resolve_pthread(&sess->fd, &sess->resolver, hostname)) {
1121 #elif defined _WIN32
1122 if (gg_resolve_win32thread(&sess->fd, &sess->resolver, hostname)) {
1123 #else
1124 if (gg_resolve(&sess->fd, &sess->pid, hostname)) {
1125 #endif
1126 gg_debug(GG_DEBUG_MISC, "// gg_login() resolving failed (errno=%d, %s)\n", errno, strerror(errno)); 901 gg_debug(GG_DEBUG_MISC, "// gg_login() resolving failed (errno=%d, %s)\n", errno, strerror(errno));
1127 goto fail; 902 goto fail;
1128 } 903 }
1129 } else { 904 } else {
1130 if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) { 905 if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) {
1131 gg_debug(GG_DEBUG_MISC, "// gg_login() direct connection failed (errno=%d, %s)\n", errno, strerror(errno)); 906 gg_debug(GG_DEBUG_MISC, "// gg_login() direct connection failed (errno=%d, %s)\n", errno, strerror(errno));
1132 goto fail; 907 goto fail;
1133 } 908 }
1134 sess->state = GG_STATE_CONNECTING_GG; 909 sess->state = GG_STATE_CONNECTING_GG;
1135 sess->check = GG_CHECK_WRITE; 910 sess->check = GG_CHECK_WRITE;
911 sess->soft_timeout = 1;
1136 } 912 }
1137 913
1138 return sess; 914 return sess;
1139 915
1140 fail: 916 fail:
1141 if (sess) { 917 if (sess) {
1142 if (sess->password) 918 free(sess->password);
1143 free(sess->password); 919 free(sess->initial_descr);
1144 if (sess->initial_descr)
1145 free(sess->initial_descr);
1146 free(sess); 920 free(sess);
1147 } 921 }
1148 922
1149 return NULL; 923 return NULL;
1150 } 924 }
1151 925
1152 /* 926 /**
1153 * gg_free_session() 927 * Wysy艂a do serwera pakiet utrzymania po艂膮czenia.
1154 * 928 *
1155 * pr骲uje zamkn辨 po潮czenia i zwalnia pami赕 zajmowan przez sesj. 929 * Klient powinien regularnie co minut臋 wysy艂a膰 pakiet utrzymania po艂膮czenia,
1156 * 930 * inaczej serwer uzna, 偶e klient straci艂 艂膮czno艣膰 z sieci膮 i zerwie
1157 * - sess - opis sesji 931 * po艂膮czenie.
1158 */ 932 *
1159 void gg_free_session(struct gg_session *sess) 933 * \param sess Struktura sesji
934 *
935 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
936 *
937 * \ingroup login
938 */
939 int gg_ping(struct gg_session *sess)
940 {
941 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_ping(%p);\n", sess);
942
943 if (!sess) {
944 errno = EFAULT;
945 return -1;
946 }
947
948 if (sess->state != GG_STATE_CONNECTED) {
949 errno = ENOTCONN;
950 return -1;
951 }
952
953 return gg_send_packet(sess, GG_PING, NULL);
954 }
955
956 /**
957 * Ko艅czy po艂膮czenie z serwerem.
958 *
959 * Funkcja nie zwalnia zasob贸w, wi臋c po jej wywo艂aniu nale偶y u偶y膰
960 * \c gg_free_session(). Je艣li chce si臋 ustawi膰 opis niedost臋pno艣ci, nale偶y
961 * wcze艣niej wywo艂a膰 funkcj臋 \c gg_change_status_descr() lub
962 * \c gg_change_status_descr_time().
963 *
964 * \note Je艣li w buforze nadawczym po艂膮czenia z serwerem znajduj膮 si臋 jeszcze
965 * dane (np. z powodu strat pakiet贸w na 艂膮czu), prawdopodobnie zostan膮 one
966 * utracone przy zrywaniu po艂膮czenia.
967 *
968 * \param sess Struktura sesji
969 *
970 * \ingroup login
971 */
972 void gg_logoff(struct gg_session *sess)
1160 { 973 {
1161 if (!sess) 974 if (!sess)
1162 return; 975 return;
1163 976
1164 /* XXX dopisa zwalnianie i zamykanie wszystkiego, co mog硂 zosta */ 977 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_logoff(%p);\n", sess);
1165 978
1166 if (sess->password) 979 if (GG_S_NA(sess->status))
1167 free(sess->password);
1168
1169 if (sess->initial_descr)
1170 free(sess->initial_descr);
1171
1172 if (sess->client_version)
1173 free(sess->client_version);
1174
1175 if (sess->header_buf)
1176 free(sess->header_buf);
1177
1178 #ifdef __GG_LIBGADU_HAVE_OPENSSL
1179 if (sess->ssl)
1180 SSL_free(sess->ssl);
1181
1182 if (sess->ssl_ctx)
1183 SSL_CTX_free(sess->ssl_ctx);
1184 #endif
1185
1186 #ifdef __GG_LIBGADU_HAVE_PTHREAD
1187 if (sess->resolver) {
1188 pthread_cancel(*((pthread_t*) sess->resolver));
1189 free(sess->resolver);
1190 sess->resolver = NULL;
1191 }
1192 #elif defined _WIN32
1193 if (sess->resolver) {
1194 HANDLE h = sess->resolver;
1195 TerminateThread(h, 0);
1196 CloseHandle(h);
1197 sess->resolver = NULL;
1198 }
1199 #else
1200 if (sess->pid != -1)
1201 waitpid(sess->pid, NULL, WNOHANG);
1202 #endif
1203
1204 if (sess->fd != -1)
1205 close(sess->fd);
1206
1207 while (sess->images)
1208 gg_image_queue_remove(sess, sess->images, 1);
1209
1210 free(sess);
1211 }
1212
1213 /*
1214 * gg_change_status()
1215 *
1216 * zmienia status u縴tkownika. przydatne do /away i /busy oraz /quit.
1217 *
1218 * - sess - opis sesji
1219 * - status - nowy status u縴tkownika
1220 *
1221 * 0, -1.
1222 */
1223 int gg_change_status(struct gg_session *sess, int status)
1224 {
1225 struct gg_new_status p;
1226
1227 gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status(%p, %d);\n", sess, status);
1228
1229 if (!sess) {
1230 errno = EFAULT;
1231 return -1;
1232 }
1233
1234 if (sess->state != GG_STATE_CONNECTED) {
1235 errno = ENOTCONN;
1236 return -1;
1237 }
1238
1239 p.status = gg_fix32(status);
1240
1241 sess->status = status;
1242
1243 return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), NULL);
1244 }
1245
1246 /*
1247 * gg_change_status_descr()
1248 *
1249 * zmienia status u縴tkownika na opisowy.
1250 *
1251 * - sess - opis sesji
1252 * - status - nowy status u縴tkownika
1253 * - descr - opis statusu
1254 *
1255 * 0, -1.
1256 */
1257 int gg_change_status_descr(struct gg_session *sess, int status, const char *descr)
1258 {
1259 struct gg_new_status p;
1260
1261 gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status_descr(%p, %d, \"%s\");\n", sess, status, descr);
1262
1263 if (!sess || !descr) {
1264 errno = EFAULT;
1265 return -1;
1266 }
1267
1268 if (sess->state != GG_STATE_CONNECTED) {
1269 errno = ENOTCONN;
1270 return -1;
1271 }
1272
1273 p.status = gg_fix32(status);
1274
1275 sess->status = status;
1276
1277 return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), descr, (strlen(descr) > GG_STATUS_DESCR_MAXSIZE) ? GG_STATUS_DESCR_MAXSIZE : strlen(descr), NULL);
1278 }
1279
1280 /*
1281 * gg_change_status_descr_time()
1282 *
1283 * zmienia status u縴tkownika na opisowy z godzin powrotu.
1284 *
1285 * - sess - opis sesji
1286 * - status - nowy status u縴tkownika
1287 * - descr - opis statusu
1288 * - time - czas w formacie uniksowym
1289 *
1290 * 0, -1.
1291 */
1292 int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time)
1293 {
1294 struct gg_new_status p;
1295 uint32_t newtime;
1296
1297 gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status_descr_time(%p, %d, \"%s\", %d);\n", sess, status, descr, time);
1298
1299 if (!sess || !descr || !time) {
1300 errno = EFAULT;
1301 return -1;
1302 }
1303
1304 if (sess->state != GG_STATE_CONNECTED) {
1305 errno = ENOTCONN;
1306 return -1;
1307 }
1308
1309 p.status = gg_fix32(status);
1310
1311 sess->status = status;
1312
1313 newtime = gg_fix32(time);
1314
1315 return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), descr, (strlen(descr) > GG_STATUS_DESCR_MAXSIZE) ? GG_STATUS_DESCR_MAXSIZE : strlen(descr), &newtime, sizeof(newtime), NULL);
1316 }
1317
1318 /*
1319 * gg_logoff()
1320 *
1321 * wylogowuje u縴tkownika i zamyka po潮czenie, ale nie zwalnia pami阠i.
1322 *
1323 * - sess - opis sesji
1324 */
1325 void gg_logoff(struct gg_session *sess)
1326 {
1327 if (!sess)
1328 return;
1329
1330 gg_debug(GG_DEBUG_FUNCTION, "** gg_logoff(%p);\n", sess);
1331
1332 if (GG_S_NA(sess->status & ~GG_STATUS_FRIENDS_MASK))
1333 gg_change_status(sess, GG_STATUS_NOT_AVAIL); 980 gg_change_status(sess, GG_STATUS_NOT_AVAIL);
1334 981
1335 #ifdef __GG_LIBGADU_HAVE_OPENSSL 982 #ifdef GG_CONFIG_HAVE_OPENSSL
1336 if (sess->ssl) 983 if (sess->ssl)
1337 SSL_shutdown(sess->ssl); 984 SSL_shutdown(sess->ssl);
1338 #endif 985 #endif
1339 986
1340 #ifdef __GG_LIBGADU_HAVE_PTHREAD 987 sess->resolver_cleanup(&sess->resolver, 1);
1341 if (sess->resolver) { 988
1342 pthread_cancel(*((pthread_t*) sess->resolver));
1343 free(sess->resolver);
1344 sess->resolver = NULL;
1345 }
1346 #elif defined _WIN32
1347 if (sess->resolver) {
1348 HANDLE h = sess->resolver;
1349 TerminateThread(h, 0);
1350 CloseHandle(h);
1351 sess->resolver = NULL;
1352 }
1353 #else
1354 if (sess->pid != -1) {
1355 waitpid(sess->pid, NULL, WNOHANG);
1356 sess->pid = -1;
1357 }
1358 #endif
1359
1360 if (sess->fd != -1) { 989 if (sess->fd != -1) {
1361 shutdown(sess->fd, SHUT_RDWR); 990 shutdown(sess->fd, SHUT_RDWR);
1362 close(sess->fd); 991 close(sess->fd);
1363 sess->fd = -1; 992 sess->fd = -1;
1364 } 993 }
1365 } 994
1366 995 if (sess->send_buf) {
1367 /* 996 free(sess->send_buf);
1368 * gg_image_request() 997 sess->send_buf = NULL;
1369 * 998 sess->send_left = 0;
1370 * wysy砤 勘danie wys砤nia obrazka o podanych parametrach. 999 }
1371 * 1000 }
1372 * - sess - opis sesji 1001
1373 * - recipient - numer adresata 1002 /**
1374 * - size - rozmiar obrazka 1003 * Zwalnia zasoby u偶ywane przez po艂膮czenie z serwerem. Funkcj臋 nale偶y wywo艂a膰
1375 * - crc32 - suma kontrolna obrazka 1004 * po zamkni臋ciu po艂膮czenia z serwerem, by nie doprowadzi膰 do wycieku zasob贸w
1376 * 1005 * systemowych.
1377 * 0/-1 1006 *
1007 * \param sess Struktura sesji
1008 *
1009 * \ingroup login
1010 */
1011 void gg_free_session(struct gg_session *sess)
1012 {
1013 struct gg_dcc7 *dcc;
1014
1015 if (!sess)
1016 return;
1017
1018 /* XXX dopisa膰 zwalnianie i zamykanie wszystkiego, co mog艂o zosta膰 */
1019
1020 free(sess->password);
1021 free(sess->initial_descr);
1022 free(sess->client_version);
1023 free(sess->header_buf);
1024
1025 #ifdef GG_CONFIG_HAVE_OPENSSL
1026 if (sess->ssl)
1027 SSL_free(sess->ssl);
1028
1029 if (sess->ssl_ctx)
1030 SSL_CTX_free(sess->ssl_ctx);
1031 #endif
1032
1033 sess->resolver_cleanup(&sess->resolver, 1);
1034
1035 if (sess->fd != -1)
1036 close(sess->fd);
1037
1038 while (sess->images)
1039 gg_image_queue_remove(sess, sess->images, 1);
1040
1041 free(sess->send_buf);
1042
1043 for (dcc = sess->dcc7_list; dcc; dcc = dcc->next)
1044 dcc->sess = NULL;
1045
1046 free(sess);
1047 }
1048
1049 #ifndef DOXYGEN
1050
1051 /**
1052 * \internal Funkcja wysy艂aj膮ca pakiet zmiany statusu u偶ytkownika.
1053 *
1054 * \param sess Struktura sesji
1055 * \param status Nowy status u偶ytkownika
1056 * \param descr Opis statusu u偶ytkownika (lub \c NULL)
1057 * \param time Czas powrotu w postaci uniksowego znacznika czasu (lub 0)
1058 *
1059 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
1060 *
1061 * \ingroup status
1062 */
1063 static int gg_change_status_common(struct gg_session *sess, int status, const char *descr, int time)
1064 {
1065 char *new_descr = NULL;
1066 uint32_t new_time;
1067 int descr_len = 0;
1068 int descr_len_max;
1069 int packet_type;
1070 int append_null = 0;
1071 int res;
1072
1073 if (!sess) {
1074 errno = EFAULT;
1075 return -1;
1076 }
1077
1078 if (sess->state != GG_STATE_CONNECTED) {
1079 errno = ENOTCONN;
1080 return -1;
1081 }
1082
1083 /* XXX, obcina膰 stany kt贸rych stary protok贸艂 niezna (czyt. dnd->aw; ffc->av) */
1084
1085 /* dodaj flag臋 obs艂ugi po艂膮cze艅 g艂osowych zgodn膮 z GG 7.x */
1086 if ((sess->protocol_version >= 0x2a) && (sess->protocol_version < 0x2d /* ? */ ) && (sess->protocol_flags & GG_HAS_AUDIO_MASK) && !GG_S_I(status))
1087 status |= GG_STATUS_VOICE_MASK;
1088
1089 sess->status = status;
1090
1091 if (sess->protocol_version >= 0x2d) {
1092 if (descr != NULL && sess->encoding != GG_ENCODING_UTF8) {
1093 new_descr = gg_cp_to_utf8(descr);
1094
1095 if (!new_descr)
1096 return -1;
1097 }
1098
1099 if (sess->protocol_version >= 0x2e)
1100 packet_type = GG_NEW_STATUS80;
1101 else /* sess->protocol_version == 0x2d */
1102 packet_type = GG_NEW_STATUS80BETA;
1103 descr_len_max = GG_STATUS_DESCR_MAXSIZE;
1104 append_null = 1;
1105
1106 } else {
1107 packet_type = GG_NEW_STATUS;
1108 descr_len_max = GG_STATUS_DESCR_MAXSIZE_PRE_8_0;
1109
1110 if (time != 0)
1111 append_null = 1;
1112 }
1113
1114 if (descr) {
1115 descr_len = strlen((new_descr) ? new_descr : descr);
1116
1117 if (descr_len > descr_len_max)
1118 descr_len = descr_len_max;
1119
1120 // XXX pami臋ta膰 o tym, 偶eby nie ucina膰 w 艣rodku znaku utf-8
1121 }
1122
1123 if (time)
1124 new_time = gg_fix32(time);
1125
1126 if (packet_type == GG_NEW_STATUS80) {
1127 struct gg_new_status80 p;
1128
1129 p.status = gg_fix32(status);
1130 p.flags = gg_fix32(0x00800001);
1131 p.description_size = gg_fix32(descr_len);
1132 res = gg_send_packet(sess,
1133 packet_type,
1134 &p,
1135 sizeof(p),
1136 (new_descr) ? new_descr : descr,
1137 descr_len,
1138 NULL);
1139
1140 } else {
1141 struct gg_new_status p;
1142
1143 p.status = gg_fix32(status);
1144 res = gg_send_packet(sess,
1145 packet_type,
1146 &p,
1147 sizeof(p),
1148 (new_descr) ? new_descr : descr,
1149 descr_len,
1150 (append_null) ? "\0" : NULL,
1151 (append_null) ? 1 : 0,
1152 (time) ? &new_time : NULL,
1153 (time) ? sizeof(new_time) : 0,
1154 NULL);
1155 }
1156
1157 free(new_descr);
1158 return res;
1159 }
1160
1161 #endif /* DOXYGEN */
1162
1163 /**
1164 * Zmienia status u偶ytkownika.
1165 *
1166 * \param sess Struktura sesji
1167 * \param status Nowy status u偶ytkownika
1168 *
1169 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
1170 *
1171 * \ingroup status
1172 */
1173 int gg_change_status(struct gg_session *sess, int status)
1174 {
1175 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status(%p, %d);\n", sess, status);
1176
1177 return gg_change_status_common(sess, status, NULL, 0);
1178 }
1179
1180 /**
1181 * Zmienia status u偶ytkownika na status opisowy.
1182 *
1183 * \param sess Struktura sesji
1184 * \param status Nowy status u偶ytkownika
1185 * \param descr Opis statusu u偶ytkownika
1186 *
1187 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
1188 *
1189 * \ingroup status
1190 */
1191 int gg_change_status_descr(struct gg_session *sess, int status, const char *descr)
1192 {
1193 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status_descr(%p, %d, \"%s\");\n", sess, status, descr);
1194
1195 return gg_change_status_common(sess, status, descr, 0);
1196 }
1197
1198 /**
1199 * Zmienia status u偶ytkownika na status opisowy z podanym czasem powrotu.
1200 *
1201 * \param sess Struktura sesji
1202 * \param status Nowy status u偶ytkownika
1203 * \param descr Opis statusu u偶ytkownika
1204 * \param time Czas powrotu w postaci uniksowego znacznika czasu
1205 *
1206 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
1207 *
1208 * \ingroup status
1209 */
1210 int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time)
1211 {
1212 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status_descr_time(%p, %d, \"%s\", %d);\n", sess, status, descr, time);
1213
1214 return gg_change_status_common(sess, status, descr, time);
1215 }
1216
1217 /**
1218 * Wysy艂a wiadomo艣膰 do u偶ytkownika.
1219 *
1220 * Zwraca losowy numer sekwencyjny, kt贸ry mo偶na zignorowa膰 albo wykorzysta膰
1221 * do potwierdzenia.
1222 *
1223 * \param sess Struktura sesji
1224 * \param msgclass Klasa wiadomo艣ci
1225 * \param recipient Numer adresata
1226 * \param message Tre艣膰 wiadomo艣ci
1227 *
1228 * \return Numer sekwencyjny wiadomo艣ci lub -1 w przypadku b艂臋du.
1229 *
1230 * \ingroup messages
1231 */
1232 int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message)
1233 {
1234 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message(%p, %d, %u, %p)\n", sess, msgclass, recipient, message);
1235
1236 return gg_send_message_confer_richtext(sess, msgclass, 1, &recipient, message, NULL, 0);
1237 }
1238
1239 /**
1240 * Wysy艂a wiadomo艣膰 formatowan膮.
1241 *
1242 * Zwraca losowy numer sekwencyjny, kt贸ry mo偶na zignorowa膰 albo wykorzysta膰
1243 * do potwierdzenia.
1244 *
1245 * \param sess Struktura sesji
1246 * \param msgclass Klasa wiadomo艣ci
1247 * \param recipient Numer adresata
1248 * \param message Tre艣膰 wiadomo艣ci
1249 * \param format Informacje o formatowaniu
1250 * \param formatlen D艂ugo艣膰 informacji o formatowaniu
1251 *
1252 * \return Numer sekwencyjny wiadomo艣ci lub -1 w przypadku b艂臋du.
1253 *
1254 * \ingroup messages
1255 */
1256 int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen)
1257 {
1258 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_richtext(%p, %d, %u, %p, %p, %d);\n", sess, msgclass, recipient, message, format, formatlen);
1259
1260 return gg_send_message_confer_richtext(sess, msgclass, 1, &recipient, message, format, formatlen);
1261 }
1262
1263 /**
1264 * Wysy艂a wiadomo艣膰 w ramach konferencji.
1265 *
1266 * Zwraca losowy numer sekwencyjny, kt贸ry mo偶na zignorowa膰 albo wykorzysta膰
1267 * do potwierdzenia.
1268 *
1269 * \param sess Struktura sesji
1270 * \param msgclass Klasa wiadomo艣ci
1271 * \param recipients_count Liczba adresat贸w
1272 * \param recipients Wska藕nik do tablicy z numerami adresat贸w
1273 * \param message Tre艣膰 wiadomo艣ci
1274 *
1275 * \return Numer sekwencyjny wiadomo艣ci lub -1 w przypadku b艂臋du.
1276 *
1277 * \ingroup messages
1278 */
1279 int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message)
1280 {
1281 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_confer(%p, %d, %d, %p, %p);\n", sess, msgclass, recipients_count, recipients, message);
1282
1283 return gg_send_message_confer_richtext(sess, msgclass, recipients_count, recipients, message, NULL, 0);
1284 }
1285
1286 /**
1287 * \internal Dodaje tekst na koniec bufora.
1288 *
1289 * \param dst Wska藕nik na bufor roboczy
1290 * \param pos Wska藕nik na aktualne po艂o偶enie w buforze roboczym
1291 * \param src Dodawany tekst
1292 * \param len D艂ugo艣膰 dodawanego tekstu
1293 */
1294 static void gg_append(char *dst, int *pos, const void *src, int len)
1295 {
1296 if (dst != NULL)
1297 memcpy(&dst[*pos], src, len);
1298
1299 *pos += len;
1300 }
1301
1302 /**
1303 * \internal Zamienia tekst z formatowaniem Gadu-Gadu na HTML.
1304 *
1305 * \param dst Bufor wynikowy (mo偶e by膰 \c NULL)
1306 * \param utf_msg Tekst 藕r贸d艂owy
1307 * \param format Atrybuty tekstu 藕r贸d艂owego
1308 * \param format_len D艂ugo艣膰 bloku atrybut贸w tekstu 藕r贸d艂owego
1309 *
1310 * \note Dokleja \c \\0 na ko艅cu bufora wynikowego.
1311 *
1312 * \return D艂ugo艣膰 tekstu wynikowego bez \c \\0 (nawet je艣li \c dst to \c NULL).
1313 */
1314 static int gg_convert_to_html(char *dst, const char *utf_msg, const unsigned char *format, int format_len)
1315 {
1316 const char span_fmt[] = "<span style=\"color:#%02x%02x%02x; font-family:'MS Shell Dlg 2'; font-size:9pt; \">";
1317 const int span_len = 75;
1318 const char img_fmt[] = "<img src=\"%02x%02x%02x%02x%02x%02x%02x%02x\">";
1319 const int img_len = 28;
1320 int char_pos = 0;
1321 int format_idx = 3;
1322 unsigned char old_attr = 0;
1323 const unsigned char *color = (const unsigned char*) "\x00\x00\x00";
1324 int len, i;
1325
1326 len = 0;
1327
1328 for (i = 0; utf_msg[i] != 0; i++) {
1329 unsigned char attr;
1330 int attr_pos;
1331
1332 if (format_idx + 3 <= format_len) {
1333 attr_pos = format[format_idx] | (format[format_idx + 1] << 8);
1334 attr = format[format_idx + 2];
1335 } else {
1336 attr_pos = -1;
1337 attr = 0;
1338 }
1339
1340 if (attr_pos == char_pos) {
1341 format_idx += 3;
1342
1343 if ((attr & (GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR)) != 0) {
1344 if (char_pos != 0) {
1345 if ((old_attr & GG_FONT_UNDERLINE) != 0)
1346 gg_append(dst, &len, "</u>", 4);
1347
1348 if ((old_attr & GG_FONT_ITALIC) != 0)
1349 gg_append(dst, &len, "</i>", 4);
1350
1351 if ((old_attr & GG_FONT_BOLD) != 0)
1352 gg_append(dst, &len, "</b>", 4);
1353
1354 gg_append(dst, &len, "</span>", 7);
1355 }
1356
1357 if (((attr & GG_FONT_COLOR) != 0) && (format_idx + 3 <= format_len)) {
1358 color = &format[format_idx];
1359 format_idx += 3;
1360 } else {
1361 color = (const unsigned char*) "\x00\x00\x00";
1362 }
1363
1364 if (dst != NULL)
1365 sprintf(&dst[len], span_fmt, color[0], color[1], color[2]);
1366 len += span_len;
1367 } else if (char_pos == 0) {
1368 if (dst != NULL)
1369 sprintf(&dst[len], span_fmt, 0, 0, 0);
1370 len += span_len;
1371 }
1372
1373 if ((attr & GG_FONT_BOLD) != 0)
1374 gg_append(dst, &len, "<b>", 3);
1375
1376 if ((attr & GG_FONT_ITALIC) != 0)
1377 gg_append(dst, &len, "<i>", 3);
1378
1379 if ((attr & GG_FONT_UNDERLINE) != 0)
1380 gg_append(dst, &len, "<u>", 3);
1381
1382 if (((attr & GG_FONT_IMAGE) != 0) && (format_idx + 10 <= format_len)) {
1383 if (dst != NULL) {
1384 sprintf(&dst[len], img_fmt,
1385 format[format_idx + 9],
1386 format[format_idx + 8],
1387 format[format_idx + 7],
1388 format[format_idx + 6],
1389 format[format_idx + 5],
1390 format[format_idx + 4],
1391 format[format_idx + 3],
1392 format[format_idx + 2]);
1393 }
1394
1395 len += img_len;
1396 format_idx += 10;
1397 }
1398
1399 old_attr = attr;
1400 } else if (i == 0) {
1401 if (dst != NULL)
1402 sprintf(&dst[len], span_fmt, 0, 0, 0);
1403
1404 len += span_len;
1405 }
1406
1407 switch (utf_msg[i]) {
1408 case '&':
1409 gg_append(dst, &len, "&amp;", 5);
1410 break;
1411 case '<':
1412 gg_append(dst, &len, "&lt;", 4);
1413 break;
1414 case '>':
1415 gg_append(dst, &len, "&gt;", 4);
1416 break;
1417 case '\'':
1418 gg_append(dst, &len, "&apos;", 6);
1419 break;
1420 case '\"':
1421 gg_append(dst, &len, "&quot;", 6);
1422 break;
1423 case '\n':
1424 gg_append(dst, &len, "<br>", 4);
1425 break;
1426 case '\r':
1427 break;
1428 default:
1429 if (dst != NULL)
1430 dst[len] = utf_msg[i];
1431 len++;
1432 }
1433
1434 /* Sprawd藕, czy bajt nie jest kontynuacj膮 znaku unikodowego. */
1435
1436 if ((utf_msg[i] & 0xc0) != 0xc0)
1437 char_pos++;
1438 }
1439
1440 if ((old_attr & GG_FONT_UNDERLINE) != 0)
1441 gg_append(dst, &len, "</u>", 4);
1442
1443 if ((old_attr & GG_FONT_ITALIC) != 0)
1444 gg_append(dst, &len, "</i>", 4);
1445
1446 if ((old_attr & GG_FONT_BOLD) != 0)
1447 gg_append(dst, &len, "</b>", 4);
1448
1449 /* Dla pustych tekst贸w dodaj pusty <span>. */
1450
1451 if (i == 0) {
1452 if (dst != NULL)
1453 sprintf(&dst[len], span_fmt, 0, 0, 0);
1454
1455 len += span_len;
1456 }
1457
1458 gg_append(dst, &len, "</span>", 7);
1459
1460 if (dst != NULL)
1461 dst[len] = 0;
1462
1463 return len;
1464 }
1465
1466 /**
1467 * Wysy艂a wiadomo艣膰 formatowan膮 w ramach konferencji.
1468 *
1469 * Zwraca losowy numer sekwencyjny, kt贸ry mo偶na zignorowa膰 albo wykorzysta膰
1470 * do potwierdzenia.
1471 *
1472 * \param sess Struktura sesji
1473 * \param msgclass Klasa wiadomo艣ci
1474 * \param recipients_count Liczba adresat贸w
1475 * \param recipients Wska藕nik do tablicy z numerami adresat贸w
1476 * \param message Tre艣膰 wiadomo艣ci
1477 * \param format Informacje o formatowaniu
1478 * \param formatlen D艂ugo艣膰 informacji o formatowaniu
1479 *
1480 * \return Numer sekwencyjny wiadomo艣ci lub -1 w przypadku b艂臋du.
1481 *
1482 * \ingroup messages
1483 */
1484 int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen)
1485 {
1486 struct gg_send_msg s;
1487 struct gg_send_msg80 s80;
1488 struct gg_msg_recipients r;
1489 char *cp_msg = NULL;
1490 char *utf_msg = NULL;
1491 char *html_msg = NULL;
1492 int seq_no;
1493 int i, j, k;
1494 uin_t *recps;
1495
1496 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_confer_richtext(%p, %d, %d, %p, %p, %p, %d);\n", sess, msgclass, recipients_count, recipients, message, format, formatlen);
1497
1498 if (!sess) {
1499 errno = EFAULT;
1500 return -1;
1501 }
1502
1503 if (sess->state != GG_STATE_CONNECTED) {
1504 errno = ENOTCONN;
1505 return -1;
1506 }
1507
1508 if (message == NULL || recipients_count <= 0 || recipients_count > 0xffff || (recipients_count != 1 && recipients == NULL)) {
1509 errno = EINVAL;
1510 return -1;
1511 }
1512
1513 if (sess->encoding == GG_ENCODING_UTF8) {
1514 if (!(cp_msg = gg_utf8_to_cp((const char *) message)))
1515 return -1;
1516
1517 utf_msg = (char*) message;
1518 } else {
1519 if (sess->protocol_version >= 0x2d) {
1520 if (!(utf_msg = gg_cp_to_utf8((const char *) message)))
1521 return -1;
1522 }
1523
1524 cp_msg = (char*) message;
1525 }
1526
1527 if (sess->protocol_version < 0x2d) {
1528 if (!sess->seq)
1529 sess->seq = 0x01740000 | (rand() & 0xffff);
1530 seq_no = sess->seq;
1531 sess->seq += (rand() % 0x300) + 0x300;
1532
1533 s.msgclass = gg_fix32(msgclass);
1534 s.seq = gg_fix32(seq_no);
1535 } else {
1536 int len;
1537
1538 // Drobne odchylenie od protoko艂u. Je艣li wysy艂amy kilka
1539 // wiadomo艣ci w ci膮gu jednej sekundy, zwi臋kszamy poprzedni膮
1540 // warto艣膰, 偶eby ka偶da wiadomo艣膰 mia艂a unikalny numer.
1541
1542 seq_no = time(NULL);
1543
1544 if (seq_no <= sess->seq)
1545 seq_no = sess->seq + 1;
1546
1547 sess->seq = seq_no;
1548
1549 if (format == NULL || formatlen < 3) {
1550 format = (unsigned char*) "\x02\x06\x00\x00\x00\x08\x00\x00\x00";
1551 formatlen = 9;
1552 }
1553
1554 len = gg_convert_to_html(NULL, utf_msg, format, formatlen);
1555
1556 html_msg = malloc(len + 1);
1557
1558 if (html_msg == NULL) {
1559 seq_no = -1;
1560 goto cleanup;
1561 }
1562
1563 gg_convert_to_html(html_msg, utf_msg, format, formatlen);
1564
1565 s80.seq = gg_fix32(seq_no);
1566 s80.msgclass = gg_fix32(msgclass);
1567 s80.offset_plain = gg_fix32(sizeof(s80) + strlen(html_msg) + 1);
1568 s80.offset_attr = gg_fix32(sizeof(s80) + strlen(html_msg) + 1 + strlen(cp_msg) + 1);
1569 }
1570
1571 if (recipients_count > 1) {
1572 r.flag = 0x01;
1573 r.count = gg_fix32(recipients_count - 1);
1574
1575 recps = malloc(sizeof(uin_t) * recipients_count);
1576
1577 if (!recps) {
1578 seq_no = -1;
1579 goto cleanup;
1580 }
1581
1582 for (i = 0; i < recipients_count; i++) {
1583 for (j = 0, k = 0; j < recipients_count; j++) {
1584 if (recipients[j] != recipients[i]) {
1585 recps[k] = gg_fix32(recipients[j]);
1586 k++;
1587 }
1588 }
1589
1590 if (sess->protocol_version < 0x2d) {
1591 s.recipient = gg_fix32(recipients[i]);
1592
1593 if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), cp_msg, strlen(cp_msg) + 1, &r, sizeof(r), recps, (recipients_count - 1) * sizeof(uin_t), format, formatlen, NULL) == -1)
1594 seq_no = -1;
1595 } else {
1596 s80.recipient = gg_fix32(recipients[i]);
1597
1598 if (gg_send_packet(sess, GG_SEND_MSG80, &s80, sizeof(s80), html_msg, strlen(html_msg) + 1, cp_msg, strlen(cp_msg) + 1, &r, sizeof(r), recps, (recipients_count - 1) * sizeof(uin_t), format, formatlen, NULL) == -1)
1599 seq_no = -1;
1600 }
1601 }
1602
1603 free(recps);
1604 } else {
1605 if (sess->protocol_version < 0x2d) {
1606 s.recipient = gg_fix32(recipients[0]);
1607
1608 if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), cp_msg, strlen(cp_msg) + 1, format, formatlen, NULL) == -1)
1609 seq_no = -1;
1610 } else {
1611 s80.recipient = gg_fix32(recipients[0]);
1612
1613 if (gg_send_packet(sess, GG_SEND_MSG80, &s80, sizeof(s80), html_msg, strlen(html_msg) + 1, cp_msg, strlen(cp_msg) + 1, format, formatlen, NULL) == -1)
1614 seq_no = -1;
1615 }
1616 }
1617
1618 cleanup:
1619 if (cp_msg != (char*) message)
1620 free(cp_msg);
1621
1622 if (utf_msg != (char*) message)
1623 free(utf_msg);
1624
1625 free(html_msg);
1626
1627 return seq_no;
1628 }
1629
1630 /**
1631 * Wysy艂a wiadomo艣膰 binarn膮 przeznaczon膮 dla klienta.
1632 *
1633 * Wiadomo艣ci mi臋dzy klientami przesy艂a si臋 np. w celu wywo艂ania zwrotnego
1634 * po艂膮czenia bezpo艣redniego. Funkcja zwraca losowy numer sekwencyjny,
1635 * kt贸ry mo偶na zignorowa膰 albo wykorzysta膰 do potwierdzenia.
1636 *
1637 * \param sess Struktura sesji
1638 * \param msgclass Klasa wiadomo艣ci
1639 * \param recipient Numer adresata
1640 * \param message Tre艣膰 wiadomo艣ci
1641 * \param message_len D艂ugo艣膰 wiadomo艣ci
1642 *
1643 * \return Numer sekwencyjny wiadomo艣ci lub -1 w przypadku b艂臋du.
1644 *
1645 * \ingroup messages
1646 */
1647 int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len)
1648 {
1649 struct gg_send_msg s;
1650
1651 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_ctcp(%p, %d, %u, ...);\n", sess, msgclass, recipient);
1652
1653 if (!sess) {
1654 errno = EFAULT;
1655 return -1;
1656 }
1657
1658 if (sess->state != GG_STATE_CONNECTED) {
1659 errno = ENOTCONN;
1660 return -1;
1661 }
1662
1663 s.recipient = gg_fix32(recipient);
1664 s.seq = gg_fix32(0);
1665 s.msgclass = gg_fix32(msgclass);
1666
1667 return gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, message_len, NULL);
1668 }
1669
1670 /**
1671 * Wysy艂a 偶膮danie obrazka o podanych parametrach.
1672 *
1673 * Wiadomo艣ci obrazkowe nie zawieraj膮 samych obrazk贸w, a tylko ich rozmiary
1674 * i sumy kontrolne. Odbiorca najpierw szuka obrazk贸w w swojej pami臋ci
1675 * podr臋cznej i dopiero gdy ich nie znajdzie, wysy艂a 偶膮danie do nadawcy.
1676 * Wynik zostanie przekazany zdarzeniem \c GG_EVENT_IMAGE_REPLY.
1677 *
1678 * \param sess Struktura sesji
1679 * \param recipient Numer adresata
1680 * \param size Rozmiar obrazka w bajtach
1681 * \param crc32 Suma kontrola obrazka
1682 *
1683 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
1684 *
1685 * \ingroup messages
1378 */ 1686 */
1379 int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32) 1687 int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32)
1380 { 1688 {
1381 struct gg_send_msg s; 1689 struct gg_send_msg s;
1382 struct gg_msg_image_request r; 1690 struct gg_msg_image_request r;
1383 char dummy = 0; 1691 char dummy = 0;
1384 int res; 1692 int res;
1385 1693
1386 gg_debug(GG_DEBUG_FUNCTION, "** gg_image_request(%p, %d, %u, 0x%.4x);\n", sess, recipient, size, crc32); 1694 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_request(%p, %d, %u, 0x%.4x);\n", sess, recipient, size, crc32);
1387 1695
1388 if (!sess) { 1696 if (!sess) {
1389 errno = EFAULT; 1697 errno = EFAULT;
1390 return -1; 1698 return -1;
1391 } 1699 }
1392 1700
1393 if (sess->state != GG_STATE_CONNECTED) { 1701 if (sess->state != GG_STATE_CONNECTED) {
1394 errno = ENOTCONN; 1702 errno = ENOTCONN;
1395 return -1; 1703 return -1;
1396 } 1704 }
1397 1705
1405 s.msgclass = gg_fix32(GG_CLASS_MSG); 1713 s.msgclass = gg_fix32(GG_CLASS_MSG);
1406 1714
1407 r.flag = 0x04; 1715 r.flag = 0x04;
1408 r.size = gg_fix32(size); 1716 r.size = gg_fix32(size);
1409 r.crc32 = gg_fix32(crc32); 1717 r.crc32 = gg_fix32(crc32);
1410 1718
1411 res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), &dummy, 1, &r, sizeof(r), NULL); 1719 res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), &dummy, 1, &r, sizeof(r), NULL);
1412 1720
1413 if (!res) { 1721 if (!res) {
1414 struct gg_image_queue *q = malloc(sizeof(*q)); 1722 struct gg_image_queue *q = malloc(sizeof(*q));
1415 char *buf; 1723 char *buf;
1416 1724
1417 if (!q) { 1725 if (!q) {
1418 gg_debug(GG_DEBUG_MISC, "// gg_image_request() not enough memory for image queue\n"); 1726 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_request() not enough memory for image queue\n");
1419 return -1; 1727 return -1;
1420 } 1728 }
1421 1729
1422 buf = malloc(size); 1730 buf = malloc(size);
1423 if (size && !buf) 1731 if (size && !buf)
1424 { 1732 {
1425 gg_debug(GG_DEBUG_MISC, "// gg_image_request() not enough memory for image\n"); 1733 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_request() not enough memory for image\n");
1426 free(q); 1734 free(q);
1427 return -1; 1735 return -1;
1428 } 1736 }
1429 1737
1430 memset(q, 0, sizeof(*q)); 1738 memset(q, 0, sizeof(*q));
1447 } 1755 }
1448 1756
1449 return res; 1757 return res;
1450 } 1758 }
1451 1759
1452 /* 1760 /**
1453 * gg_image_reply() 1761 * Wysy艂a 偶膮dany obrazek.
1454 * 1762 *
1455 * wysy砤 勘dany obrazek. 1763 * \param sess Struktura sesji
1456 * 1764 * \param recipient Numer adresata
1457 * - sess - opis sesji 1765 * \param filename Nazwa pliku
1458 * - recipient - numer adresata 1766 * \param image Bufor z obrazkiem
1459 * - filename - nazwa pliku 1767 * \param size Rozmiar obrazka
1460 * - image - bufor z obrazkiem 1768 *
1461 * - size - rozmiar obrazka 1769 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
1462 * 1770 *
1463 * 0/-1 1771 * \ingroup messages
1464 */ 1772 */
1465 int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const unsigned char *image, int size) 1773 int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size)
1466 { 1774 {
1467 struct gg_msg_image_reply *r; 1775 struct gg_msg_image_reply *r;
1468 struct gg_send_msg s; 1776 struct gg_send_msg s;
1469 const char *tmp; 1777 const char *tmp;
1470 char buf[1910]; 1778 char buf[1910];
1471 int res = -1; 1779 int res = -1;
1472 1780
1473 gg_debug(GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, \"%s\", %p, %d);\n", sess, recipient, filename, image, size); 1781 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, \"%s\", %p, %d);\n", sess, recipient, filename, image, size);
1474 1782
1475 if (!sess || !filename || !image) { 1783 if (!sess || !filename || !image) {
1476 errno = EFAULT; 1784 errno = EFAULT;
1477 return -1; 1785 return -1;
1478 } 1786 }
1485 if (size < 0) { 1793 if (size < 0) {
1486 errno = EINVAL; 1794 errno = EINVAL;
1487 return -1; 1795 return -1;
1488 } 1796 }
1489 1797
1490 /* wytnij 禼ie縦i, zostaw tylko nazw pliku */ 1798 /* wytnij 艣cie偶ki, zostaw tylko nazw臋 pliku */
1491 while ((tmp = strrchr(filename, '/')) || (tmp = strrchr(filename, '\\'))) 1799 while ((tmp = strrchr(filename, '/')) || (tmp = strrchr(filename, '\\')))
1492 filename = tmp + 1; 1800 filename = tmp + 1;
1493 1801
1494 if (strlen(filename) < 1 || strlen(filename) > 1024) { 1802 if (strlen(filename) < 1 || strlen(filename) > 1024) {
1495 errno = EINVAL; 1803 errno = EINVAL;
1496 return -1; 1804 return -1;
1497 } 1805 }
1498 1806
1499 s.recipient = gg_fix32(recipient); 1807 s.recipient = gg_fix32(recipient);
1500 s.seq = gg_fix32(0); 1808 s.seq = gg_fix32(0);
1501 s.msgclass = gg_fix32(GG_CLASS_MSG); 1809 s.msgclass = gg_fix32(GG_CLASS_MSG);
1502 1810
1503 buf[0] = 0; 1811 buf[0] = 0;
1504 r = (void*) &buf[1]; 1812 r = (void*) &buf[1];
1505 1813
1506 r->flag = 0x05; 1814 r->flag = 0x05;
1507 r->size = gg_fix32(size); 1815 r->size = gg_fix32(size);
1508 r->crc32 = gg_fix32(gg_crc32(0, image, size)); 1816 r->crc32 = gg_fix32(gg_crc32(0, (unsigned char*) image, size));
1509 1817
1510 while (size > 0) { 1818 while (size > 0) {
1511 size_t buflen, chunklen; 1819 int buflen, chunklen;
1512 1820
1513 /* \0 + struct gg_msg_image_reply */ 1821 /* \0 + struct gg_msg_image_reply */
1514 buflen = sizeof(struct gg_msg_image_reply) + 1; 1822 buflen = sizeof(struct gg_msg_image_reply) + 1;
1515 1823
1516 /* w pierwszym kawa砶u jest nazwa pliku */ 1824 /* w pierwszym kawa艂ku jest nazwa pliku */
1517 if (r->flag == 0x05) { 1825 if (r->flag == 0x05) {
1518 strcpy(buf + buflen, filename); 1826 strcpy(buf + buflen, filename);
1519 buflen += strlen(filename) + 1; 1827 buflen += strlen(filename) + 1;
1520 } 1828 }
1521 1829
1522 chunklen = ((size_t)size >= sizeof(buf) - buflen) ? (sizeof(buf) - buflen) : (size_t)size; 1830 chunklen = (size >= sizeof(buf) - buflen) ? (sizeof(buf) - buflen) : size;
1523 1831
1524 memcpy(buf + buflen, image, chunklen); 1832 memcpy(buf + buflen, image, chunklen);
1525 size -= chunklen; 1833 size -= chunklen;
1526 image += chunklen; 1834 image += chunklen;
1527 1835
1528 res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), buf, buflen + chunklen, NULL); 1836 res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), buf, buflen + chunklen, NULL);
1529 1837
1530 if (res == -1) 1838 if (res == -1)
1531 break; 1839 break;
1532 1840
1534 } 1842 }
1535 1843
1536 return res; 1844 return res;
1537 } 1845 }
1538 1846
1539 /* 1847 /**
1540 * gg_send_message_ctcp() 1848 * Wysy艂a do serwera list臋 kontakt贸w.
1541 * 1849 *
1542 * wysy砤 wiadomo舵 do innego u縴tkownika. zwraca losowy numer 1850 * Funkcja informuje serwer o li艣cie kontakt贸w, kt贸rych statusy b臋d膮
1543 * sekwencyjny, kt髍y mo縩a zignorowa albo wykorzysta do potwierdzenia. 1851 * obserwowane lub kontakt贸w, kt贸re bed膮 blokowane. Dla ka偶dego z \c count
1544 * 1852 * kontakt贸w tablica \c userlist zawiera numer, a tablica \c types rodzaj
1545 * - sess - opis sesji 1853 * kontaktu (\c GG_USER_NORMAL, \c GG_USER_OFFLINE, \c GG_USER_BLOCKED).
1546 * - msgclass - rodzaj wiadomo禼i 1854 *
1547 * - recipient - numer adresata 1855 * List臋 kontakt贸w nale偶y \b zawsze wysy艂a膰 po po艂膮czeniu, nawet je艣li
1548 * - message - tre舵 wiadomo禼i 1856 * jest pusta.
1549 * - message_len - d硊go舵 1857 *
1550 * 1858 * \param sess Struktura sesji
1551 * numer sekwencyjny wiadomo禼i lub -1 w przypadku b酬du. 1859 * \param userlist Wska藕nik do tablicy numer贸w kontakt贸w
1552 */ 1860 * \param types Wska藕nik do tablicy rodzaj贸w kontakt贸w
1553 int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len) 1861 * \param count Liczba kontakt贸w
1554 { 1862 *
1555 struct gg_send_msg s; 1863 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
1556 1864 *
1557 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_ctcp(%p, %d, %u, ...);\n", sess, msgclass, recipient); 1865 * \ingroup contacts
1558
1559 if (!sess) {
1560 errno = EFAULT;
1561 return -1;
1562 }
1563
1564 if (sess->state != GG_STATE_CONNECTED) {
1565 errno = ENOTCONN;
1566 return -1;
1567 }
1568
1569 s.recipient = gg_fix32(recipient);
1570 s.seq = gg_fix32(0);
1571 s.msgclass = gg_fix32(msgclass);
1572
1573 return gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, message_len, NULL);
1574 }
1575
1576 /*
1577 * gg_send_message()
1578 *
1579 * wysy砤 wiadomo舵 do innego u縴tkownika. zwraca losowy numer
1580 * sekwencyjny, kt髍y mo縩a zignorowa albo wykorzysta do potwierdzenia.
1581 *
1582 * - sess - opis sesji
1583 * - msgclass - rodzaj wiadomo禼i
1584 * - recipient - numer adresata
1585 * - message - tre舵 wiadomo禼i
1586 *
1587 * numer sekwencyjny wiadomo禼i lub -1 w przypadku b酬du.
1588 */
1589 int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message)
1590 {
1591 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message(%p, %d, %u, %p)\n", sess, msgclass, recipient, message);
1592
1593 return gg_send_message_richtext(sess, msgclass, recipient, message, NULL, 0);
1594 }
1595
1596 /*
1597 * gg_send_message_richtext()
1598 *
1599 * wysy砤 kolorow wiadomo舵 do innego u縴tkownika. zwraca losowy numer
1600 * sekwencyjny, kt髍y mo縩a zignorowa albo wykorzysta do potwierdzenia.
1601 *
1602 * - sess - opis sesji
1603 * - msgclass - rodzaj wiadomo禼i
1604 * - recipient - numer adresata
1605 * - message - tre舵 wiadomo禼i
1606 * - format - informacje o formatowaniu
1607 * - formatlen - d硊go舵 informacji o formatowaniu
1608 *
1609 * numer sekwencyjny wiadomo禼i lub -1 w przypadku b酬du.
1610 */
1611 int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen)
1612 {
1613 struct gg_send_msg s;
1614
1615 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_richtext(%p, %d, %u, %p, %p, %d);\n", sess, msgclass, recipient, message, format, formatlen);
1616
1617 if (!sess) {
1618 errno = EFAULT;
1619 return -1;
1620 }
1621
1622 if (sess->state != GG_STATE_CONNECTED) {
1623 errno = ENOTCONN;
1624 return -1;
1625 }
1626
1627 if (!message) {
1628 errno = EFAULT;
1629 return -1;
1630 }
1631
1632 s.recipient = gg_fix32(recipient);
1633 if (!sess->seq)
1634 sess->seq = 0x01740000 | (rand() & 0xffff);
1635 s.seq = gg_fix32(sess->seq);
1636 s.msgclass = gg_fix32(msgclass);
1637 sess->seq += (rand() % 0x300) + 0x300;
1638
1639 if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, strlen((const char *)message) + 1, format, formatlen, NULL) == -1)
1640 return -1;
1641
1642 return gg_fix32(s.seq);
1643 }
1644
1645 /*
1646 * gg_send_message_confer()
1647 *
1648 * wysy砤 wiadomo舵 do kilku u縴tkownikow (konferencja). zwraca losowy numer
1649 * sekwencyjny, kt髍y mo縩a zignorowa albo wykorzysta do potwierdzenia.
1650 *
1651 * - sess - opis sesji
1652 * - msgclass - rodzaj wiadomo禼i
1653 * - recipients_count - ilo舵 adresat體
1654 * - recipients - numerki adresat體
1655 * - message - tre舵 wiadomo禼i
1656 *
1657 * numer sekwencyjny wiadomo禼i lub -1 w przypadku b酬du.
1658 */
1659 int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message)
1660 {
1661 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_confer(%p, %d, %d, %p, %p);\n", sess, msgclass, recipients_count, recipients, message);
1662
1663 return gg_send_message_confer_richtext(sess, msgclass, recipients_count, recipients, message, NULL, 0);
1664 }
1665
1666 /*
1667 * gg_send_message_confer_richtext()
1668 *
1669 * wysy砤 kolorow wiadomo舵 do kilku u縴tkownikow (konferencja). zwraca
1670 * losowy numer sekwencyjny, kt髍y mo縩a zignorowa albo wykorzysta do
1671 * potwierdzenia.
1672 *
1673 * - sess - opis sesji
1674 * - msgclass - rodzaj wiadomo禼i
1675 * - recipients_count - ilo舵 adresat體
1676 * - recipients - numerki adresat體
1677 * - message - tre舵 wiadomo禼i
1678 * - format - informacje o formatowaniu
1679 * - formatlen - d硊go舵 informacji o formatowaniu
1680 *
1681 * numer sekwencyjny wiadomo禼i lub -1 w przypadku b酬du.
1682 */
1683 int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen)
1684 {
1685 struct gg_send_msg s;
1686 struct gg_msg_recipients r;
1687 int i, j, k;
1688 uin_t *recps;
1689
1690 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_confer_richtext(%p, %d, %d, %p, %p, %p, %d);\n", sess, msgclass, recipients_count, recipients, message, format, formatlen);
1691
1692 if (!sess) {
1693 errno = EFAULT;
1694 return -1;
1695 }
1696
1697 if (sess->state != GG_STATE_CONNECTED) {
1698 errno = ENOTCONN;
1699 return -1;
1700 }
1701
1702 if (!message || recipients_count <= 0 || recipients_count > 0xffff || !recipients) {
1703 errno = EINVAL;
1704 return -1;
1705 }
1706
1707 r.flag = 0x01;
1708 r.count = gg_fix32(recipients_count - 1);
1709
1710 if (!sess->seq)
1711 sess->seq = 0x01740000 | (rand() & 0xffff);
1712 s.seq = gg_fix32(sess->seq);
1713 s.msgclass = gg_fix32(msgclass);
1714
1715 recps = malloc(sizeof(uin_t) * recipients_count);
1716 if (!recps)
1717 return -1;
1718
1719 for (i = 0; i < recipients_count; i++) {
1720
1721 s.recipient = gg_fix32(recipients[i]);
1722
1723 for (j = 0, k = 0; j < recipients_count; j++)
1724 if (recipients[j] != recipients[i]) {
1725 recps[k] = gg_fix32(recipients[j]);
1726 k++;
1727 }
1728
1729 if (!i)
1730 sess->seq += (rand() % 0x300) + 0x300;
1731
1732 if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, strlen((const char *)message) + 1, &r, sizeof(r), recps, (recipients_count - 1) * sizeof(uin_t), format, formatlen, NULL) == -1) {
1733 free(recps);
1734 return -1;
1735 }
1736 }
1737
1738 free(recps);
1739
1740 return gg_fix32(s.seq);
1741 }
1742
1743 /*
1744 * gg_ping()
1745 *
1746 * wysy砤 do serwera pakiet ping.
1747 *
1748 * - sess - opis sesji
1749 *
1750 * 0, -1.
1751 */
1752 int gg_ping(struct gg_session *sess)
1753 {
1754 gg_debug(GG_DEBUG_FUNCTION, "** gg_ping(%p);\n", sess);
1755
1756 if (!sess) {
1757 errno = EFAULT;
1758 return -1;
1759 }
1760
1761 if (sess->state != GG_STATE_CONNECTED) {
1762 errno = ENOTCONN;
1763 return -1;
1764 }
1765
1766 return gg_send_packet(sess, GG_PING, NULL);
1767 }
1768
1769 /*
1770 * gg_notify_ex()
1771 *
1772 * wysy砤 serwerowi list kontakt體 (wraz z odpowiadaj眂ymi im typami user體),
1773 * dzi阫i czemu wie, czyj stan nas interesuje.
1774 *
1775 * - sess - opis sesji
1776 * - userlist - wska糿ik do tablicy numer體
1777 * - types - wska糿ik do tablicy typ體 u縴tkownik體
1778 * - count - ilo舵 numerk體
1779 *
1780 * 0, -1.
1781 */ 1866 */
1782 int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count) 1867 int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count)
1783 { 1868 {
1784 struct gg_notify *n; 1869 struct gg_notify *n;
1785 uin_t *u; 1870 uin_t *u;
1786 char *t; 1871 char *t;
1787 int i, res = 0; 1872 int i, res = 0;
1788 1873
1789 gg_debug(GG_DEBUG_FUNCTION, "** gg_notify_ex(%p, %p, %p, %d);\n", sess, userlist, types, count); 1874 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_notify_ex(%p, %p, %p, %d);\n", sess, userlist, types, count);
1790 1875
1791 if (!sess) { 1876 if (!sess) {
1792 errno = EFAULT; 1877 errno = EFAULT;
1793 return -1; 1878 return -1;
1794 } 1879 }
1795 1880
1796 if (sess->state != GG_STATE_CONNECTED) { 1881 if (sess->state != GG_STATE_CONNECTED) {
1797 errno = ENOTCONN; 1882 errno = ENOTCONN;
1798 return -1; 1883 return -1;
1799 } 1884 }
1800 1885
1801 if (!userlist || !count) 1886 if (!userlist || !count)
1802 return gg_send_packet(sess, GG_LIST_EMPTY, NULL); 1887 return gg_send_packet(sess, GG_LIST_EMPTY, NULL);
1803 1888
1804 while (count > 0) { 1889 while (count > 0) {
1805 int part_count, packet_type; 1890 int part_count, packet_type;
1806 1891
1807 if (count > 400) { 1892 if (count > 400) {
1808 part_count = 400; 1893 part_count = 400;
1809 packet_type = GG_NOTIFY_FIRST; 1894 packet_type = GG_NOTIFY_FIRST;
1810 } else { 1895 } else {
1811 part_count = count; 1896 part_count = count;
1812 packet_type = GG_NOTIFY_LAST; 1897 packet_type = GG_NOTIFY_LAST;
1813 } 1898 }
1814 1899
1815 if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count))) 1900 if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count)))
1816 return -1; 1901 return -1;
1817 1902
1818 for (u = userlist, t = types, i = 0; i < part_count; u++, t++, i++) { 1903 for (u = userlist, t = types, i = 0; i < part_count; u++, t++, i++) {
1819 n[i].uin = gg_fix32(*u); 1904 n[i].uin = gg_fix32(*u);
1820 n[i].dunno1 = *t; 1905 n[i].dunno1 = *t;
1821 } 1906 }
1822 1907
1823 if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) { 1908 if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) {
1824 free(n); 1909 free(n);
1825 res = -1; 1910 res = -1;
1826 break; 1911 break;
1827 } 1912 }
1834 } 1919 }
1835 1920
1836 return res; 1921 return res;
1837 } 1922 }
1838 1923
1839 /* 1924 /**
1840 * gg_notify() 1925 * Wysy艂a do serwera list臋 kontakt贸w.
1841 * 1926 *
1842 * wysy砤 serwerowi list kontakt體, dzi阫i czemu wie, czyj stan nas 1927 * Funkcja jest odpowiednikiem \c gg_notify_ex(), gdzie wszystkie kontakty
1843 * interesuje. 1928 * s膮 rodzaju \c GG_USER_NORMAL.
1844 * 1929 *
1845 * - sess - opis sesji 1930 * \param sess Struktura sesji
1846 * - userlist - wska糿ik do tablicy numer體 1931 * \param userlist Wska藕nik do tablicy numer贸w kontakt贸w
1847 * - count - ilo舵 numerk體 1932 * \param count Liczba kontakt贸w
1848 * 1933 *
1849 * 0, -1. 1934 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
1935 *
1936 * \ingroup contacts
1850 */ 1937 */
1851 int gg_notify(struct gg_session *sess, uin_t *userlist, int count) 1938 int gg_notify(struct gg_session *sess, uin_t *userlist, int count)
1852 { 1939 {
1853 struct gg_notify *n; 1940 struct gg_notify *n;
1854 uin_t *u; 1941 uin_t *u;
1855 int i, res = 0; 1942 int i, res = 0;
1856 1943
1857 gg_debug(GG_DEBUG_FUNCTION, "** gg_notify(%p, %p, %d);\n", sess, userlist, count); 1944 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_notify(%p, %p, %d);\n", sess, userlist, count);
1858 1945
1859 if (!sess) { 1946 if (!sess) {
1860 errno = EFAULT; 1947 errno = EFAULT;
1861 return -1; 1948 return -1;
1862 } 1949 }
1863 1950
1864 if (sess->state != GG_STATE_CONNECTED) { 1951 if (sess->state != GG_STATE_CONNECTED) {
1865 errno = ENOTCONN; 1952 errno = ENOTCONN;
1866 return -1; 1953 return -1;
1867 } 1954 }
1868 1955
1869 if (!userlist || !count) 1956 if (!userlist || !count)
1870 return gg_send_packet(sess, GG_LIST_EMPTY, NULL); 1957 return gg_send_packet(sess, GG_LIST_EMPTY, NULL);
1871 1958
1872 while (count > 0) { 1959 while (count > 0) {
1873 int part_count, packet_type; 1960 int part_count, packet_type;
1874 1961
1875 if (count > 400) { 1962 if (count > 400) {
1876 part_count = 400; 1963 part_count = 400;
1877 packet_type = GG_NOTIFY_FIRST; 1964 packet_type = GG_NOTIFY_FIRST;
1878 } else { 1965 } else {
1879 part_count = count; 1966 part_count = count;
1880 packet_type = GG_NOTIFY_LAST; 1967 packet_type = GG_NOTIFY_LAST;
1881 } 1968 }
1882 1969
1883 if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count))) 1970 if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count)))
1884 return -1; 1971 return -1;
1885 1972
1886 for (u = userlist, i = 0; i < part_count; u++, i++) { 1973 for (u = userlist, i = 0; i < part_count; u++, i++) {
1887 n[i].uin = gg_fix32(*u); 1974 n[i].uin = gg_fix32(*u);
1888 n[i].dunno1 = GG_USER_NORMAL; 1975 n[i].dunno1 = GG_USER_NORMAL;
1889 } 1976 }
1890 1977
1891 if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) { 1978 if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) {
1892 res = -1; 1979 res = -1;
1893 free(n); 1980 free(n);
1894 break; 1981 break;
1895 } 1982 }
1901 } 1988 }
1902 1989
1903 return res; 1990 return res;
1904 } 1991 }
1905 1992
1906 /* 1993 /**
1907 * gg_add_notify_ex() 1994 * Dodaje kontakt.
1908 * 1995 *
1909 * dodaje do listy kontakt體 dany numer w trakcie po潮czenia. 1996 * Dodaje do listy kontakt贸w dany numer w trakcie po艂膮czenia. Aby zmieni膰
1910 * dodawanemu u縴tkownikowi okre秎amy jego typ (patrz protocol.html) 1997 * rodzaj kontaktu (np. z normalnego na zablokowany), nale偶y najpierw usun膮膰
1911 * 1998 * poprzedni rodzaj, poniewa偶 serwer operuje na maskach bitowych.
1912 * - sess - opis sesji 1999 *
1913 * - uin - numer 2000 * \param sess Struktura sesji
1914 * - type - typ 2001 * \param uin Numer kontaktu
1915 * 2002 * \param type Rodzaj kontaktu
1916 * 0, -1. 2003 *
2004 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
2005 *
2006 * \ingroup contacts
1917 */ 2007 */
1918 int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type) 2008 int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type)
1919 { 2009 {
1920 struct gg_add_remove a; 2010 struct gg_add_remove a;
1921 2011
1922 gg_debug(GG_DEBUG_FUNCTION, "** gg_add_notify_ex(%p, %u, %d);\n", sess, uin, type); 2012 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_add_notify_ex(%p, %u, %d);\n", sess, uin, type);
1923 2013
1924 if (!sess) { 2014 if (!sess) {
1925 errno = EFAULT; 2015 errno = EFAULT;
1926 return -1; 2016 return -1;
1927 } 2017 }
1928 2018
1929 if (sess->state != GG_STATE_CONNECTED) { 2019 if (sess->state != GG_STATE_CONNECTED) {
1930 errno = ENOTCONN; 2020 errno = ENOTCONN;
1931 return -1; 2021 return -1;
1932 } 2022 }
1933 2023
1934 a.uin = gg_fix32(uin); 2024 a.uin = gg_fix32(uin);
1935 a.dunno1 = type; 2025 a.dunno1 = type;
1936 2026
1937 return gg_send_packet(sess, GG_ADD_NOTIFY, &a, sizeof(a), NULL); 2027 return gg_send_packet(sess, GG_ADD_NOTIFY, &a, sizeof(a), NULL);
1938 } 2028 }
1939 2029
1940 /* 2030 /**
1941 * gg_add_notify() 2031 * Dodaje kontakt.
1942 * 2032 *
1943 * dodaje do listy kontakt體 dany numer w trakcie po潮czenia. 2033 * Funkcja jest odpowiednikiem \c gg_add_notify_ex(), gdzie rodzaj wszystkich
1944 * 2034 * kontakt贸w to \c GG_USER_NORMAL.
1945 * - sess - opis sesji 2035 *
1946 * - uin - numer 2036 * \param sess Struktura sesji
1947 * 2037 * \param uin Numer kontaktu
1948 * 0, -1. 2038 *
2039 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
2040 *
2041 * \ingroup contacts
1949 */ 2042 */
1950 int gg_add_notify(struct gg_session *sess, uin_t uin) 2043 int gg_add_notify(struct gg_session *sess, uin_t uin)
1951 { 2044 {
1952 return gg_add_notify_ex(sess, uin, GG_USER_NORMAL); 2045 return gg_add_notify_ex(sess, uin, GG_USER_NORMAL);
1953 } 2046 }
1954 2047
1955 /* 2048 /**
1956 * gg_remove_notify_ex() 2049 * Usuwa kontakt.
1957 * 2050 *
1958 * usuwa z listy kontakt體 w trakcie po潮czenia. 2051 * Usuwa z listy kontakt贸w dany numer w trakcie po艂膮czenia.
1959 * usuwanemu u縴tkownikowi okre秎amy jego typ (patrz protocol.html) 2052 *
1960 * 2053 * \param sess Struktura sesji
1961 * - sess - opis sesji 2054 * \param uin Numer kontaktu
1962 * - uin - numer 2055 * \param type Rodzaj kontaktu
1963 * - type - typ 2056 *
1964 * 2057 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
1965 * 0, -1. 2058 *
2059 * \ingroup contacts
1966 */ 2060 */
1967 int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type) 2061 int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type)
1968 { 2062 {
1969 struct gg_add_remove a; 2063 struct gg_add_remove a;
1970 2064
1971 gg_debug(GG_DEBUG_FUNCTION, "** gg_remove_notify_ex(%p, %u, %d);\n", sess, uin, type); 2065 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_remove_notify_ex(%p, %u, %d);\n", sess, uin, type);
1972 2066
1973 if (!sess) { 2067 if (!sess) {
1974 errno = EFAULT; 2068 errno = EFAULT;
1975 return -1; 2069 return -1;
1976 } 2070 }
1977 2071
1980 return -1; 2074 return -1;
1981 } 2075 }
1982 2076
1983 a.uin = gg_fix32(uin); 2077 a.uin = gg_fix32(uin);
1984 a.dunno1 = type; 2078 a.dunno1 = type;
1985 2079
1986 return gg_send_packet(sess, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL); 2080 return gg_send_packet(sess, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL);
1987 } 2081 }
1988 2082
1989 /* 2083 /**
1990 * gg_remove_notify() 2084 * Usuwa kontakt.
1991 * 2085 *
1992 * usuwa z listy kontakt體 w trakcie po潮czenia. 2086 * Funkcja jest odpowiednikiem \c gg_add_notify_ex(), gdzie rodzaj wszystkich
1993 * 2087 * kontakt贸w to \c GG_USER_NORMAL.
1994 * - sess - opis sesji 2088 *
1995 * - uin - numer 2089 * \param sess Struktura sesji
1996 * 2090 * \param uin Numer kontaktu
1997 * 0, -1. 2091 *
2092 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
2093 *
2094 * \ingroup contacts
1998 */ 2095 */
1999 int gg_remove_notify(struct gg_session *sess, uin_t uin) 2096 int gg_remove_notify(struct gg_session *sess, uin_t uin)
2000 { 2097 {
2001 return gg_remove_notify_ex(sess, uin, GG_USER_NORMAL); 2098 return gg_remove_notify_ex(sess, uin, GG_USER_NORMAL);
2002 } 2099 }
2003 2100
2004 /* 2101 /**
2005 * gg_userlist_request() 2102 * Wysy艂a do serwera zapytanie dotycz膮ce listy kontakt贸w.
2006 * 2103 *
2007 * wysy砤 勘danie/zapytanie listy kontakt體 na serwerze. 2104 * Funkcja s艂u偶y do importu lub eksportu listy kontakt贸w do serwera.
2008 * 2105 * W odr贸偶nieniu od funkcji \c gg_notify(), ta lista kontakt贸w jest przez
2009 * - sess - opis sesji 2106 * serwer jedynie przechowywana i nie ma wp艂ywu na po艂膮czenie. Format
2010 * - type - rodzaj zapytania/勘dania 2107 * listy kontakt贸w jest ignorowany przez serwer, ale ze wzgl臋du na
2011 * - request - tre舵 zapytania/勘dania (mo縠 by NULL) 2108 * kompatybilno艣膰 z innymi klientami, nale偶y przechowywa膰 dane w tym samym
2012 * 2109 * formacie co oryginalny klient Gadu-Gadu.
2013 * 0, -1 2110 *
2111 * Program nie musi si臋 przejmowa膰 fragmentacj膮 listy kontakt贸w wynikaj膮c膮
2112 * z protoko艂u -- wysy艂a i odbiera kompletn膮 list臋.
2113 *
2114 * \param sess Struktura sesji
2115 * \param type Rodzaj zapytania
2116 * \param request Tre艣膰 zapytania (mo偶e by膰 r贸wne NULL)
2117 *
2118 * \return 0 je艣li si臋 powiod艂o, -1 w przypadku b艂臋du
2119 *
2120 * \ingroup importexport
2014 */ 2121 */
2015 int gg_userlist_request(struct gg_session *sess, char type, const char *request) 2122 int gg_userlist_request(struct gg_session *sess, char type, const char *request)
2016 { 2123 {
2017 int len; 2124 int len;
2018 2125
2019 if (!sess) { 2126 if (!sess) {
2020 errno = EFAULT; 2127 errno = EFAULT;
2021 return -1; 2128 return -1;
2022 } 2129 }
2023 2130
2024 if (sess->state != GG_STATE_CONNECTED) { 2131 if (sess->state != GG_STATE_CONNECTED) {
2025 errno = ENOTCONN; 2132 errno = ENOTCONN;
2026 return -1; 2133 return -1;
2027 } 2134 }
2028 2135
2029 if (!request) { 2136 if (!request) {
2030 sess->userlist_blocks = 1; 2137 sess->userlist_blocks = 1;
2031 return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), NULL); 2138 return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), NULL);
2032 } 2139 }
2033 2140
2034 len = strlen(request); 2141 len = strlen(request);
2035 2142
2036 sess->userlist_blocks = 0; 2143 sess->userlist_blocks = 0;
2037 2144
2038 while (len > 2047) { 2145 while (len > 2047) {
2050 2157
2051 sess->userlist_blocks++; 2158 sess->userlist_blocks++;
2052 2159
2053 return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, len, NULL); 2160 return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, len, NULL);
2054 } 2161 }
2162
2163 /* @} */
2055 2164
2056 /* 2165 /*
2057 * Local variables: 2166 * Local variables:
2058 * c-indentation-style: k&r 2167 * c-indentation-style: k&r
2059 * c-basic-offset: 8 2168 * c-basic-offset: 8