Mercurial > pidgin.yaz
comparison src/protocols/gg/libgg.c @ 2792:9123abd0db92
[gaim-migrate @ 2805]
Arkadiusz Miskiewicz's updates to Gadu-Gadu
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Mon, 26 Nov 2001 21:22:56 +0000 |
parents | 04a5f68f640c |
children | 4b3f17ca66bf |
comparison
equal
deleted
inserted
replaced
2791:8f6365332a05 | 2792:9123abd0db92 |
---|---|
1 /* $Id: libgg.c 2608 2001-10-24 08:35:55Z warmenhoven $ */ | 1 /* $Id: libgg.c 2805 2001-11-26 21:22:56Z warmenhoven $ */ |
2 | 2 |
3 /* | 3 /* |
4 * (C) Copyright 2001 Wojtek Kaniewski <wojtekka@irc.pl> | 4 * (C) Copyright 2001 Wojtek Kaniewski <wojtekka@irc.pl>, |
5 * Robert J. Woźny <speedy@atman.pl> | |
5 * | 6 * |
6 * This program is free software; you can redistribute it and/or modify | 7 * This program is free software; you can redistribute it and/or modify |
7 * it under the terms of the GNU General Public License Version 2 as | 8 * it under the terms of the GNU General Public License Version 2 as |
8 * published by the Free Software Foundation. | 9 * published by the Free Software Foundation. |
9 * | 10 * |
24 #include <sys/socket.h> | 25 #include <sys/socket.h> |
25 #include <netinet/in.h> | 26 #include <netinet/in.h> |
26 #include <arpa/inet.h> | 27 #include <arpa/inet.h> |
27 #include <sys/ioctl.h> | 28 #include <sys/ioctl.h> |
28 #include <sys/wait.h> | 29 #include <sys/wait.h> |
29 #include <sys/types.h> | 30 #include <sys/time.h> |
30 #include <fcntl.h> | |
31 #include <netdb.h> | 31 #include <netdb.h> |
32 #include <errno.h> | 32 #include <errno.h> |
33 #include <string.h> | 33 #ifndef _AIX |
34 # include <string.h> | |
35 #endif | |
34 #include <stdarg.h> | 36 #include <stdarg.h> |
35 #include <pwd.h> | 37 #include <pwd.h> |
38 #include <time.h> | |
39 #ifdef sun | |
40 #include <sys/filio.h> | |
41 #endif | |
36 #include <glib.h> | 42 #include <glib.h> |
43 #if G_BYTE_ORDER == G_BIG_ENDIAN | |
44 # define WORDS_BIGENDIAN 1 | |
45 #endif | |
37 #include "libgg.h" | 46 #include "libgg.h" |
47 #include "config.h" | |
38 | 48 |
39 int gg_debug_level = 0; | 49 int gg_debug_level = 0; |
40 | 50 |
41 #ifdef GG_DEBUG | 51 #ifndef lint |
42 | 52 |
43 /* | 53 static char rcsid[] |
44 * gg_debug_real() | 54 #ifdef __GNUC__ |
55 __attribute__ ((unused)) | |
56 #endif | |
57 = "$Id: libgg.c 2805 2001-11-26 21:22:56Z warmenhoven $"; | |
58 | |
59 #endif | |
60 | |
61 /* | |
62 * gg_debug() | |
45 * | 63 * |
46 * wyrzuca komunikat o danym poziomie, o ile użytkownik sobie tego życzy. | 64 * wyrzuca komunikat o danym poziomie, o ile użytkownik sobie tego życzy. |
47 * | 65 * |
48 * - level - poziom wiadomości, | 66 * - level - poziom wiadomości, |
49 * - format... - treść wiadomości (printf-alike.) | 67 * - format... - treść wiadomości (printf-alike.) |
50 * | 68 * |
51 * niczego nie zwraca. | 69 * niczego nie zwraca. |
52 */ | 70 */ |
53 void gg_debug_real(int level, char *format, ...) | 71 void gg_debug(int level, char *format, ...) |
54 { | 72 { |
55 va_list ap; | 73 va_list ap; |
56 | 74 |
57 if ((gg_debug_level & level)) { | 75 if ((gg_debug_level & level)) { |
58 va_start(ap, format); | 76 va_start(ap, format); |
59 vprintf(format, ap); | 77 vprintf(format, ap); |
60 va_end(ap); | 78 va_end(ap); |
61 } | 79 } |
62 } | 80 } |
63 | 81 |
64 #endif /* GG_DEBUG */ | |
65 | |
66 /* | 82 /* |
67 * fix32() // funkcja wewnętrzna | 83 * fix32() // funkcja wewnętrzna |
68 * | 84 * |
69 * dla maszyn big-endianowych zamienia kolejność bajtów w ,,long''ach. | 85 * dla maszyn big-endianowych zamienia kolejność bajtów w ,,long''ach. |
70 */ | 86 */ |
71 static inline unsigned long fix32(unsigned long x) | 87 static inline unsigned long fix32(unsigned long x) |
72 { | 88 { |
73 #if G_BYTE_ORDER == G_LITTLE_ENDIAN | 89 #ifndef WORDS_BIGENDIAN |
74 return x; | 90 return x; |
75 #else | 91 #else |
76 return (unsigned long) | 92 return (unsigned long) |
77 (((x & (unsigned long) 0x000000ffU) << 24) | | 93 (((x & (unsigned long)0x000000ffU) << 24) | |
78 ((x & (unsigned long) 0x0000ff00U) << 8) | | 94 ((x & (unsigned long)0x0000ff00U) << 8) | |
79 ((x & (unsigned long) 0x00ff0000U) >> 8) | | 95 ((x & (unsigned long)0x00ff0000U) >> 8) | ((x & (unsigned long)0xff000000U) >> 24)); |
80 ((x & (unsigned long) 0xff000000U) >> 24)); | 96 #endif |
81 #endif | |
82 } | 97 } |
83 | 98 |
84 /* | 99 /* |
85 * fix16() // funkcja wewnętrzna | 100 * fix16() // funkcja wewnętrzna |
86 * | 101 * |
87 * dla maszyn big-endianowych zamienia kolejność bajtów w ,,short''ach. | 102 * dla maszyn big-endianowych zamienia kolejność bajtów w ,,short''ach. |
88 */ | 103 */ |
89 static inline unsigned short fix16(unsigned short x) | 104 static inline unsigned short fix16(unsigned short x) |
90 { | 105 { |
91 #if G_BYTE_ORDER == G_LITTLE_ENDIAN | 106 #ifndef WORDS_BIGENDIAN |
92 return x; | 107 return x; |
93 #else | 108 #else |
94 return (unsigned short) | 109 return (unsigned short) |
95 (((x & (unsigned short) 0x00ffU) << 8) | | 110 (((x & (unsigned short)0x00ffU) << 8) | ((x & (unsigned short)0xff00U) >> 8)); |
96 ((x & (unsigned short) 0xff00U) >> 8)); | |
97 #endif | 111 #endif |
98 } | 112 } |
99 | 113 |
100 /* | 114 /* |
101 * gg_alloc_sprintf() // funkcja wewnętrzna | 115 * gg_alloc_sprintf() // funkcja wewnętrzna |
102 * | 116 * |
103 * robi dokładnie to samo, co sprintf(), tyle że alokuje sobie wcześniej | 117 * robi dokładnie to samo, co sprintf(), tyle że alokuje sobie wcześniej |
104 * miejsce na dane. jak znam życie, ze względu na różnice między funkcjami | 118 * miejsce na dane. powinno działać na tych maszynach, które mają funkcję |
105 * vsnprintf() na różnych platformach, nie będzie działało ;) | 119 * vsnprintf() zgodną z C99, jak i na wcześniejszych. |
106 * | 120 * |
107 * - format, ... - parametry takie same jak w innych funkcjach *printf() | 121 * - format, ... - parametry takie same jak w innych funkcjach *printf() |
108 * | 122 * |
109 * zwraca zaalokowany buforek, który wypadałoby później zwolnić, lub NULL | 123 * zwraca zaalokowany buforek, który wypadałoby później zwolnić, lub NULL |
110 * jeśli nie udało się wykonać zadania. | 124 * jeśli nie udało się wykonać zadania. |
111 */ | 125 */ |
112 char *gg_alloc_sprintf(char *format, ...) | 126 char *gg_alloc_sprintf(char *format, ...) |
113 { | 127 { |
114 va_list ap; | 128 va_list ap; |
115 char *buf = NULL; | 129 char *buf = NULL, *tmp; |
116 int size; | 130 int size = 0, res; |
117 | 131 |
118 va_start(ap, format); | 132 va_start(ap, format); |
119 | 133 |
120 if ((size = vsnprintf(buf, 0, format, ap)) < 0) | 134 if ((size = vsnprintf(buf, 0, format, ap)) < 1) { |
135 size = 128; | |
136 do { | |
137 size *= 2; | |
138 if (!(tmp = realloc(buf, size))) { | |
139 free(buf); | |
140 return NULL; | |
141 } | |
142 buf = tmp; | |
143 res = vsnprintf(buf, size, format, ap); | |
144 } while (res == size - 1); | |
145 } else { | |
146 if (!(buf = malloc(size + 1))) | |
147 return NULL; | |
148 } | |
149 | |
150 vsnprintf(buf, size + 1, format, ap); | |
151 | |
152 va_end(ap); | |
153 | |
154 return buf; | |
155 } | |
156 | |
157 /* | |
158 * gg_get_line() // funkcja wewnętrzna | |
159 * | |
160 * podaje kolejną linię z bufora tekstowego. psuje co bezpowrotnie, dzieląc | |
161 * na kolejne stringi. zdarza się, nie ma potrzeby pisania funkcji dublującej | |
162 * bufor żeby tylko mieć nieruszone dane wejściowe, skoro i tak nie będą nam | |
163 * poźniej potrzebne. obcina `\r\n'. | |
164 * | |
165 * - ptr - wskaźnik do zmiennej, która przechowuje aktualną pozycję | |
166 * w przemiatanym buforze. | |
167 * | |
168 * wskaźnik do kolejnej linii tekstu lub NULL, jeśli to już koniec bufora. | |
169 */ | |
170 char *gg_get_line(char **ptr) | |
171 { | |
172 char *foo, *res; | |
173 | |
174 if (!ptr || !*ptr || !strcmp(*ptr, "")) | |
121 return NULL; | 175 return NULL; |
122 | 176 |
123 if (!(buf = malloc(size + 1))) | 177 res = *ptr; |
124 return NULL; | 178 |
125 | 179 if (!(foo = strchr(*ptr, '\n'))) |
126 vsnprintf(buf, size + 1, format, ap); | 180 *ptr += strlen(*ptr); |
127 | 181 else { |
128 va_end(ap); | 182 *ptr = foo + 1; |
129 | 183 *foo = 0; |
130 return buf; | 184 if (res[strlen(res) - 1] == '\r') |
185 res[strlen(res) - 1] = 0; | |
186 } | |
187 | |
188 return res; | |
131 } | 189 } |
132 | 190 |
133 /* | 191 /* |
134 * gg_resolve() // funkcja wewnętrzna | 192 * gg_resolve() // funkcja wewnętrzna |
135 * | 193 * |
148 { | 206 { |
149 int pipes[2], res; | 207 int pipes[2], res; |
150 struct in_addr a; | 208 struct in_addr a; |
151 | 209 |
152 gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve(..., \"%s\");\n", hostname); | 210 gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve(..., \"%s\");\n", hostname); |
153 | 211 |
154 if (!fd | !pid) { | 212 if (!fd | !pid) { |
155 errno = EFAULT; | 213 errno = EFAULT; |
156 return -1; | 214 return -1; |
157 } | 215 } |
158 | 216 |
163 return -1; | 221 return -1; |
164 | 222 |
165 if (!res) { | 223 if (!res) { |
166 if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { | 224 if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { |
167 struct hostent *he; | 225 struct hostent *he; |
168 | 226 |
169 if (!(he = gethostbyname(hostname))) | 227 if (!(he = gethostbyname(hostname))) |
170 a.s_addr = INADDR_NONE; | 228 a.s_addr = INADDR_NONE; |
171 else | 229 else |
172 memcpy((char*) &a, he->h_addr, sizeof(a)); | 230 memcpy((char *)&a, he->h_addr, sizeof(a)); |
173 } | 231 } |
174 | 232 |
175 write(pipes[1], &a, sizeof(a)); | 233 write(pipes[1], &a, sizeof(a)); |
176 | 234 |
177 exit(0); | 235 exit(0); |
203 int sock, one = 1; | 261 int sock, one = 1; |
204 struct sockaddr_in sin; | 262 struct sockaddr_in sin; |
205 struct in_addr *a = addr; | 263 struct in_addr *a = addr; |
206 | 264 |
207 gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async); | 265 gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async); |
208 | 266 |
209 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { | 267 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { |
210 gg_debug(GG_DEBUG_MISC, "-- socket() failed. errno = %d (%s)\n", errno, strerror(errno)); | 268 gg_debug(GG_DEBUG_MISC, "-- socket() failed. errno = %d (%s)\n", errno, strerror(errno)); |
211 return -1; | 269 return -1; |
212 } | 270 } |
213 | 271 |
214 if (async) { | 272 if (async) { |
215 #ifdef FIONBIO | |
216 if (ioctl(sock, FIONBIO, &one) == -1) { | 273 if (ioctl(sock, FIONBIO, &one) == -1) { |
217 #else | 274 gg_debug(GG_DEBUG_MISC, "-- ioctl() failed. errno = %d (%s)\n", errno, |
218 int flags = fcntl (sock, F_GETFL); | 275 strerror(errno)); |
219 if (flags < 0 || | |
220 fcntl (sock, F_SETFL, flags | O_NONBLOCK) < 0) { | |
221 #endif | |
222 gg_debug(GG_DEBUG_MISC, "-- ioctl() failed. errno = %d (%s)\n", errno, strerror(errno)); | |
223 return -1; | 276 return -1; |
224 } | 277 } |
225 } | 278 } |
226 | 279 |
227 sin.sin_port = htons(port); | 280 sin.sin_port = htons(port); |
228 sin.sin_family = AF_INET; | 281 sin.sin_family = AF_INET; |
229 sin.sin_addr.s_addr = a->s_addr; | 282 sin.sin_addr.s_addr = a->s_addr; |
230 | 283 |
231 if (connect(sock, (struct sockaddr*) &sin, sizeof(sin)) == -1) { | 284 if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) { |
232 gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d (%s)\n", errno, strerror(errno)); | 285 if (errno && (!async || errno != EINPROGRESS)) { |
233 if (errno && (!async || errno != EINPROGRESS)) | 286 gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d (%s)\n", errno, |
287 strerror(errno)); | |
234 return -1; | 288 return -1; |
235 } | 289 } |
236 | 290 gg_debug(GG_DEBUG_MISC, "-- connect() in progress\n"); |
291 } | |
292 | |
237 return sock; | 293 return sock; |
238 } | 294 } |
239 | 295 |
240 /* | 296 /* |
241 * gg_read_line() // funkcja wewnętrzna | 297 * gg_read_line() // funkcja wewnętrzna |
251 static void gg_read_line(int sock, char *buf, int length) | 307 static void gg_read_line(int sock, char *buf, int length) |
252 { | 308 { |
253 int ret; | 309 int ret; |
254 | 310 |
255 gg_debug(GG_DEBUG_FUNCTION, "** gg_read_line(...);\n"); | 311 gg_debug(GG_DEBUG_FUNCTION, "** gg_read_line(...);\n"); |
256 | 312 |
257 for (; length > 1; buf++, length--) { | 313 for (; length > 1; buf++, length--) { |
258 do { | 314 do { |
259 if ((ret = read(sock, buf, 1)) == -1 && errno != EINTR) { | 315 if ((ret = read(sock, buf, 1)) == -1 && errno != EINTR) { |
260 *buf = 0; | 316 *buf = 0; |
261 return; | 317 return; |
287 struct gg_header h; | 343 struct gg_header h; |
288 char *buf = NULL; | 344 char *buf = NULL; |
289 int ret = 0, offset, size = 0; | 345 int ret = 0, offset, size = 0; |
290 | 346 |
291 gg_debug(GG_DEBUG_FUNCTION, "** gg_recv_packet(...);\n"); | 347 gg_debug(GG_DEBUG_FUNCTION, "** gg_recv_packet(...);\n"); |
292 | 348 |
293 if (!sess) { | 349 if (!sess) { |
294 errno = EFAULT; | 350 errno = EFAULT; |
295 return NULL; | 351 return NULL; |
296 } | 352 } |
297 | 353 |
299 while (ret != sizeof(h)) { | 355 while (ret != sizeof(h)) { |
300 ret = read(sess->fd, &h, sizeof(h)); | 356 ret = read(sess->fd, &h, sizeof(h)); |
301 gg_debug(GG_DEBUG_MISC, "-- header recv(..., %d) = %d\n", sizeof(h), ret); | 357 gg_debug(GG_DEBUG_MISC, "-- header recv(..., %d) = %d\n", sizeof(h), ret); |
302 if (ret < sizeof(h)) { | 358 if (ret < sizeof(h)) { |
303 if (errno != EINTR) { | 359 if (errno != EINTR) { |
304 gg_debug(GG_DEBUG_MISC, "-- errno = %d (%s)\n", errno, strerror(errno)); | 360 gg_debug(GG_DEBUG_MISC, "-- errno = %d (%s)\n", errno, |
361 strerror(errno)); | |
305 return NULL; | 362 return NULL; |
306 } | 363 } |
307 } | 364 } |
308 } | 365 } |
309 | 366 |
341 ret = read(sess->fd, buf + sizeof(h) + offset, size); | 398 ret = read(sess->fd, buf + sizeof(h) + offset, size); |
342 gg_debug(GG_DEBUG_MISC, "-- body recv(..., %d) = %d\n", size, ret); | 399 gg_debug(GG_DEBUG_MISC, "-- body recv(..., %d) = %d\n", size, ret); |
343 if (ret > -1 && ret <= size) { | 400 if (ret > -1 && ret <= size) { |
344 offset += ret; | 401 offset += ret; |
345 size -= ret; | 402 size -= ret; |
346 } else if (ret == -1) { | 403 } else if (ret == -1) { |
347 gg_debug(GG_DEBUG_MISC, "-- errno = %d (%s)\n", errno, strerror(errno)); | 404 gg_debug(GG_DEBUG_MISC, "-- errno = %d (%s)\n", errno, strerror(errno)); |
348 if (errno == EAGAIN) { | 405 if (errno == EAGAIN) { |
349 gg_debug(GG_DEBUG_MISC, "-- %d bytes received, %d left\n", offset, size); | 406 gg_debug(GG_DEBUG_MISC, "-- %d bytes received, %d left\n", offset, size); |
350 sess->recv_buf = buf; | 407 sess->recv_buf = buf; |
351 sess->recv_left = size; | 408 sess->recv_left = size; |
352 sess->recv_done = offset; | 409 sess->recv_done = offset; |
353 return NULL; | 410 return NULL; |
354 } | 411 } |
355 if (errno != EINTR) { | 412 if (errno != EINTR) { |
356 /* errno = EINVAL; */ | 413 // errno = EINVAL; |
357 free(buf); | 414 free(buf); |
358 return NULL; | 415 return NULL; |
359 } | 416 } |
360 } | 417 } |
361 } | 418 } |
362 | 419 |
363 sess->recv_left = 0; | 420 sess->recv_left = 0; |
364 | 421 |
365 #ifdef GG_DEBUG | |
366 if ((gg_debug_level & GG_DEBUG_DUMP)) { | 422 if ((gg_debug_level & GG_DEBUG_DUMP)) { |
367 int i; | 423 int i; |
368 | 424 |
369 gg_debug(GG_DEBUG_DUMP, ">> received packet (type=%.2x):", h.type); | 425 gg_debug(GG_DEBUG_DUMP, ">> received packet (type=%.2x):", h.type); |
370 for (i = 0; i < sizeof(h) + h.length; i++) | 426 for (i = 0; i < sizeof(h) + h.length; i++) |
371 gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) buf[i]); | 427 gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char)buf[i]); |
372 gg_debug(GG_DEBUG_DUMP, "\n"); | 428 gg_debug(GG_DEBUG_DUMP, "\n"); |
373 } | 429 } |
374 #endif | |
375 | 430 |
376 return buf; | 431 return buf; |
377 } | 432 } |
378 | 433 |
379 /* | 434 /* |
390 * | 445 * |
391 * jeśli poszło dobrze, zwraca 0. w przypadku błędu -1. jeśli errno=ENOMEM, | 446 * jeśli poszło dobrze, zwraca 0. w przypadku błędu -1. jeśli errno=ENOMEM, |
392 * zabrakło pamięci. inaczej był błąd przy wysyłaniu pakietu. dla errno=0 | 447 * zabrakło pamięci. inaczej był błąd przy wysyłaniu pakietu. dla errno=0 |
393 * nie wysłano całego pakietu. | 448 * nie wysłano całego pakietu. |
394 */ | 449 */ |
395 static int gg_send_packet(int sock, int type, void *packet, int length, void *payload, int payload_length) | 450 static int gg_send_packet(int sock, int type, void *packet, int length, void *payload, |
451 int payload_length) | |
396 { | 452 { |
397 struct gg_header *h; | 453 struct gg_header *h; |
398 int res, plen; | 454 int res, plen; |
399 char *tmp; | 455 char *tmp; |
400 | 456 |
401 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_packet(0x%.2x, %d, %d);\n", type, length, payload_length); | 457 gg_debug(GG_DEBUG_FUNCTION, "** gg_send_packet(0x%.2x, %d, %d);\n", type, length, |
402 | 458 payload_length); |
459 | |
403 if (length < 0 || payload_length < 0) { | 460 if (length < 0 || payload_length < 0) { |
404 gg_debug(GG_DEBUG_MISC, "-- invalid packet/payload length\n"); | 461 gg_debug(GG_DEBUG_MISC, "-- invalid packet/payload length\n"); |
405 errno = ERANGE; | 462 errno = ERANGE; |
406 return -1; | 463 return -1; |
407 } | 464 } |
409 if (!(tmp = malloc(sizeof(struct gg_header) + length + payload_length))) { | 466 if (!(tmp = malloc(sizeof(struct gg_header) + length + payload_length))) { |
410 gg_debug(GG_DEBUG_MISC, "-- not enough memory\n"); | 467 gg_debug(GG_DEBUG_MISC, "-- not enough memory\n"); |
411 return -1; | 468 return -1; |
412 } | 469 } |
413 | 470 |
414 h = (struct gg_header*) tmp; | 471 h = (struct gg_header *)tmp; |
415 h->type = fix32(type); | 472 h->type = fix32(type); |
416 h->length = fix32(length + payload_length); | 473 h->length = fix32(length + payload_length); |
417 | 474 |
418 if (packet) | 475 if (packet) |
419 memcpy(tmp + sizeof(struct gg_header), packet, length); | 476 memcpy(tmp + sizeof(struct gg_header), packet, length); |
420 if (payload) | 477 if (payload) |
421 memcpy(tmp + sizeof(struct gg_header) + length, payload, payload_length); | 478 memcpy(tmp + sizeof(struct gg_header) + length, payload, payload_length); |
422 | 479 |
423 #ifdef GG_DEBUG | |
424 if ((gg_debug_level & GG_DEBUG_DUMP)) { | 480 if ((gg_debug_level & GG_DEBUG_DUMP)) { |
425 int i; | 481 int i; |
426 | 482 |
427 gg_debug(GG_DEBUG_DUMP, "%%%% sending packet (type=%.2x):", fix32(h->type)); | 483 gg_debug(GG_DEBUG_DUMP, "%%%% sending packet (type=%.2x):", fix32(h->type)); |
428 for (i = 0; i < sizeof(struct gg_header) + fix32(h->length); i++) | 484 for (i = 0; i < sizeof(struct gg_header) + fix32(h->length); i++) |
429 gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) tmp[i]); | 485 gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char)tmp[i]); |
430 gg_debug(GG_DEBUG_DUMP, "\n"); | 486 gg_debug(GG_DEBUG_DUMP, "\n"); |
431 } | 487 } |
432 #endif | |
433 | 488 |
434 plen = sizeof(struct gg_header) + length + payload_length; | 489 plen = sizeof(struct gg_header) + length + payload_length; |
435 | 490 |
436 if ((res = write(sock, tmp, plen)) < plen) { | 491 if ((res = write(sock, tmp, plen)) < plen) { |
437 gg_debug(GG_DEBUG_MISC, "-- write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno)); | 492 gg_debug(GG_DEBUG_MISC, "-- write() failed. res = %d, errno = %d (%s)\n", res, errno, |
493 strerror(errno)); | |
438 free(tmp); | 494 free(tmp); |
439 return -1; | 495 return -1; |
440 } | 496 } |
441 | 497 |
442 free(tmp); | 498 free(tmp); |
443 return 0; | 499 return 0; |
444 } | 500 } |
445 | 501 |
446 | 502 |
447 /* | 503 /* |
477 sess->state = GG_STATE_RESOLVING; | 533 sess->state = GG_STATE_RESOLVING; |
478 sess->check = GG_CHECK_READ; | 534 sess->check = GG_CHECK_READ; |
479 sess->async = async; | 535 sess->async = async; |
480 sess->seq = 0; | 536 sess->seq = 0; |
481 sess->recv_left = 0; | 537 sess->recv_left = 0; |
538 sess->last_pong = 0; | |
539 sess->server_ip = 0; | |
540 sess->initial_status = 0; | |
482 | 541 |
483 if (async) { | 542 if (async) { |
484 if (gg_resolve(&sess->fd, &sess->pid, GG_APPMSG_HOST)) { | 543 if (gg_resolve(&sess->fd, &sess->pid, GG_APPMSG_HOST)) { |
485 gg_debug(GG_DEBUG_MISC, "-- resolving failed\n"); | 544 gg_debug(GG_DEBUG_MISC, "-- resolving failed\n"); |
486 free(sess); | 545 free(sess); |
489 } else { | 548 } else { |
490 struct in_addr a; | 549 struct in_addr a; |
491 | 550 |
492 if ((a.s_addr = inet_addr(GG_APPMSG_HOST)) == INADDR_NONE) { | 551 if ((a.s_addr = inet_addr(GG_APPMSG_HOST)) == INADDR_NONE) { |
493 struct hostent *he; | 552 struct hostent *he; |
494 | 553 |
495 if (!(he = gethostbyname(GG_APPMSG_HOST))) { | 554 if (!(he = gethostbyname(GG_APPMSG_HOST))) { |
496 gg_debug(GG_DEBUG_MISC, "-- host %s not found\n", GG_APPMSG_HOST); | 555 gg_debug(GG_DEBUG_MISC, "-- host %s not found\n", GG_APPMSG_HOST); |
497 free(sess); | 556 free(sess); |
498 return NULL; | 557 return NULL; |
499 } else | 558 } else |
500 memcpy((char*) &a, he->h_addr, sizeof(a)); | 559 memcpy((char *)&a, he->h_addr, sizeof(a)); |
501 } | 560 } |
502 | 561 |
503 if (!(sess->fd = gg_connect(&a, GG_APPMSG_PORT, 0)) == -1) { | 562 if (!(sess->fd = gg_connect(&a, GG_APPMSG_PORT, 0)) == -1) { |
504 gg_debug(GG_DEBUG_MISC, "-- connection failed\n"); | 563 gg_debug(GG_DEBUG_MISC, "-- connection failed\n"); |
505 free(sess); | 564 free(sess); |
516 free(sess); | 575 free(sess); |
517 return NULL; | 576 return NULL; |
518 } | 577 } |
519 | 578 |
520 if (e->type == GG_EVENT_CONN_FAILED) { | 579 if (e->type == GG_EVENT_CONN_FAILED) { |
580 errno = EACCES; | |
521 gg_debug(GG_DEBUG_MISC, "-- could not login\n"); | 581 gg_debug(GG_DEBUG_MISC, "-- could not login\n"); |
522 gg_free_event(e); | 582 gg_free_event(e); |
523 free(sess); | 583 free(sess); |
524 return NULL; | 584 return NULL; |
525 } | 585 } |
596 | 656 |
597 gg_debug(GG_DEBUG_FUNCTION, "** gg_logoff(...);\n"); | 657 gg_debug(GG_DEBUG_FUNCTION, "** gg_logoff(...);\n"); |
598 | 658 |
599 if (sess->state == GG_STATE_CONNECTED) | 659 if (sess->state == GG_STATE_CONNECTED) |
600 gg_change_status(sess, GG_STATUS_NOT_AVAIL); | 660 gg_change_status(sess, GG_STATUS_NOT_AVAIL); |
601 | 661 |
602 if (sess->fd) { | 662 if (sess->fd) { |
603 shutdown(sess->fd, 2); | 663 shutdown(sess->fd, 2); |
604 close(sess->fd); | 664 close(sess->fd); |
605 } | 665 } |
606 } | 666 } |
624 | 684 |
625 if (!sess) { | 685 if (!sess) { |
626 errno = EFAULT; | 686 errno = EFAULT; |
627 return -1; | 687 return -1; |
628 } | 688 } |
629 | 689 |
630 if (sess->state != GG_STATE_CONNECTED) { | 690 if (sess->state != GG_STATE_CONNECTED) { |
631 errno = ENOTCONN; | 691 errno = ENOTCONN; |
632 return -1; | 692 return -1; |
633 } | 693 } |
634 | 694 |
638 if (!sess->seq) | 698 if (!sess->seq) |
639 sess->seq = 0x01740000 | (rand() & 0xffff); | 699 sess->seq = 0x01740000 | (rand() & 0xffff); |
640 s.seq = fix32(sess->seq); | 700 s.seq = fix32(sess->seq); |
641 s.msgclass = fix32(msgclass); | 701 s.msgclass = fix32(msgclass); |
642 sess->seq += (rand() % 0x300) + 0x300; | 702 sess->seq += (rand() % 0x300) + 0x300; |
643 | 703 |
644 if (gg_send_packet(sess->fd, GG_SEND_MSG, &s, sizeof(s), message, strlen(message) + 1) == -1) | 704 if (gg_send_packet(sess->fd, GG_SEND_MSG, &s, sizeof(s), message, strlen(message) + 1) == -1) |
645 return -1; | 705 return -1; |
646 | 706 |
647 return fix32(s.seq); | 707 return fix32(s.seq); |
648 } | 708 } |
702 * - userlist - wskaźnik do tablicy numerów, | 762 * - userlist - wskaźnik do tablicy numerów, |
703 * - count - ilość numerków. | 763 * - count - ilość numerków. |
704 * | 764 * |
705 * jeśli udało się, zwraca 0. jeśli błąd, dostajemy -1. | 765 * jeśli udało się, zwraca 0. jeśli błąd, dostajemy -1. |
706 */ | 766 */ |
707 int gg_notify(struct gg_session *sess, uin_t *userlist, int count) | 767 int gg_notify(struct gg_session *sess, uin_t * userlist, int count) |
708 { | 768 { |
709 struct gg_notify *n; | 769 struct gg_notify *n; |
710 uin_t *u; | 770 uin_t *u; |
711 int i, res = 0; | 771 int i, res = 0; |
712 | 772 |
713 if (!sess) { | 773 if (!sess) { |
714 errno = EFAULT; | 774 errno = EFAULT; |
715 return -1; | 775 return -1; |
716 } | 776 } |
717 | 777 |
718 if (sess->state != GG_STATE_CONNECTED) { | 778 if (sess->state != GG_STATE_CONNECTED) { |
719 errno = ENOTCONN; | 779 errno = ENOTCONN; |
720 return -1; | 780 return -1; |
721 } | 781 } |
722 | 782 |
723 gg_debug(GG_DEBUG_FUNCTION, "** gg_notify(..., %d);\n", count); | 783 gg_debug(GG_DEBUG_FUNCTION, "** gg_notify(..., %d);\n", count); |
724 | 784 |
725 if (!userlist || !count) | 785 if (!userlist || !count) |
726 return 0; | 786 return 0; |
727 | 787 |
728 if (!(n = (struct gg_notify*) malloc(sizeof(*n) * count))) | 788 if (!(n = (struct gg_notify *)malloc(sizeof(*n) * count))) |
729 return -1; | 789 return -1; |
730 | 790 |
731 for (u = userlist, i = 0; i < count; u++, i++) { | 791 for (u = userlist, i = 0; i < count; u++, i++) { |
732 n[i].uin = fix32(*u); | 792 n[i].uin = fix32(*u); |
733 n[i].dunno1 = 3; | 793 n[i].dunno1 = 3; |
734 } | 794 } |
735 | 795 |
736 if (gg_send_packet(sess->fd, GG_NOTIFY, n, sizeof(*n) * count, NULL, 0) == -1) | 796 if (gg_send_packet(sess->fd, GG_NOTIFY, n, sizeof(*n) * count, NULL, 0) == -1) |
737 res = -1; | 797 res = -1; |
738 | 798 |
739 free(n); | 799 free(n); |
740 | 800 |
762 | 822 |
763 if (sess->state != GG_STATE_CONNECTED) { | 823 if (sess->state != GG_STATE_CONNECTED) { |
764 errno = ENOTCONN; | 824 errno = ENOTCONN; |
765 return -1; | 825 return -1; |
766 } | 826 } |
767 | 827 |
768 gg_debug(GG_DEBUG_FUNCTION, "** gg_add_notify(..., %u);\n", uin); | 828 gg_debug(GG_DEBUG_FUNCTION, "** gg_add_notify(..., %u);\n", uin); |
769 | 829 |
770 a.uin = fix32(uin); | 830 a.uin = fix32(uin); |
771 a.dunno1 = 3; | 831 a.dunno1 = 3; |
772 | 832 |
773 return gg_send_packet(sess->fd, GG_ADD_NOTIFY, &a, sizeof(a), NULL, 0); | 833 return gg_send_packet(sess->fd, GG_ADD_NOTIFY, &a, sizeof(a), NULL, 0); |
774 } | 834 } |
775 | 835 |
776 /* | 836 /* |
777 * gg_remove_notify() | 837 * gg_remove_notify() |
796 errno = ENOTCONN; | 856 errno = ENOTCONN; |
797 return -1; | 857 return -1; |
798 } | 858 } |
799 | 859 |
800 gg_debug(GG_DEBUG_FUNCTION, "** gg_remove_notify(..., %u);\n", uin); | 860 gg_debug(GG_DEBUG_FUNCTION, "** gg_remove_notify(..., %u);\n", uin); |
801 | 861 |
802 a.uin = fix32(uin); | 862 a.uin = fix32(uin); |
803 a.dunno1 = 3; | 863 a.dunno1 = 3; |
804 | 864 |
805 return gg_send_packet(sess->fd, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL, 0); | 865 return gg_send_packet(sess->fd, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL, 0); |
806 } | 866 } |
807 | 867 |
808 /* | 868 /* |
809 * gg_watch_fd_connected() // funkcja wewnętrzna | 869 * gg_watch_fd_connected() // funkcja wewnętrzna |
825 } | 885 } |
826 | 886 |
827 gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd_connected(...);\n"); | 887 gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd_connected(...);\n"); |
828 | 888 |
829 if (!(h = gg_recv_packet(sess))) { | 889 if (!(h = gg_recv_packet(sess))) { |
830 gg_debug(GG_DEBUG_MISC, "-- gg_recv_packet failed. errno = %d (%d)\n", errno, strerror(errno)); | 890 gg_debug(GG_DEBUG_MISC, "-- gg_recv_packet failed. errno = %d (%d)\n", errno, |
831 return -1; | 891 strerror(errno)); |
832 } | 892 return -1; |
833 | 893 } |
834 p = (void*) h + sizeof(struct gg_header); | 894 |
835 | 895 p = (void *)h + sizeof(struct gg_header); |
896 | |
836 if (h->type == GG_RECV_MSG) { | 897 if (h->type == GG_RECV_MSG) { |
837 struct gg_recv_msg *r = p; | 898 struct gg_recv_msg *r = p; |
838 | 899 |
839 gg_debug(GG_DEBUG_MISC, "-- received a message\n"); | 900 gg_debug(GG_DEBUG_MISC, "-- received a message\n"); |
840 | 901 |
841 if (h->length >= sizeof(*r)) { | 902 if (h->length >= sizeof(*r)) { |
842 e->type = GG_EVENT_MSG; | 903 e->type = GG_EVENT_MSG; |
843 e->event.msg.msgclass = fix32(r->msgclass); | 904 e->event.msg.msgclass = fix32(r->msgclass); |
844 e->event.msg.sender = fix32(r->sender); | 905 e->event.msg.sender = fix32(r->sender); |
845 e->event.msg.message = strdup((char*) r + sizeof(*r)); | 906 e->event.msg.message = strdup((char *)r + sizeof(*r)); |
907 e->event.msg.time = fix32(r->time); | |
846 } | 908 } |
847 } | 909 } |
848 | 910 |
849 if (h->type == GG_NOTIFY_REPLY) { | 911 if (h->type == GG_NOTIFY_REPLY) { |
850 struct gg_notify_reply *n = p; | 912 struct gg_notify_reply *n = p; |
851 int count, i; | 913 int count, i; |
852 | 914 |
853 gg_debug(GG_DEBUG_MISC, "-- received a notify reply\n"); | 915 gg_debug(GG_DEBUG_MISC, "-- received a notify reply\n"); |
854 | 916 |
855 e->type = GG_EVENT_NOTIFY; | 917 e->type = GG_EVENT_NOTIFY; |
856 if (!(e->event.notify = (void*) malloc(h->length + 2 * sizeof(*n)))) { | 918 if (!(e->event.notify = (void *)malloc(h->length + 2 * sizeof(*n)))) { |
857 gg_debug(GG_DEBUG_MISC, "-- not enough memory\n"); | 919 gg_debug(GG_DEBUG_MISC, "-- not enough memory\n"); |
858 free(h); | 920 free(h); |
859 return -1; | 921 return -1; |
860 } | 922 } |
861 count = h->length / sizeof(*n); | 923 count = h->length / sizeof(*n); |
891 e->event.ack.recipient = fix32(s->recipient); | 953 e->event.ack.recipient = fix32(s->recipient); |
892 e->event.ack.seq = fix32(s->seq); | 954 e->event.ack.seq = fix32(s->seq); |
893 } | 955 } |
894 } | 956 } |
895 | 957 |
958 if (h->type == GG_PONG) { | |
959 gg_debug(GG_DEBUG_MISC, "-- received a pong\n"); | |
960 | |
961 sess->last_pong = time(NULL); | |
962 } | |
963 | |
896 free(h); | 964 free(h); |
897 | 965 |
898 return 0; | 966 return 0; |
899 } | 967 } |
900 | 968 |
942 return NULL; | 1010 return NULL; |
943 } | 1011 } |
944 | 1012 |
945 gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd(...);\n"); | 1013 gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd(...);\n"); |
946 | 1014 |
947 if (!(e = (void*) malloc(sizeof(*e)))) { | 1015 if (!(e = (void *)malloc(sizeof(*e)))) { |
948 gg_debug(GG_DEBUG_MISC, "-- not enough memory\n"); | 1016 gg_debug(GG_DEBUG_MISC, "-- not enough memory\n"); |
949 return NULL; | 1017 return NULL; |
950 } | 1018 } |
951 | 1019 |
952 e->type = GG_EVENT_NONE; | 1020 e->type = GG_EVENT_NONE; |
953 | 1021 |
954 switch (sess->state) { | 1022 switch (sess->state) { |
955 case GG_STATE_RESOLVING: | 1023 case GG_STATE_RESOLVING: |
956 { | 1024 { |
957 struct in_addr a; | 1025 struct in_addr a; |
958 | 1026 |
959 gg_debug(GG_DEBUG_MISC, "== GG_STATE_RESOLVING\n"); | 1027 gg_debug(GG_DEBUG_MISC, "== GG_STATE_RESOLVING\n"); |
960 | 1028 |
961 if (read(sess->fd, &a, sizeof(a)) < sizeof(a) || a.s_addr == INADDR_NONE) { | 1029 if (read(sess->fd, &a, sizeof(a)) < sizeof(a) || a.s_addr == INADDR_NONE) { |
962 gg_debug(GG_DEBUG_MISC, "-- resolving failed\n"); | 1030 gg_debug(GG_DEBUG_MISC, "-- resolving failed\n"); |
963 | 1031 |
1032 errno = ENOENT; | |
964 e->type = GG_EVENT_CONN_FAILED; | 1033 e->type = GG_EVENT_CONN_FAILED; |
965 e->event.failure = GG_FAILURE_RESOLVING; | 1034 e->event.failure = GG_FAILURE_RESOLVING; |
966 sess->state = GG_STATE_IDLE; | 1035 sess->state = GG_STATE_IDLE; |
967 | 1036 |
968 close(sess->fd); | 1037 close(sess->fd); |
969 | 1038 |
970 break; | 1039 break; |
971 } | 1040 } |
972 | 1041 |
1042 sess->server_ip = a.s_addr; | |
1043 | |
973 close(sess->fd); | 1044 close(sess->fd); |
974 | 1045 |
975 waitpid(sess->pid, NULL, 0); | 1046 waitpid(sess->pid, NULL, 0); |
976 | 1047 |
977 gg_debug(GG_DEBUG_MISC, "-- resolved, now connecting\n"); | 1048 gg_debug(GG_DEBUG_MISC, "-- resolved, now connecting\n"); |
978 | 1049 |
979 if ((sess->fd = gg_connect(&a, GG_APPMSG_PORT, sess->async)) == -1) { | 1050 if ((sess->fd = gg_connect(&a, GG_APPMSG_PORT, sess->async)) == -1) { |
980 gg_debug(GG_DEBUG_MISC, "-- connection failed\n"); | 1051 struct in_addr *addr = (struct in_addr *)&sess->server_ip; |
981 | 1052 |
982 e->type = GG_EVENT_CONN_FAILED; | 1053 gg_debug(GG_DEBUG_MISC, |
983 e->event.failure = GG_FAILURE_CONNECTING; | 1054 "-- connection failed, trying direct connection\n"); |
984 sess->state = GG_STATE_IDLE; | 1055 |
985 break; | 1056 if ((sess->fd = gg_connect(addr, GG_DEFAULT_PORT, sess->async)) == -1) { |
986 } | 1057 gg_debug(GG_DEBUG_MISC, |
987 | 1058 "-- connection failed, trying https connection\n"); |
988 sess->state = GG_STATE_CONNECTING_HTTP; | 1059 if ((sess->fd = |
989 sess->check = GG_CHECK_WRITE; | 1060 gg_connect(&a, GG_HTTPS_PORT, sess->async)) == -1) { |
1061 gg_debug(GG_DEBUG_MISC, | |
1062 "-- connect() failed. errno = %d (%s)\n", errno, | |
1063 strerror(errno)); | |
1064 | |
1065 e->type = GG_EVENT_CONN_FAILED; | |
1066 e->event.failure = GG_FAILURE_CONNECTING; | |
1067 sess->state = GG_STATE_IDLE; | |
1068 break; | |
1069 } | |
1070 } | |
1071 sess->state = GG_STATE_CONNECTING_GG; | |
1072 sess->check = GG_CHECK_WRITE; | |
1073 } else { | |
1074 sess->state = GG_STATE_CONNECTING_HTTP; | |
1075 sess->check = GG_CHECK_WRITE; | |
1076 } | |
990 | 1077 |
991 break; | 1078 break; |
992 } | 1079 } |
993 | 1080 |
994 case GG_STATE_CONNECTING_HTTP: | 1081 case GG_STATE_CONNECTING_HTTP: |
995 { | 1082 { |
996 char buf[1024]; | 1083 char buf[1024]; |
997 int res, res_size = sizeof(res); | 1084 int res, res_size = sizeof(res); |
998 | 1085 |
999 gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTING_HTTP\n"); | 1086 gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTING_HTTP\n"); |
1000 | 1087 |
1001 if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { | 1088 if (sess->async |
1002 gg_debug(GG_DEBUG_MISC, "-- http connection failed, errno = %d (%s)\n", res, strerror(res)); | 1089 && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { |
1003 | 1090 struct in_addr *addr = (struct in_addr *)&sess->server_ip; |
1004 errno = res; | 1091 gg_debug(GG_DEBUG_MISC, |
1005 e->type = GG_EVENT_CONN_FAILED; | 1092 "-- http connection failed, errno = %d (%s), trying direct connection\n", |
1006 e->event.failure = GG_FAILURE_CONNECTING; | 1093 res, strerror(res)); |
1007 sess->state = GG_STATE_IDLE; | 1094 |
1095 if ((sess->fd = gg_connect(addr, GG_DEFAULT_PORT, sess->async)) == -1) { | |
1096 gg_debug(GG_DEBUG_MISC, | |
1097 "-- connection failed, trying https connection\n"); | |
1098 if ((sess->fd = | |
1099 gg_connect(addr, GG_HTTPS_PORT, sess->async)) == -1) { | |
1100 gg_debug(GG_DEBUG_MISC, | |
1101 "-- connect() failed. errno = %d (%s)\n", errno, | |
1102 strerror(errno)); | |
1103 | |
1104 e->type = GG_EVENT_CONN_FAILED; | |
1105 e->event.failure = GG_FAILURE_CONNECTING; | |
1106 sess->state = GG_STATE_IDLE; | |
1107 break; | |
1108 } | |
1109 } | |
1110 | |
1111 sess->state = GG_STATE_CONNECTING_GG; | |
1112 sess->check = GG_CHECK_WRITE; | |
1008 break; | 1113 break; |
1009 } | 1114 } |
1010 | 1115 |
1011 gg_debug(GG_DEBUG_MISC, "-- http connection succeded, sending query\n"); | 1116 gg_debug(GG_DEBUG_MISC, "-- http connection succeded, sending query\n"); |
1012 | 1117 |
1013 | |
1014 snprintf(buf, sizeof(buf) - 1, | 1118 snprintf(buf, sizeof(buf) - 1, |
1015 "GET /appsvc/appmsg.asp?fmnumber=%u HTTP/1.0\r\n" | 1119 "GET /appsvc/appmsg.asp?fmnumber=%lu HTTP/1.0\r\n" |
1016 "Host: " GG_APPMSG_HOST "\r\n" | 1120 "Host: " GG_APPMSG_HOST "\r\n" |
1017 "User-Agent: Mozilla/4.7 [en] (Win98; I)\r\n" | 1121 "User-Agent: " GG_HTTP_USERAGENT "\r\n" |
1018 "Pragma: no-cache\r\n" | 1122 "Pragma: no-cache\r\n" "\r\n", sess->uin); |
1019 "\r\n", sess->uin); | |
1020 | 1123 |
1021 if (write(sess->fd, buf, strlen(buf)) < strlen(buf)) { | 1124 if (write(sess->fd, buf, strlen(buf)) < strlen(buf)) { |
1022 gg_debug(GG_DEBUG_MISC, "-- sending query failed\n"); | 1125 gg_debug(GG_DEBUG_MISC, "-- sending query failed\n"); |
1023 | 1126 |
1127 errno = EIO; | |
1024 e->type = GG_EVENT_CONN_FAILED; | 1128 e->type = GG_EVENT_CONN_FAILED; |
1025 e->event.failure = GG_FAILURE_WRITING; | 1129 e->event.failure = GG_FAILURE_WRITING; |
1026 sess->state = GG_STATE_IDLE; | 1130 sess->state = GG_STATE_IDLE; |
1027 break; | 1131 break; |
1028 } | 1132 } |
1031 sess->check = GG_CHECK_READ; | 1135 sess->check = GG_CHECK_READ; |
1032 | 1136 |
1033 break; | 1137 break; |
1034 } | 1138 } |
1035 | 1139 |
1036 case GG_STATE_WRITING_HTTP: | 1140 case GG_STATE_WRITING_HTTP: |
1037 { | 1141 { |
1038 char buf[1024], *tmp, *host; | 1142 char buf[1024], *tmp, *host; |
1039 int port = GG_DEFAULT_PORT; | 1143 int port = GG_DEFAULT_PORT; |
1040 struct in_addr a; | 1144 struct in_addr a; |
1041 | 1145 |
1042 gg_debug(GG_DEBUG_MISC, "== GG_STATE_WRITING_HTTP\n"); | 1146 gg_debug(GG_DEBUG_MISC, "== GG_STATE_WRITING_HTTP\n"); |
1043 | 1147 |
1044 gg_read_line(sess->fd, buf, sizeof(buf) - 1); | 1148 gg_read_line(sess->fd, buf, sizeof(buf) - 1); |
1045 gg_chomp(buf); | 1149 gg_chomp(buf); |
1046 | 1150 |
1047 gg_debug(GG_DEBUG_TRAFFIC, "-- got http response (%s)\n", buf); | 1151 gg_debug(GG_DEBUG_TRAFFIC, "-- got http response (%s)\n", buf); |
1048 | 1152 |
1049 if (strncmp(buf, "HTTP/1.", 7) || strncmp(buf + 9, "200", 3)) { | 1153 if (strncmp(buf, "HTTP/1.", 7) || strncmp(buf + 9, "200", 3)) { |
1050 gg_debug(GG_DEBUG_MISC, "-- but that's not what we've expected\n"); | 1154 gg_debug(GG_DEBUG_MISC, "-- but that's not what we've expected\n"); |
1051 | 1155 |
1156 errno = EINVAL; | |
1052 e->type = GG_EVENT_CONN_FAILED; | 1157 e->type = GG_EVENT_CONN_FAILED; |
1053 e->event.failure = GG_FAILURE_INVALID; | 1158 e->event.failure = GG_FAILURE_INVALID; |
1054 sess->state = GG_STATE_IDLE; | 1159 sess->state = GG_STATE_IDLE; |
1055 break; | 1160 break; |
1056 } | 1161 } |
1057 | 1162 |
1058 while (strcmp(buf, "\r\n") && strcmp(buf, "")) | 1163 while (strcmp(buf, "\r\n") && strcmp(buf, "")) |
1059 gg_read_line(sess->fd, buf, sizeof(buf) - 1); | 1164 gg_read_line(sess->fd, buf, sizeof(buf) - 1); |
1060 | 1165 |
1061 gg_read_line(sess->fd, buf, sizeof(buf) - 1); | 1166 gg_read_line(sess->fd, buf, sizeof(buf) - 1); |
1062 gg_chomp(buf); | 1167 gg_chomp(buf); |
1063 | 1168 |
1064 close(sess->fd); | 1169 close(sess->fd); |
1065 | 1170 |
1066 gg_debug(GG_DEBUG_TRAFFIC, "-- received http data (%s)\n", buf); | 1171 gg_debug(GG_DEBUG_TRAFFIC, "-- received http data (%s)\n", buf); |
1067 | 1172 |
1068 tmp = buf; | 1173 tmp = buf; |
1069 while (*tmp && *tmp != ' ') | 1174 while (*tmp && *tmp != ' ') |
1070 tmp++; | 1175 tmp++; |
1083 tmp++; | 1188 tmp++; |
1084 *tmp = 0; | 1189 *tmp = 0; |
1085 | 1190 |
1086 if ((tmp = strchr(host, ':'))) { | 1191 if ((tmp = strchr(host, ':'))) { |
1087 *tmp = 0; | 1192 *tmp = 0; |
1088 port = atoi(tmp+1); | 1193 port = atoi(tmp + 1); |
1089 } | 1194 } |
1090 | 1195 |
1091 a.s_addr = inet_addr(host); | 1196 a.s_addr = inet_addr(host); |
1197 sess->server_ip = a.s_addr; | |
1092 | 1198 |
1093 if ((sess->fd = gg_connect(&a, port, sess->async)) == -1) { | 1199 if ((sess->fd = gg_connect(&a, port, sess->async)) == -1) { |
1094 gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d (%s)\n", errno, strerror(errno)); | 1200 gg_debug(GG_DEBUG_MISC, |
1095 | 1201 "-- connection failed, trying https connection\n"); |
1096 e->type = GG_EVENT_CONN_FAILED; | 1202 if ((sess->fd = gg_connect(&a, GG_HTTPS_PORT, sess->async)) == -1) { |
1097 e->event.failure = GG_FAILURE_CONNECTING; | 1203 gg_debug(GG_DEBUG_MISC, |
1098 sess->state = GG_STATE_IDLE; | 1204 "-- connection failed, errno = %d (%s)\n", errno, |
1099 break; | 1205 strerror(errno)); |
1206 | |
1207 e->type = GG_EVENT_CONN_FAILED; | |
1208 e->event.failure = GG_FAILURE_CONNECTING; | |
1209 sess->state = GG_STATE_IDLE; | |
1210 break; | |
1211 } | |
1100 } | 1212 } |
1101 | 1213 |
1102 sess->state = GG_STATE_CONNECTING_GG; | 1214 sess->state = GG_STATE_CONNECTING_GG; |
1103 sess->check = GG_CHECK_WRITE; | 1215 sess->check = GG_CHECK_WRITE; |
1104 | 1216 |
1105 break; | 1217 break; |
1106 } | 1218 } |
1107 | 1219 |
1108 case GG_STATE_CONNECTING_GG: | 1220 case GG_STATE_CONNECTING_GG: |
1109 { | 1221 { |
1110 int res, res_size = sizeof(res); | 1222 int res, res_size = sizeof(res); |
1111 | 1223 |
1112 gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTING_GG\n"); | 1224 gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTING_GG\n"); |
1113 | 1225 |
1114 if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { | 1226 if (sess->async |
1115 gg_debug(GG_DEBUG_MISC, "-- connection failed, errno = %d (%s)\n", errno, strerror(errno)); | 1227 && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { |
1116 | 1228 struct in_addr *addr = (struct in_addr *)&sess->server_ip; |
1117 errno = res; | 1229 |
1118 e->type = GG_EVENT_CONN_FAILED; | 1230 gg_debug(GG_DEBUG_MISC, |
1119 e->event.failure = GG_FAILURE_CONNECTING; | 1231 "-- connection failed, trying https connection\n"); |
1120 sess->state = GG_STATE_IDLE; | 1232 if ((sess->fd = gg_connect(addr, GG_HTTPS_PORT, sess->async)) == -1) { |
1121 break; | 1233 gg_debug(GG_DEBUG_MISC, |
1234 "-- connection failed, errno = %d (%s)\n", errno, | |
1235 strerror(errno)); | |
1236 | |
1237 e->type = GG_EVENT_CONN_FAILED; | |
1238 e->event.failure = GG_FAILURE_CONNECTING; | |
1239 sess->state = GG_STATE_IDLE; | |
1240 break; | |
1241 } | |
1122 } | 1242 } |
1123 | 1243 |
1124 gg_debug(GG_DEBUG_MISC, "-- connected\n"); | 1244 gg_debug(GG_DEBUG_MISC, "-- connected\n"); |
1125 | 1245 |
1126 sess->state = GG_STATE_WAITING_FOR_KEY; | 1246 sess->state = GG_STATE_WAITING_FOR_KEY; |
1127 sess->check = GG_CHECK_READ; | 1247 sess->check = GG_CHECK_READ; |
1128 | 1248 |
1129 break; | 1249 break; |
1130 } | 1250 } |
1131 | 1251 |
1132 case GG_STATE_WAITING_FOR_KEY: | 1252 case GG_STATE_WAITING_FOR_KEY: |
1133 { | 1253 { |
1134 struct gg_header *h; | 1254 struct gg_header *h; |
1135 struct gg_welcome *w; | 1255 struct gg_welcome *w; |
1136 struct gg_login l; | 1256 struct gg_login l; |
1137 unsigned int hash; | 1257 unsigned int hash; |
1138 char *password = sess->password; | 1258 char *password = sess->password; |
1139 | 1259 |
1140 gg_debug(GG_DEBUG_MISC, "== GG_STATE_WAITING_FOR_KEY\n"); | 1260 gg_debug(GG_DEBUG_MISC, "== GG_STATE_WAITING_FOR_KEY\n"); |
1141 | 1261 |
1142 if (!(h = gg_recv_packet(sess))) { | 1262 if (!(h = gg_recv_packet(sess))) { |
1143 gg_debug(GG_DEBUG_MISC, "-- gg_recv_packet() failed. errno = %d (%s)\n", errno, strerror(errno)); | 1263 gg_debug(GG_DEBUG_MISC, "-- gg_recv_packet() failed. errno = %d (%s)\n", |
1264 errno, strerror(errno)); | |
1144 | 1265 |
1145 e->type = GG_EVENT_CONN_FAILED; | 1266 e->type = GG_EVENT_CONN_FAILED; |
1146 e->event.failure = GG_FAILURE_READING; | 1267 e->event.failure = GG_FAILURE_READING; |
1147 sess->state = GG_STATE_IDLE; | 1268 sess->state = GG_STATE_IDLE; |
1148 close(sess->fd); | 1269 close(sess->fd); |
1149 break; | 1270 break; |
1150 } | 1271 } |
1151 | 1272 |
1152 if (h->type != GG_WELCOME) { | 1273 if (h->type != GG_WELCOME) { |
1153 gg_debug(GG_DEBUG_MISC, "-- invalid packet received\n"); | 1274 gg_debug(GG_DEBUG_MISC, "-- invalid packet received\n"); |
1154 | 1275 |
1155 free(h); | 1276 free(h); |
1156 close(sess->fd); | 1277 close(sess->fd); |
1278 errno = EINVAL; | |
1157 e->type = GG_EVENT_CONN_FAILED; | 1279 e->type = GG_EVENT_CONN_FAILED; |
1158 e->event.failure = GG_FAILURE_INVALID; | 1280 e->event.failure = GG_FAILURE_INVALID; |
1159 sess->state = GG_STATE_IDLE; | 1281 sess->state = GG_STATE_IDLE; |
1160 break; | 1282 break; |
1161 } | 1283 } |
1162 | 1284 |
1163 w = (void*) h + sizeof(struct gg_header); | 1285 w = (void *)h + sizeof(struct gg_header); |
1164 w->key = fix32(w->key); | 1286 w->key = fix32(w->key); |
1165 | 1287 |
1166 for (hash = 1; *password; password++) | 1288 for (hash = 1; *password; password++) |
1167 hash *= (*password) + 1; | 1289 hash *= (*password) + 1; |
1168 hash *= w->key; | 1290 hash *= w->key; |
1169 | 1291 |
1170 gg_debug(GG_DEBUG_DUMP, "%%%% klucz serwera %.4x, hash hasła %.8x\n", w->key, hash); | 1292 gg_debug(GG_DEBUG_DUMP, "%%%% klucz serwera %.4x, hash hasła %.8x\n", w->key, |
1171 | 1293 hash); |
1294 | |
1172 free(h); | 1295 free(h); |
1173 | 1296 |
1174 free(sess->password); | 1297 free(sess->password); |
1175 sess->password = NULL; | 1298 sess->password = NULL; |
1176 | 1299 |
1177 l.uin = fix32(sess->uin); | 1300 l.uin = fix32(sess->uin); |
1178 l.hash = fix32(hash); | 1301 l.hash = fix32(hash); |
1179 l.status = fix32(GG_STATUS_AVAIL); | 1302 l.status = fix32(sess->initial_status ? sess->initial_status : GG_STATUS_AVAIL); |
1180 l.dunno = fix32(0x0b); | 1303 l.dunno = fix32(0x0b); |
1181 l.local_ip = 0; | 1304 l.local_ip = 0; |
1182 l.local_port = 0; | 1305 l.local_port = 0; |
1183 | 1306 |
1184 gg_debug(GG_DEBUG_TRAFFIC, "-- sending GG_LOGIN packet\n"); | 1307 gg_debug(GG_DEBUG_TRAFFIC, "-- sending GG_LOGIN packet\n"); |
1185 | 1308 |
1186 if (gg_send_packet(sess->fd, GG_LOGIN, &l, sizeof(l), NULL, 0) == -1) { | 1309 if (gg_send_packet(sess->fd, GG_LOGIN, &l, sizeof(l), NULL, 0) == -1) { |
1187 gg_debug(GG_DEBUG_TRAFFIC, "-- oops, failed. errno = %d (%s)\n", errno, strerror(errno)); | 1310 gg_debug(GG_DEBUG_TRAFFIC, "-- oops, failed. errno = %d (%s)\n", errno, |
1311 strerror(errno)); | |
1188 | 1312 |
1189 close(sess->fd); | 1313 close(sess->fd); |
1190 e->type = GG_EVENT_CONN_FAILED; | 1314 e->type = GG_EVENT_CONN_FAILED; |
1191 e->event.failure = GG_FAILURE_WRITING; | 1315 e->event.failure = GG_FAILURE_WRITING; |
1192 sess->state = GG_STATE_IDLE; | 1316 sess->state = GG_STATE_IDLE; |
1193 break; | 1317 break; |
1194 } | 1318 } |
1195 | 1319 |
1196 sess->state = GG_STATE_SENDING_KEY; | 1320 sess->state = GG_STATE_SENDING_KEY; |
1197 | 1321 |
1198 break; | 1322 break; |
1199 } | 1323 } |
1200 | 1324 |
1201 case GG_STATE_SENDING_KEY: | 1325 case GG_STATE_SENDING_KEY: |
1202 { | 1326 { |
1203 struct gg_header *h; | 1327 struct gg_header *h; |
1204 | 1328 |
1205 gg_debug(GG_DEBUG_MISC, "== GG_STATE_SENDING_KEY\n"); | 1329 gg_debug(GG_DEBUG_MISC, "== GG_STATE_SENDING_KEY\n"); |
1206 | 1330 |
1210 e->event.failure = GG_FAILURE_READING; | 1334 e->event.failure = GG_FAILURE_READING; |
1211 sess->state = GG_STATE_IDLE; | 1335 sess->state = GG_STATE_IDLE; |
1212 close(sess->fd); | 1336 close(sess->fd); |
1213 break; | 1337 break; |
1214 } | 1338 } |
1215 | 1339 |
1216 if (h->type == GG_LOGIN_OK) { | 1340 if (h->type == GG_LOGIN_OK) { |
1217 gg_debug(GG_DEBUG_MISC, "-- login succeded\n"); | 1341 gg_debug(GG_DEBUG_MISC, "-- login succeded\n"); |
1218 e->type = GG_EVENT_CONN_SUCCESS; | 1342 e->type = GG_EVENT_CONN_SUCCESS; |
1219 sess->state = GG_STATE_CONNECTED; | 1343 sess->state = GG_STATE_CONNECTED; |
1344 free(h); | |
1220 break; | 1345 break; |
1221 } | 1346 } |
1222 | 1347 |
1223 if (h->type == GG_LOGIN_FAILED) { | 1348 if (h->type == GG_LOGIN_FAILED) { |
1224 gg_debug(GG_DEBUG_MISC, "-- login failed\n"); | 1349 gg_debug(GG_DEBUG_MISC, "-- login failed\n"); |
1225 e->event.failure = GG_FAILURE_PASSWORD; | 1350 e->event.failure = GG_FAILURE_PASSWORD; |
1226 errno = EACCES; | 1351 errno = EACCES; |
1227 } else { | 1352 } else { |
1228 gg_debug(GG_DEBUG_MISC, "-- invalid packet\n"); | 1353 gg_debug(GG_DEBUG_MISC, "-- invalid packet\n"); |
1229 e->event.failure = GG_FAILURE_INVALID; | 1354 e->event.failure = GG_FAILURE_INVALID; |
1355 errno = EINVAL; | |
1230 } | 1356 } |
1231 | 1357 |
1232 e->type = GG_EVENT_CONN_FAILED; | 1358 e->type = GG_EVENT_CONN_FAILED; |
1233 sess->state = GG_STATE_IDLE; | 1359 sess->state = GG_STATE_IDLE; |
1234 close(sess->fd); | 1360 close(sess->fd); |
1361 free(h); | |
1235 | 1362 |
1236 break; | 1363 break; |
1237 } | 1364 } |
1238 | 1365 |
1239 case GG_STATE_CONNECTED: | 1366 case GG_STATE_CONNECTED: |
1240 { | 1367 { |
1241 gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTED\n"); | 1368 gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTED\n"); |
1242 | 1369 |
1243 if ((res = gg_watch_fd_connected(sess, e)) == -1) { | 1370 if ((res = gg_watch_fd_connected(sess, e)) == -1) { |
1244 | 1371 |
1245 gg_debug(GG_DEBUG_MISC, "-- watch_fd_connected failed. errno = %d (%s)\n", errno, strerror(errno)); | 1372 gg_debug(GG_DEBUG_MISC, |
1246 | 1373 "-- watch_fd_connected failed. errno = %d (%s)\n", errno, |
1247 if (errno == EAGAIN) { | 1374 strerror(errno)); |
1375 | |
1376 if (errno == EAGAIN) { | |
1248 e->type = GG_EVENT_NONE; | 1377 e->type = GG_EVENT_NONE; |
1249 res = 0; | 1378 res = 0; |
1250 } else | 1379 } else |
1251 res = -1; | 1380 res = -1; |
1252 } | 1381 } |
1259 e = NULL; | 1388 e = NULL; |
1260 } | 1389 } |
1261 | 1390 |
1262 return e; | 1391 return e; |
1263 } | 1392 } |
1264 | |
1265 |