summaryrefslogtreecommitdiff
path: root/src
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
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 'src')
-rw-r--r--src/formula.h3
-rw-r--r--src/linux_compatibility.h2
-rw-r--r--src/socket.cpp49
-rw-r--r--src/tests/socketbreak.cpp27
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
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
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
4int 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