Пример #1
0
static void
relay(int s_rcv, int s_snd, const char *service, int direction)
{
	int atmark, error, maxfd;
	struct timeval tv;
	fd_set oreadfds, owritefds, oexceptfds;

	FD_ZERO(&readfds);
	FD_ZERO(&writefds);
	FD_ZERO(&exceptfds);
	fcntl(s_snd, F_SETFD, O_NONBLOCK);
	oreadfds = readfds; owritefds = writefds; oexceptfds = exceptfds;
	if (s_rcv >= FD_SETSIZE)
		exit_failure("descriptor too big");
	FD_SET(s_rcv, &readfds);
	FD_SET(s_rcv, &exceptfds);
	oob_exists = 0;
	maxfd = (s_rcv > s_snd) ? s_rcv : s_snd;

	for (;;) {
		tv.tv_sec = FAITH_TIMEOUT / 4;
		tv.tv_usec = 0;
		oreadfds = readfds;
		owritefds = writefds;
		oexceptfds = exceptfds;
		error = select(maxfd + 1, &readfds, &writefds, &exceptfds, &tv);
		if (error == -1) {
			if (errno == EINTR)
				continue;
			exit_failure("select: %s", strerror(errno));
		} else if (error == 0) {
			readfds = oreadfds;
			writefds = owritefds;
			exceptfds = oexceptfds;
			notify_inactive();
			continue;
		}

		/* activity notification */
		notify_active();

		if (FD_ISSET(s_rcv, &exceptfds)) {
			error = ioctl(s_rcv, SIOCATMARK, &atmark);
			if (error != -1 && atmark == 1) {
				int cc;
			    oob_read_retry:
				cc = read(s_rcv, atmark_buf, 1);
				if (cc == 1) {
					if (s_rcv >= FD_SETSIZE)
						exit_failure("descriptor too big");
					FD_CLR(s_rcv, &exceptfds);
					if (s_snd >= FD_SETSIZE)
						exit_failure("descriptor too big");
					FD_SET(s_snd, &writefds);
					oob_exists = 1;
				} else if (cc == -1) {
					if (errno == EINTR)
						goto oob_read_retry;
					exit_failure("reading oob data failed"
						     ": %s",
						     strerror(errno));
				}
			}
		}
		if (FD_ISSET(s_rcv, &readfds)) {
		    relaydata_read_retry:
			tblen = read(s_rcv, tcpbuf, sizeof(tcpbuf));
			tboff = 0;

			switch (tblen) {
			case -1:
				if (errno == EINTR)
					goto relaydata_read_retry;
				exit_failure("reading relay data failed: %s",
					     strerror(errno));
				/* NOTREACHED */
			case 0:
				/* to close opposite-direction relay process */
				shutdown(s_snd, 0);

				close(s_rcv);
				close(s_snd);
				exit_success("terminating %s relay", service);
				/* NOTREACHED */
			default:
				if (s_rcv >= FD_SETSIZE)
					exit_failure("descriptor too big");
				FD_CLR(s_rcv, &readfds);
				if (s_snd >= FD_SETSIZE)
					exit_failure("descriptor too big");
				FD_SET(s_snd, &writefds);
				break;
			}
		}
		if (FD_ISSET(s_snd, &writefds))
			send_data(s_rcv, s_snd, service, direction);
	}
}
Пример #2
0
void CRtkService::Run(__uint, char **)
#endif
{
	
	__uint res;

	// report to the SCM that we're about to start
	utils_trace("Starting %s...\n", versionString.c_str());

	ReportStatus(SERVICE_START_PENDING);

	signal(SIGINT, _ctrl_c);

	try{
		if(!_init()){
			throw(this);
		}
	
		ReportStatus(SERVICE_RUNNING);		
		__int logCounter = 24*3600*1000/PrimaryCheckInterval;
		
		while(!bExit){
			res = m_hStop.Wait(PrimaryCheckInterval);
			switch(res){
			case WAIT_OBJECT_0:
				switch(m_dwStopReason){
				case 0:
					bExit = true;
					break;
				case 1:
					_restart();
					ReportStatus(SERVICE_RUNNING);
					break;
				case 2:
					break;
				}
				if(get_power_state()==PWR_RUNNING){
					notify_active();
				}
				break;
			case WAIT_TIMEOUT:
				switch(get_power_state()){
				case PWR_RUNNING:
					notify_active();
					break;
				case PWR_BACKUP:
					PrimaryWatchDogCounter--;
					if(PrimaryWatchDogCounter <= 0){
						utils_trace("Primary site failed, resuming responsibility.\n");
						switch_to_primary();
					}
					break;
				}
				logCounter--;
				if(logCounter <= 0){
					close_log();
					open_log();
					logCounter = 24*3600*1000/PrimaryCheckInterval;
				}
				break;
			}
		}
		_uninit();
	}catch(CRtkService *){
		utils_error("Aborted.\n");
	}

	ReportStatus(SERVICE_STOPPED);
}