Browse Source

Added code to implement SO_NOSIGPIPE socket option when MSG_NOSIGLAL is not available.

Updated some exception descriptions networking.* to improve clarity and fix some copy-typos.

git-svn-id: https://svn.microneil.com/svn/CodeDweller/trunk@17 d34b734f-a00e-4b39-a726-e4eeb87269ab
wx
madscientist 15 years ago
parent
commit
dc9be6db84
2 changed files with 73 additions and 15 deletions
  1. 63
    11
      networking.cpp
  2. 10
    4
      networking.hpp

+ 63
- 11
networking.cpp View File

@@ -281,7 +281,7 @@ TCPListener::TCPListener(unsigned short Port) {
LastError = Network.getLastError(); // grab the error code and
throw Networking::SocketCreationError( // throw.
Network.DescriptiveError(
"TCPListener::open().socket()", LastError));
"TCPListener::TCPListener().socket()", LastError));
}
}

@@ -301,7 +301,7 @@ TCPListener::TCPListener(SocketAddress& WhereToBind) {
LastError = Network.getLastError(); // grab the error code and
throw Networking::SocketCreationError( // throw.
Network.DescriptiveError(
"TCPListener::open().socket()", LastError));
"TCPListener::TCPListener().socket()", LastError));
}
}

@@ -331,7 +331,7 @@ void TCPListener::open() {
LastError = Network.getLastError(); // Capture the error information and
throw Networking::SocketSetSockOptError( // throw.
Network.DescriptiveError(
"TCPListener::open().setsockopt()", LastError));
"TCPListener::open().setsockopt(SO_REUSEADDR)", LastError));
}
OpenStage1Complete = true; // Stage 1 complete now.
} // End of open() stage 1
@@ -388,11 +388,35 @@ TCPClient* TCPListener::acceptClient() {
if(!Network.WouldBlock(LastError)) { // If it's not a EWOULDBLOCK error
throw Networking::SocketAcceptError( // then we need to throw.
Network.DescriptiveError(
"TCPListener::acceptClient()", LastError));
"TCPListener::acceptClient().accept()", LastError));
} else { // EWOULDBLOCK errors are normal in
return NULL; // non blocking mode so we return
} // 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));
}
}

// If things have gone well we can do what we came for.

@@ -420,7 +444,7 @@ int TCPClient::transmit(const char* bfr, int size) {
} else { // If this was a different kind of error
throw Networking::SocketWriteError( // then throw!
Network.DescriptiveError(
"TCPClient::transmit()", LastError));
"TCPClient::transmit().send()", LastError));
}
}
return ByteCount; // Ultimately return the byte count.
@@ -483,7 +507,7 @@ TCPHost::TCPHost(unsigned short Port) {
LastError = Network.getLastError(); // grab the error code and
throw Networking::SocketCreationError( // throw.
Network.DescriptiveError(
"TCPHost::open().socket()", LastError));
"TCPHost::TCPHost().socket()", LastError));
}
}

@@ -503,7 +527,7 @@ TCPHost::TCPHost(SocketAddress& Remote) {
LastError = Network.getLastError(); // grab the error code and
throw Networking::SocketCreationError( // throw.
Network.DescriptiveError(
"TCPHost::open().socket()", LastError));
"TCPHost::TCPHost().socket()", LastError));
}
}

@@ -516,16 +540,19 @@ void TCPHost::open() {
LastError = 0; // Clear our LastError value.
bool SuccessFlag = true; // Begin optimistically.

// Set SO_REUSEADDR if turned on
// Set Socket Options
if(!OpenStage1Complete) { // If we haven't done this yet:
// Set SO_REUSEADDR if turned on
int ReuseAddress_Flag = (ReuseAddress? 1:0); // Setup an appropriate integer flag.
int result = // Set SO_REUSEADDR before bind().
setsockopt(
Handle,
SOL_SOCKET,
SO_REUSEADDR,
(char *)&ReuseAddress_Flag,
(char*) &ReuseAddress_Flag,
sizeof(ReuseAddress_Flag));

if(0 > result) { // If there was an error then
@@ -533,8 +560,33 @@ void TCPHost::open() {
LastError = Network.getLastError(); // Capture the error information and
throw Networking::SocketSetSockOptError( // throw.
Network.DescriptiveError(
"TCPListener::open().setsockopt()", 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));
}
}
OpenStage1Complete = true; // Skip this section from now on.
} // Done with stage 1.


+ 10
- 4
networking.hpp View File

@@ -46,10 +46,6 @@ using namespace std;
typedef int socklen_t; // Posix uses socklen_t so we mimic it.
typedef SOCKET hSocket; // Winx handles Socket is opaque.
#ifndef NO_SIGNALS
const int MSG_NOSIGNAL = 0; // Make NO_SIGNALS for winsock.
#endif

#else

//// GNU Headers...
@@ -70,6 +66,16 @@ const hSocket INVALID_SOCKET = -1;

#endif

//// Handling SIGPIPE //////////////////////////////////////////////////////////
#ifndef MSG_NOSIGNAL
const int MSG_NOSIGNAL = 0; // Fake this if it isn't defined.
#endif
#ifndef SO_NOSIGPIPE
const int SO_NOSIGPIPE = 0; // Fake this if it isn't defined.
#endif
//// Tuning and Constants //////////////////////////////////////////////////////

const unsigned long LOCALHOST = 0x7F000001; // 127.0.0.1 as an integer.

Loading…
Cancel
Save