| //// Platform Specific Stuff /////////////////////////////////////////////////// | //// Platform Specific Stuff /////////////////////////////////////////////////// | ||||
| #if defined(WIN32) || defined(WIN64) | #if defined(WIN32) || defined(WIN64) | ||||
| #include "winerror.h" | |||||
| //////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||||
| //// Being Windows specific code | //// Being Windows specific code | ||||
| return NULL; // non blocking mode so we return | return NULL; // non blocking mode so we return | ||||
| } // NULL when we see them. | } // NULL when we see them. | ||||
| } | } | ||||
| // Set SO_NOSIGPIPE if needed | |||||
| if( // On some systems we may have to | |||||
| 0 != SO_NOSIGPIPE && // use SO_NOSIPIPE but if they offer | |||||
| 0 == MSG_NOSIGNAL // MSG_NOSIGNAL we prefer that instead. | |||||
| ) { | |||||
| int TurnedOn = 1; // Prepare to turn this option on. | |||||
| int result = // Set SO_NOSIGPIPE. | |||||
| setsockopt( | |||||
| NewHandle, | |||||
| SOL_SOCKET, | |||||
| SO_NOSIGPIPE, | |||||
| (char*) &TurnedOn, | |||||
| sizeof(TurnedOn)); | |||||
| if(0 > result) { // If there was an error then | |||||
| LastError = Network.getLastError(); // Capture the error information | |||||
| Network.closeSocket(NewHandle); // close the handle (avoid leaks) | |||||
| throw Networking::SocketSetSockOptError( // and throw a descriptive exception. | |||||
| Network.DescriptiveError( | |||||
| "TCPListener::acceptClient().setsockopt(SO_NOSIGPIPE)", LastError)); | |||||
| } | |||||
| } | |||||
| // Set SO_NOSIGPIPE if needed | |||||
| if( // On some systems we may have to | |||||
| 0 != SO_NOSIGPIPE && // use SO_NOSIPIPE but if they offer | |||||
| 0 == MSG_NOSIGNAL // MSG_NOSIGNAL we prefer that instead. | |||||
| ) { | |||||
| int TurnedOn = 1; // Prepare to turn this option on. | |||||
| int result = // Set SO_NOSIGPIPE. | |||||
| setsockopt( | |||||
| NewHandle, | |||||
| SOL_SOCKET, | |||||
| SO_NOSIGPIPE, | |||||
| (char*) &TurnedOn, | |||||
| sizeof(TurnedOn)); | |||||
| if(0 > result) { // If there was an error then | |||||
| LastError = Network.getLastError(); // Capture the error information | |||||
| Network.closeSocket(NewHandle); // close the handle (avoid leaks) | |||||
| throw Networking::SocketSetSockOptError( // and throw a descriptive exception. | |||||
| Network.DescriptiveError( | |||||
| "TCPListener::acceptClient().setsockopt(SO_NOSIGPIPE)", LastError)); | |||||
| } | |||||
| } | |||||
| // If things have gone well we can do what we came for. | // If things have gone well we can do what we came for. | ||||
| if(0 > size) // Watch out for bad sizes. | if(0 > size) // Watch out for bad sizes. | ||||
| throw Networking::SocketWriteError("TCPClient::transmit() 0 > size!"); | throw Networking::SocketWriteError("TCPClient::transmit() 0 > size!"); | ||||
| LastError = 0; // No errors yet. | |||||
| int ByteCount = 0; // No bytes sent yet this pass. | |||||
| LastError = 0; // No errors yet. | |||||
| int ByteCount = 0; // No bytes sent yet this pass. | |||||
| ByteCount = send(Handle, bfr, size, MSG_NOSIGNAL); // Try to send and capture the count. | ByteCount = send(Handle, bfr, size, MSG_NOSIGNAL); // Try to send and capture the count. | ||||
| LastError = Network.getLastError(); // Grab any error code. | |||||
| bool AnErrorOccurred = (0 > ByteCount); // How to know if an error occurred. | |||||
| const int NoBytesSent = 0; // This is our "Would Block" result. | |||||
| LastError = Network.getLastError(); // Grab any error code. | |||||
| bool AnErrorOccurred = (0 > ByteCount); // How to know if an error occurred. | |||||
| const int NoBytesSent = 0; // This is our "Would Block" result. | |||||
| if(AnErrorOccurred) { // If there was an error check it out. | if(AnErrorOccurred) { // If there was an error check it out. | ||||
| if(Network.WouldBlock(LastError)) { // If the error was "Would Block" then | if(Network.WouldBlock(LastError)) { // If the error was "Would Block" then | ||||
| return NoBytesSent; // return no bytes sent (try again). | return NoBytesSent; // return no bytes sent (try again). | ||||
| "TCPClient::transmit().send()", LastError)); | "TCPClient::transmit().send()", LastError)); | ||||
| } | } | ||||
| } | } | ||||
| return ByteCount; // Usually: return the sent byte count. | return ByteCount; // Usually: return the sent byte count. | ||||
| } | } | ||||
| LastError = 0; // Clear our LastError value. | LastError = 0; // Clear our LastError value. | ||||
| bool SuccessFlag = true; // Begin optimistically. | bool SuccessFlag = true; // Begin optimistically. | ||||
| // Set Socket Options | |||||
| // Set Socket Options | |||||
| if(!OpenStage1Complete) { // If we haven't done this yet: | if(!OpenStage1Complete) { // If we haven't done this yet: | ||||
| // Set SO_REUSEADDR if turned on | |||||
| // Set SO_REUSEADDR if turned on | |||||
| int ReuseAddress_Flag = (ReuseAddress? 1:0); // Setup an appropriate integer flag. | int ReuseAddress_Flag = (ReuseAddress? 1:0); // Setup an appropriate integer flag. | ||||
| int result = // Set SO_REUSEADDR before bind(). | int result = // Set SO_REUSEADDR before bind(). | ||||
| setsockopt( | setsockopt( | ||||
| Network.DescriptiveError( | Network.DescriptiveError( | ||||
| "TCPHost::open().setsockopt(SO_REUSEADDR)", LastError)); | "TCPHost::open().setsockopt(SO_REUSEADDR)", LastError)); | ||||
| } | } | ||||
| // Set SO_NOSIGPIPE if needed | |||||
| if( // On some systems we may have to | |||||
| 0 != SO_NOSIGPIPE && // use SO_NOSIPIPE but if they offer | |||||
| 0 == MSG_NOSIGNAL // MSG_NOSIGNAL we prefer that instead. | |||||
| ) { | |||||
| int TurnedOn = 1; // Prepare to turn this option on. | |||||
| int result = // Set SO_NOSIGPIPE. | |||||
| setsockopt( | |||||
| Handle, | |||||
| SOL_SOCKET, | |||||
| SO_NOSIGPIPE, | |||||
| (char*) &TurnedOn, | |||||
| sizeof(TurnedOn)); | |||||
| if(0 > result) { // If there was an error then | |||||
| SuccessFlag = false; // we did not succeed. | |||||
| LastError = Network.getLastError(); // Capture the error information and | |||||
| throw Networking::SocketSetSockOptError( // throw. | |||||
| Network.DescriptiveError( | |||||
| "TCPHost::open().setsockopt(SO_NOSIGPIPE)", LastError)); | |||||
| } | |||||
| } | |||||
| // Set SO_NOSIGPIPE if needed | |||||
| if( // On some systems we may have to | |||||
| 0 != SO_NOSIGPIPE && // use SO_NOSIPIPE but if they offer | |||||
| 0 == MSG_NOSIGNAL // MSG_NOSIGNAL we prefer that instead. | |||||
| ) { | |||||
| int TurnedOn = 1; // Prepare to turn this option on. | |||||
| int result = // Set SO_NOSIGPIPE. | |||||
| setsockopt( | |||||
| Handle, | |||||
| SOL_SOCKET, | |||||
| SO_NOSIGPIPE, | |||||
| (char*) &TurnedOn, | |||||
| sizeof(TurnedOn)); | |||||
| if(0 > result) { // If there was an error then | |||||
| SuccessFlag = false; // we did not succeed. | |||||
| LastError = Network.getLastError(); // Capture the error information and | |||||
| throw Networking::SocketSetSockOptError( // throw. | |||||
| Network.DescriptiveError( | |||||
| "TCPHost::open().setsockopt(SO_NOSIGPIPE)", LastError)); | |||||
| } | |||||
| } | |||||
| OpenStage1Complete = true; // Skip this section from now on. | OpenStage1Complete = true; // Skip this section from now on. | ||||
| } // Done with stage 1. | } // Done with stage 1. | ||||
| //// WIN32 Strong Entropy Source == CryptGenRandom() /////////////////////////// | //// WIN32 Strong Entropy Source == CryptGenRandom() /////////////////////////// | ||||
| #include <winsock2.h> | |||||
| #include <windows.h> | #include <windows.h> | ||||
| #include <wincrypt.h> | #include <wincrypt.h> | ||||
| #include <set> | #include <set> | ||||
| #include <vector> | #include <vector> | ||||
| #include <string> | #include <string> | ||||
| #include <queue> | |||||
| #include "faults.hpp" | |||||
| #include <queue> | |||||
| #include "faults.hpp" | |||||
| using namespace std; | using namespace std; | ||||
| Pointer(P), | Pointer(P), | ||||
| Type(&T), | Type(&T), | ||||
| State(&S), | State(&S), | ||||
| Name(N), | |||||
| Name(N), | |||||
| isRunning(R), | isRunning(R), | ||||
| isBad(B), | isBad(B), | ||||
| Fault(F) | Fault(F) | ||||
| isRunning = Right.isRunning; | isRunning = Right.isRunning; | ||||
| isBad = Right.isBad; | isBad = Right.isBad; | ||||
| Fault = Right.Fault; | Fault = Right.Fault; | ||||
| Name = Right.Name; | |||||
| Name = Right.Name; | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| // When in WIN32 land... | // When in WIN32 land... | ||||
| // Remember to compile (on GNU anyway) with -mthreads | // Remember to compile (on GNU anyway) with -mthreads | ||||
| #include <winsock2.h> | |||||
| #include <windows.h> | #include <windows.h> | ||||
| #include <process.h> | #include <process.h> | ||||
| // End Thread Manager | // End Thread Manager | ||||
| //////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||||
| //////////////////////////////////////////////////////////////////////////////// | |||||
| // A ProductionQueue is a templated, thread safe mechanism for implementing | |||||
| // a producer/consumer relationship. The objects in the queue should be simple | |||||
| // data so that they can be created, destroyed, and copied without trouble. Put | |||||
| // another way - the objects in the ProductionQueue should be lightweight | |||||
| // handles for other things. Those things should be created and destroyed | |||||
| // elsewhere. | |||||
| template<typename T> // Templatized | |||||
| class ProductionQueue { // Production Queue Class | |||||
| private: | |||||
| Mutex myMutex; // Contains a mutex and | |||||
| volatile unsigned int LatestSize; // a volatile (blinking light) size | |||||
| ProductionGateway myGateway; // integrated with a production | |||||
| queue<T> myQueue; // gateway and a queue. | |||||
| public: | |||||
| ProductionQueue() : LatestSize(0) {} // The size always starts at zero. | |||||
| T take() { // To consume a queued object | |||||
| myGateway.consume(); // we wait on the production gateway | |||||
| ScopeMutex OneAtATimePlease(myMutex); // and when we get through we lock | |||||
| T O = myQueue.front(); // the mutext, take the object on the | |||||
| myQueue.pop(); // front of the queue, pop it out, | |||||
| LatestSize = myQueue.size(); // and rest our size (blinking light). | |||||
| return O; // Then return the object we got. | |||||
| } | |||||
| void give(T O) { // To produce a queued object | |||||
| ScopeMutex OneAtATimePlease(myMutex); // we wait on the mutex. When we | |||||
| myQueue.push(O); // get through we push our object | |||||
| LatestSize = myQueue.size(); // into the queue, reset our size | |||||
| myGateway.produce(); // indicator and tell the gateway. | |||||
| } // When we're done it can be grabbed. | |||||
| unsigned int size() { // To check the size we look at | |||||
| return LatestSize; // the blinking light. | |||||
| } | |||||
| }; | |||||
| // End Production Queue | |||||
| //////////////////////////////////////////////////////////////////////////////// | |||||
| //////////////////////////////////////////////////////////////////////////////// | |||||
| // A ProductionQueue is a templated, thread safe mechanism for implementing | |||||
| // a producer/consumer relationship. The objects in the queue should be simple | |||||
| // data so that they can be created, destroyed, and copied without trouble. Put | |||||
| // another way - the objects in the ProductionQueue should be lightweight | |||||
| // handles for other things. Those things should be created and destroyed | |||||
| // elsewhere. | |||||
| template<typename T> // Templatized | |||||
| class ProductionQueue { // Production Queue Class | |||||
| private: | |||||
| Mutex myMutex; // Contains a mutex and | |||||
| volatile unsigned int LatestSize; // a volatile (blinking light) size | |||||
| ProductionGateway myGateway; // integrated with a production | |||||
| queue<T> myQueue; // gateway and a queue. | |||||
| public: | |||||
| ProductionQueue() : LatestSize(0) {} // The size always starts at zero. | |||||
| T take() { // To consume a queued object | |||||
| myGateway.consume(); // we wait on the production gateway | |||||
| ScopeMutex OneAtATimePlease(myMutex); // and when we get through we lock | |||||
| T O = myQueue.front(); // the mutext, take the object on the | |||||
| myQueue.pop(); // front of the queue, pop it out, | |||||
| LatestSize = myQueue.size(); // and rest our size (blinking light). | |||||
| return O; // Then return the object we got. | |||||
| } | |||||
| void give(T O) { // To produce a queued object | |||||
| ScopeMutex OneAtATimePlease(myMutex); // we wait on the mutex. When we | |||||
| myQueue.push(O); // get through we push our object | |||||
| LatestSize = myQueue.size(); // into the queue, reset our size | |||||
| myGateway.produce(); // indicator and tell the gateway. | |||||
| } // When we're done it can be grabbed. | |||||
| unsigned int size() { // To check the size we look at | |||||
| return LatestSize; // the blinking light. | |||||
| } | |||||
| }; | |||||
| // End Production Queue | |||||
| //////////////////////////////////////////////////////////////////////////////// | |||||
| #endif | #endif | ||||
| // Platform Specific Includes ////////////////////////////////////////////////// | // Platform Specific Includes ////////////////////////////////////////////////// | ||||
| #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) | ||||
| #include <winsock2.h> | |||||
| #include <windows.h> | #include <windows.h> | ||||
| #endif | #endif | ||||
| if(x < MinimumSleeperTime || | if(x < MinimumSleeperTime || | ||||
| x > MaximumSleeperTime) // If it's not a good time value | x > MaximumSleeperTime) // If it's not a good time value | ||||
| throw BadSleeperValue(); // then throw the exception. | throw BadSleeperValue(); // then throw the exception. | ||||
| MillisecondsToSleep = x; // If it is good - set it. | |||||
| MillisecondsToSleep = x; // If it is good - set it. | |||||
| return MillisecondsToSleep; // Return the set value. | return MillisecondsToSleep; // Return the set value. | ||||
| } | } | ||||
| // a natural spiral. | // a natural spiral. | ||||
| /////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||
| PollTimer::PollTimer(int Nom, int Max) : | |||||
| NominalPollTime(MinimumSleeperTime), | |||||
| PollTimer::PollTimer(int Nom, int Max) : | |||||
| NominalPollTime(MinimumSleeperTime), | |||||
| MaximumPollTime(MinimumSleeperTime) { // Construction requires a | MaximumPollTime(MinimumSleeperTime) { // Construction requires a | ||||
| setNominalPollTime(Nom); // nominal delay to use and | setNominalPollTime(Nom); // nominal delay to use and | ||||
| setMaximumPollTime(Max); // a maximum delay to allow. | setMaximumPollTime(Max); // a maximum delay to allow. |