libpurple/protocols/gg/lib/dcc7.c

changeset 35557
e83a87761544
parent 33710
0d7ead568881
child 35620
fb20cfee648a
--- 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);

mercurial