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.