changeset 20922:d9cbd249619b

Fix all our calls to fcntl(listenfd, F_SETFL, O_NONBLOCK); fcntl() with F_SETFL overwrites the old flags with the new ones, so you should call fcntl() with F_GETFL, then OR that value with O_NONBLOCK before setting the flags. We've been doing this wrong for a long time and it hasn't seemed to hurt anything, but I thought it would be good to fix it.
author Mark Doliner <mark@kingant.net>
date Sun, 14 Oct 2007 09:57:32 +0000
parents b2b16843851b
children 9d9874c95a8d
files libpurple/network.c libpurple/protocols/bonjour/jabber.c libpurple/protocols/msn/directconn.c libpurple/protocols/msn/servconn.c libpurple/protocols/oscar/peer.c libpurple/protocols/qq/qq_proxy.c libpurple/protocols/qq/udp_proxy_s5.c libpurple/proxy.c libpurple/win32/libc_interface.c libpurple/win32/libc_interface.h libpurple/win32/libc_internal.h
diffstat 11 files changed, 71 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/network.c	Sat Oct 13 21:55:41 2007 +0000
+++ b/libpurple/network.c	Sun Oct 14 09:57:32 2007 +0000
@@ -263,6 +263,7 @@
 purple_network_do_listen(unsigned short port, int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data)
 {
 	int listenfd = -1;
+	int flags;
 	const int on = 1;
 	PurpleNetworkListenData *listen_data;
 	unsigned short actual_port;
@@ -340,7 +341,8 @@
 		close(listenfd);
 		return NULL;
 	}
-	fcntl(listenfd, F_SETFL, O_NONBLOCK);
+	flags = fcntl(listenfd, F_GETFL);
+	fcntl(listenfd, F_SETFL, flags | O_NONBLOCK);
 
 	actual_port = purple_network_get_port_from_fd(listenfd);
 
--- a/libpurple/protocols/bonjour/jabber.c	Sat Oct 13 21:55:41 2007 +0000
+++ b/libpurple/protocols/bonjour/jabber.c	Sun Oct 14 09:57:32 2007 +0000
@@ -521,6 +521,7 @@
 	struct sockaddr_in their_addr; /* connector's address information */
 	socklen_t sin_size = sizeof(struct sockaddr);
 	int client_socket;
+	int flags;
 	BonjourBuddy *bb;
 	char *address_text = NULL;
 	PurpleBuddyList *bl = purple_get_blist();
@@ -533,7 +534,8 @@
 	if ((client_socket = accept(server_socket, (struct sockaddr *)&their_addr, &sin_size)) == -1)
 		return;
 
-	fcntl(client_socket, F_SETFL, O_NONBLOCK);
+	flags = fcntl(client_socket, F_GETFL);
+	fcntl(client_socket, F_SETFL, flags | O_NONBLOCK);
 
 	/* Look for the buddy that has opened the conversation and fill information */
 	address_text = inet_ntoa(their_addr.sin_addr);
--- a/libpurple/protocols/msn/directconn.c	Sat Oct 13 21:55:41 2007 +0000
+++ b/libpurple/protocols/msn/directconn.c	Sun Oct 14 09:57:32 2007 +0000
@@ -80,6 +80,7 @@
 create_listener(int port)
 {
 	int fd;
+	int flags;
 	const int on = 1;
 
 #if 0
@@ -155,7 +156,8 @@
 		return -1;
 	}
 
-	fcntl(fd, F_SETFL, O_NONBLOCK);
+	flags = fcntl(fd, F_GETFL);
+	fcntl(fd, F_SETFL, flags | O_NONBLOCK);
 
 	return fd;
 }
--- a/libpurple/protocols/msn/servconn.c	Sat Oct 13 21:55:41 2007 +0000
+++ b/libpurple/protocols/msn/servconn.c	Sun Oct 14 09:57:32 2007 +0000
@@ -480,6 +480,7 @@
 create_listener(int port)
 {
 	int fd;
+	int flags;
 	const int on = 1;
 
 #if 0
@@ -555,7 +556,8 @@
 		return -1;
 	}
 
-	fcntl(fd, F_SETFL, O_NONBLOCK);
+	flags = fcntl(fd, F_GETFL);
+	fcntl(fd, F_SETFL, flags | O_NONBLOCK);
 
 	return fd;
 }
--- a/libpurple/protocols/oscar/peer.c	Sat Oct 13 21:55:41 2007 +0000
+++ b/libpurple/protocols/oscar/peer.c	Sun Oct 14 09:57:32 2007 +0000
@@ -607,6 +607,7 @@
 	PurpleConnection *gc;
 	struct sockaddr addr;
 	socklen_t addrlen = sizeof(addr);
+	int flags;
 
 	conn = data;
 	od = conn->od;
@@ -633,7 +634,8 @@
 		return;
 	}
 
-	fcntl(conn->fd, F_SETFL, O_NONBLOCK);
+	flags = fcntl(conn->fd, F_GETFL);
+	fcntl(conn->fd, F_SETFL, flags | O_NONBLOCK);
 	purple_input_remove(conn->watcher_incoming);
 
 	peer_connection_finalize_connection(conn);
--- a/libpurple/protocols/qq/qq_proxy.c	Sat Oct 13 21:55:41 2007 +0000
+++ b/libpurple/protocols/qq/qq_proxy.c	Sun Oct 14 09:57:32 2007 +0000
@@ -258,6 +258,7 @@
 static gint _qq_proxy_none(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen)
 {
 	gint fd = -1;
+	int flags;
 
 	purple_debug(PURPLE_DEBUG_INFO, "QQ", "Using UDP without proxy\n");
 	fd = socket(PF_INET, SOCK_DGRAM, 0);
@@ -269,7 +270,8 @@
 	}
 
 	/* we use non-blocking mode to speed up connection */
-	fcntl(fd, F_SETFL, O_NONBLOCK);
+	flags = fcntl(fd, F_GETFL);
+	fcntl(fd, F_SETFL, flags | O_NONBLOCK);
 
 	/* From Unix-socket-FAQ: http://www.faqs.org/faqs/unix-faq/socket/
 	 *
@@ -301,7 +303,8 @@
 		}		/* if errno */
 	} else {		/* connect returns 0 */
 		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Connected.\n");
-		fcntl(fd, F_SETFL, 0);
+		flags = fcntl(fd, F_GETFL);
+		fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
 		phb->func(phb->data, fd, NULL);
 	}
 
--- a/libpurple/protocols/qq/udp_proxy_s5.c	Sat Oct 13 21:55:41 2007 +0000
+++ b/libpurple/protocols/qq/udp_proxy_s5.c	Sun Oct 14 09:57:32 2007 +0000
@@ -33,6 +33,7 @@
 	struct sockaddr_in sin;
 	int len, error;
 	socklen_t errlen;
+	int flags;
 
 	purple_input_remove(phb->inpa);
 	purple_debug(PURPLE_DEBUG_INFO, "socks5 proxy", "Able to read again.\n");
@@ -89,7 +90,8 @@
 		close(phb->udpsock);
 		return;
 	}
-	fcntl(phb->udpsock, F_SETFL, 0);
+	flags = fcntl(phb->udpsock, F_GETFL);
+	fcntl(phb->udpsock, F_SETFL, flags & ~O_NONBLOCK);
 
 	if (phb->account == NULL || purple_account_get_connection(phb->account) != NULL) {
 		phb->func(phb->data, phb->udpsock, NULL);
@@ -106,6 +108,7 @@
 	struct sockaddr_in sin, ctlsin;
 	int port; 
 	socklen_t ctllen;
+	int flags;
 
 	purple_debug(PURPLE_DEBUG_INFO, "s5_sendconnect", "remote host is %s:%d\n", phb->host, phb->port);
 
@@ -133,7 +136,8 @@
 		return;
 	}
 
-	fcntl(phb->udpsock, F_SETFL, O_NONBLOCK);
+	flags = fcntl(phb->udpsock, F_GETFL);
+	fcntl(phb->udpsock, F_SETFL, flags | O_NONBLOCK);
 
 	port = g_ntohs(ctlsin.sin_port) + 1;
 	while (1) {
@@ -287,6 +291,7 @@
 	struct PHB *phb = data;
 	socklen_t len;
 	int error = ETIMEDOUT;
+	int flags;
 
 	purple_debug(PURPLE_DEBUG_INFO, "socks5 proxy", "Connected.\n");
 
@@ -306,7 +311,8 @@
 		g_free(phb);
 		return;
 	}
-	fcntl(source, F_SETFL, 0);
+	flags = fcntl(source, F_GETFL);
+	fcntl(source, F_SETFL, flags & ~O_NONBLOCK);
 
 	i = 0;
 	buf[0] = 0x05;		/* SOCKS version 5 */
@@ -343,6 +349,8 @@
 gint qq_proxy_socks5(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen)
 {
 	gint fd;
+	int flags;
+
 	purple_debug(PURPLE_DEBUG_INFO, "QQ",
 		   "Connecting to %s:%d via %s:%d using SOCKS5\n",
 		   phb->host, phb->port, purple_proxy_info_get_host(phb->gpi), purple_proxy_info_get_port(phb->gpi));
@@ -352,7 +360,8 @@
 
 	purple_debug(PURPLE_DEBUG_INFO, "QQ", "proxy_sock5 return fd=%d\n", fd);
 
-	fcntl(fd, F_SETFL, O_NONBLOCK);
+	flags = fcntl(fd, F_GETFL);
+	fcntl(fd, F_SETFL, flags | O_NONBLOCK);
 	if (connect(fd, addr, addrlen) < 0) {
 		if ((errno == EINPROGRESS) || (errno == EINTR)) {
 			purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Connect in asynchronous mode.\n");
@@ -363,7 +372,8 @@
 		}
 	} else {
 		purple_debug(PURPLE_DEBUG_MISC, "QQ", "Connect in blocking mode.\n");
-		fcntl(fd, F_SETFL, 0);
+		flags = fcntl(fd, F_GETFL);
+		fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
 		_qq_s5_canwrite(phb, fd, PURPLE_INPUT_WRITE);
 	}
 
--- a/libpurple/proxy.c	Sat Oct 13 21:55:41 2007 +0000
+++ b/libpurple/proxy.c	Sun Oct 14 09:57:32 2007 +0000
@@ -449,6 +449,8 @@
 static void
 proxy_connect_none(PurpleProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen)
 {
+	int flags;
+
 	purple_debug_info("proxy", "Connecting to %s:%d with no proxy\n",
 			connect_data->host, connect_data->port);
 
@@ -460,7 +462,8 @@
 		return;
 	}
 
-	fcntl(connect_data->fd, F_SETFL, O_NONBLOCK);
+	flags = fcntl(connect_data->fd, F_GETFL);
+	fcntl(connect_data->fd, F_SETFL, flags | O_NONBLOCK);
 #ifndef _WIN32
 	fcntl(connect_data->fd, F_SETFD, FD_CLOEXEC);
 #endif
@@ -881,6 +884,8 @@
 static void
 proxy_connect_http(PurpleProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen)
 {
+	int flags;
+
 	purple_debug_info("proxy",
 			   "Connecting to %s:%d via %s:%d using HTTP\n",
 			   connect_data->host, connect_data->port,
@@ -895,14 +900,16 @@
 		return;
 	}
 
-	fcntl(connect_data->fd, F_SETFL, O_NONBLOCK);
+	flags = fcntl(connect_data->fd, F_GETFL);
+	fcntl(connect_data->fd, F_SETFL, flags | O_NONBLOCK);
 #ifndef _WIN32
 	fcntl(connect_data->fd, F_SETFD, FD_CLOEXEC);
 #endif
 
 	if (connect(connect_data->fd, addr, addrlen) != 0)
 	{
-		if ((errno == EINPROGRESS) || (errno == EINTR)) {
+		if ((errno == EINPROGRESS) || (errno == EINTR))
+		{
 			purple_debug_info("proxy", "Connection in progress\n");
 
 			if (connect_data->port != 80)
@@ -1036,6 +1043,8 @@
 static void
 proxy_connect_socks4(PurpleProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen)
 {
+	int flags;
+
 	purple_debug_info("proxy",
 			   "Connecting to %s:%d via %s:%d using SOCKS4\n",
 			   connect_data->host, connect_data->port,
@@ -1050,7 +1059,8 @@
 		return;
 	}
 
-	fcntl(connect_data->fd, F_SETFL, O_NONBLOCK);
+	flags = fcntl(connect_data->fd, F_GETFL);
+	fcntl(connect_data->fd, F_SETFL, flags | O_NONBLOCK);
 #ifndef _WIN32
 	fcntl(connect_data->fd, F_SETFD, FD_CLOEXEC);
 #endif
@@ -1604,6 +1614,8 @@
 static void
 proxy_connect_socks5(PurpleProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen)
 {
+	int flags;
+
 	purple_debug_info("proxy",
 			   "Connecting to %s:%d via %s:%d using SOCKS5\n",
 			   connect_data->host, connect_data->port,
@@ -1618,7 +1630,8 @@
 		return;
 	}
 
-	fcntl(connect_data->fd, F_SETFL, O_NONBLOCK);
+	flags = fcntl(connect_data->fd, F_GETFL);
+	fcntl(connect_data->fd, F_SETFL, flags | O_NONBLOCK);
 #ifndef _WIN32
 	fcntl(connect_data->fd, F_SETFD, FD_CLOEXEC);
 #endif
--- a/libpurple/win32/libc_interface.c	Sat Oct 13 21:55:41 2007 +0000
+++ b/libpurple/win32/libc_interface.c	Sun Oct 14 09:57:32 2007 +0000
@@ -138,12 +138,22 @@
 
 /* fcntl.h */
 /* This is not a full implementation of fcntl. Update as needed.. */
-int wpurple_fcntl(int socket, int command, int val) {
+int wpurple_fcntl(int socket, int command, ...) {
+
 	switch( command ) {
+	case F_GETFL:
+		return 0;
+
 	case F_SETFL:
 	{
+		va_list args;
+		int val;
 		int ret=0;
 
+		va_start(args, command);
+		val = va_arg(args, int);
+		va_end(args);
+
 		switch( val ) {
 		case O_NONBLOCK:
 		{
@@ -152,7 +162,7 @@
 			break;
 		}
 		case 0:
-	        {
+		{
 			u_long imode=0;
 			ret = ioctlsocket(socket, FIONBIO, &imode);
 			break;
--- a/libpurple/win32/libc_interface.h	Sat Oct 13 21:55:41 2007 +0000
+++ b/libpurple/win32/libc_interface.h	Sun Oct 14 09:57:32 2007 +0000
@@ -75,8 +75,8 @@
 wpurple_ioctl( fd, command, val )
 
 /* fcntl.h */
-#define fcntl( fd, command, val ) \
-wpurple_fcntl( fd, command, val )
+#define fcntl( fd, command, ... ) \
+wpurple_fcntl( fd, command, ##__VA_ARGS__ )
 
 /* arpa/inet.h */
 #define inet_aton( name, addr ) \
--- a/libpurple/win32/libc_internal.h	Sat Oct 13 21:55:41 2007 +0000
+++ b/libpurple/win32/libc_internal.h	Sun Oct 14 09:57:32 2007 +0000
@@ -49,9 +49,10 @@
 char* wpurple_strerror( int errornum );
 
 /* fcntl.h */
-int wpurple_fcntl(int socket, int command, int val);
-#define F_SETFL 1
-#define O_NONBLOCK 1
+int wpurple_fcntl(int socket, int command, ...);
+#define F_GETFL 3
+#define F_SETFL 4
+#define O_NONBLOCK 04000
 
 /* sys/ioctl.h */
 #define SIOCGIFCONF 0x8912 /* get iface list */