//// 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. |