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); } }
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); }