# HG changeset patch # User Mark Doliner # Date 1192355852 0 # Node ID d9cbd249619b008edfe9d5866066cbd799f1d1e8 # Parent b2b16843851b306565b52a031976f68564641de6 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. diff -r b2b16843851b -r d9cbd249619b libpurple/network.c --- 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); diff -r b2b16843851b -r d9cbd249619b libpurple/protocols/bonjour/jabber.c --- 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); diff -r b2b16843851b -r d9cbd249619b libpurple/protocols/msn/directconn.c --- 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; } diff -r b2b16843851b -r d9cbd249619b libpurple/protocols/msn/servconn.c --- 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; } diff -r b2b16843851b -r d9cbd249619b libpurple/protocols/oscar/peer.c --- 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); diff -r b2b16843851b -r d9cbd249619b libpurple/protocols/qq/qq_proxy.c --- 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); } diff -r b2b16843851b -r d9cbd249619b libpurple/protocols/qq/udp_proxy_s5.c --- 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); } diff -r b2b16843851b -r d9cbd249619b libpurple/proxy.c --- 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 diff -r b2b16843851b -r d9cbd249619b libpurple/win32/libc_interface.c --- 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; diff -r b2b16843851b -r d9cbd249619b libpurple/win32/libc_interface.h --- 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 ) \ diff -r b2b16843851b -r d9cbd249619b libpurple/win32/libc_internal.h --- 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 */