static int do_connect(char *host, int port, int timeout) { int sock, status, connected = 0; struct sockaddr_in addr, check_connect; fd_set rset, wset; // timeout struct timeval timeout_struct; timeout_struct.tv_sec = timeout / 1000; timeout_struct.tv_usec = (timeout % 1000) * 1000; #ifdef WIN32 WORD version; WSADATA wsaData; int size, error; u_long no = 0; const char yes = 1; version = MAKEWORD(2,2); error = WSAStartup(version, &wsaData); if (error != 0) { return 0; } // create socket sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == INVALID_SOCKET) { return 0; } #else uint size; int yes = 1; // create socket if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { croak("couldn't create socket: %s\n", strerror(errno)); return -1; } #endif // get addresses if (!mongo_link_sockaddr(&addr, host, port)) { return -1; } setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, INT_32); setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &yes, INT_32); #ifdef WIN32 ioctlsocket(sock, FIONBIO, (u_long*)&yes); #else fcntl(sock, F_SETFL, O_NONBLOCK); #endif FD_ZERO(&rset); FD_SET(sock, &rset); FD_ZERO(&wset); FD_SET(sock, &wset); // connect status = connect(sock, (struct sockaddr*)&addr, sizeof(addr)); if (status == -1) { #ifdef WIN32 errno = WSAGetLastError(); if (errno != WSAEINPROGRESS && errno != WSAEWOULDBLOCK) #else if (errno != EINPROGRESS) #endif { return -1; } if (!select(sock+1, &rset, &wset, 0, &timeout_struct)) { return -1; } size = sizeof(check_connect); connected = getpeername(sock, (struct sockaddr*)&addr, &size); if (connected == -1) { return -1; } } else if (status == 0) { connected = 1; } // reset flags #ifdef WIN32 ioctlsocket(sock, FIONBIO, &no); #else fcntl(sock, F_SETFL, 0); #endif return sock; }
/* * Returns -1 on failure, the socket fh on success. * * Note: this cannot return 0 on failure, because reconnecting sometimes makes * the fh 0 (briefly). */ void non_ssl_connect(mongo_link* link) { int sock, status, connected = 0; struct sockaddr_in addr; #ifdef WIN32 WORD version; WSADATA wsaData; int error; u_long no = 0; const char yes = 1; version = MAKEWORD(2,2); error = WSAStartup(version, &wsaData); if (error != 0) { return; } // create socket sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == INVALID_SOCKET) { return; } #else int yes = 1; // create socket if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { croak("couldn't create socket: %s\n", strerror(errno)); return; } #endif // get addresses if (!mongo_link_sockaddr(&addr, link->master->host, link->master->port)) { return; } setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, INT_32); setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &yes, INT_32); set_timeout(sock, link->timeout); #ifdef WIN32 ioctlsocket(sock, FIONBIO, (u_long*)&yes); #else fcntl(sock, F_SETFL, O_NONBLOCK); #endif // connect status = connect(sock, (struct sockaddr*)&addr, sizeof(addr)); if (status == -1) { socklen_t size; #ifdef WIN32 errno = WSAGetLastError(); if (errno != WSAEINPROGRESS && errno != WSAEWOULDBLOCK) #else if (errno != EINPROGRESS) #endif { return; } if (!mongo_link_timeout(sock, link->timeout)) { return; } size = sizeof(addr); connected = getpeername(sock, (struct sockaddr*)&addr, &size); if (connected == -1){ return; } } else if (status == 0) { connected = 1; } // reset flags #ifdef WIN32 ioctlsocket(sock, FIONBIO, &no); #else fcntl(sock, F_SETFL, 0); #endif link->master->socket = sock; link->master->connected = 1; return; }