aboutsummaryrefslogtreecommitdiff
path: root/src/socket.cpp
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2009-01-19 21:46:48 +0000
committerMike Buland <eichlan@xagasoft.com>2009-01-19 21:46:48 +0000
commit9d099f181674ae075aa8ccaeb56acc7b732638af (patch)
treea376da5671e044e74b4014d43c9125974b4dee0c /src/socket.cpp
parent8c1f4d7bace6ff2c99d546cedaba890b349e88f8 (diff)
downloadlibbu++-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.
Diffstat (limited to '')
-rw-r--r--src/socket.cpp49
1 files changed, 31 insertions, 18 deletions
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
137size_t Bu::Socket::read( void *pBuf, size_t nBytes ) 139size_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
160size_t Bu::Socket::read( void *pBuf, size_t nBytes, 173size_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
204size_t Bu::Socket::write( const void *pBuf, size_t nBytes ) 217size_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