ref: bb8cb7a3de5aedafea43bfc8160e4099f4c48680
parent: e88aa498b8e09d129583127aa40d6689d37a8f31
author: Timothy B. Terriberry <tterribe@xiph.org>
date: Sun Oct 14 07:31:08 EDT 2012
Fix some socket connection bugs. The big one was that if the connect() call failed, it would loop forever (thanks to some code re-factoring, the loop was no longer advancing to the next address as originally designed).
--- a/src/http.c
+++ b/src/http.c
@@ -1381,6 +1381,7 @@
if(addr==NULL)return OP_FALSE;
if(connect(_fd,addr->ai_addr,addr->ai_addrlen)>=0)return 1;
if(OP_LIKELY(errno==EINPROGRESS))return 0;
+ addr=addr->ai_next;
}
}
@@ -1437,8 +1438,8 @@
if(OP_LIKELY(fds[pi].fd>=0)){
if(OP_LIKELY(op_sock_set_nonblocking(fds[pi].fd,1)>=0)){
ret=op_sock_connect_next(fds[pi].fd,addrs+pi,ai_family);
- if(ret>1){
- /*It succeeded right away, so stop.*/
+ if(OP_UNLIKELY(ret>0)){
+ /*It succeeded right away (technically possible), so stop.*/
nprotos=pi+1;
break;
}
@@ -1462,10 +1463,12 @@
/*Still waiting...*/
if(!fds[pi].revents)continue;
errlen=sizeof(err);
- if(getsockopt(fds[pi].fd,SOL_SOCKET,SO_ERROR,&err,&errlen)>=0&&err==0){
- /*Success!*/
- break;
- }
+ /*Some platforms will return the pending error in &err and return 0.
+ Otherwise will put it in errno and return -1.*/
+ ret=getsockopt(fds[pi].fd,SOL_SOCKET,SO_ERROR,&err,&errlen);
+ if(ret<0)err=errno;
+ /*Success!*/
+ if(err==0||err==EISCONN)break;
/*Move on to the next address for this protocol.*/
ai_family=addrs[pi]->ai_family;
addrs[pi]=addrs[pi]->ai_next;