Ejemplo n.º 1
0
// 为删除录像而停止录像服务
void RecordStopServiceForDel()
{
	int chNum = REAL_CHANNEL_NUM;
	int i;
	rec_manage.recordManageRunFlag = 0;    
	if(0 != ThreadJoin(rec_manage.recordManageId,NULL))
    {
    	SVPrint("error:ThreadJoin(rec_manage.recordManageId,NULL)\r\n");
    }

	for(i=0;i<chNum;i++)
    {
    	if(REC_SLEEP != GetRecordCtlFlag(i))
        {
        	SetRecordCtlFlag( i, REC_STOP );
        	RecordPoolSignal( i );
        }
    }
    
	for(i=0;i<chNum;i++)
    {
    	while(REC_SLEEP != GetRecordCtlFlag(i))
        {
        	Usleep(50);
        }
    }
    
	sync();    
}
Ejemplo n.º 2
0
/*
 * Initialize.
 */
bool BQ24250_drv_init(ARM_DRIVER_I2C *i2c_drv, bool ts_enable)
{
    tz10xx_drv_i2c = i2c_drv;
    
    if (tz10xx_drv_i2c->Initialize(NULL) != ARM_I2C_OK) {
        return false;
    }
    
    if (tz10xx_drv_i2c->PowerControl(ARM_POWER_FULL) != ARM_I2C_OK) {
        return false;
    }
    
    if (tz10xx_drv_i2c->BusSpeed(ARM_I2C_BUS_SPEED_STANDARD) != ARM_I2C_OK) {
        return false;
    }
    
    if (bq24250_drv_reset() == false) {
        return false;
    }
   
    if (ts_enable == false) {
        Usleep(200000);
        /* TS Disable */
        if (BQ24250_drv_reg06_set(BQ24250_DEF_06) == false) {
            return false;
        }
    }
    
    return true;
}
/** System **/
bool TZ01_system_init(void)
{
#if TZ01_POW_MGR
    Usleep(TZ01_SYSTEM_PW_HLD_DELAY);
#endif
    /* PMU */
    tz10xx_drv_pmu->Initialize(NULL);
    tz10xx_drv_pmu->SelectClockSource(PMU_CSM_MAIN, PMU_CLOCK_SOURCE_PLL);
    tz10xx_drv_pmu->SetPrescaler(PMU_CD_MPIER, 1);	/* 48MHz */
    tz10xx_drv_pmu->SetPrescaler(PMU_CD_PPIER0, 4);	/* 12MHz */
    tz10xx_drv_pmu->SetPrescaler(PMU_CD_PPIER1, 4);	/* 12MHz */
    tz10xx_drv_pmu->SetPrescaler(PMU_CD_PPIER2, 4);	/* 12MHz */
#if TZ01_POW_MGR
    tz10xx_drv_pmu->StandbyInputBuffer(PMU_IO_FUNC_GPIO_1, 0);   /* Power Switch */
    tz10xx_drv_pmu->StandbyInputBuffer(PMU_IO_FUNC_GPIO_4, 0);   /* UVdetect */
#endif
    /* GPIO */
    tz10xx_drv_gpio->Initialize();
    tz10xx_drv_gpio->PowerControl(ARM_POWER_FULL);
    /** DO **/
    tz10xx_drv_gpio->Configure(TZ01_SYSTEM_PWSW_PORT_LED, GPIO_DIRECTION_OUTPUT_2MA, GPIO_EVENT_DISABLE, NULL);  /* Power LED  */
#if TZ01_POW_MGR
    tz10xx_drv_gpio->Configure(TZ01_SYSTEM_PWSW_PORT_HLD, GPIO_DIRECTION_OUTPUT_2MA, GPIO_EVENT_DISABLE, NULL);  /* Power Hold */
#endif
    /** DI **/
#if TZ01_POW_MGR
    tz10xx_drv_gpio->Configure(TZ01_SYSTEM_PWSW_PORT_SW,  GPIO_DIRECTION_INPUT_HI_Z, GPIO_EVENT_DISABLE, NULL);  /* Power Switch */
    tz10xx_drv_gpio->Configure(TZ01_SYSTEM_PWSW_PORT_UVD, GPIO_DIRECTION_INPUT_HI_Z, GPIO_EVENT_DISABLE, NULL);  /* UVdetect */
#endif
    /* TMR */
    if (tz10xx_drv_tmr->Initialize(NULL, 0) == TMR_OK) {
        tz10xx_drv_tmr->Configure(32, TMR_COUNT_MODE_FREE_RUN, 1);
    }
    if (tz10xx_drv_tmr->IsRunning() == false) {
        tz10xx_drv_tmr->PowerControl(ARM_POWER_FULL);
        if (tz10xx_drv_tmr->Start(0xfffffffe) == TMR_ERROR) {
            return false;
        }
    }
#if TZ01_POW_MGR
    /* Power On */
    if (tz01_system_pwsw_powon() == false) {
        return false;
    }
#endif
    /* SW check timer enable. */
    TZ01_system_tick_start(SYSTICK_NO_PWSW_CHECK, 0);
    TZ01_system_tick_start(SYSTICK_NO_LED_BLINK, 500);

    return true;
}
Ejemplo n.º 4
0
/**********************************************************
* 停止录像模块的所有线程
***********************************************************/
void FiRecStopRecordService(void)
{
	int chNum = REAL_CHANNEL_NUM;
	int i;    
    
	rec_manage.recordManageRunFlag = 0;    
	if(0 != ThreadJoin(rec_manage.recordManageId,NULL))
    {
    	SVPrint("error:ThreadJoin(rec_manage.recordManageId,NULL)\r\n");
    }

	for(i=0;i<chNum;i++)
    {
    	if(REC_SLEEP != GetRecordCtlFlag(i))
        {
        	SetRecordCtlFlag(i,REC_STOP);            
        	RecordPoolSignal( i );
        }
    }
	for( i=0; i<chNum; i++ )
    {
    	while(REC_SLEEP != GetRecordCtlFlag(i))
        {
        	Usleep(50);
        }
    }
    
	for( i=0; i<chNum; i++ )
    {
    	rec_thread[i].recordThreadRunFlag = 0;            
    }
    
	for( i=0; i<chNum; i++ )
    {
    	if( 0 != ThreadJoin( rec_thread[i].recordThreadId, NULL) )
        {
        	SVPrint("ThreadJoin(rec_thread[%d].recordThreadId,NULL)\r\n",i);
        }
    }
    
	StopRecordGetH264Thread();
	FiRecDelRecordInit();
	return;
}
Ejemplo n.º 5
0
static void *WriteRecordFileThread(void *arg)
{
	static unsigned int stopCount = 0;
	PCP_NODE_T *pRecPcp = NULL;
	int channel = (int)arg;
	time_t utc = 0;
	uint recordType = 0;
	uint writeSize = 0;
	uchar frameType = 0;
	RECORD_THREAD *p_rec = NULL;
	int recordCtlFlag = REC_SLEEP;
	int ret = 0;
    
	SVPrint("ch(%d) WriteRecordFileThread:%d!\r\n",channel,ThreadSelf());
	p_rec = &rec_thread[channel];
	while(p_rec->recordThreadRunFlag) 
    {    
    	recordCtlFlag = GetRecordCtlFlag(channel);
                    
    	switch(recordCtlFlag)
        {
        	case REC_START:    
            	stopCount = 0;
            	recordType = 0;
            	CloseRecLed(channel);
            	StartH264Stream(channel);
            	pRecPcp = RecordPoolRead( channel );
            	if( NULL == pRecPcp )
                {
                	RecordPoolWait( channel );
                }
            	else
                {
                	AnalysisFrameData( channel, pRecPcp, &utc, &recordType, 
                                                    &writeSize, &frameType );

                	FiPrint2( "wait I frame,frameType(%d)!\r\n",
                            	pRecPcp->pcpHead.type);
                	if( FI_FRAME_TYPE_VIDEO_I != pRecPcp->pcpHead.type )
                    {
                    	FiPrint2( "start record but no I frame(%d)!\r\n",
                                        	pRecPcp->pcpHead.type);
                    	RecordPoolFree( pRecPcp );
                    	continue;
                    }    
                	ret = CreateRecordAndIndexFile( channel, utc );
                	if(FI_SUCCESS == ret)
                    {
                    	ResetIndexStruct( channel );
                    	ret = WriteDataToDisk( channel, pRecPcp, writeSize, recordType, utc );
                    	if(FI_SUCCESS == ret)
                        {
                        	SetRecordCtlFlag( channel, REC_WRITE );
                        	OpenRecLed( channel );
                        }    
                    }
                	RecordPoolFree( pRecPcp );                    
                	if(FI_SUCCESS != ret)
                    {
                    	sleep(1);
                    }    
                }
            	break;
        	case REC_WRITE:    
            	RecordPoolWait( channel );
            	while( 1 )
                {
                	if( NULL == (pRecPcp=RecordPoolRead(channel)) )
                    {
                    	break;
                    }                    
                	AnalysisFrameData( channel, pRecPcp, &utc, &recordType, 
                                                    &writeSize, &frameType );
                	ret = WriteDataToDisk( channel, pRecPcp, writeSize, recordType, utc );
                	if( FI_SUCCESS != ret )
                    {
                    	SetRecordCtlFlag( channel, REC_START );
                    }
                	RecordPoolFree( pRecPcp );
                }                
            	break;
        	case REC_SWITCH:
            	stopCount = 0;
            	RecordPoolWait( channel );
            	while( 1 )
                {
                	if( NULL == (pRecPcp=RecordPoolRead(channel)) )
                    {
                    	break;
                    }
                	AnalysisFrameData( channel, pRecPcp, &utc, &recordType,
                                                &writeSize, &frameType );
                    
                	if( FI_FRAME_TYPE_VIDEO_I != pRecPcp->pcpHead.type )
                    {
                    	ret = WriteDataToDisk( channel, pRecPcp, writeSize, recordType, utc );
                    	if( FI_SUCCESS != ret )
                        {
                        	SetRecordCtlFlag( channel, REC_START );
                        }
                    }
                	else 
                    {    
                    	CloseRecordAndIndexFile( channel );
                    	utc = time( NULL );
                    	ret = CreateRecordAndIndexFile( channel, utc );                        
                    	if( FI_SUCCESS == ret )
                        {
                        	ResetIndexStruct( channel );
                        	ret = WriteDataToDisk( channel, pRecPcp, 
                                    	writeSize, recordType, utc );
                        	if( FI_SUCCESS == ret )
                            {
                            	SetRecordCtlFlag( channel, REC_WRITE );
                            }                            
                        }
                    	else //if(FI_SUCCESS != ret)
                        {
                        	SetRecordCtlFlag( channel, REC_START );
                        	Usleep(1000);
                        }    
                    }    
                	RecordPoolFree( pRecPcp );
                }                
            	break;
        	case REC_STOP:
            	while( 1 )
                {
                	pRecPcp = RecordPoolRead( channel );
                	SVPrint( "ql debug -ch(%d), pRecPcp(0x%X), stopCount(%u)!\r\n",
                        	channel, pRecPcp, stopCount );
                	if( NULL == pRecPcp ||
                        ++stopCount >= (MAX_RECORD_DATA_NODE << 1) )
                    {
                    	break; // while( 1 )
                    }
                	AnalysisFrameData( channel, pRecPcp, &utc, &recordType, 
                                                &writeSize, &frameType );
                	ret = WriteDataToDisk( channel, pRecPcp, writeSize, recordType, utc );
                	RecordPoolFree( pRecPcp );
                	if( FI_SUCCESS != ret )
                    {
                    	break; // while( 1 )
                    }                        
                }                
                
            	CloseRecordAndIndexFile( channel );
            	SetRecordCtlFlag( channel, REC_SLEEP );
            	CloseH264Stream( channel );
            	CloseRecLed( channel );
            	break;
        	case REC_SLEEP:
        	default:
            	Usleep( 500000 );
            	break;
        } //switch	        
    }    //while(1)    
	SVPrint("quit ch(%d) WriteRecordFileThread!\r\n",channel);
	return NULL;
}
Ejemplo n.º 6
0
/*********************************************************
  录像监视线程,该线程与系统时间有关,
  请在启动应用线程后再启动该线程
  并在启动此次线程再启动录像线程
***********************************************************/
static void *ManageRecordThread(void *arg)
{
	int chNum = REAL_CHANNEL_NUM;
	int i,j;
	int real_time[chNum];
	int base_time[REAL_CHANNEL_NUM] = {-1};
	int real_year[chNum],real_month[chNum],real_day[chNum];
	int base_year[chNum],base_month[chNum],base_day[chNum];
	uint base_rec_type[REAL_CHANNEL_NUM];
	uint real_rec_type[REAL_CHANNEL_NUM];    
	int alarm_real_time[REAL_CHANNEL_NUM];
	int alarm_base_time[REAL_CHANNEL_NUM];    
	char real_parh[RECORD_FILENAME_LEN] = {0};
	char base_path[RECORD_FILENAME_LEN] = {0};

	SVPrint("start ManageRecordThread:%d!\r\n",ThreadSelf());
    
	while(rec_manage.recordManageRunFlag)
    {
    	FiRecStartAutoDelOldFile();
        /*录像分区改变切换文件,优先级最高*/
    	if(FI_FAIL == FiHddGetUsingPartition(real_parh))
        {
        	for(i=0;i<chNum;i++)
            {
            	if(REC_SLEEP != GetRecordCtlFlag(i))
                	SetRecordCtlFlag(i,REC_STOP);
            }
        	sleep(1);
        	continue;
        }
    	else
        {
        	if(0 != strcmp(base_path,real_parh))
            {
            	strcpy(base_path,real_parh);
            	for(i=0;i<chNum;i++)
                {
                	if(REC_WRITE == GetRecordCtlFlag(i))
                    {
                    	SVPrint("record switch partition.\r\n");    
                    	RefrechAlarmBaseTimeCursor(i);
                    	RefrechTimerBaseTimeCursor(&real_time[i],&real_year[i],&real_month[i],&real_day[i],
                                        &base_time[i],&base_year[i],&base_month[i],&base_day[i]);
                    	SetRecordCtlFlag(i,REC_SWITCH);    //仅仅录像分区,不做任何时间检测
                    }
                }
            }
        }
        
    	if(-1 == manage_init_flag)
        {            
            
        	for(j=0;j<chNum;j++)
            {
                /*初始化定时录像监测*/
            	real_time[j] = time(NULL);
            	base_time[j] = real_time[j];
            	FiTimeUtcToHuman(base_time[j],&base_year[j],&base_month[j],&base_day[j],NULL,NULL,NULL);

                /*初始化录像类型切换监测*/            
            	real_rec_type[j] = GetRecordType(j);
            	base_rec_type[j] = real_rec_type[j];

            	RefrechAlarmBaseTimeCursor(j);
            	alarm_real_time[j] = SysRunTimeGet();
            }
            
        	manage_init_flag = 0;
        }        
        
        /*监测手动和定时录像*/
    	for(i=0;i<chNum;i++)
        {
        	ManageHandRecord(i);
        	ManageTimerRecordTime(i);            
        }
        
        /*定时录像切文件*/
    	for(i=0;i<chNum;i++)
        {            
        	real_time[i] = time(NULL);
        	FiTimeUtcToHuman(real_time[i],&real_year[i],&real_month[i],&real_day[i],NULL,NULL,NULL);
        	if(( real_time[i] - base_time[i] >= FiRecGetRecFileSwitchTime() ) || 
                (real_time[i] - base_time[i] < 0 && base_time[i] - real_time[i] > RECORD_TIME_ERROR_RANGE)    || 
                (real_year[i] != base_year[i]) || (real_month[i] != base_month[i]) || (real_day[i] != base_day[i]))
            {
            	SVPrint("ch(%d),%d-%d=%d\r\n",i,real_time[i],base_time[i],real_time[i]-base_time[i]);    
            	RefrechAlarmBaseTimeCursor(i);
            	RefrechTimerBaseTimeCursor(&real_time[i],&real_year[i],&real_month[i],&real_day[i],
                                    &base_time[i],&base_year[i],&base_month[i],&base_day[i]);
            	if(REC_WRITE == GetRecordCtlFlag(i))
                {                        
                	SetRecordCtlFlag(i,REC_SWITCH);                    
                }    
            }
        } 
        /*报警录像情况的录像类型改变从而切换文件*/
    	for(i=0;i<chNum;i++)
        {
        	real_rec_type[i] = GetRecordType(i);            
        	if(real_rec_type[i] & RECORD_TYPE_ALARM_ALL)
            {                
            	alarm_base_time[i] = getAlarmBaseTimeCursor(i);
            	alarm_real_time[i] = SysRunTimeGet();
            	if( alarm_real_time[i] - alarm_base_time[i] >= FiRecGetRecFileSwitchTimeAlarm() )
                {
                	SVPrint("%d-%d=%d\r\n",alarm_real_time[i] , alarm_base_time[i],alarm_real_time[i] - alarm_base_time[i]);
                	FiRecStopRecord(i,RECORD_TYPE_ALARM_ALL);
                	RefrechAlarmBaseTimeCursor(i);                        
                	RefrechTimerBaseTimeCursor(&real_time[i],&real_year[i],&real_month[i],&real_day[i],
                                    &base_time[i],&base_year[i],&base_month[i],&base_day[i]);                
                	if(real_rec_type[i] & (RECORD_TYPE_ALL&(~RECORD_TYPE_ALARM_ALL)))                    
                    {
                    	SetRecordCtlFlag(i,REC_SWITCH);                            
                    }    
                }
            }            
        }	

        /* 控制录像线程启动录像 ,是否启动录像*/
    	for(i=0;i<chNum;i++)
        {
        	real_rec_type[i] = GetRecordType(i);
        	if(real_rec_type[i] & RECORD_TYPE_ALL)
            {
            	if(FI_TRUE == ControlRecordThreadStartRecord(i))
                {
                	RefrechAlarmBaseTimeCursor(i);                        
                	RefrechTimerBaseTimeCursor(&real_time[i],&real_year[i],&real_month[i],&real_day[i],
                                    &base_time[i],&base_year[i],&base_month[i],&base_day[i]);
                }
            }
        	else
            {
            	ControlRecordThreadStopRecord(i);
            }
        }    
        
    	Usleep(500000); //500ms
    }    //while(rec_manage.recordManageRunFlag)
    
	SVPrint("quit ManageRecordThread!\r\n");
    
	return NULL;
}
Ejemplo n.º 7
0
int relaysxX(RelayCtrl *relayCtrl,int timeout,int sdc,int sdv[][2],int sdx[],int rccs[],IFUNCP funcv[],void *argv[])
{	int fi;
	int pc,pi,pfv[32],pxv[32];
	int fds[32],errv[32],rfds[32];
	int isreg[32];
	int wccs[32];
	int sdxb[32];
	int cntv[32];
	int rcode,rcc,wcc;
	IFUNCP funcvb[32];
	void *argvb[32];
	int nready;
	double Lastin[32],Now,Timeout,Idlest,Time();
	double Start;
	int timeouti;
	int prepi;
	int fj;
	int dobreak;
	int packs;
	relayCB cb;
	int otimeout = timeout;

	RELAY_stat = 0;
	if( SILENCE_TIMEOUT )
	syslog_ERROR("relays(%d) start: TIMEOUT=io:%ds,silence:%ds\n",
		sdc,timeout/1000,SILENCE_TIMEOUT);
	else
	syslog_ERROR("relays(%d) start: timeout=%dmsec\n",sdc,timeout);
	if( lMULTIST()){
		if( RELAY_threads_timeout ){
			syslog_ERROR("relays thread (%d/%d) timeout=%d <= %d\n",
				actthreads(),numthreads(),
				RELAY_threads_timeout,timeout/1000);
			timeout = RELAY_threads_timeout * 1000;
		}
	}

	if( funcv == NULL ){
		funcv = funcvb;
		for( fi = 0; fi < sdc; fi++ )
			funcv[fi] = NULL;
	}
	if( argv == NULL ){
		argv = argvb;
		for( fi = 0; fi < sdc; fi++ )
			argv[fi] = NULL;
	}

	Now = Time();
	Start = Now;
	for( fi = 0; fi < sdc; fi++ ){
/*
sv1log("#### NODELAY\n");
set_nodelay(sdv[fi][1],1);
*/
		fds[fi] = sdv[fi][0];
		isreg[fi] = file_isreg(fds[fi]);
		errv[fi] = 0;
		rccs[fi] = 0;
		cntv[fi] = 0;
		wccs[fi] = 0;
		Lastin[fi] = Now;
		if( funcv[fi] == NULL )
			funcv[fi] = (IFUNCP)relay1;

/*
fcntl(fds[fi],F_SETOWN,getpid());
signal(SIGURG,sigURG);
*/

		if( sdx == NULL ){
			sdxb[fi] = 0;
			if( RELAYS_IGNEOF ){
				if( file_issock(sdv[fi][0]) < 0 )
					sdxb[fi] |= IGN_EOF;
			}
		}
	}
	if( sdx == NULL )
		sdx = sdxb;

	RELAY_num_turns = 0;
	dobreak = 0;
	prepi = -1;
	packs = 0;
	for(;;){
	    pc = 0;
	    Idlest = Now = Time();
	    for( fi = 0; fi < sdc; fi++ ){
		if( errv[fi] == 0 ){
			pfv[pc] = fds[fi];
			pxv[pc] = fi;
			pc++;
		}
		if( Lastin[fi] < Idlest ){
			Idlest = Lastin[fi];
		}
	    }
	    if( pc == 0 )
		break;

	    if( lSINGLEP() ){
		int nith;
		/* with no idle threads ... and ready to accept()? */
		/* 9.9.7 this restriction became less necessary with http-sp */
		if( lMULTIST() && RELAY_threads_timeout ){
			/* 9.9.8 for CONNECT/yyshd */
		}else
		if( (nith = idlethreads()) < 3 ){
			int ntimeout = (10+nith*2)*1000;
			nready = PollIns(1,pc,pfv,rfds);
			if( nready == 0 )
			if( ntimeout < timeout ){
				syslog_ERROR("shorten timeout %.2f <= %.2f (%d/%d)\n",
					ntimeout/1000.0,timeout/1000.0,
					nith,actthreads());
				timeout = ntimeout;
			}
		}
	    }

	    errno = 0;

	    if( RELAY_idle_cb ){
		int cbtime;

		nready = PollIns(1,pc,pfv,rfds);
		if( nready )
			goto POLLED;

		if( cb = RELAY_idle_cb ){
			cbtime = (*cb)(relayCtrl,Now-Start,RELAY_num_turns);
		    if( cbtime <= 0 ){
			nready = 0;
			syslog_ERROR("## relaysx: idle_cb timeout %d/%.2f %X\n",
				cbtime,Now-Start,xp2i(RELAY_idle_cb));
		    }else{
			if( timeout < cbtime )
				cbtime = timeout;
			nready = PollIns(cbtime,pc,pfv,rfds);
			if( nready ){
				goto POLLED;
			}
		    }
			if( cb = RELAY_idle_cb ){
				Now = Time();
				(*cb)(relayCtrl,Now-Start,RELAY_num_turns);
			}
		}
	    	errno = 0;
	    }
	    if( SILENCE_TIMEOUT ){
		timeouti = (int)(1000*(SILENCE_TIMEOUT - (Now-Idlest)));
		if( timeouti <= 0 )
			break;
		if( timeouti <= timeout ){
			nready = PollIns(timeouti,pc,pfv,rfds);
			goto POLLED;
		}
	    }
if(0)
	    if( dobreak ){
		/* shorten the timeout of the connection to be broken */
		timeouti = 1000*2;
		if( timeouti <= timeout ){
			syslog_ERROR("## EXIT relaysx: shorten timeout %d\n",
				timeouti);
			nready = PollIns(timeouti,pc,pfv,rfds);
			goto POLLED;
		}
	    }

	    if( 0 <= RELAY_getxfd() ){
		int elp,rem,to1;
		elp = 0;
		rem = timeout;
		for( rem = timeout; 0 < rem; rem -= to1 ){
			if( 200 < rem )
				to1 = 200;
			else	to1 = rem;
	    		nready = PollIns(to1,pc,pfv,rfds);
			if( nready ){
				break;
			}
			if( inputReady(RELAY_getxfd(),0) ){
				if( lCONNECT() )
		fprintf(stderr,"--{c} relaysx: xfd ready: %d/%d/%d/%d\n",
					to1,rem,elp,timeout);
				if( 400 < rem ){
					rem = 400;
				}
			}
			elp += to1;
	    	}
	    }else
	    nready = PollIns(timeout,pc,pfv,rfds);
	/*
should ignore EINTR, by SIGSTOP/SIGCONT
	    if( nready < 0 && errno == EINTR ){
		continue;
	    }
	*/
POLLED:
/*
	    if( nready == 0 && errno == 0 ){
*/
	    if( nready == 0 && errno == 0 || gotOOB(-1) ){
		int fi,sync;
		int oob = 0;

if(nready==0)
syslog_ERROR("-- relaysx: pc=%d nready==0 errno==%d OOB=%d (%.2f)\n",pc,errno,
	gotOOB(-1),Time()-Idlest);

		if( nready == 0 && errno == 0 ){
			syslog_ERROR("relaysx: TIMEOUT=io:%.2f (%.2f)\n",
				timeout/1000.0,Time()-Start);
		}

		sync = 0;
		for( fi = 0; fi < sdc; fi++ )
		{
			if( !isreg[fi] )
			if( withOOB(sdv[fi][0]) )
			{
			oob++;
			sync += relayOOB(sdv[fi][0],sdv[fi][1]);
				if( sync == 0 && isWindowsCE() ){
					/* 9.9.7 no-OOB on WinCE */
					int ifd,alv;
					ifd = sdv[fi][0];
					alv = IsAlive(ifd);
 syslog_ERROR("non-OOB [%d] alive=%d, rdy=%d,err=%d\n",ifd,alv,nready,errno);
					goto RELAYS; /* to detect EOF */
				}
			}
		}
		if( oob ){
		if( sync )
			continue;

		Usleep(1);
		nready = PollIns(1,pc,pfv,rfds);
		if( 0 < nready ){
			syslog_ERROR("## tcprelay: ignore OOB? rdy=%d/%d,oob=%d\n",nready,pc,oob);
			if( 1 ){
			    /* 9.9.7 break loop on shutdown socket (FreeBSD8) */
			    for( fi = 0; fi < sdc; fi++ ){
				int ifd = sdv[fi][0];
				if( !isreg[fi] && !IsAlive(ifd) ){
 syslog_ERROR("non-OOB [%d] Not-alive, rdy=%d,err=%d\n",ifd,nready,errno);
					goto RELAYS;
				}
			    }
			}
			continue;
		}
		}
	    }
	RELAYS:
	    if( nready <= 0 )
		break;

	    if( RELAY_half_dup ){
		if( 0 < RELAY_max_paras || 1 < RELAY_concat ){
			/* be tolerant about non-half-dup */
		}else
		/* to more strictly checking non-half_dup */
		if( nready < pc ){
			Usleep(1000);
			nready = PollIns(1,pc,pfv,rfds);
		}
		if( nready == pc ){
			if( 2 <= pc && toBeBroken(relayCtrl,pc,pfv) ){
				/*
			syslog_ERROR("## EXIT relaysx: not half_duplex\n");
			RELAY_stat = RELAY_NOTHALFDUP;
			goto EXIT;
				*/

		fj = pxv[0<prepi?prepi:0];
		syslog_ERROR("## EXIT relaysx: not half_duplex %d[%d] %d/%d\n",
			RELAY_num_turns,fj,rccs[fj],cntv[fj]);

				dobreak = 3;
			}
		}
	    }
	    for( pi = 0; pi < pc; pi++ ){
		if( 0 < rfds[pi] ){
			int pushed;
			int nx = 0;
			int tl = 0;
		RELAY1:
			if( RELAY_half_dup && nready == pc ){
				if( pi != prepi ){
					/* postpone for serialize,
					 * relay as half-dup as possible
					 */
					continue;
				}
			}
			fi = pxv[pi];
			if( pi != prepi ){
				if( dobreak ){
				/*
				syslog_ERROR("## EXIT relaysx: %d\n",dobreak);
				*/
		fj = pxv[0<prepi?prepi:0];
		syslog_ERROR("## EXIT relaysx: break=%d %d [%d] %d/%d\n",
			dobreak,RELAY_num_turns,fj,rccs[fj],cntv[fj]);
					goto EXIT;
				}
				RELAY_num_turns++;
				packs = 0;
			}
			if( RELAY_max_packintvl ){
				if( pi == prepi ){
					double intvl;
					intvl = Time() - Lastin[fi];
					if( RELAY_max_packintvl < intvl ){
						if( RELAY_num_turns <= 5 ){
syslog_ERROR("## %d[%d] max-intvl(%d)<%d\n",
	RELAY_num_turns,pi,(int)(1000*RELAY_max_packintvl),(int)(1000*intvl));
				syslog_ERROR("## %d[%d] max-intvl<%d\n",
					RELAY_num_turns,pi,(int)(1000*intvl));
						}else
						{
						RELAY_packintvl = intvl;
						dobreak = 1;
						/*
				syslog_ERROR("## EXIT relaysx: max-intvl<%d\n",
					(int)(1000*intvl));
						*/
		fj = pxv[0<prepi?prepi:0];
		syslog_ERROR("## EXIT relaysx: max-intvl<%d %d [%d] %d/%d\n",
			(int)(1000*intvl),RELAY_num_turns,fj,rccs[fj],cntv[fj]);
						}
					}
				}else{
					if( dobreak )
						goto EXIT;
				}
			}
			if( RELAY_max_turns && pi != prepi ){
				if( Now-Start < RELAY_thru_time ){
				}else
				if( RELAY_max_turns < RELAY_num_turns ){
				syslog_ERROR("## EXIT relaysx: max_turns=%d\n",
					RELAY_num_turns);
					goto EXIT;
				}
			}
			prepi = pi;

			pushed = 0 <= top_fd(sdv[fi][0],0);
			rcode = (*funcv[fi])(argv[fi],sdv[fi][0],sdv[fi][1],&rcc,&wcc);
			Lastin[fi] = Time();
			/*
			rccs[fi] += wcc;
			*/
			rccs[fi] += rcc;
			wccs[fi] += wcc;
			cntv[fi] += 1;

			packs += 1;
			if( RELAY_half_dup /* && RELAY_ssl_only */ ){
				CStr(spack,32);
				unsigned char *up = (unsigned char*)lastpack;
				sprintf(spack,"%2X %2X %2X %2X %2X",
					up[0],up[1],up[2],up[3],up[4]);
				syslog_DEBUG("%2d.%d %2d->%2d %4d [%s]\n",
					RELAY_num_turns,packs,
					sdv[fi][0],sdv[fi][1],rcc,
					spack);

				/* the first packet in the turn of the side
				 * must begin with a heaer of a SSL frame.
				 * (CONNECT for STARTTLS on HTTP might be
				 * allowed...)
				 */
			   if( RELAY_ssl_peek || RELAY_ssl_only ){
				if( RELAY_ssl_peek ){ /* new-140518b */
				    syslog_ERROR("SSL %2d.%d [%d]->[%d] %4d [%s]\n",
					RELAY_num_turns,packs,
					sdv[fi][0],sdv[fi][1],rcc,
					spack);
				}
				if( packs == 1 && 5 <= lastpackLeng ){
					/*
					if( 0x20 < up[0] && up[0] != 0x80 ){
					*/
					if( isSSLrecord(up,spack,lastpackLeng,pfv[fi]) < 0 ){
					    if( RELAY_ssl_only ){ /* mod-140518a */
				syslog_ERROR("## EXIT relaysx: non-SSL [%s]\n",
					spack);
						dobreak = 2;
					    }
					}
				}
				lastpackLeng = 0;

				if( RELAY_half_dup ){
					int s1 = sdv[fi][0];
					if( concat(relayCtrl,s1,nx,tl,rcode,nready) ){
						nx++;
						tl += rcode;
						goto RELAY1;
					}
				}
			    }
			}

			if( pushed && rcode == -1 && errno == EAGAIN ){
				syslog_ERROR("## relaysx() pop_fd:%d\n",
					sdv[fi][0]);
			}else
			if( rcode <= 0 ){
				syslog_ERROR(
					"relays[%d]: [%d->EOF] %d(%di+%do)\n",
					fi,fds[fi],rcode,rcc,wcc);
				if( sdx == NULL || (sdx[fi] & IGN_EOF) == 0 )
					goto EXIT;
				else	errv[fi] = 1;
			}
		}
	    }
	}
EXIT:
	for( fi = 0; fi < sdc; fi++ )
		syslog_ERROR("relays[%d]: [%d->%d] %d bytes / %d -> %d\n",fi,
			sdv[fi][0],sdv[fi][1],rccs[fi],cntv[fi],wccs[fi]);
	/*
		syslog_ERROR("relays[%d]: [%d->%d] %d bytes / %d\n",fi,
			sdv[fi][0],sdv[fi][1],rccs[fi],cntv[fi]);
	*/
	return 0;
}