Mercurial > pidgin.yaz
diff libpurple/protocols/gg/lib/events.c @ 32072:3a90a59ddea2
Update libgadu to 0.11.0 plus local changes; thanks to Tomasz Wasilczyk.
Fixes 14248
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Sun, 05 Jun 2011 01:28:53 +0000 |
parents | 93b08d43f684 |
children | ef01f180114b |
line wrap: on
line diff
--- a/libpurple/protocols/gg/lib/events.c Tue May 24 01:48:26 2011 +0000 +++ b/libpurple/protocols/gg/lib/events.c Sun Jun 05 01:28:53 2011 +0000 @@ -1,4 +1,4 @@ -/* $Id: events.c 1062 2011-03-13 18:10:24Z wojtekka $ */ +/* $Id: events.c 1105 2011-05-25 21:34:50Z wojtekka $ */ /* * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl> @@ -27,22 +27,22 @@ * \brief Obsługa zdarzeń */ -#include "libgadu.h" -#include "libgadu-internal.h" -#include "libgadu-debug.h" - #include <sys/types.h> - #ifndef _WIN32 # include <sys/ioctl.h> # include <sys/socket.h> # include <netinet/in.h> # include <arpa/inet.h> #endif +#include <ctype.h> #include "compat.h" +#include "libgadu.h" +#include "libgadu-config.h" #include "protocol.h" +#include "libgadu-internal.h" #include "encoding.h" +#include "libgadu-debug.h" #include "session.h" #include <errno.h> @@ -156,7 +156,7 @@ break; } - + case GG_EVENT_MULTILOGON_INFO: { int i; @@ -168,6 +168,10 @@ break; } + + case GG_EVENT_USERLIST100_REPLY: + free(e->event.userlist100_reply.reply); + break; } free(e); @@ -258,9 +262,9 @@ gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() write() failed (errno=%d, %s)\n", errno, strerror(errno)); if (sess->state == GG_STATE_READING_REPLY) - goto fail_connecting; - else - goto done; + e->event.failure = GG_FAILURE_CONNECTING; + + goto fail; } if (res == sess->send_left) { @@ -299,7 +303,7 @@ if (failed) { errno = errno2; - goto fail_resolving; + goto fail_proxy_hub; } /* jeśli jesteśmy w resolverze i mamy ustawiony port @@ -326,7 +330,7 @@ /* jeśli w trybie asynchronicznym gg_connect() * zwróci błąd, nie ma sensu próbować dalej. */ gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), critical\n", errno, strerror(errno)); - goto fail_connecting; + goto fail_proxy_hub; } /* jeśli podano serwer i łączmy się przez proxy, @@ -357,19 +361,20 @@ /* jeśli asynchroniczne, sprawdzamy, czy nie wystąpił * przypadkiem jakiś błąd. */ if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { - if (sess->proxy_addr && sess->proxy_port) - gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", res, strerror(res)); - else - gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection to hub failed (errno=%d, %s)\n", res, strerror(res)); - - goto fail_connecting; + gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection to %s failed (errno=%d, %s)\n", (sess->proxy_addr && sess->proxy_port) ? "proxy" : "hub", res, strerror(res)); + goto fail_proxy_hub; } gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connected to hub, sending query\n"); - if (!(client = gg_urlencode((sess->client_version) ? sess->client_version : GG_DEFAULT_CLIENT_VERSION))) { + if (sess->client_version != NULL && isdigit(sess->client_version[0])) + client = gg_urlencode(sess->client_version); + else + client = gg_urlencode(GG_DEFAULT_CLIENT_VERSION); + + if (client == NULL) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() out of memory for client version\n"); - goto fail_connecting; + goto fail; } if (!gg_proxy_http_only && sess->proxy_addr && sess->proxy_port) @@ -407,13 +412,7 @@ * stało się coś złego. */ if (write(sess->fd, buf, strlen(buf)) < (signed)strlen(buf)) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sending query failed\n"); - - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_WRITING; - sess->state = GG_STATE_IDLE; - close(sess->fd); - sess->fd = -1; - break; + goto fail_proxy_hub; } sess->state = GG_STATE_READING_DATA; @@ -439,7 +438,7 @@ /* sprawdzamy, czy wszystko w porządku. */ if (strncmp(buf, "HTTP/1.", 7) || strncmp(buf + 9, "200", 3)) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() invalid http reply, connection failed\n"); - goto fail_connecting; + goto fail_proxy_hub; } /* ignorujemy resztę nagłówka. */ @@ -447,7 +446,10 @@ gg_read_line(sess->fd, buf, sizeof(buf) - 1); /* czytamy pierwszą linię danych. */ - gg_read_line(sess->fd, buf, sizeof(buf) - 1); + if (gg_read_line(sess->fd, buf, sizeof(buf) - 1) == NULL) { + gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() read error\n"); + goto fail_proxy_hub; + } gg_chomp(buf); /* jeśli pierwsza liczba w linii nie jest równa zeru, @@ -479,6 +481,7 @@ } close(sess->fd); + sess->fd = -1; gg_debug_session(sess, GG_DEBUG_TRAFFIC, "// gg_watch_fd() received http data (%s)\n", buf); @@ -503,10 +506,16 @@ port = atoi(tmp + 1); } + if (strcmp(host, "") == 0) { + gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() invalid response\n"); + e->event.failure = GG_FAILURE_HUB; + goto fail; + } + if (!strcmp(host, "notoperating")) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() service unavailable\n", errno, strerror(errno)); - sess->fd = -1; - goto fail_unavailable; + e->event.failure = GG_FAILURE_UNAVAILABLE; + goto fail; } addr.s_addr = inet_addr(host); @@ -517,7 +526,8 @@ if ((sess->fd = gg_connect(&sess->proxy_addr, sess->proxy_port, sess->async)) == -1) { /* nie wyszło? trudno. */ gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; + e->event.failure = GG_FAILURE_PROXY; + goto fail; } sess->state = GG_STATE_CONNECTING_GG; @@ -533,7 +543,7 @@ if (sess->server_addr == INADDR_NONE) { if (sess->resolver_start(&sess->fd, &sess->resolver, host) == -1) { gg_debug(GG_DEBUG_MISC, "// gg_login() resolving failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_resolving; + goto fail; } sess->state = GG_STATE_RESOLVING_GG; @@ -553,7 +563,8 @@ /* ostatnia deska ratunku zawiodła? * w takim razie zwijamy manatki. */ gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; + e->event.failure = GG_FAILURE_CONNECTING; + goto fail; } } @@ -585,7 +596,8 @@ if (failed) { errno = errno2; - goto fail_resolving; + e->event.failure = GG_FAILURE_RESOLVING; + goto fail; } sess->server_addr = addr.s_addr; @@ -601,7 +613,8 @@ /* ostatnia deska ratunku zawiodła? * w takim razie zwijamy manatki. */ gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; + e->event.failure = GG_FAILURE_CONNECTING; + goto fail; } } @@ -628,7 +641,8 @@ * nie mamy czego próbować więcej. */ if (sess->proxy_addr && sess->proxy_port) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", res, strerror(res)); - goto fail_connecting; + e->event.failure = GG_FAILURE_PROXY; + goto fail; } close(sess->fd); @@ -648,21 +662,25 @@ if (sess->ssl) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", res, strerror(res)); - goto fail_connecting; + e->event.failure = GG_FAILURE_CONNECTING; + goto fail; } #endif gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", res, strerror(res)); - if (sess->port == GG_HTTPS_PORT) - goto fail_connecting; + if (sess->port == GG_HTTPS_PORT) { + e->event.failure = GG_FAILURE_CONNECTING; + goto fail; + } sess->port = GG_HTTPS_PORT; /* próbujemy na port 443. */ if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; + e->event.failure = GG_FAILURE_CONNECTING; + goto fail; } sess->state = GG_STATE_CONNECTING_GG; @@ -698,7 +716,8 @@ if (write(sess->fd, buf, strlen(buf)) < (signed)strlen(buf)) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n"); free(auth); - goto fail_connecting; + e->event.failure = GG_FAILURE_PROXY; + goto fail; } if (auth) { @@ -706,7 +725,8 @@ if (write(sess->fd, auth, strlen(auth)) < (signed)strlen(auth)) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n"); free(auth); - goto fail_connecting; + e->event.failure = GG_FAILURE_PROXY; + goto fail; } free(auth); @@ -714,7 +734,8 @@ if (write(sess->fd, "\r\n", 2) < 2) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n"); - goto fail_connecting; + e->event.failure = GG_FAILURE_PROXY; + goto fail; } } @@ -904,7 +925,14 @@ { struct gg_header *gh; - gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTED\n"); + if (sess->state == GG_STATE_READING_KEY) + gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_KEY\n"); + else if (sess->state == GG_STATE_READING_REPLY) + gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_REPLY\n"); + else if (sess->state == GG_STATE_CONNECTED) + gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTED\n"); + else if (sess->state == GG_STATE_DISCONNECTING) + gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_DISCONNECTING\n"); /* XXX bardzo, bardzo, bardzo głupi pomysł na pozbycie * się tekstu wrzucanego przez proxy. */ @@ -936,64 +964,56 @@ if (gh == NULL) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd_connected() gg_recv_packet failed (errno=%d, %s)\n", errno, strerror(errno)); - if (errno == EAGAIN) { - e->type = GG_EVENT_NONE; - res = 0; - } else { - res = -1; + + if (errno != EAGAIN) + goto fail; + } else { + if (gg_session_handle_packet(sess, gh->type, (const char *) gh + sizeof(struct gg_header), gh->length, e) == -1) { + free(gh); + goto fail; } - goto done; + free(gh); } - if (gg_session_handle_packet(sess, gh->type, (const char *) gh + sizeof(struct gg_header), gh->length, e) == -1) { - free(gh); - res = -1; - goto done; - } - - free(gh); - sess->check = GG_CHECK_READ; break; } } -done: - if (res == -1) { - free(e); - e = NULL; - } else { - if (sess->send_buf && (sess->state == GG_STATE_READING_REPLY || sess->state == GG_STATE_CONNECTED)) - sess->check |= GG_CHECK_WRITE; - } + if (sess->send_buf && (sess->state == GG_STATE_READING_REPLY || sess->state == GG_STATE_CONNECTED)) + sess->check |= GG_CHECK_WRITE; return e; -fail_connecting: +fail_proxy_hub: + if (sess->proxy_port) + e->event.failure = GG_FAILURE_PROXY; + else + e->event.failure = GG_FAILURE_HUB; + +fail: + sess->resolver_cleanup(&sess->resolver, 1); + + sess->state = GG_STATE_IDLE; + if (sess->fd != -1) { + int errno2; + errno2 = errno; close(sess->fd); errno = errno2; sess->fd = -1; } - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_CONNECTING; - sess->state = GG_STATE_IDLE; - goto done; -fail_resolving: - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_RESOLVING; - sess->state = GG_STATE_IDLE; - goto done; - -fail_unavailable: - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_UNAVAILABLE; - sess->state = GG_STATE_IDLE; - goto done; + if (e->event.failure != 0) { + e->type = GG_EVENT_CONN_FAILED; + return e; + } else { + free(e); + return NULL; + } } /*