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