diff options
| author | Mike Buland <eichlan@xagasoft.com> | 2009-01-19 21:46:48 +0000 |
|---|---|---|
| committer | Mike Buland <eichlan@xagasoft.com> | 2009-01-19 21:46:48 +0000 |
| commit | 9d099f181674ae075aa8ccaeb56acc7b732638af (patch) | |
| tree | a376da5671e044e74b4014d43c9125974b4dee0c | |
| parent | 8c1f4d7bace6ff2c99d546cedaba890b349e88f8 (diff) | |
| download | libbu++-9d099f181674ae075aa8ccaeb56acc7b732638af.tar.gz libbu++-9d099f181674ae075aa8ccaeb56acc7b732638af.tar.bz2 libbu++-9d099f181674ae075aa8ccaeb56acc7b732638af.tar.xz libbu++-9d099f181674ae075aa8ccaeb56acc7b732638af.zip | |
This should fix the problem of never knowing if your sockets are closed. Now
Bu::Socket::read will throw an exception if the socket has been closed. Also,
you'll get an exception at object creation if the socket could connect to a
computer, but not the given port.
| -rw-r--r-- | src/formula.h | 3 | ||||
| -rw-r--r-- | src/linux_compatibility.h | 2 | ||||
| -rw-r--r-- | src/socket.cpp | 49 | ||||
| -rw-r--r-- | src/tests/socketbreak.cpp | 27 |
4 files changed, 62 insertions, 19 deletions
diff --git a/src/formula.h b/src/formula.h index c57c4bb..c88e409 100644 --- a/src/formula.h +++ b/src/formula.h | |||
| @@ -44,8 +44,9 @@ namespace Bu | |||
| 44 | { | 44 | { |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | prec run( const char *sFormula ) | 47 | prec run( const Bu::FString &sFormulaSrc ) |
| 48 | { | 48 | { |
| 49 | const char *sFormula = sFormulaSrc.getStr(); | ||
| 49 | for(;;) | 50 | for(;;) |
| 50 | { | 51 | { |
| 51 | uint8_t tNum = nextToken( &sFormula ); | 52 | uint8_t tNum = nextToken( &sFormula ); |
diff --git a/src/linux_compatibility.h b/src/linux_compatibility.h index 67016a7..6d3d85e 100644 --- a/src/linux_compatibility.h +++ b/src/linux_compatibility.h | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | #define bu_bind bind | 15 | #define bu_bind bind |
| 16 | #define bu_listen listen | 16 | #define bu_listen listen |
| 17 | #define bu_accept accept | 17 | #define bu_accept accept |
| 18 | #define bu_send send | ||
| 19 | #define bu_recv recv | ||
| 18 | 20 | ||
| 19 | #define bu_gai_strerror gai_strerror | 21 | #define bu_gai_strerror gai_strerror |
| 20 | 22 | ||
diff --git a/src/socket.cpp b/src/socket.cpp index dd19d39..3e4f3c7 100644 --- a/src/socket.cpp +++ b/src/socket.cpp | |||
| @@ -115,6 +115,7 @@ Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout ) | |||
| 115 | close(); | 115 | close(); |
| 116 | throw ExceptionBase("Connection timeout.\n"); | 116 | throw ExceptionBase("Connection timeout.\n"); |
| 117 | } | 117 | } |
| 118 | read( NULL, 0 ); // See if we can get any errors out of the way early. | ||
| 118 | } | 119 | } |
| 119 | } | 120 | } |
| 120 | 121 | ||
| @@ -129,6 +130,7 @@ void Bu::Socket::close() | |||
| 129 | #ifndef WIN32 | 130 | #ifndef WIN32 |
| 130 | fsync( nSocket ); | 131 | fsync( nSocket ); |
| 131 | #endif | 132 | #endif |
| 133 | shutdown( nSocket, SHUT_RDWR ); | ||
| 132 | ::close( nSocket ); | 134 | ::close( nSocket ); |
| 133 | } | 135 | } |
| 134 | bActive = false; | 136 | bActive = false; |
| @@ -136,25 +138,36 @@ void Bu::Socket::close() | |||
| 136 | 138 | ||
| 137 | size_t Bu::Socket::read( void *pBuf, size_t nBytes ) | 139 | size_t Bu::Socket::read( void *pBuf, size_t nBytes ) |
| 138 | { | 140 | { |
| 139 | #ifdef WIN32 | 141 | fd_set rfds; |
| 140 | int nRead = TEMP_FAILURE_RETRY( | 142 | FD_ZERO(&rfds); |
| 141 | bu_recv( nSocket, (char *) pBuf, nBytes, 0 ) ); | 143 | FD_SET(nSocket, &rfds); |
| 142 | #else | 144 | struct timeval tv = {0, 0}; |
| 143 | int nRead = TEMP_FAILURE_RETRY( ::read( nSocket, pBuf, nBytes ) ); | 145 | if( bu_select( nSocket+1, &rfds, NULL, NULL, &tv ) < 0 ) |
| 144 | #endif | 146 | throw SocketException( SocketException::cRead, strerror(errno) ); |
| 145 | if( nRead < 0 ) | 147 | if( FD_ISSET( nSocket, &rfds ) ) |
| 146 | { | 148 | { |
| 149 | int nRead = TEMP_FAILURE_RETRY( | ||
| 150 | bu_recv( nSocket, (char *) pBuf, nBytes, 0 ) ); | ||
| 151 | if( nRead == 0 ) | ||
| 152 | { | ||
| 153 | bActive = false; | ||
| 154 | throw SocketException( SocketException::cClosed, "Socket closed."); | ||
| 155 | } | ||
| 156 | if( nRead < 0 ) | ||
| 157 | { | ||
| 147 | #ifdef WIN32 | 158 | #ifdef WIN32 |
| 148 | int iWSAError = bu_WSAGetLastError(); | 159 | int iWSAError = bu_WSAGetLastError(); |
| 149 | if( iWSAError == WSAEWOULDBLOCK ) | 160 | if( iWSAError == WSAEWOULDBLOCK ) |
| 150 | return 0; | 161 | return 0; |
| 151 | #else | 162 | #else |
| 152 | if( errno == EAGAIN ) | 163 | if( errno == EAGAIN ) |
| 153 | return 0; | 164 | return 0; |
| 154 | throw SocketException( SocketException::cRead, strerror(errno) ); | 165 | throw SocketException( SocketException::cRead, strerror(errno) ); |
| 155 | #endif | 166 | #endif |
| 167 | } | ||
| 168 | return nRead; | ||
| 156 | } | 169 | } |
| 157 | return nRead; | 170 | return 0; |
| 158 | } | 171 | } |
| 159 | 172 | ||
| 160 | size_t Bu::Socket::read( void *pBuf, size_t nBytes, | 173 | size_t Bu::Socket::read( void *pBuf, size_t nBytes, |
| @@ -203,12 +216,12 @@ size_t Bu::Socket::read( void *pBuf, size_t nBytes, | |||
| 203 | 216 | ||
| 204 | size_t Bu::Socket::write( const void *pBuf, size_t nBytes ) | 217 | size_t Bu::Socket::write( const void *pBuf, size_t nBytes ) |
| 205 | { | 218 | { |
| 206 | #ifdef WIN32 | 219 | //#ifdef WIN32 |
| 207 | int nWrote = TEMP_FAILURE_RETRY( | 220 | int nWrote = TEMP_FAILURE_RETRY( |
| 208 | bu_send( nSocket, (const char *) pBuf, nBytes, 0 ) ); | 221 | bu_send( nSocket, (const char *) pBuf, nBytes, 0 ) ); |
| 209 | #else | 222 | //#else |
| 210 | int nWrote = TEMP_FAILURE_RETRY( ::write( nSocket, pBuf, nBytes ) ); | 223 | // int nWrote = TEMP_FAILURE_RETRY( ::write( nSocket, pBuf, nBytes ) ); |
| 211 | #endif | 224 | //#endif |
| 212 | if( nWrote < 0 ) | 225 | if( nWrote < 0 ) |
| 213 | { | 226 | { |
| 214 | #ifdef WIN32 | 227 | #ifdef WIN32 |
diff --git a/src/tests/socketbreak.cpp b/src/tests/socketbreak.cpp new file mode 100644 index 0000000..82069de --- /dev/null +++ b/src/tests/socketbreak.cpp | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #include "bu/serversocket.h" | ||
| 2 | #include "bu/socket.h" | ||
| 3 | |||
| 4 | int main() | ||
| 5 | { | ||
| 6 | Bu::ServerSocket sSrv( 9987 ); | ||
| 7 | |||
| 8 | Bu::Socket sSend("localhost", 9987 ); | ||
| 9 | |||
| 10 | Bu::Socket sRecv( sSrv.accept() ); | ||
| 11 | |||
| 12 | printf("Connected sockets.\n"); | ||
| 13 | |||
| 14 | sleep( 1 ); | ||
| 15 | printf("Closing sRecv.\n"); | ||
| 16 | sRecv.close(); | ||
| 17 | sleep( 1 ); | ||
| 18 | |||
| 19 | char buf[3]; | ||
| 20 | printf("About to write.\n"); | ||
| 21 | printf("write: %d\n", sSend.write("hi", 2 ) ); | ||
| 22 | printf("About to read.\n"); | ||
| 23 | printf("read: %d\n", sSend.read( buf, 2 ) ); | ||
| 24 | |||
| 25 | return 0; | ||
| 26 | } | ||
| 27 | |||
