timeoutconn.c (2344B)
1 #include "timeoutconn.h" 2 3 #include <sys/types.h> 4 #include <sys/socket.h> 5 #include <netinet/in.h> 6 #include <arpa/inet.h> 7 #include "ndelay.h" 8 #include "select.h" 9 #include "error.h" 10 #include "readwrite.h" 11 #include "ip.h" 12 #include "byte.h" 13 14 int timeoutbindconn(int s, struct ip_address *ip, struct ip_address *bip, unsigned int port, int timeout) 15 { 16 char ch; 17 int is6 = AF_INET; 18 union { 19 struct sockaddr_in a; 20 struct sockaddr_in6 aaaa; 21 } sin; 22 union { 23 struct sockaddr_in a; 24 struct sockaddr_in6 aaaa; 25 } bsin; 26 char *x; 27 fd_set wfds; 28 struct timeval tv; 29 30 if (bip != NULL) if (bip->is6 != ip->is6) return (errno = EOPNOTSUPP, -1); /* erm... Reinhilde Bjornsdottir */ 31 32 if (ip->is6) { 33 is6 = AF_INET6; 34 byte_zero(&sin,sizeof(sin)); 35 byte_copy(&sin.aaaa.sin6_addr,16,ip->ip.aaaa.d); 36 x = (char *) &sin.aaaa.sin6_port; 37 x[1] = port; port >>= 8; x[0] = port; 38 if (bip != NULL) { 39 byte_zero(&bsin,sizeof(bsin)); 40 byte_copy(&bsin.aaaa.sin6_addr,16,bip->ip.aaaa.d); 41 x = (char *) &bsin.aaaa.sin6_port; 42 x[1] = 0; x[0] = 0; 43 } 44 sin.aaaa.sin6_family = is6; 45 } else { 46 byte_zero(&sin,sizeof(sin)); 47 byte_copy(&sin.a.sin_addr,4,ip->ip.a.d); 48 x = (char *) &sin.a.sin_port; 49 x[1] = port; port >>= 8; x[0] = port; 50 if (bip != NULL) { 51 byte_zero(&bsin,sizeof(bsin)); 52 byte_copy(&bsin.a.sin_addr,4,bip->ip.a.d); 53 x = (char *) &bsin.a.sin_port; 54 x[1] = 0; x[0] = 0; 55 } 56 sin.a.sin_family = is6; 57 } 58 59 if (ndelay_on(s) == -1) return -1; 60 61 /* XXX: could bind s */ 62 63 if (connect(s,(struct sockaddr *) &sin,ip->is6 ? sizeof(sin.aaaa) : sizeof(sin.a)) == 0) { 64 ndelay_off(s); 65 return 0; 66 } 67 if ((errno != error_inprogress) && (errno != error_wouldblock)) return -1; 68 69 FD_ZERO(&wfds); 70 FD_SET(s,&wfds); 71 tv.tv_sec = timeout; tv.tv_usec = 0; 72 73 if (select(s + 1,NULL,&wfds,NULL,&tv) == -1) return -1; 74 if (FD_ISSET(s,&wfds)) { 75 unsigned int dummy; 76 dummy = sizeof(sin); 77 if (getpeername(s,(struct sockaddr *) &sin,&dummy) == -1) { 78 read(s,&ch,1); 79 return -1; 80 } 81 ndelay_off(s); 82 return 0; 83 } 84 errno = error_timeout; /* note that connect attempt is continuing */ 85 return -1; 86 } 87 88 int timeoutconn(int s, struct ip_address *ip, unsigned int port, int timeout) 89 { 90 return timeoutbindconn(s, ip, NULL, port, timeout); 91 } 92