// snfXCImgr.hpp // Copyright (C) 2007 - 2009 ARM Research Labs, LLC. // See www.armresearch.com for the copyright terms. // XML Command Interface manager. // This module uperates a TCP server to accept requests for scans, GBUdb // operations, etc on behalf of an snf_EngineHandler. #pragma once #include #include #include "../CodeDweller/timing.hpp" #ifdef WIN32 // Required because threading.hpp includes windows.h. #include #endif #include "../CodeDweller/threading.hpp" #include "../CodeDweller/networking.hpp" #include "snf_xci.hpp" namespace cd = codedweller; // We need to know these exist ;-) class snf_RulebaseHandler; // These exist. class snf_EngineHandler; // These exist. // Handy references and "standards" static const std::string XCIErrorResponse = // Unrecognized request error. "\n"; static const std::string XCIBadSetResponse = // Empty GBUdb set command error. "\n"; // snfXCIServerCommandHandler Base Class for Server Command Processing. class snfXCIServerCommandHandler { // Server Command Handler Base Class. public: virtual std::string processXCIRequest(snf_xci& X); // Server provides a useful processor. }; // snfXCIJob encapsulates a single XCI transaction. class snfXCIJob { // Job Packet. public: std::string Request; // XCI formatted request. std::string Response; // XCI formatted response. int SetupTime; // Setup time so far in ms. void clear(); // Clear the buffers. }; // snfXCIJobProcessor encapsulates the logic to respond to an XCI request. class snfXCIJobProcessor { // XCI job processor. private: snf_xci myXCI; // XCI interpreter. snf_RulebaseHandler* myHome; // Rulebase to use. snf_EngineHandler* myEngine; // Scanner (set up internally). bool isScanJob(); // True if myXCI is a scan job. bool isGBUdbJob(); // True if myXCI is a GBUdb job. bool isReportJob(); // True if myXCI is a Report job. bool isCommandJob(); // True if myXCI is a Command job. void processScan(snfXCIJob& J); // Process a scan request. std::string processGBUdb(); // Process a GBUdb request. std::string processStatusReport(); // Process a report request. public: snfXCIJobProcessor(snf_RulebaseHandler* H); // Setup scanner. ~snfXCIJobProcessor(); // Tear down scanner. void process(snfXCIJob& J); // Process a Job. }; // ChannelJob encapsulates a Client Job while in the queue and how long it has // been in the system (since created). class ChannelJob { // Wraper for job queue. private: cd::TCPClient* myClient; // We have a TCPClient. cd::Timer Lifetime; // We have a timer. public: ChannelJob(); // We can be blank but usually ChannelJob(cd::TCPClient* C); // we are created like this. cd::msclock Age(); // How old is this job? cd::TCPClient* Client(); // What client does it hold? }; // snfXCITCPChannel encapsulates the logic to queue and handle TCPClients for // the XCI interface. The queued TCPClients each represent a single request. // Each request is handled in turn by reading the request into an snfXCIJob, // handing that snfXCIJob to an snfXCIJobProcessor, transmitting the result // back to the TCPClient, closing the connection, and recycling the snfXCIJob // object for the next round. // snfXCITCPChannel shuts down when given a NULL TCPClient; This allows any // jobs in queue to be handled before the thread stops. To shut down a channel // { C->submit(NULL); C->join(); delete C; C = NULL;} const int LineBufferSize = 256; // Line buffer size. class snfXCITCPChannel : private cd::Thread { // TCPClient processor & queue. private: snf_RulebaseHandler* myHome; // Rulebase handler. snfXCIJobProcessor Processor; // XCI processor. snfXCIJob Job; // XCI Job buffer. volatile int LatestSize; // Queue Size Blinking Light. cd::Mutex QueueMutex; // Serializes queue changes. cd::ProductionGateway QueueGateway; // Keeps track of give and take. std::queue JobQueue; // Queue of clients. void give(ChannelJob& J); // give a client to the queue. ChannelJob take(); // take a client from the queue. char LineBuffer[LineBufferSize]; // Read Line Buffer. void readRequest(cd::TCPClient* Client); // Read Job.Request from Client. void writeResponse(cd::TCPClient* Client); // Write Job.Request from Client. void myTask(); // Thread's main loop. public: snfXCITCPChannel(snf_RulebaseHandler* H, std::string N); // Create these with a home rulebase. ~snfXCITCPChannel(); // Destroy them very carefully. int Size(); // Keep track of how full they are. void submit(cd::TCPClient* C); // This is how we submit jobs. const static cd::ThreadType Type; // The thread's type. const static cd::ThreadState XCI_Wait; const static cd::ThreadState XCI_Read; const static cd::ThreadState XCI_Process; const static cd::ThreadState XCI_Write; const static cd::ThreadState XCI_Close; const static cd::ThreadState XCI_Clear; const static cd::ThreadState XCI_Shutdown; //const static ThreadState ThreadInitialized; // Constructed successfully. }; // snfXCImgr encapsulates a service engine that takes XCI requests via TCP, // performs the required actions, and returns an XCI response. It also checks // to see if the configuration for the XCI interface has changed. class snfXCImgr : private cd::Thread { // XCI manager. private: cd::Mutex ChannelMutex; // Safety Channel Up/Down events. bool CFG_XCI_ON; // Is XCI turned on? int CFG_XCI_PORT; // What port we listen to? void checkCFG(); // Checks the configuration. snf_RulebaseHandler* myHome; // Rulebase handler to service. snfXCITCPChannel* C0; // XCI channel 0 snfXCITCPChannel* C1; // XCI channel 1 snfXCITCPChannel* C2; // XCI channel 2 snfXCITCPChannel* C3; // XCI channel 3 snfXCITCPChannel* C4; // XCI channel 4 snfXCITCPChannel* C5; // XCI channel 5 snfXCITCPChannel* C6; // XCI channel 6 snfXCITCPChannel* C7; // XCI channel 7 snfXCITCPChannel* BestAvailableChannel(); // Selects XCI channel w/ lowest queue. cd::TCPListener* Listener; // XCI Listener. bool XCI_UP; // True if XCI is alive. void startup_Listener(); // Listener startup function. void shutdown_Listener(); // Listener shutdown function. void startup_XCI(); // XCI startup function. void shutdown_XCI(); // XCI shutdown function. void myTask(); // Main thread task. volatile int diagLoopCount; volatile int diagClientCount; bool TimeToStop; // True when shutting down. public: snfXCImgr(); // Construct with no home. ~snfXCImgr(); // Destroy to shut down. void linkHome(snf_RulebaseHandler* Home); // Link to Home and set up shop. int TotalQueue(); // Return the total work queue size. void stop(); // Called to shut down. int pollLoopCount(); // Get diagnostic loop count. int pollClientCount(); // Get diagnostic client count. const static cd::ThreadType Type; // The thread's type. const static cd::ThreadState XCI_InitialConfig; // Getting initial configuration. const static cd::ThreadState XCI_InitialStartup; // Performing first startup. const static cd::ThreadState XCI_CheckConfig; // Checking configuration. const static cd::ThreadState XCI_PollingListener; // Polling Listener for jobs. const static cd::ThreadState XCI_SubmittingJob; // Submitting a new job. const static cd::ThreadState XCI_ListenerDown; // Listener is down. const static cd::ThreadState XCI_Stopping; // XCImgr Exiting Big Loop };