Socket::Socket(const Socket &orig) : ucommon::Socket() { setSocket(); so = dupSocket(orig.so,orig.state); if(so == INVALID_SOCKET) error(errCopyFailed,(char *)"Could not duplicate socket handle",socket_errno); state = orig.state; }
int connectTOX(int sock,SAP addr,int leng,int timeout,PVStr(cstat)) { int rcode; int ri; double Start = Time(); int delay; int poolN; /* 9.8.2 trial to avoid too slow connect() ... */ /* int expsockbuf(int sock,int in,int out); int set_keepalive(int sock,int on); void setsockREUSE(int sock,int onoff); int setsockSHARE(int sock,int onoff); if( isWindowsCE() ){ set_keepalive(sock,1); //expsockbuf(sock,8*1024,8*1024); setsockREUSE(sock,1); setsockSHARE(sock,1); } */ poolN = sockPoolN; LOGX_tcpCon++; rcode = connectTO1(sock,addr,leng,timeout,BVStr(cstat)); if( rcode == 0 ){ LOGX_tcpConSuccess++; delay = (int)((Time()-Start)*1000); LOGX_tcpConDelays += delay; if( LOGX_tcpConDelayMax < delay ) LOGX_tcpConDelayMax = delay; if( lCONNQUE() ) if( sockPoolN <= poolN ) { int nsock,nrcode; nsock = dupSocket(sock); setNonblockingIO(nsock,1); nrcode = connect(nsock,addr,leng); setNonblockingIO(nsock,0); putConnSocket(sock,nsock,addr,leng,"queued",nrcode); } } if( rcode != 0 ){ switch( errno ){ case ECONNREFUSED: case EFAULT: /* should be the default */ break; case EHOSTUNREACH: case ENETUNREACH: default: rcode = dialup(sock,addr,leng,timeout,BVStr(cstat),rcode); break; } } return rcode; }
Socket &Socket::operator=(const Socket &from) { if(so == from.so) return *this; if(state != INITIAL) endSocket(); so = dupSocket(from.so,from.state); if(so == INVALID_SOCKET) { error(errCopyFailed,(char *)"Could not duplicate socket handle",socket_errno); state = INITIAL; } else state = from.state; return *this; }
static int dialup(int sock,SAP addr,int leng,int timeout,PVStr(cstat),int rcode){ int serrno = errno; int ccode; int nrcode; int nerrno; int nsock; int ri; if( !isWindowsCE() ){ return -1; } nsock = dupSocket(sock); ccode = dialupTOX("CONNECT",sock,addr,leng,timeout,BVStr(cstat)); if( 0 ){ // no dialup goto EXIT; } setNonblockingIO(nsock,1); for( ri = 0; ri < 10; ri++ ){ nrcode = connect(nsock,addr,leng); if( errno == EISCONN ){ nrcode = 0; serrno = 0; rcode = 0; break; } if( nrcode == 0 ) break; nerrno = errno; msleep(500); } setNonblockingIO(nsock,0); if( nrcode == 0 ){ dup2(nsock,sock); serrno = nerrno; rcode = 0; } EXIT: close(nsock); errno = serrno; return rcode; }
int connectTO1(int sock,SAP addr,int leng,int timeout,PVStr(cstat)) { int NB; int rcode; int nready; int serrno; double Start = Time(); int csock; int pending = 0; if( 0 <= getConnSocket(sock,addr,leng,&csock,&pending) ){ dup2(csock,sock); close(csock); LOGX_tcpConPrefOk++; sprintf(cstat,"Prf"); return 0; } if( timeout == 0 ) { rcode = connect(sock,addr,leng); if( rcode != 0 ){ switch( errno ){ case ECONNREFUSED: case ENETUNREACH: case EHOSTUNREACH: LOGX_tcpConRefused++; break; default: LOGX_tcpConTimeout++; break; } } return rcode; } NB = getNonblockingIO(sock); if( NB < 0 ){ syslog_ERROR("connectTO: assume in non-blocking mode\n"); NB = 0; } if( !NB ) rcode = setNonblockingIO(sock,1); errno = 0; rcode = connect(sock,addr,leng); serrno = errno; if( rcode == 0 ){ if( !NB ) setNonblockingIO(sock,0); return 0; } if( errno == EISCONN ){ if( !NB ) setNonblockingIO(sock,0); return 0; } switch( errno ){ case ECONNREFUSED: case ENETUNREACH: case EHOSTUNREACH: syslog_ERROR("## connect[%d] refused (%d)\n",sock,errno); LOGX_tcpConRefused++; return -1; } nready = 0; if( lCONNPARA() && 0 < SLOW_CONN && SLOW_CONN < timeout ){ /* should poll pending connect() too ... */ if( pending ){ } nready = PollOut(sock,SLOW_CONN); if( nready == 0 ){ if( pending && 0 <= getConnSocket(sock,addr,leng,&csock,&pending) ){ putConnSocket(sock,dup(sock),addr,leng,"pending",rcode); dup2(csock,sock); close(csock); LOGX_tcpConParaOk++; sprintf(cstat,"Pnd"); }else if( PCON_PERSERV < pending ){ /* don't make too many pending connect() to a server */ }else{ int nsock; nsock = dupSocket(sock); if( 0 <= nsock ){ int rdv[2]; if( !NB ) setNonblockingIO(nsock,1); errno = 0; rcode = connect(nsock,addr,leng); LOGX_tcpConParaTried++; if( rcode == 0 ){ nready = 9; }else{ int skv[2]; skv[0] = sock; skv[1] = nsock; nready = PollOuts(timeout-SLOW_CONN,2,skv,rdv); timeout = 1; } if( nready == 9 || 0 < nready && rdv[0] == 0 && 0 < rdv[1] ){ putConnSocket(sock,dup(sock),addr,leng,"overtook",rcode); dup2(nsock,sock); close(nsock); LOGX_tcpConParaOk++; sprintf(cstat,"Ovr"); porting_dbg("## para.conn.%d %d/%d+%d %.2f %d", nready, LOGX_tcpConParaOk,LOGX_tcpConParaTried, LOGX_tcpConSuccess,Time()-Start,errno); }else{ putConnSocket(nsock,nsock,addr,leng,"unused",rcode); } } } } } if( !NB ) setNonblockingIO(sock,0); if( nready == 0 ){ nready = PollOut(sock,timeout); } /* 9.8.0 get appropriate errno by SO_ERROR in non-blocking connect */ /* if( serrno == EINPROGRESS ){ */ if( serrno == EINPROGRESS || serrno == EWOULDBLOCK /* 9.8.2 Windows returns this */ ){ int err = 0; int len = sizeof(err); if( getsockopt(sock,SOL_SOCKET,SO_ERROR,&err,&len) == 0 ){ syslog_DEBUG("connect[%d] ready=%d, err=%d\n", sock,nready,err); if( err != 0 ) if( err != ECONNREFUSED ) porting_dbg("[%X][%u] connectTO rdy=%d err=%d/%d/%d GOT %d/%d %s %.2f/%d", TID,getppid(),nready,serrno,EWOULDBLOCK,EINPROGRESS,err,len, VSA_ntoa((VSAddr*)addr),Time()-Start,timeout); switch( err ){ case ECONNREFUSED: case ENETUNREACH: case EHOSTUNREACH: errno = err; LOGX_tcpConRefused++; return -1; } } else{ /* fprintf(stderr,"-- %X connectTO rdy=%d err=%d/%d/%d NG errno=%d\n", TID,nready,serrno,EWOULDBLOCK,EINPROGRESS,errno); */ } } if( nready <= 0 ){ if( *cstat == '-' ){ /* ( ConnectFlags & COF_TERSE ) */ }else syslog_ERROR("## connect[%d] TIMEOUT(%d) e%d\n",sock,timeout,serrno); errno = ETIMEDOUT; LOGX_tcpConTimeout++; return -1; } if( !sock_isconnected(sock) ){ msleep(10); if( !sock_isconnected(sock) ){ syslog_ERROR("## connect[%d] failure (%d)\n",sock,errno); errno = ETIMEDOUT; LOGX_tcpConTimeout++; return -1; } else{ syslog_ERROR("## connect[%d] delayed success\n",sock); } } return 0; }