|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
#include <ctime>
|
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
#include <iomanip>
|
|
|
|
|
|
#include <fstream>
|
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
#include <queue>
|
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
#include <exception>
|
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
#include "unistd.h"
|
|
|
|
|
|
#include "timing.hpp"
|
|
|
|
|
|
#include "threading.hpp"
|
|
|
|
|
|
#include "networking.hpp"
|
|
|
|
|
|
#include "SNFMulti.hpp"
|
|
|
|
|
|
#include "snf_xci.hpp"
|
|
|
|
|
|
#include "snf_sync.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
|
|
// temporary - proving base64codec
|
|
|
|
|
|
|
|
|
|
|
|
#include "base64codec.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
//#include "../nvwa-0.6/nvwa/debug_new.h"
|
|
|
|
|
|
using namespace std; // Introduce standard namespace.
|
|
|
|
|
|
|
|
|
|
|
|
const char* SERVER_VERSION_INFO = "SNF Server Version " PACKAGE_VERSION " Build: " __DATE__ " " __TIME__;
|
|
|
|
|
|
|
|
|
|
|
|
static const string XCIShutdownResponse =
|
|
|
|
|
|
"<snf><xci><server><response message=\'shutdown in progress\' code=\'0\'/></server></xci></snf>\n";
|
|
|
|
|
|
|
|
|
|
|
|
class XCIShutdownWatcher : public snfXCIServerCommandHandler { // Shutdown watcher.
|
|
|
|
|
|
public:
|
|
|
|
|
|
XCIShutdownWatcher():TimeToStop(false){} // Construct with shutdown flag false.
|
|
|
|
|
|
bool TimeToStop; // Here is the flag.
|
|
|
|
|
|
string processXCIRequest(snf_xci& X) { // Here is how we process requests.
|
|
|
|
|
|
if(0 == X.xci_server_command.find("shutdown")) { // If we find shutdown then
|
|
|
|
|
|
TimeToStop = true; // set the shutdown flag
|
|
|
|
|
|
return XCIShutdownResponse; // and let them know we got it.
|
|
|
|
|
|
} // If we get some other request
|
|
|
|
|
|
return XCIErrorResponse; // return the error response.
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Thread Status Analysis For Debugging.
|
|
|
|
|
|
|
|
|
|
|
|
void ThreadStatusToCout() { // Produce a thread status list.
|
|
|
|
|
|
ThreadStatusReport R = Threads.StatusReport(); // Get a report from Threads.
|
|
|
|
|
|
cout << endl; // Break the line.
|
|
|
|
|
|
for(
|
|
|
|
|
|
ThreadStatusReport::iterator iR = R.begin(); // Loop through the report.
|
|
|
|
|
|
iR != R.end(); iR++
|
|
|
|
|
|
) {
|
|
|
|
|
|
ThreadStatusRecord& S = (*iR); // Take each status report and
|
|
|
|
|
|
cout // send it to cout on it's own line.
|
|
|
|
|
|
<< S.getName() << " (" << S.getPointer() << "), "
|
|
|
|
|
|
<< S.getType().Name << ", "
|
|
|
|
|
|
<< S.getState().Name << ", "
|
|
|
|
|
|
<< ((S.getRunning()) ? "Running, " : "Not Running, ")
|
|
|
|
|
|
<< ((S.getBad()) ? "Broken, " : "Ok, ")
|
|
|
|
|
|
<< S.getFault()
|
|
|
|
|
|
<< endl;
|
|
|
|
|
|
}
|
|
|
|
|
|
cout << endl; // Leave a blank line at the end.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Here in the main thread is where we get executive tasks done.
|
|
|
|
|
|
|
|
|
|
|
|
int go(int argc, char* argv[]) { //// go() stands in for main(). main() catches any unhandled exceptions.
|
|
|
|
|
|
|
|
|
|
|
|
// Check for debug mode.
|
|
|
|
|
|
|
|
|
|
|
|
bool DebugMode = false; // This will be our debug mode.
|
|
|
|
|
|
string argv0(argv[0]); // Capture how we were called.
|
|
|
|
|
|
if(
|
|
|
|
|
|
string::npos != argv0.find("Debug") || // If we find "Debug" or
|
|
|
|
|
|
string::npos != argv0.find("debug") // "debug" in our command path
|
|
|
|
|
|
) { // then we are in DebugMode.
|
|
|
|
|
|
DebugMode = true; // Set the flag and tell the
|
|
|
|
|
|
cout << "Debug Mode" << endl; // watchers.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// DebugMode = true; // Force it when needed.
|
|
|
|
|
|
|
|
|
|
|
|
// Announce Version / Build Info.
|
|
|
|
|
|
|
|
|
|
|
|
cout << SERVER_VERSION_INFO << endl; // Shout out our version.
|
|
|
|
|
|
cout << SNF_ENGINE_VERSION << endl; // Shout out the engine version.
|
|
|
|
|
|
|
|
|
|
|
|
// Sanity checks before we get going.
|
|
|
|
|
|
|
|
|
|
|
|
if(2 != argc) { // Check the command line args.
|
|
|
|
|
|
cout << "Use: SNFServer <path-to-config-file>" << endl; // If wrong, say how we work.
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(0 != access(argv[1], R_OK)) { // Check the config file path.
|
|
|
|
|
|
cout << "Can't read " << argv[1] << endl; // If it's not accessible, punt.
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
cout << "Launching with " << argv[1] << endl; // Tell them we're going.
|
|
|
|
|
|
snf_RulebaseHandler MyRulebase; // Create a rulebase manager.
|
|
|
|
|
|
MyRulebase.PlatformVersion(SERVER_VERSION_INFO); // Set the Platform version string.
|
|
|
|
|
|
XCIShutdownWatcher ShutdownWatcher; // Make a server shutdown processor
|
|
|
|
|
|
MyRulebase.XCIServerCommandHandler(ShutdownWatcher); // and register it with the engine.
|
|
|
|
|
|
MyRulebase.open(argv[1], "", ""); // Open a configured rulebase.
|
|
|
|
|
|
|
|
|
|
|
|
Sleeper WaitATic(1000); // Learn to wait a second.
|
|
|
|
|
|
|
|
|
|
|
|
cout << "Running." << endl << endl; // Tell them we're running.
|
|
|
|
|
|
char Tic = '\\'; // Tic/Toc indicator.
|
|
|
|
|
|
while(false == ShutdownWatcher.TimeToStop) { // While running, update the screen.
|
|
|
|
|
|
WaitATic(); // One second between updates.
|
|
|
|
|
|
|
|
|
|
|
|
// Animate the Tick/Toc Indicator
|
|
|
|
|
|
|
|
|
|
|
|
switch(Tic) {
|
|
|
|
|
|
case '\\': Tic = '|'; break;
|
|
|
|
|
|
case '|': Tic = '/'; break;
|
|
|
|
|
|
case '/': Tic = '-'; break;
|
|
|
|
|
|
default: Tic = '\\'; break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Format and output the screen update. At the end post a \r so that
|
|
|
|
|
|
// the line appears to update in place.
|
|
|
|
|
|
|
|
|
|
|
|
cout
|
|
|
|
|
|
<< "M/min: " << setw(4) << (int) MyRulebase.MyLOGmgr.MessagesPerMinute() << " "
|
|
|
|
|
|
<< "SP: " << setw(6) << setprecision(2) << setiosflags(ios::fixed) <<
|
|
|
|
|
|
((0 < MyRulebase.MyLOGmgr.MessagesPerMinute()) ?
|
|
|
|
|
|
(100 * MyRulebase.MyLOGmgr.SpamPerMinute() / MyRulebase.MyLOGmgr.MessagesPerMinute()) : 0.0) << "% "
|
|
|
|
|
|
<< "LR:" << setw(7) << MyRulebase.MyLOGmgr.LatestRuleID()
|
|
|
|
|
|
<< " ["
|
|
|
|
|
|
<< MyRulebase.MyXCImgr.pollClientCount() << "/"
|
|
|
|
|
|
<< MyRulebase.MyXCImgr.pollLoopCount() << " "
|
|
|
|
|
|
<< Tic << " " << (int) MyRulebase.MyXCImgr.TotalQueue() << "] "
|
|
|
|
|
|
<< "W:" << (int) MyRulebase.MyLOGmgr.WhitePerMinute() << " "
|
|
|
|
|
|
<< "C:" << (int) MyRulebase.MyLOGmgr.CautionPerMinute() << " "
|
|
|
|
|
|
<< "B:" << (int) MyRulebase.MyLOGmgr.BlackPerMinute() << " "
|
|
|
|
|
|
<< "T:" << (int) MyRulebase.MyLOGmgr.TruncatePerMinute() << " "
|
|
|
|
|
|
<< "S:" << (int) MyRulebase.MyLOGmgr.SamplePerMinute()
|
|
|
|
|
|
<< " \r" << flush;
|
|
|
|
|
|
|
|
|
|
|
|
if(DebugMode) ThreadStatusToCout(); // Debug? Show Thread Status Report.
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
cout << endl << endl << "Shutdown Received." << endl;
|
|
|
|
|
|
|
|
|
|
|
|
// When this loop fails it is time to shut down.
|
|
|
|
|
|
// All the rest happens via XCI now.
|
|
|
|
|
|
|
|
|
|
|
|
cout << "Closing Rulebase Handler..." << endl;
|
|
|
|
|
|
|
|
|
|
|
|
MyRulebase.close();
|
|
|
|
|
|
|
|
|
|
|
|
// All done...
|
|
|
|
|
|
|
|
|
|
|
|
cout << "Bye bye." << endl;
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
class DebugExceptionHandler { // Hand wrapper for exception handler.
|
|
|
|
|
|
public:
|
|
|
|
|
|
DebugExceptionHandler() {
|
|
|
|
|
|
LoadLibrary("exchndl.dll");
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static DebugExceptionHandler TheDebugExceptionHandler; // Global exception handler.
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char* argv[]) {
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
go(argc, argv);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch(exception& e) {
|
|
|
|
|
|
cout << "Unhandled Exception: " << e.what() << " Thrown!" << endl;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch(...) {
|
|
|
|
|
|
cout << "Unknown, Unhandled Exception Discovered!" << endl;
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|