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; }
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; }
void SetNonblockingIO(PCStr(what),int sock,int on) { int onbio,nnbio; if( sock < 0 ) return; onbio = getNonblockingIO(sock); setNonblockingIO(sock,on); nnbio = getNonblockingIO(sock); if( onbio != nnbio ) syslog_DEBUG("NBIO[%s][%d] %d -> %d\n",what,sock,onbio,nnbio); }
int gunzipFilterX(FILE *in,FILE *out,SyncF syncf,void *sp,int si){ gzFile gz; int rcc; int wcc; int werr; CStr(buf,1024*8); int size; double Start = Time(); const char *em; int en; int ef; int ready; int rd; int eof = 0; int nonblock; int serrno = 0; int ibz = sizeof(buf); int gi; int fd = -1; inlen = 0; errno = 0; fd = dup(fileno(in)); if( isWindows() ){ int pollPipe(int,int); nonblock = 0; ready = fPollIn(in,10*1000); gz = GZdopen(fd,"r"); if( gz == 0 ) syslog_ERROR("##gunzipFilter[%d/%d] gz=%X ready=%d/%d\n", fd,fileno(in),p2i(gz),ready,pollPipe(fd,1)); }else{ /* * to make smooth streaming of data relayed on narrow network * apply NBIO to gzopen() which will do fread() at the start. * applying NBIO also to gzread() seems to break the gzip. */ /* setNonblockingIO(fileno(in),1); */ setNonblockingIO(fd,1); nonblock = 1; ready = fPollIn(in,10*1000); if( ready == 0 ){ fprintf(stderr,"----[%d] gunzipFilter: ready[%d]=%d\n", getpid(),fileno(in),ready); } /* gz = GZdopen(fd = dup(fileno(in)),"r"); */ gz = GZdopen(fd,"r"); if( DGzlibVer == 0 ) { /* setNonblockingIO(fileno(in),0); */ setNonblockingIO(fd,0); nonblock = 0; } } if( syncf != 0 ){ syslog_ERROR("--- gunzipFX SYNC %X(%X,%d)\n",xp2i(syncf),p2i(sp),si); (*syncf)(sp,si); } ibz = 1024; //ibz = 256; size = 0; /* if( gz = GZdopen(dup(fileno(in)),"r") ){ */ if( gz ){ LOGX_gunzip++; setCloseOnFork("GUNZIPstart",fd); em = gzerror(gz,&en); /* while( 0 < (rcc = gzread(gz,buf,sizeof(buf))) ){ */ for( gi = 0;; gi++ ){ if( gotsigTERM("gunzip gi=%d em=%X",gi,p2i(em)) ){ if( numthreads() ){ if( em ){ putfLog("thread-gunzip gi=%d _exit() em=(%s)",gi,em?em:""); _exit(0); } thread_exit(0); } break; } if( nonblock ){ if( 0 < gi ){ /* setNonblockingIO(fileno(in),0); */ setNonblockingIO(fd,0); nonblock = 0; } } /* if( 0 < size && inputReady(fileno(in),NULL) == 0 ){ */ /* if( 0 < size && inputReady(fd,NULL) == 0 ){ */ if( eof == 0 ) if( 0 < size ) if( ready = inputReady(fd,&rd) ){ if( ready == 2 ){ /* both PS_IN and PS_PRI */ eof = 1; } }else{ //fprintf(stderr,"[%d] -- gzread#%d %d / %d FLUSH\n",getpid(),gi,rcc,size); fflush(out); } ready = fPollIn(in,10*1000); errno = 0; rcc = gzread(gz,buf,QVSSize(buf,ibz)); serrno = errno; if( rcc <= 0 ){ break; } //fprintf(stderr,"[%d] -- gzread %d / %d\n",getpid(),rcc,size); wcc = fwrite(buf,1,rcc,out); /* this fflush seems significant */ werr = fflush(out); if( wcc < rcc || werr || ferror(out) || gotSIGPIPE() ){ porting_dbg("+++EPIPE[%d] gunzip fwrite() %d/%d err=%d/%d %d SIG*%d",fileno(out),wcc,rcc,werr,ferror(out),size,gotSIGPIPE()); break; } size += rcc; if( size < sizeof(buf) ){ fflush(out); }else{ ibz = sizeof(buf); } } fflush(out); if( rcc < 0 || size == 0 ){ em = gzerror(gz,&en); ef = gzeof(gz); if( en == -1 /* see errno */ && serrno == 0 ){ /* no error */ }else{ daemonlog("F","FATAL: gzread(%d)=%d/%d eof=%d %d %s %d\n", fd,rcc,size,ef,en,em,serrno); porting_dbg("FATAL: gzread(%d)=%d/%d eof=%d %d %s", fd,rcc,size,ef,en,em); if( lTHREAD() ) fprintf(stderr,"--[%d]gzread(%d)=%d/%d eof=%d %d %s\n", getpid(),fd,rcc,size,ef,en,em); } } clearCloseOnFork("GUNZIPend",fd); GZclose(gz); if( isWindowsCE() || lMULTIST() ){ /* duplicated close of fd is harmful */ }else if( isWindows() ) close(fd); fseek(out,0,0); syslog_DEBUG("(%f)gunzipFilter -> %d\n",Time()-Start,size); if( lTHREAD() ) if( 0 < inlen ) syslog_ERROR("###GUNZIP filter %d/%d\n",inlen,size); return size; } return 0; }
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; }
void notify_ADMINX(Connection *xConn,PCStr(admin),PCStr(what),PCStr(body)) { FILE *tmp; FILE *bt; Connection ConnBuff,*Conn = &ConnBuff; CStr(head,1024); CStr(me,128); CStr(date,128); CStr(load,128); CStr(cwd,1024); CStr(uname,128); int now; const char *bugbox = "*****@*****.**"; CStr(msgid,1024); CStr(buf,1024); if( strncasecmp(what,"sig",3) != 0 ) if( strncasecmp(what,"failed",6) != 0 ) if( strncasecmp(what,"modified",8) != 0 ) if( strncasecmp(what,"approved",8) != 0 ) if( strncasecmp(what,"detected",8) != 0 ) if( strncasecmp(what,"[",1) != 0 ) /* abort in child process */ return; if( admin == NULL || *admin == 0 ) admin = getADMIN1(); now = time(NULL); if( xConn ) *Conn = *xConn; else bzero(Conn,sizeof(Connection)); tmp = TMPFILE("NOTIFY"); head[0] = 0; if( gethostname(me,sizeof(me)) != 0 ) strcpy(me,"?"); sprintf(msgid,"%d.%d.%d@%s",getpid(),itime(0),getuid(),me); StrftimeLocal(AVStr(date),sizeof(date),TIMEFORM_RFC822,now,0); Xsprintf(TVStr(head),"Subject: DeleGate-Report: %s\r\n",what); Xsprintf(TVStr(head),"From: [%d]@%s\r\n",getuid(),me); Xsprintf(TVStr(head),"To: %s (DeleGate ADMIN)\r\n",admin); Xsprintf(TVStr(head),"Reply-To: %s\r\n",bugbox); Xsprintf(TVStr(head),"Date: %s\r\n",date); Xsprintf(TVStr(head),"Message-Id: <%s>\r\n",msgid); Xsprintf(TVStr(head),"Content-Type: text/plain\r\n"); fprintf(tmp,"%s\r\n",head); fprintf(tmp,"PLEASE FORWARD THIS MESSAGE TO <%s>.\r\n",bugbox); fprintf(tmp,"IT WILL BE HELPFUL FOR DEBUGGING.\r\n"); fprintf(tmp,"\r\n"); fprintf(tmp,"%s",head); fprintf(tmp,"Event: %s\r\n",what); Uname(AVStr(uname)); fprintf(tmp,"Version: %s (%s)\r\n",DELEGATE_verdate(),uname); fprintf(tmp,"Host: %s\r\n",me); fprintf(tmp,"Owner: uid=%d/%d, gid=%d/%d\r\n", geteuid(),getuid(),getegid(),getgid()); StrftimeLocal(AVStr(date),sizeof(date),TIMEFORM_RFC822,START_TIME,0); fprintf(tmp,"Started: %s\r\n",date); fprintf(tmp,"Pid: %d\r\n",getpid()); cwd[0] = 0; IGNRETS getcwd(cwd,sizeof(cwd)); fprintf(tmp,"Cwd: %s\r\n",cwd); strfLoadStat(AVStr(load),sizeof(load),"%L (%l)",now); fprintf(tmp,"Load: %s\r\n",load); fprintf(tmp,"Stack: %X %d/%d\r\n",p2i(STACK_PEAK),ll2i(STACK_BASE-STACK_PEAK), STACK_SIZE); fprintf(tmp,"\r\n"); if( iamServer() ) { } else { fprintf(tmp,"Client-Proto: %s\r\n",CLNT_PROTO); fprintf(tmp,"Client-Host: %s:%d\r\n",Client_Addr(buf),Client_Port); if( TeleportHost[0] ) fprintf(tmp,"Rident-Host: %s:%d..%s:%d\r\n",TelesockHost,TelesockPort, TeleportAddr,TeleportPort); fprintf(tmp,"\r\n"); } fprintf(tmp,"%s\r\n",body); /* if( strncasecmp(what,"sig",3) == 0 || *what == '[' ){ */ if( strncasecmp(what,"sig",3) == 0 || strncasecmp(what,"failed",6) == 0 || *what == '[' ) { fprintf(tmp,"--iLog--begin\r\n"); iLOGdump1(tmp,0); fprintf(tmp,"--iLog--end\r\n"); fprintf(tmp,"\r\n"); fprintf(tmp,"--AbortLog--begin\r\n"); putAbortLog(tmp); fprintf(tmp,"--AbortLog--end\r\n"); } if( strncasecmp(what,"sig",3) == 0 ) { int btout[2]; double Start = Time(); int rcc; fprintf(tmp,"\r\n"); fprintf(tmp,"--BackTrace--begin\r\n"); fflush(tmp); if( pipe(btout) == 0 ) { setNonblockingIO(btout[1],1); bt = fdopen(btout[1],"w"); putBackTrace(bt); fclose(bt); bt = fdopen(btout[0],"r"); rcc = file_copyTimeout(bt,tmp,NULL,128*1024,NULL,15); fclose(bt); sv1log("BatckTrace: %dB / %.1fs\n",rcc,Time()-Start); } else { bt = TMPFILE("BackTrace"); putBackTrace(bt); fseek(bt,0,0); copyfile1(bt,tmp); fclose(bt); } fprintf(tmp,"\r\n"); fprintf(tmp,"--BackTrace--end\r\n"); } fflush(tmp); fseek(tmp,0,0); if( curLogFp() ) { CStr(line,1024); while( fgets(line,sizeof(line),tmp) != NULL ) fprintf(curLogFp(),"--ABORT-- %s",line); fseek(tmp,0,0); } Conn->co_mask = (CONN_NOPROXY | CONN_NOMASTER); sendmail1(Conn,admin,admin,tmp,NULL); fclose(tmp); }