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

LastError = Network.getLastError(); // grab the error code and LastError = Network.getLastError(); // grab the error code and
throw Networking::SocketCreationError( // throw. throw Networking::SocketCreationError( // throw.
Network.DescriptiveError( Network.DescriptiveError(
"TCPListener::open().socket()", LastError));
"TCPListener::TCPListener().socket()", LastError));
} }
} }


LastError = Network.getLastError(); // grab the error code and LastError = Network.getLastError(); // grab the error code and
throw Networking::SocketCreationError( // throw. throw Networking::SocketCreationError( // throw.
Network.DescriptiveError( Network.DescriptiveError(
"TCPListener::open().socket()", LastError));
"TCPListener::TCPListener().socket()", LastError));
} }
} }


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


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


} else { // If this was a different kind of error } else { // If this was a different kind of error
throw Networking::SocketWriteError( // then throw! throw Networking::SocketWriteError( // then throw!
Network.DescriptiveError( Network.DescriptiveError(
"TCPClient::transmit()", LastError));
"TCPClient::transmit().send()", LastError));
} }
} }
return ByteCount; // Ultimately return the byte count. return ByteCount; // Ultimately return the byte count.
LastError = Network.getLastError(); // grab the error code and LastError = Network.getLastError(); // grab the error code and
throw Networking::SocketCreationError( // throw. throw Networking::SocketCreationError( // throw.
Network.DescriptiveError( Network.DescriptiveError(
"TCPHost::open().socket()", LastError));
"TCPHost::TCPHost().socket()", LastError));
} }
} }


LastError = Network.getLastError(); // grab the error code and LastError = Network.getLastError(); // grab the error code and
throw Networking::SocketCreationError( // throw. throw Networking::SocketCreationError( // throw.
Network.DescriptiveError( Network.DescriptiveError(
"TCPHost::open().socket()", LastError));
"TCPHost::TCPHost().socket()", LastError));
} }
} }


LastError = 0; // Clear our LastError value. LastError = 0; // Clear our LastError value.
bool SuccessFlag = true; // Begin optimistically. bool SuccessFlag = true; // Begin optimistically.


// Set SO_REUSEADDR if turned on
// 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
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(
Handle, Handle,
SOL_SOCKET, SOL_SOCKET,
SO_REUSEADDR, SO_REUSEADDR,
(char *)&ReuseAddress_Flag,
(char*) &ReuseAddress_Flag,
sizeof(ReuseAddress_Flag)); sizeof(ReuseAddress_Flag));


if(0 > result) { // If there was an error then if(0 > result) { // If there was an error then
LastError = Network.getLastError(); // Capture the error information and LastError = Network.getLastError(); // Capture the error information and
throw Networking::SocketSetSockOptError( // throw. throw Networking::SocketSetSockOptError( // throw.
Network.DescriptiveError( 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. OpenStage1Complete = true; // Skip this section from now on.
} // Done with stage 1. } // Done with stage 1.



+ 10
- 4
networking.hpp View File

typedef int socklen_t; // Posix uses socklen_t so we mimic it. typedef int socklen_t; // Posix uses socklen_t so we mimic it.
typedef SOCKET hSocket; // Winx handles Socket is opaque. typedef SOCKET hSocket; // Winx handles Socket is opaque.
#ifndef NO_SIGNALS
const int MSG_NOSIGNAL = 0; // Make NO_SIGNALS for winsock.
#endif

#else #else


//// GNU Headers... //// GNU Headers...


#endif #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 ////////////////////////////////////////////////////// //// Tuning and Constants //////////////////////////////////////////////////////


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

Loading…
Cancel
Save