📄 fatcontroller.cpp
字号:
timeval t; // timeval struct t.tv_sec = timeout; t.tv_usec = 0; if (selectEINTR(fd + 1, NULL, &fdSet, NULL, &t) < 1) { return false; // on timeout or error } return true;}int FatController::getLineFromFD(int fd, char* buff, int size, int timeout) { if (!checkForInput(fd, timeout)) { return -1; } char b[1]; int rc = -1; // only set to prevent compiler warnings int i = 0; b[0] = 0; while(i < (size - 1)) { while (true) { if (!checkForInput(fd, 12)) { break; } rc = recv(fd, b, 1, 0); if (rc < 0) { if (errno == EINTR && !reloadconfig) { continue; } } break; } if (rc < 0) { return -1; // error } if (rc == 0) { // eof, other end closed so b[0] = '\n'; // force it to return what read } buff[i] = b[0]; i++; if (b[0] == '\n') { buff[i - 1] = '\0'; break; } } buff[i] = '\0'; return i;}bool FatController::checkForInput(int fd, int timeout) { fd_set fdSet; FD_ZERO(&fdSet); // clear the set FD_SET(fd, &fdSet); // add fd to the set if (timeout > 0) { timeval t; // timeval struct t.tv_sec = timeout; t.tv_usec = 0; if (selectEINTR(fd + 1, &fdSet, NULL, NULL, &t) < 1) { return false; } } if (selectEINTR(fd + 1, &fdSet, NULL, NULL, NULL) < 1) { return false; } return true; // Innnppppuuuuttt!!!! </#5>}int FatController::selectEINTR(int numfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout) { int rc; while (true) { // using the while as a restart point with continue rc = select(numfds, readfds, writefds, exceptfds, timeout); if (rc < 0) { if (errno == EINTR && !reloadconfig) { continue; // was interupted by a signal so restart } } break; // end the while } return rc; // return status}void FatController::mopUpAfterKids() { pid_t pid; int stat_val; while(true) { pid = waitpid(-1, &stat_val, WNOHANG); if (pid < 1) { break; } if (WIFEXITED(stat_val) ) { // exited normally deleteChild((int)pid, WEXITSTATUS(stat_val)); } else { deleteChild((int)pid, -1); } }}int FatController::logListener(std::string log_location, int logconerror) { #ifdef DGDEBUG std::cout << "log listener started" << std::endl; #endif if (!dropPrivCompletely()) { return 1; //error } UDSocket ipcpeersock; // the socket which will contain the ipc connection ipcpeersock.close(); // don't need default fd as will be accept()ing int rc, ipcsockfd; char* logline = new char[8192]; ofstream logfile(log_location.c_str(), ios::app); if (logfile.fail()) { syslog(LOG_ERR, "%s","Error opening/creating log file."); #ifdef DGDEBUG std::cout << "Error opening/creating log file: " << log_location << std::endl; #endif return 1; // return with error } ipcsockfd = ipcsock.getFD(); fd_set fdSet; // our set of fds (only 1) that select monitors for us fd_set fdcpy; // select modifes the set so we need to use a copy FD_ZERO(&fdSet); // clear the set FD_SET(ipcsockfd, &fdSet); // add ipcsock to the set while (true) { // loop, essentially, for ever fdcpy = fdSet; // take a copy rc = select(ipcsockfd + 1, &fdcpy, NULL, NULL, NULL); // block // until something happens if (rc < 0) { // was an error if (errno == EINTR) { continue; // was interupted by a signal so restart } if (logconerror == 1) { syslog(LOG_ERR, "%s","ipc rc<0. (Ignorable)"); } continue; } if (rc < 1) { if (logconerror == 1) { syslog(LOG_ERR, "%s","ipc rc<0. (Ignorable)"); } continue; } if (FD_ISSET(ipcsockfd, &fdcpy)) { #ifdef DGDEBUG std::cout << "received a log request" << std::endl; #endif ipcpeersock = ipcsock.accept(); if (ipcpeersock.getFD() < 0) { ipcpeersock.close(); if (logconerror == 1) { syslog(LOG_ERR, "%s","Error accepting ipc. (Ignorable)"); } continue; // if the fd of the new socket < 0 there was error // but we ignore it as its not a problem } try { rc = ipcpeersock.getline(logline, 8192, 3); // throws on err } catch (exception& e) { ipcpeersock.close(); if (logconerror == 1) { syslog(LOG_ERR, "%s","Error reading ipc. (Ignorable)"); } continue; } logfile << logline << std::endl; // append the line #ifdef DGDEBUG std::cout << logline << std::endl; #endif ipcpeersock.close(); // close the connection #ifdef DGDEBUG std::cout << "logged" << std::endl; #endif continue; // go back to listening } // should never get here syslog(LOG_ERR, "%s","Something wicked has ipc happened"); } delete[] logline; logfile.close(); // close the file and ipcsock.close(); // be nice and neat return 1; // It is only possible to reach here with an error}extern "C" { // The kernel knows nothing of objects so // we have to have a lump of c void sig_term(int signo) { sig_term_killall = true; ttg = true; // its time to go } void sig_termsafe(int signo) { ttg = true; // its time to go } void sig_hup(int signo) { reloadconfig = true; #ifdef DGDEBUG std::cout << "HUP received." << std::endl; #endif } void sig_usr1(int signo) { gentlereload = true; #ifdef DGDEBUG std::cout << "USR1 received." << std::endl; #endif }}int FatController::urlListListener(int logconerror) { #ifdef DGDEBUG std::cout << "url listener started" << std::endl; #endif if (!dropPrivCompletely()) { return 1; //error } UDSocket ipcpeersock; // the socket which will contain the ipc connection ipcpeersock.close(); // don't need default fd as will be accept()ing int rc, ipcsockfd; char* logline = new char[32000]; String reply; DynamicURLList urllist; #ifdef DGDEBUG std::cout << "setting url list size-age:" << o.url_cache_number << "-" << o.url_cache_age << std::endl; #endif urllist.setListSize(o.url_cache_number, o.url_cache_age); ipcsockfd = urllistsock.getFD(); #ifdef DGDEBUG std::cout << "url ipcsockfd:" << ipcsockfd << std::endl; #endif fd_set fdSet; // our set of fds (only 1) that select monitors for us fd_set fdcpy; // select modifes the set so we need to use a copy FD_ZERO(&fdSet); // clear the set FD_SET(ipcsockfd, &fdSet); // add ipcsock to the set #ifdef DGDEBUG std::cout << "url listener entering select()" << std::endl; #endif while (true) { // loop, essentially, for ever fdcpy = fdSet; // take a copy rc = select(ipcsockfd + 1, &fdcpy, NULL, NULL, NULL); // block // until something happens #ifdef DGDEBUG std::cout << "url listener select returned" << std::endl; #endif if (rc < 0) { // was an error if (errno == EINTR) { continue; // was interupted by a signal so restart } if (logconerror == 1) { syslog(LOG_ERR, "%s","url ipc rc<0. (Ignorable)"); } continue; } if (FD_ISSET(ipcsockfd, &fdcpy)) { #ifdef DGDEBUG std::cout << "received an url request" << std::endl; #endif ipcpeersock = urllistsock.accept(); if (ipcpeersock.getFD() < 0) { ipcpeersock.close(); if (logconerror == 1) { #ifdef DGDEBUG std::cout << "Error accepting url ipc. (Ignorable)" << std::endl; #endif syslog(LOG_ERR, "%s","Error accepting url ipc. (Ignorable)"); } continue; // if the fd of the new socket < 0 there was error // but we ignore it as its not a problem } try { rc = ipcpeersock.getline(logline, 32000, 3); // throws on err } catch (exception& e) { ipcpeersock.close(); // close the connection if (logconerror == 1) { #ifdef DGDEBUG std::cout << "Error reading ip ipc. (Ignorable)" << std::endl; std::cerr << e.what() << std::endl; #endif syslog(LOG_ERR, "%s","Error reading ip ipc. (Ignorable)"); syslog(LOG_ERR, "%s", e.what()); } continue; } if (logline[0] == 'F' && logline[1] == ' ') { ipcpeersock.close(); // close the connection urllist.flush(); #ifdef DGDEBUG std::cout << "url FLUSH request" << std::endl; #endif continue; } if (logline[0] == 'A' && logline[1] == ' ') { ipcpeersock.close(); // close the connection urllist.addEntry(logline + 2); #ifdef DGDEBUG std::cout << "url add request:" << logline << std::endl; #endif continue; } #ifdef DGDEBUG std::cout << "url search request:" << logline << std::endl; #endif if (urllist.inURLList(logline)) { reply = "Y\n"; } else { reply = "N\n"; } try { ipcpeersock.writeString(reply.toCharArray()); } catch (exception& e) { ipcpeersock.close(); // close the connection if (logconerror == 1) { syslog(LOG_ERR, "%s","Error writing url ipc. (Ignorable)"); syslog(LOG_ERR, "%s", e.what()); } continue; } ipcpeersock.close(); // close the connection #ifdef DGDEBUG std::cout << "url list reply:" << reply << std::endl; #endif continue; // go back to listening } } delete[] logline; urllistsock.close(); // be nice and neat return 1; // It is only possible to reach here with an error}bool FatController::dropPrivCompletely() { // This is done to solve the problem where the total processes for the // uid rather than euid is taken for RLIMIT_NPROC and so can't fork() // as many as expected. // It is also more secure. // // Suggested fix by Lawrence Manning Tue 25th February 2003 // int rc = seteuid(o.root_user); // need to be root again to drop properly if (rc == -1) { syslog(LOG_ERR, "%s","Unable to seteuid(suid)"); #ifdef DGDEBUG std::cout << strerror(errno) << std::endl; #endif return false; // setuid failed for some reason so exit with error } rc = setuid(o.proxy_user); if (rc == -1) { syslog(LOG_ERR, "%s","Unable to setuid()"); return false; // setuid failed for some reason so exit with error } return true;}void FatController::flushURLCache() { if (o.url_cache_number < 1) { return; // no cache running to flush } UDSocket fipcsock; if (fipcsock.getFD() < 0) { syslog(LOG_ERR, "%s","Error creating ipc socket to url cache for flush"); return; } if (fipcsock.connect((char*) o.urlipc_filename.c_str()) < 0) { // conn to dedicated url cach proc syslog(LOG_ERR, "%s","Error connecting via ipc to url cache for flush"); #ifdef DGDEBUG std::cout << "Error connecting via ipc to url cache for flush" << std::endl; #endif return; } String request = "F \n"; try { fipcsock.writeString(request.toCharArray()); // throws on err } catch (exception& e) { #ifdef DGDEBUG std::cerr << "Exception flushing url cache" << std::endl; std::cerr << e.what() << std::endl; #endif syslog(LOG_ERR, "%s","Exception flushing url cache"); syslog(LOG_ERR, "%s", e.what()); } fipcsock.close();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -