Mercurial > pidgin
diff src/protocols/gg/libgg.c @ 2846:4b3f17ca66bf
[gaim-migrate @ 2859]
so here it comes - some bugs fixed, new ones introduced:
- password changing (was in part 1)
- update to latest libgg (fixes password change on alpha)
- auto away on idle (remembers GG_STATE_FRIENDS_MASK)
- handle_errcode() can now use hide_login_progress()
- remove encode_postdata() and use gg_urlencode() from libgg
+ encode only fields (not whole url)
- fixed status related ugly bug in GG_EVENT_NOTIFY (!!!)
- remove linefeed from messages
Thanks, Arkadiusz Miskiewicz
committer: Tailor Script <tailor@pidgin.im>
| author | Eric Warmenhoven <eric@warmenhoven.org> |
|---|---|
| date | Wed, 05 Dec 2001 09:48:56 +0000 |
| parents | 9123abd0db92 |
| children | 9682c0e022c6 |
line wrap: on
line diff
--- a/src/protocols/gg/libgg.c Tue Dec 04 19:51:27 2001 +0000 +++ b/src/protocols/gg/libgg.c Wed Dec 05 09:48:56 2001 +0000 @@ -1,8 +1,8 @@ -/* $Id: libgg.c 2805 2001-11-26 21:22:56Z warmenhoven $ */ +/* $Id: libgg.c 2859 2001-12-05 09:48:56Z warmenhoven $ */ /* * (C) Copyright 2001 Wojtek Kaniewski <wojtekka@irc.pl>, - * Robert J. Woźny <speedy@atman.pl> + * Robert J. Woźny <speedy@ziew.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as @@ -37,7 +37,7 @@ #include <pwd.h> #include <time.h> #ifdef sun -#include <sys/filio.h> + #include <sys/filio.h> #endif #include <glib.h> #if G_BYTE_ORDER == G_BIG_ENDIAN @@ -47,37 +47,19 @@ #include "config.h" int gg_debug_level = 0; +int gg_http_use_proxy = 0; +int gg_http_proxy_port = 0; +char *gg_http_proxy_host = NULL; -#ifndef lint +#ifndef lint static char rcsid[] #ifdef __GNUC__ - __attribute__ ((unused)) +__attribute__ ((unused)) #endif - = "$Id: libgg.c 2805 2001-11-26 21:22:56Z warmenhoven $"; - -#endif += "$Id: libgg.c 2859 2001-12-05 09:48:56Z warmenhoven $"; -/* - * gg_debug() - * - * wyrzuca komunikat o danym poziomie, o ile użytkownik sobie tego życzy. - * - * - level - poziom wiadomości, - * - format... - treść wiadomości (printf-alike.) - * - * niczego nie zwraca. - */ -void gg_debug(int level, char *format, ...) -{ - va_list ap; - - if ((gg_debug_level & level)) { - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - } -} +#endif /* * fix32() // funkcja wewnętrzna @@ -90,10 +72,11 @@ return x; #else return (unsigned long) - (((x & (unsigned long)0x000000ffU) << 24) | - ((x & (unsigned long)0x0000ff00U) << 8) | - ((x & (unsigned long)0x00ff0000U) >> 8) | ((x & (unsigned long)0xff000000U) >> 24)); -#endif + (((x & (unsigned long) 0x000000ffU) << 24) | + ((x & (unsigned long) 0x0000ff00U) << 8) | + ((x & (unsigned long) 0x00ff0000U) >> 8) | + ((x & (unsigned long) 0xff000000U) >> 24)); +#endif } /* @@ -107,88 +90,12 @@ return x; #else return (unsigned short) - (((x & (unsigned short)0x00ffU) << 8) | ((x & (unsigned short)0xff00U) >> 8)); + (((x & (unsigned short) 0x00ffU) << 8) | + ((x & (unsigned short) 0xff00U) >> 8)); #endif } /* - * gg_alloc_sprintf() // funkcja wewnętrzna - * - * robi dokładnie to samo, co sprintf(), tyle że alokuje sobie wcześniej - * miejsce na dane. powinno działać na tych maszynach, które mają funkcję - * vsnprintf() zgodną z C99, jak i na wcześniejszych. - * - * - format, ... - parametry takie same jak w innych funkcjach *printf() - * - * zwraca zaalokowany buforek, który wypadałoby później zwolnić, lub NULL - * jeśli nie udało się wykonać zadania. - */ -char *gg_alloc_sprintf(char *format, ...) -{ - va_list ap; - char *buf = NULL, *tmp; - int size = 0, res; - - va_start(ap, format); - - if ((size = vsnprintf(buf, 0, format, ap)) < 1) { - size = 128; - do { - size *= 2; - if (!(tmp = realloc(buf, size))) { - free(buf); - return NULL; - } - buf = tmp; - res = vsnprintf(buf, size, format, ap); - } while (res == size - 1); - } else { - if (!(buf = malloc(size + 1))) - return NULL; - } - - vsnprintf(buf, size + 1, format, ap); - - va_end(ap); - - return buf; -} - -/* - * gg_get_line() // funkcja wewnętrzna - * - * podaje kolejną linię z bufora tekstowego. psuje co bezpowrotnie, dzieląc - * na kolejne stringi. zdarza się, nie ma potrzeby pisania funkcji dublującej - * bufor żeby tylko mieć nieruszone dane wejściowe, skoro i tak nie będą nam - * poźniej potrzebne. obcina `\r\n'. - * - * - ptr - wskaźnik do zmiennej, która przechowuje aktualną pozycję - * w przemiatanym buforze. - * - * wskaźnik do kolejnej linii tekstu lub NULL, jeśli to już koniec bufora. - */ -char *gg_get_line(char **ptr) -{ - char *foo, *res; - - if (!ptr || !*ptr || !strcmp(*ptr, "")) - return NULL; - - res = *ptr; - - if (!(foo = strchr(*ptr, '\n'))) - *ptr += strlen(*ptr); - else { - *ptr = foo + 1; - *foo = 0; - if (res[strlen(res) - 1] == '\r') - res[strlen(res) - 1] = 0; - } - - return res; -} - -/* * gg_resolve() // funkcja wewnętrzna * * tworzy pipe'y, forkuje się i w drugim procesie zaczyna resolvować @@ -208,7 +115,7 @@ struct in_addr a; gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve(..., \"%s\");\n", hostname); - + if (!fd | !pid) { errno = EFAULT; return -1; @@ -223,11 +130,11 @@ if (!res) { if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { struct hostent *he; - + if (!(he = gethostbyname(hostname))) a.s_addr = INADDR_NONE; else - memcpy((char *)&a, he->h_addr, sizeof(a)); + memcpy((char*) &a, he->h_addr, sizeof(a)); } write(pipes[1], &a, sizeof(a)); @@ -244,91 +151,6 @@ } /* - * gg_connect() // funkcja wewnętrzna - * - * łączy się z serwerem. pierwszy argument jest typu (void *), żeby nie - * musieć niczego inkludować w libgg.h i nie psuć jakiś głupich zależności - * na dziwnych systemach. - * - * - addr - adres serwera (struct in_addr *), - * - port - port serwera, - * - async - ma być asynchroniczne połączenie? - * - * zwraca połączonego socketa lub -1 w przypadku błędu. zobacz errno. - */ -int gg_connect(void *addr, int port, int async) -{ - int sock, one = 1; - struct sockaddr_in sin; - struct in_addr *a = addr; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async); - - if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { - gg_debug(GG_DEBUG_MISC, "-- socket() failed. errno = %d (%s)\n", errno, strerror(errno)); - return -1; - } - - if (async) { - if (ioctl(sock, FIONBIO, &one) == -1) { - gg_debug(GG_DEBUG_MISC, "-- ioctl() failed. errno = %d (%s)\n", errno, - strerror(errno)); - return -1; - } - } - - sin.sin_port = htons(port); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = a->s_addr; - - if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) { - if (errno && (!async || errno != EINPROGRESS)) { - gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d (%s)\n", errno, - strerror(errno)); - return -1; - } - gg_debug(GG_DEBUG_MISC, "-- connect() in progress\n"); - } - - return sock; -} - -/* - * gg_read_line() // funkcja wewnętrzna - * - * czyta jedną linię tekstu z socketa. - * - * - sock - socket, - * - buf - wskaźnik bufora, - * - length - długość bufora. - * - * olewa błędy. jeśli na jakiś trafi, potraktuje go jako koniec linii. - */ -static void gg_read_line(int sock, char *buf, int length) -{ - int ret; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_read_line(...);\n"); - - for (; length > 1; buf++, length--) { - do { - if ((ret = read(sock, buf, 1)) == -1 && errno != EINTR) { - *buf = 0; - return; - } - } while (ret == -1 && errno == EINTR); - - if (*buf == '\n') { - buf++; - break; - } - } - - *buf = 0; - return; -} - -/* * gg_recv_packet() // funkcja wewnętrzna * * odbiera jeden pakiet gg i zwraca wskaźnik do niego. pamięć po nim @@ -345,7 +167,7 @@ int ret = 0, offset, size = 0; gg_debug(GG_DEBUG_FUNCTION, "** gg_recv_packet(...);\n"); - + if (!sess) { errno = EFAULT; return NULL; @@ -357,8 +179,7 @@ gg_debug(GG_DEBUG_MISC, "-- header recv(..., %d) = %d\n", sizeof(h), ret); if (ret < sizeof(h)) { if (errno != EINTR) { - gg_debug(GG_DEBUG_MISC, "-- errno = %d (%s)\n", errno, - strerror(errno)); + gg_debug(GG_DEBUG_MISC, "-- errno = %d (%s)\n", errno, strerror(errno)); return NULL; } } @@ -400,7 +221,7 @@ if (ret > -1 && ret <= size) { offset += ret; size -= ret; - } else if (ret == -1) { + } else if (ret == -1) { gg_debug(GG_DEBUG_MISC, "-- errno = %d (%s)\n", errno, strerror(errno)); if (errno == EAGAIN) { gg_debug(GG_DEBUG_MISC, "-- %d bytes received, %d left\n", offset, size); @@ -410,7 +231,7 @@ return NULL; } if (errno != EINTR) { -// errno = EINVAL; +// errno = EINVAL; free(buf); return NULL; } @@ -423,8 +244,8 @@ int i; gg_debug(GG_DEBUG_DUMP, ">> received packet (type=%.2x):", h.type); - for (i = 0; i < sizeof(h) + h.length; i++) - gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char)buf[i]); + for (i = 0; i < sizeof(h) + h.length; i++) + gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) buf[i]); gg_debug(GG_DEBUG_DUMP, "\n"); } @@ -447,16 +268,14 @@ * zabrakło pamięci. inaczej był błąd przy wysyłaniu pakietu. dla errno=0 * nie wysłano całego pakietu. */ -static int gg_send_packet(int sock, int type, void *packet, int length, void *payload, - int payload_length) +static int gg_send_packet(int sock, int type, void *packet, int length, void *payload, int payload_length) { struct gg_header *h; int res, plen; char *tmp; - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_packet(0x%.2x, %d, %d);\n", type, length, - payload_length); - + gg_debug(GG_DEBUG_FUNCTION, "** gg_send_packet(0x%.2x, %d, %d);\n", type, length, payload_length); + if (length < 0 || payload_length < 0) { gg_debug(GG_DEBUG_MISC, "-- invalid packet/payload length\n"); errno = ERANGE; @@ -468,7 +287,7 @@ return -1; } - h = (struct gg_header *)tmp; + h = (struct gg_header*) tmp; h->type = fix32(type); h->length = fix32(length + payload_length); @@ -482,20 +301,19 @@ gg_debug(GG_DEBUG_DUMP, "%%%% sending packet (type=%.2x):", fix32(h->type)); for (i = 0; i < sizeof(struct gg_header) + fix32(h->length); i++) - gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char)tmp[i]); + gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) tmp[i]); gg_debug(GG_DEBUG_DUMP, "\n"); } plen = sizeof(struct gg_header) + length + payload_length; - + if ((res = write(sock, tmp, plen)) < plen) { - gg_debug(GG_DEBUG_MISC, "-- write() failed. res = %d, errno = %d (%s)\n", res, errno, - strerror(errno)); + gg_debug(GG_DEBUG_MISC, "-- write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno)); free(tmp); return -1; } - free(tmp); + free(tmp); return 0; } @@ -519,6 +337,8 @@ struct gg_session *gg_login(uin_t uin, char *password, int async) { struct gg_session *sess; + char *hostname; + int port; gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%u, \"...\", %d);\n", uin, async); @@ -538,9 +358,18 @@ sess->last_pong = 0; sess->server_ip = 0; sess->initial_status = 0; + sess->type = GG_SESSION_GG; + + if (gg_http_use_proxy) { + hostname = gg_http_proxy_host; + port = gg_http_proxy_port; + } else { + hostname = GG_APPMSG_HOST; + port = GG_APPMSG_PORT; + }; if (async) { - if (gg_resolve(&sess->fd, &sess->pid, GG_APPMSG_HOST)) { + if (gg_resolve(&sess->fd, &sess->pid, hostname)) { gg_debug(GG_DEBUG_MISC, "-- resolving failed\n"); free(sess); return NULL; @@ -548,24 +377,24 @@ } else { struct in_addr a; - if ((a.s_addr = inet_addr(GG_APPMSG_HOST)) == INADDR_NONE) { + if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { struct hostent *he; - - if (!(he = gethostbyname(GG_APPMSG_HOST))) { - gg_debug(GG_DEBUG_MISC, "-- host %s not found\n", GG_APPMSG_HOST); + + if (!(he = gethostbyname(hostname))) { + gg_debug(GG_DEBUG_MISC, "-- host %s not found\n", hostname); free(sess); return NULL; } else - memcpy((char *)&a, he->h_addr, sizeof(a)); + memcpy((char*) &a, he->h_addr, sizeof(a)); } - if (!(sess->fd = gg_connect(&a, GG_APPMSG_PORT, 0)) == -1) { + if (!(sess->fd = gg_connect(&a, port, 0)) == -1) { gg_debug(GG_DEBUG_MISC, "-- connection failed\n"); free(sess); return NULL; } - sess->state = GG_STATE_CONNECTING_HTTP; + sess->state = GG_STATE_CONNECTING; while (sess->state != GG_STATE_CONNECTED) { struct gg_event *e; @@ -658,7 +487,7 @@ if (sess->state == GG_STATE_CONNECTED) gg_change_status(sess, GG_STATUS_NOT_AVAIL); - + if (sess->fd) { shutdown(sess->fd, 2); close(sess->fd); @@ -686,7 +515,7 @@ errno = EFAULT; return -1; } - + if (sess->state != GG_STATE_CONNECTED) { errno = ENOTCONN; return -1; @@ -700,7 +529,7 @@ s.seq = fix32(sess->seq); s.msgclass = fix32(msgclass); sess->seq += (rand() % 0x300) + 0x300; - + if (gg_send_packet(sess->fd, GG_SEND_MSG, &s, sizeof(s), message, strlen(message) + 1) == -1) return -1; @@ -764,7 +593,7 @@ * * jeśli udało się, zwraca 0. jeśli błąd, dostajemy -1. */ -int gg_notify(struct gg_session *sess, uin_t * userlist, int count) +int gg_notify(struct gg_session *sess, uin_t *userlist, int count) { struct gg_notify *n; uin_t *u; @@ -774,25 +603,25 @@ errno = EFAULT; return -1; } - + if (sess->state != GG_STATE_CONNECTED) { errno = ENOTCONN; return -1; } gg_debug(GG_DEBUG_FUNCTION, "** gg_notify(..., %d);\n", count); - + if (!userlist || !count) return 0; - - if (!(n = (struct gg_notify *)malloc(sizeof(*n) * count))) + + if (!(n = (struct gg_notify*) malloc(sizeof(*n) * count))) return -1; - - for (u = userlist, i = 0; i < count; u++, i++) { + + for (u = userlist, i = 0; i < count; u++, i++) { n[i].uin = fix32(*u); n[i].dunno1 = 3; } - + if (gg_send_packet(sess->fd, GG_NOTIFY, n, sizeof(*n) * count, NULL, 0) == -1) res = -1; @@ -824,12 +653,12 @@ errno = ENOTCONN; return -1; } - + gg_debug(GG_DEBUG_FUNCTION, "** gg_add_notify(..., %u);\n", uin); - + a.uin = fix32(uin); a.dunno1 = 3; - + return gg_send_packet(sess->fd, GG_ADD_NOTIFY, &a, sizeof(a), NULL, 0); } @@ -858,10 +687,10 @@ } gg_debug(GG_DEBUG_FUNCTION, "** gg_remove_notify(..., %u);\n", uin); - + a.uin = fix32(uin); a.dunno1 = 3; - + return gg_send_packet(sess->fd, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL, 0); } @@ -887,13 +716,12 @@ gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd_connected(...);\n"); if (!(h = gg_recv_packet(sess))) { - gg_debug(GG_DEBUG_MISC, "-- gg_recv_packet failed. errno = %d (%d)\n", errno, - strerror(errno)); + gg_debug(GG_DEBUG_MISC, "-- gg_recv_packet failed. errno = %d (%d)\n", errno, strerror(errno)); return -1; } - p = (void *)h + sizeof(struct gg_header); - + p = (void*) h + sizeof(struct gg_header); + if (h->type == GG_RECV_MSG) { struct gg_recv_msg *r = p; @@ -903,7 +731,7 @@ e->type = GG_EVENT_MSG; e->event.msg.msgclass = fix32(r->msgclass); e->event.msg.sender = fix32(r->sender); - e->event.msg.message = strdup((char *)r + sizeof(*r)); + e->event.msg.message = strdup((char*) r + sizeof(*r)); e->event.msg.time = fix32(r->time); } } @@ -913,9 +741,9 @@ int count, i; gg_debug(GG_DEBUG_MISC, "-- received a notify reply\n"); - + e->type = GG_EVENT_NOTIFY; - if (!(e->event.notify = (void *)malloc(h->length + 2 * sizeof(*n)))) { + if (!(e->event.notify = (void*) malloc(h->length + 2 * sizeof(*n)))) { gg_debug(GG_DEBUG_MISC, "-- not enough memory\n"); free(h); return -1; @@ -967,26 +795,6 @@ } /* - * gg_chomp() // funkcja wewnętrzna - * - * ucina "\r\n" lub "\n" z końca linii. - * - * - line - ofiara operacji plastycznej. - * - * niczego nie zwraca. - */ -static void gg_chomp(char *line) -{ - if (!line || strlen(line) < 1) - return; - - if (line[strlen(line) - 1] == '\n') - line[strlen(line) - 1] = 0; - if (line[strlen(line) - 1] == '\r') - line[strlen(line) - 1] = 0; -} - -/* * gg_watch_fd() * * funkcja wywoływana, gdy coś się stanie na obserwowanym deskryptorze. @@ -1004,6 +812,7 @@ { struct gg_event *e; int res = 0; + int port; if (!sess) { errno = EFAULT; @@ -1012,7 +821,7 @@ gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd(...);\n"); - if (!(e = (void *)malloc(sizeof(*e)))) { + if (!(e = (void*) malloc(sizeof(*e)))) { gg_debug(GG_DEBUG_MISC, "-- not enough memory\n"); return NULL; } @@ -1020,14 +829,14 @@ e->type = GG_EVENT_NONE; switch (sess->state) { - case GG_STATE_RESOLVING: + case GG_STATE_RESOLVING: { struct in_addr a; gg_debug(GG_DEBUG_MISC, "== GG_STATE_RESOLVING\n"); if (read(sess->fd, &a, sizeof(a)) < sizeof(a) || a.s_addr == INADDR_NONE) { - gg_debug(GG_DEBUG_MISC, "-- resolving failed\n"); + gg_debug(GG_DEBUG_MISC, "-- resolving failed\n"); errno = ENOENT; e->type = GG_EVENT_CONN_FAILED; @@ -1038,7 +847,7 @@ break; } - + sess->server_ip = a.s_addr; close(sess->fd); @@ -1046,81 +855,87 @@ waitpid(sess->pid, NULL, 0); gg_debug(GG_DEBUG_MISC, "-- resolved, now connecting\n"); + + if (gg_http_use_proxy) { + port = gg_http_proxy_port; + } else { + port = GG_APPMSG_PORT; + }; - if ((sess->fd = gg_connect(&a, GG_APPMSG_PORT, sess->async)) == -1) { - struct in_addr *addr = (struct in_addr *)&sess->server_ip; - - gg_debug(GG_DEBUG_MISC, - "-- connection failed, trying direct connection\n"); + if ((sess->fd = gg_connect(&a, port, sess->async)) == -1) { + struct in_addr *addr = (struct in_addr*) &sess->server_ip; + + gg_debug(GG_DEBUG_MISC, "-- connection failed, trying direct connection\n"); if ((sess->fd = gg_connect(addr, GG_DEFAULT_PORT, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, - "-- connection failed, trying https connection\n"); - if ((sess->fd = - gg_connect(&a, GG_HTTPS_PORT, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, - "-- connect() failed. errno = %d (%s)\n", errno, - strerror(errno)); + gg_debug(GG_DEBUG_MISC, "-- connection failed, trying https connection\n"); + if ((sess->fd = gg_connect(&a, GG_HTTPS_PORT, sess->async)) == -1) { + gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d (%s)\n", errno, strerror(errno)); - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_CONNECTING; - sess->state = GG_STATE_IDLE; - break; - } + e->type = GG_EVENT_CONN_FAILED; + e->event.failure = GG_FAILURE_CONNECTING; + sess->state = GG_STATE_IDLE; + break; + } } sess->state = GG_STATE_CONNECTING_GG; sess->check = GG_CHECK_WRITE; } else { - sess->state = GG_STATE_CONNECTING_HTTP; + sess->state = GG_STATE_CONNECTING; sess->check = GG_CHECK_WRITE; } - + break; } - case GG_STATE_CONNECTING_HTTP: + case GG_STATE_CONNECTING: { char buf[1024]; int res, res_size = sizeof(res); - gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTING_HTTP\n"); + gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTING\n"); - if (sess->async - && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { - struct in_addr *addr = (struct in_addr *)&sess->server_ip; - gg_debug(GG_DEBUG_MISC, - "-- http connection failed, errno = %d (%s), trying direct connection\n", - res, strerror(res)); + if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { + struct in_addr *addr = (struct in_addr*) &sess->server_ip; + gg_debug(GG_DEBUG_MISC, "-- http connection failed, errno = %d (%s), trying direct connection\n", res, strerror(res)); if ((sess->fd = gg_connect(addr, GG_DEFAULT_PORT, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, - "-- connection failed, trying https connection\n"); - if ((sess->fd = - gg_connect(addr, GG_HTTPS_PORT, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, - "-- connect() failed. errno = %d (%s)\n", errno, - strerror(errno)); + gg_debug(GG_DEBUG_MISC, "-- connection failed, trying https connection\n"); + if ((sess->fd = gg_connect(addr, GG_HTTPS_PORT, sess->async)) == -1) { + gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d (%s)\n", errno, strerror(errno)); - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_CONNECTING; - sess->state = GG_STATE_IDLE; - break; - } + e->type = GG_EVENT_CONN_FAILED; + e->event.failure = GG_FAILURE_CONNECTING; + sess->state = GG_STATE_IDLE; + break; + } } sess->state = GG_STATE_CONNECTING_GG; sess->check = GG_CHECK_WRITE; break; } - + gg_debug(GG_DEBUG_MISC, "-- http connection succeded, sending query\n"); - snprintf(buf, sizeof(buf) - 1, - "GET /appsvc/appmsg.asp?fmnumber=%lu HTTP/1.0\r\n" - "Host: " GG_APPMSG_HOST "\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Pragma: no-cache\r\n" "\r\n", sess->uin); + if (gg_http_use_proxy) { + snprintf(buf, sizeof(buf) - 1, + "GET http://" GG_APPMSG_HOST "/appsvc/appmsg.asp?fmnumber=%lu HTTP/1.0\r\n" + "Host: " GG_APPMSG_HOST "\r\n" + "User-Agent: " GG_HTTP_USERAGENT "\r\n" + "Pragma: no-cache\r\n" + "\r\n", sess->uin); + } else { + snprintf(buf, sizeof(buf) - 1, + "GET /appsvc/appmsg.asp?fmnumber=%lu HTTP/1.0\r\n" + "Host: " GG_APPMSG_HOST "\r\n" + "User-Agent: " GG_HTTP_USERAGENT "\r\n" + "Pragma: no-cache\r\n" + "\r\n", sess->uin); + }; + gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", buf); + if (write(sess->fd, buf, strlen(buf)) < strlen(buf)) { gg_debug(GG_DEBUG_MISC, "-- sending query failed\n"); @@ -1131,25 +946,24 @@ break; } - sess->state = GG_STATE_WRITING_HTTP; + sess->state = GG_STATE_READING_DATA; sess->check = GG_CHECK_READ; break; } - case GG_STATE_WRITING_HTTP: + case GG_STATE_READING_DATA: { char buf[1024], *tmp, *host; int port = GG_DEFAULT_PORT; struct in_addr a; - gg_debug(GG_DEBUG_MISC, "== GG_STATE_WRITING_HTTP\n"); + gg_debug(GG_DEBUG_MISC, "== GG_STATE_READING_DATA\n"); gg_read_line(sess->fd, buf, sizeof(buf) - 1); gg_chomp(buf); - + gg_debug(GG_DEBUG_TRAFFIC, "-- got http response (%s)\n", buf); - if (strncmp(buf, "HTTP/1.", 7) || strncmp(buf + 9, "200", 3)) { gg_debug(GG_DEBUG_MISC, "-- but that's not what we've expected\n"); @@ -1159,18 +973,19 @@ sess->state = GG_STATE_IDLE; break; } - + while (strcmp(buf, "\r\n") && strcmp(buf, "")) gg_read_line(sess->fd, buf, sizeof(buf) - 1); gg_read_line(sess->fd, buf, sizeof(buf) - 1); gg_chomp(buf); - + close(sess->fd); - + gg_debug(GG_DEBUG_TRAFFIC, "-- received http data (%s)\n", buf); - + tmp = buf; + while (*tmp && *tmp != ' ') tmp++; while (*tmp && *tmp == ' ') @@ -1190,78 +1005,70 @@ if ((tmp = strchr(host, ':'))) { *tmp = 0; - port = atoi(tmp + 1); + port = atoi(tmp+1); } a.s_addr = inet_addr(host); sess->server_ip = a.s_addr; if ((sess->fd = gg_connect(&a, port, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, - "-- connection failed, trying https connection\n"); + gg_debug(GG_DEBUG_MISC, "-- connection failed, trying https connection\n"); if ((sess->fd = gg_connect(&a, GG_HTTPS_PORT, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, - "-- connection failed, errno = %d (%s)\n", errno, - strerror(errno)); + gg_debug(GG_DEBUG_MISC, "-- connection failed, errno = %d (%s)\n", errno, strerror(errno)); - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_CONNECTING; - sess->state = GG_STATE_IDLE; - break; + e->type = GG_EVENT_CONN_FAILED; + e->event.failure = GG_FAILURE_CONNECTING; + sess->state = GG_STATE_IDLE; + break; } } sess->state = GG_STATE_CONNECTING_GG; sess->check = GG_CHECK_WRITE; - + break; } - case GG_STATE_CONNECTING_GG: + case GG_STATE_CONNECTING_GG: { int res, res_size = sizeof(res); gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTING_GG\n"); - if (sess->async - && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { - struct in_addr *addr = (struct in_addr *)&sess->server_ip; + if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { + struct in_addr *addr = (struct in_addr*) &sess->server_ip; - gg_debug(GG_DEBUG_MISC, - "-- connection failed, trying https connection\n"); + gg_debug(GG_DEBUG_MISC, "-- connection failed, trying https connection\n"); if ((sess->fd = gg_connect(addr, GG_HTTPS_PORT, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, - "-- connection failed, errno = %d (%s)\n", errno, - strerror(errno)); - - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_CONNECTING; - sess->state = GG_STATE_IDLE; - break; + gg_debug(GG_DEBUG_MISC, "-- connection failed, errno = %d (%s)\n", errno, strerror(errno)); + + e->type = GG_EVENT_CONN_FAILED; + e->event.failure = GG_FAILURE_CONNECTING; + sess->state = GG_STATE_IDLE; + break; } } gg_debug(GG_DEBUG_MISC, "-- connected\n"); - - sess->state = GG_STATE_WAITING_FOR_KEY; + + sess->state = GG_STATE_READING_KEY; sess->check = GG_CHECK_READ; break; } - case GG_STATE_WAITING_FOR_KEY: + case GG_STATE_READING_KEY: { - struct gg_header *h; + struct gg_header *h; struct gg_welcome *w; struct gg_login l; unsigned int hash; char *password = sess->password; - gg_debug(GG_DEBUG_MISC, "== GG_STATE_WAITING_FOR_KEY\n"); + gg_debug(GG_DEBUG_MISC, "== GG_STATE_READING_KEY\n"); if (!(h = gg_recv_packet(sess))) { - gg_debug(GG_DEBUG_MISC, "-- gg_recv_packet() failed. errno = %d (%s)\n", - errno, strerror(errno)); + gg_debug(GG_DEBUG_MISC, "-- gg_recv_packet() failed. errno = %d (%s)\n", errno, strerror(errno)); e->type = GG_EVENT_CONN_FAILED; e->event.failure = GG_FAILURE_READING; @@ -1269,7 +1076,7 @@ close(sess->fd); break; } - + if (h->type != GG_WELCOME) { gg_debug(GG_DEBUG_MISC, "-- invalid packet received\n"); @@ -1281,34 +1088,32 @@ sess->state = GG_STATE_IDLE; break; } - - w = (void *)h + sizeof(struct gg_header); + + w = (void*) h + sizeof(struct gg_header); w->key = fix32(w->key); for (hash = 1; *password; password++) hash *= (*password) + 1; hash *= w->key; - - gg_debug(GG_DEBUG_DUMP, "%%%% klucz serwera %.4x, hash hasła %.8x\n", w->key, - hash); - + + gg_debug(GG_DEBUG_DUMP, "%%%% klucz serwera %.4x, hash hasła %.8x\n", w->key, hash); + free(h); free(sess->password); sess->password = NULL; - + l.uin = fix32(sess->uin); l.hash = fix32(hash); l.status = fix32(sess->initial_status ? sess->initial_status : GG_STATUS_AVAIL); l.dunno = fix32(0x0b); l.local_ip = 0; l.local_port = 0; - + gg_debug(GG_DEBUG_TRAFFIC, "-- sending GG_LOGIN packet\n"); if (gg_send_packet(sess->fd, GG_LOGIN, &l, sizeof(l), NULL, 0) == -1) { - gg_debug(GG_DEBUG_TRAFFIC, "-- oops, failed. errno = %d (%s)\n", errno, - strerror(errno)); + gg_debug(GG_DEBUG_TRAFFIC, "-- oops, failed. errno = %d (%s)\n", errno, strerror(errno)); close(sess->fd); e->type = GG_EVENT_CONN_FAILED; @@ -1316,17 +1121,17 @@ sess->state = GG_STATE_IDLE; break; } - - sess->state = GG_STATE_SENDING_KEY; + + sess->state = GG_STATE_READING_REPLY; break; } - case GG_STATE_SENDING_KEY: + case GG_STATE_READING_REPLY: { struct gg_header *h; - gg_debug(GG_DEBUG_MISC, "== GG_STATE_SENDING_KEY\n"); + gg_debug(GG_DEBUG_MISC, "== GG_STATE_READING_REPLY\n"); if (!(h = gg_recv_packet(sess))) { gg_debug(GG_DEBUG_MISC, "-- recv_packet failed\n"); @@ -1336,7 +1141,7 @@ close(sess->fd); break; } - + if (h->type == GG_LOGIN_OK) { gg_debug(GG_DEBUG_MISC, "-- login succeded\n"); e->type = GG_EVENT_CONN_SUCCESS; @@ -1363,17 +1168,15 @@ break; } - case GG_STATE_CONNECTED: + case GG_STATE_CONNECTED: { gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTED\n"); if ((res = gg_watch_fd_connected(sess, e)) == -1) { - gg_debug(GG_DEBUG_MISC, - "-- watch_fd_connected failed. errno = %d (%s)\n", errno, - strerror(errno)); + gg_debug(GG_DEBUG_MISC, "-- watch_fd_connected failed. errno = %d (%s)\n", errno, strerror(errno)); - if (errno == EAGAIN) { + if (errno == EAGAIN) { e->type = GG_EVENT_NONE; res = 0; } else @@ -1390,3 +1193,13 @@ return e; } + +/* + * Local variables: + * c-indentation-style: k&r + * c-basic-offset: 8 + * indent-tabs-mode: notnil + * End: + * + * vim: shiftwidth=8: + */
