fd_set *R_checkActivityEx(int usec, int ignore_stdin, void (*intr)(void)) { int maxfd; struct timeval tv; static fd_set readMask; if (R_interrupts_pending) { if (intr != NULL) intr(); else onintr(); } /* Solaris (but not POSIX) requires these times to be normalized. POSIX requires up to 31 days to be supported, and we only use up to 2147 secs here. */ tv.tv_sec = usec/1000000; tv.tv_usec = usec % 1000000; maxfd = setSelectMask(R_InputHandlers, &readMask); if (ignore_stdin) FD_CLR(fileno(stdin), &readMask); if (R_SelectEx(maxfd+1, &readMask, NULL, NULL, (usec >= 0) ? &tv : NULL, intr) > 0) return(&readMask); else return(NULL); }
int R_SockConnect(int port, char *host, int timeout) { SOCKET s; fd_set wfd, rfd; struct timeval tv; int status = 0; double used = 0.0; struct sockaddr_in server; struct hostent *hp; check_init(); s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == -1) return -1; #define CLOSE_N_RETURN(_ST_) { closesocket(s); return(_ST_); } #ifdef Win32 { u_long one = 1; status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0; } #else # ifdef HAVE_FCNTL if ((status = fcntl(s, F_GETFL, 0)) != -1) { # ifdef O_NONBLOCK status |= O_NONBLOCK; # else /* O_NONBLOCK */ # ifdef F_NDELAY status |= F_NDELAY; # endif # endif /* !O_NONBLOCK */ status = fcntl(s, F_SETFL, status); } # endif // HAVE_FCNTL if (status < 0) { CLOSE_N_RETURN(-1); } #endif if (! (hp = gethostbyname(host))) CLOSE_N_RETURN(-1); memcpy((char *)&server.sin_addr, hp->h_addr_list[0], hp->h_length); server.sin_port = htons((short)port); server.sin_family = AF_INET; if ((connect(s, (struct sockaddr *) &server, sizeof(server)) == -1)) { switch (socket_errno()) { case EINPROGRESS: case EWOULDBLOCK: break; default: CLOSE_N_RETURN(-1); } } while(1) { int maxfd = 0; R_ProcessEvents(); #ifdef Unix if(R_wait_usec > 0) { R_PolledEvents(); tv.tv_sec = 0; tv.tv_usec = R_wait_usec; } else { tv.tv_sec = timeout; tv.tv_usec = 0; } #elif defined(Win32) tv.tv_sec = 0; tv.tv_usec = 2e5; #else tv.tv_sec = timeout; tv.tv_usec = 0; #endif #ifdef Unix maxfd = setSelectMask(R_InputHandlers, &rfd); #else FD_ZERO(&rfd); #endif FD_ZERO(&wfd); FD_SET(s, &wfd); if(maxfd < s) maxfd = s; switch(R_SelectEx(maxfd+1, &rfd, &wfd, NULL, &tv, NULL)) { case 0: /* Time out */ used += tv.tv_sec + 1e-6 * tv.tv_usec; if(used < timeout) continue; CLOSE_N_RETURN(-1); case -1: /* Ermm.. ?? */ CLOSE_N_RETURN(-1); } if ( FD_ISSET(s, &wfd) ) { R_SOCKLEN_T len; len = sizeof(status); if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&status, &len) < 0){ /* Solaris error code */ return (-1); } if ( status ) { errno = status; CLOSE_N_RETURN(-1); } else return(s); #ifdef Unix } else { /* some other handler needed */ InputHandler *what; what = getSelectedHandler(R_InputHandlers, &rfd); if(what != NULL) what->handler((void*) NULL); continue; #endif } } /* not reached return(-1); */ }
/**** FIXME: add timeout argument instead of using global?? */ int R_SocketWaitMultiple(int nsock, int *insockfd, int *ready, int *write, double mytimeout) { fd_set rfd, wfd; struct timeval tv; double used = 0.0; int nready = 0; while(1) { int maxfd = 0, howmany, i; R_ProcessEvents(); #ifdef Unix if(R_wait_usec > 0) { int delta; if (mytimeout < 0 || R_wait_usec / 1e-6 < mytimeout - used) delta = R_wait_usec; else delta = (int)ceil(1e6 * (mytimeout - used)); tv.tv_sec = 0; tv.tv_usec = delta; } else if (mytimeout >= 0) { tv.tv_sec = (int)(mytimeout - used); tv.tv_usec = (int)ceil(1e6 * (mytimeout - used - tv.tv_sec)); } else { /* always poll occationally--not really necessary */ tv.tv_sec = 60; tv.tv_usec = 0; } #elif defined(Win32) tv.tv_sec = 0; tv.tv_usec = 2e5; #else if (mytimeout >= 0) { tv.tv_sec = mytimeout - used; tv.tv_usec = ceil(1e6 * (mytimeout - used - tv.tv_sec)); } else { /* always poll occasionally--not really necessary */ tv.tv_sec = timeout; tv.tv_usec = 0; } #endif #ifdef Unix maxfd = setSelectMask(R_InputHandlers, &rfd); #else FD_ZERO(&rfd); #endif FD_ZERO(&wfd); for (i = 0; i < nsock; i++) { if(write[i]) FD_SET(insockfd[i], &wfd); else FD_SET(insockfd[i], &rfd); if(maxfd < insockfd[i]) maxfd = insockfd[i]; } /* increment used value _before_ the select in case select modifies tv (as Linux does) */ used += tv.tv_sec + 1e-6 * tv.tv_usec; howmany = R_SelectEx(maxfd+1, &rfd, &wfd, NULL, &tv, NULL); if (howmany < 0) { return -socket_errno(); } if (howmany == 0) { if(mytimeout >= 0 && used >= mytimeout) { for (i = 0; i < nsock; i++) ready[i] = 0; /* FALSE */ return 0; } continue; } for (i = 0; i < nsock; i++) if ((!write[i] && FD_ISSET(insockfd[i], &rfd)) || (write[i] && FD_ISSET(insockfd[i], &wfd))) { ready[i] = 1; /* TRUE */ nready++; } else ready[i] = 0; /* FALSE */ #ifdef Unix if(howmany > nready) { /* one of the extras is ready */ InputHandler *what; what = getSelectedHandler(R_InputHandlers, &rfd); if(what != NULL) what->handler((void*) NULL); continue; } #endif /* some sockets are ready */ break; } return nready; }
static int R_SocketWait(int sockfd, int write, int timeout) { fd_set rfd, wfd; struct timeval tv; double used = 0.0; while(1) { int maxfd = 0, howmany; R_ProcessEvents(); #ifdef Unix if(R_wait_usec > 0) { tv.tv_sec = 0; tv.tv_usec = R_wait_usec; } else { tv.tv_sec = timeout; tv.tv_usec = 0; } #elif defined(Win32) tv.tv_sec = 0; tv.tv_usec = 2e5; #else tv.tv_sec = timeout; tv.tv_usec = 0; #endif #ifdef Unix maxfd = setSelectMask(R_InputHandlers, &rfd); #else FD_ZERO(&rfd); #endif FD_ZERO(&wfd); if(write) FD_SET(sockfd, &wfd); else FD_SET(sockfd, &rfd); if(maxfd < sockfd) maxfd = sockfd; /* increment used value _before_ the select in case select modifies tv (as Linux does) */ used += tv.tv_sec + 1e-6 * tv.tv_usec; howmany = R_SelectEx(maxfd+1, &rfd, &wfd, NULL, &tv, NULL); if (howmany < 0) { return -socket_errno(); } if (howmany == 0) { if(used >= timeout) return 1; continue; } #ifdef Unix if((!write && !FD_ISSET(sockfd, &rfd)) || (write && !FD_ISSET(sockfd, &wfd)) || howmany > 1) { /* was one of the extras */ InputHandler *what; what = getSelectedHandler(R_InputHandlers, &rfd); if(what != NULL) what->handler((void*) NULL); continue; } #endif /* the socket was ready */ break; } return 0; }