Fixing File Transfer

Posted by Thoughts and Ramblings on Saturday, February 24, 2007

I work on Adium from time to time, and it currently has a major issue with file transfer. The problem is that the libgaim code used a particular method to detect if a socket was closed, but this method isn’t reliable since Adium wraps the sockets in CFSockets to detect activity. So, we had to use another method. I elected to take some code from Fire since I solved the same problem there a while back. Here it is for the curious:

/*
 * Taken from Fire's FaimP2PConnection.m:
 * The job of this function is to detect if the connection failed or not
 * There has to be a better way to do this
 *
 * Any socket that fails to connect will select for reading and writing
 * and all reads and writes will fail
 * Any listening socket will select for reading, and any read will fail
 * So, select for writing, if you can write, and the write fails, not connected
 */

{
	fd_set thisfd;
	struct timeval timeout;
	
	FD_ZERO(&thisfd);
	FD_SET(fd, &thisfd);
	timeout.tv_sec = 0;
	timeout.tv_usec = 0;
	select(fd+1, NULL, &thisfd, NULL, &timeout);
	if(FD_ISSET(fd, &thisfd)){
		ssize_t length = 0;
		char buffer[4] = {0, 0, 0, 0};
		
		length = write(fd, buffer, length);
		if(length == -1)
		{
			/* Not connected */
			ret = -1;
			*error = ENOTCONN;
			AILog(@"adium_input_get_error(%i): Socket is NOT valid", fd);
		}
	}
}

Rather hackish, but it does work.