--- a/libpurple/protocols/gg/lib/dcc7.c Thu Feb 13 04:27:27 2014 +0100 +++ b/libpurple/protocols/gg/lib/dcc7.c Thu Feb 13 18:29:10 2014 +0100 @@ -1,4 +1,4 @@ -/* $Id: dcc7.c 1087 2011-04-14 20:53:25Z wojtekka $ */ +/* $Id$ */ /* * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl> @@ -29,31 +29,29 @@ * \brief Obsługa połączeń bezpośrednich od wersji Gadu-Gadu 7.x */ -#include <sys/types.h> -#include <sys/stat.h> -#ifdef sun -# include <sys/filio.h> -#endif -#include <time.h> +#include "fileio.h" +#include "network.h" +#include "strman.h" #include <ctype.h> #include <errno.h> -#include <fcntl.h> -#include <stdarg.h> #include <string.h> -#include <stdio.h> #include <stdlib.h> -#include <unistd.h> +#include <time.h> -#include "compat.h" #include "libgadu.h" #include "protocol.h" #include "resolver.h" #include "internal.h" #include "debug.h" -#define gg_debug_dcc(dcc, level, fmt...) \ +#ifdef _MSC_VER +# define gg_debug_dcc(dcc, level, fmt, ...) \ + gg_debug_session(((dcc) != NULL) ? (dcc)->sess : NULL, level, fmt, __VA_ARGS__) +#else +# define gg_debug_dcc(dcc, level, fmt...) \ gg_debug_session(((dcc) != NULL) ? (dcc)->sess : NULL, level, fmt) +#endif #define gg_debug_dump_dcc(dcc, level, buf, len) \ gg_debug_dump(((dcc) != NULL) ? (dcc)->sess : NULL, level, buf, len) @@ -140,7 +138,7 @@ for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) { if (empty) { - if (tmp->peer_uin == uin /*&& tmp->state != GG_STATE_WAITING_FOR_ACCEPT*/) + if (tmp->peer_uin == uin && tmp->state == GG_STATE_WAITING_FOR_ACCEPT) return tmp; } else { if (!memcmp(&tmp->cid, &id, sizeof(id))) @@ -430,7 +428,7 @@ dcc->size = size; dcc->seek = seek; - strncpy((char*) dcc->filename, filename1250, GG_DCC7_FILENAME_LEN - 1); + strncpy((char*) dcc->filename, filename1250, GG_DCC7_FILENAME_LEN); dcc->filename[GG_DCC7_FILENAME_LEN] = 0; memcpy(dcc->hash, hash, GG_DCC7_HASH_LEN); @@ -511,7 +509,7 @@ fail: if (fd != -1) { int errsv = errno; - close(fd); + gg_file_close(fd); errno = errsv; } @@ -633,7 +631,7 @@ for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) { gg_debug_session(sess, GG_DEBUG_MISC, "// checking dcc %p, state %d, type %d\n", tmp, tmp->state, tmp->dcc_type); - if (tmp->state != GG_STATE_REQUESTING_ID || tmp->dcc_type != gg_fix32(p->type)) + if (tmp->state != GG_STATE_REQUESTING_ID || tmp->dcc_type != (int) gg_fix32(p->type)) continue; tmp->cid = p->id; @@ -650,7 +648,9 @@ s.uin_to = gg_fix32(tmp->peer_uin); s.size = gg_fix32(tmp->size); - memcpy((char*) s.filename, (char*) tmp->filename, GG_DCC7_FILENAME_LEN); + /* Uwaga: To nie jest ciąg kończony zerem. + * Note: This is not a null-terminated string. */ + strncpy((char*) s.filename, (char*) tmp->filename, sizeof(s.filename)); tmp->state = GG_STATE_WAITING_FOR_ACCEPT; tmp->timeout = GG_DCC7_TIMEOUT_FILE_ACK; @@ -682,7 +682,7 @@ if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_accept() unknown dcc session\n"); - // XXX wysłać reject? + /* XXX wysłać reject? */ e->type = GG_EVENT_DCC7_ERROR; e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; return 0; @@ -695,7 +695,7 @@ return 0; } - // XXX czy dla odwrotnego połączenia powinniśmy wywołać już zdarzenie GG_DCC7_ACCEPT? + /* XXX czy dla odwrotnego połączenia powinniśmy wywołać już zdarzenie GG_DCC7_ACCEPT? */ dcc->offset = gg_fix32(p->offset); dcc->state = GG_STATE_WAITING_FOR_INFO; @@ -767,11 +767,15 @@ return 0; } -#if defined(HAVE_UINT64_T) && defined(HAVE_STRTOULL) +#if defined(HAVE__STRTOUI64) || defined(HAVE_STRTOULL) { uint64_t cid; +# ifdef HAVE__STRTOUI64 + cid = _strtoui64(tmp + 2, NULL, 0); +# else cid = strtoull(tmp + 2, NULL, 0); +# endif gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() info.str=%s, info.id=%llu, sess.id=%llu\n", tmp + 2, cid, *((unsigned long long*) &dcc->cid)); @@ -793,7 +797,7 @@ return 0; } - // XXX wysyłać dopiero jeśli uda się połączyć z serwerem? + /* XXX wysyłać dopiero jeśli uda się połączyć z serwerem? */ gg_send_packet(dcc->sess, GG_DCC7_INFO, payload, len, NULL); @@ -806,15 +810,17 @@ return 0; } - // jeśli nadal czekamy na połączenie przychodzące, a druga strona nie - // daje rady i oferuje namiary na siebie, bierzemy co dają. - -// if (dcc->state != GG_STATE_WAITING_FOR_INFO && (dcc->state != GG_STATE_LISTENING || dcc->reverse)) { -// gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid state\n"); -// e->type = GG_EVENT_DCC7_ERROR; -// e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; -// return 0; -// } +#if 0 + /* jeśli nadal czekamy na połączenie przychodzące, a druga strona nie + * daje rady i oferuje namiary na siebie, bierzemy co dają. + */ + if (dcc->state != GG_STATE_WAITING_FOR_INFO && (dcc->state != GG_STATE_LISTENING || dcc->reverse)) { + gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid state\n"); + e->type = GG_EVENT_DCC7_ERROR; + e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; + return 0; + } +#endif if (dcc->state == GG_STATE_LISTENING) { close(dcc->fd); @@ -877,7 +883,7 @@ e->event.dcc7_reject.dcc7 = dcc; e->event.dcc7_reject.reason = gg_fix32(p->reason); - // XXX ustawić state na rejected? + /* XXX ustawić state na rejected? */ return 0; } @@ -923,7 +929,7 @@ } dcc->size = gg_fix32(p->size); - strncpy((char*) dcc->filename, (char*) p->filename, GG_DCC7_FILENAME_LEN - 1); + strncpy((char*) dcc->filename, (char*) p->filename, GG_DCC7_FILENAME_LEN); dcc->filename[GG_DCC7_FILENAME_LEN] = 0; memcpy(dcc->hash, p->hash, GG_DCC7_HASH_LEN); @@ -1046,7 +1052,10 @@ case GG_STATE_LISTENING: { struct sockaddr_in sin; - int fd, one = 1; + int fd; +#ifdef FIONBIO + int one = 1; +#endif socklen_t sin_len = sizeof(sin); gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_LISTENING\n"); @@ -1112,7 +1121,7 @@ } if (dcc->relay_index >= dcc->relay_count) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available"); + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available\n"); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_RELAY; return e; @@ -1150,8 +1159,8 @@ struct gg_dcc7_welcome_p2p welcome, welcome_ok; welcome_ok.id = dcc->cid; - if ((res = read(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (%d, %s)\n", res, strerror(errno)); + if ((res = recv(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) { + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() recv() failed (%d, %s)\n", res, strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; return e; @@ -1168,8 +1177,8 @@ welcome_ok.magic = GG_DCC7_WELCOME_SERVER; welcome_ok.id = dcc->cid; - if ((res = read(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (%d, %s)\n", res, strerror(errno)); + if ((res = recv(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) { + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() recv() failed (%d, %s)\n", res, strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; return e; @@ -1206,8 +1215,8 @@ welcome.id = dcc->cid; - if ((res = write(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (%d, %s)\n", res, strerror(errno)); + if ((res = send(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) { + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() send() failed (%d, %s)\n", res, strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; return e; @@ -1218,8 +1227,8 @@ welcome.magic = gg_fix32(GG_DCC7_WELCOME_SERVER); welcome.id = dcc->cid; - if ((res = write(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (%d, %s)\n", res, strerror(errno)); + if ((res = send(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) { + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() send() failed (%d, %s)\n", res, strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; return e; @@ -1241,7 +1250,8 @@ case GG_STATE_SENDING_FILE: { char buf[1024]; - int chunk, res; + size_t chunk; + int res; gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_SENDING_FILE (offset=%d, size=%d)\n", dcc->offset, dcc->size); @@ -1269,8 +1279,8 @@ return e; } - if ((res = write(dcc->fd, buf, res)) == -1) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (%s)\n", strerror(errno)); + if ((res = send(dcc->fd, buf, res, 0)) == -1) { + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() send() failed (%s)\n", strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_NET; return e; @@ -1306,14 +1316,14 @@ return e; } - if ((res = read(dcc->fd, buf, sizeof(buf))) < 1) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (fd=%d, res=%d, %s)\n", dcc->fd, res, strerror(errno)); + if ((res = recv(dcc->fd, buf, sizeof(buf), 0)) < 1) { + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() recv() failed (fd=%d, res=%d, %s)\n", dcc->fd, res, strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_NET : GG_ERROR_DCC7_EOF; return e; } - // XXX zapisywać do skutku? + /* XXX zapisywać do skutku? */ if ((wres = write(dcc->file_fd, buf, res)) < res) { gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (fd=%d, res=%d, %s)\n", dcc->file_fd, wres, strerror(errno)); @@ -1341,16 +1351,22 @@ case GG_STATE_RESOLVING_RELAY: { struct in_addr addr; + int res; gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_RESOLVING_RELAY\n"); - if (read(dcc->fd, &addr, sizeof(addr)) < sizeof(addr) || addr.s_addr == INADDR_NONE) { + do { + res = gg_resolver_recv(dcc->fd, &addr, sizeof(addr)); + } while (res == -1 && errno == EINTR); + + dcc->sess->resolver_cleanup(&dcc->resolver, 0); + + if (res != sizeof(addr) || addr.s_addr == INADDR_NONE) { int errno_save = errno; gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() resolving failed\n"); close(dcc->fd); dcc->fd = -1; - dcc->sess->resolver_cleanup(&dcc->resolver, 0); errno = errno_save; e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_RELAY; @@ -1401,7 +1417,7 @@ gg_debug_dcc(dcc, GG_DEBUG_DUMP, "// gg_dcc7_watch_fd() send pkt(0x%.2x)\n", gg_fix32(pkt.magic)); gg_debug_dump_dcc(dcc, GG_DEBUG_DUMP, (const char*) &pkt, sizeof(pkt)); - if ((res = write(dcc->fd, &pkt, sizeof(pkt))) != sizeof(pkt)) { + if ((res = send(dcc->fd, &pkt, sizeof(pkt), 0)) != sizeof(pkt)) { gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() sending failed\n"); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_RELAY; @@ -1425,10 +1441,10 @@ gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_READING_RELAY\n"); - if ((res = read(dcc->fd, buf, sizeof(buf))) < sizeof(*pkt)) { + if ((res = recv(dcc->fd, buf, sizeof(buf), 0)) < (int) sizeof(*pkt)) { if (res == 0) errno = ECONNRESET; - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (%d, %s)\n", res, strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() recv() failed (%d, %s)\n", res, strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_RELAY; return e; @@ -1454,7 +1470,7 @@ dcc->relay_list = malloc(dcc->relay_count * sizeof(gg_dcc7_relay_t)); if (dcc->relay_list == NULL) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() not enough memory"); + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() not enough memory\n"); dcc->relay_count = 0; free(e); return NULL; @@ -1483,7 +1499,7 @@ } if (dcc->relay_index >= dcc->relay_count) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available"); + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available\n"); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_RELAY; return e; @@ -1523,7 +1539,7 @@ close(dcc->fd); if (dcc->file_fd != -1) - close(dcc->file_fd); + gg_file_close(dcc->file_fd); if (dcc->sess) gg_dcc7_session_remove(dcc->sess, dcc);