diff options
Diffstat (limited to 'src/socket.cpp')
-rw-r--r-- | src/socket.cpp | 146 |
1 files changed, 31 insertions, 115 deletions
diff --git a/src/socket.cpp b/src/socket.cpp index c57d97e..dd19d39 100644 --- a/src/socket.cpp +++ b/src/socket.cpp | |||
@@ -14,9 +14,10 @@ | |||
14 | #include <sys/time.h> | 14 | #include <sys/time.h> |
15 | #include <errno.h> | 15 | #include <errno.h> |
16 | #include <fcntl.h> | 16 | #include <fcntl.h> |
17 | #include "socket.h" | 17 | #include "bu/socket.h" |
18 | #include "osx_compatibility.h" | 18 | #include "bu/osx_compatibility.h" |
19 | #include "win32_compatibility.h" | 19 | #include "bu/win32_compatibility.h" |
20 | #include "bu/linux_compatibility.h" | ||
20 | 21 | ||
21 | #ifndef WIN32 | 22 | #ifndef WIN32 |
22 | #include <sys/socket.h> | 23 | #include <sys/socket.h> |
@@ -36,7 +37,7 @@ Bu::Socket::Socket( int nSocket ) : | |||
36 | bActive( true ) | 37 | bActive( true ) |
37 | { | 38 | { |
38 | #ifdef WIN32 | 39 | #ifdef WIN32 |
39 | DynamicWinsock2::Winsock2::getInstance(); | 40 | Bu::Winsock2::getInstance(); |
40 | #endif | 41 | #endif |
41 | setAddress(); | 42 | setAddress(); |
42 | } | 43 | } |
@@ -44,37 +45,19 @@ Bu::Socket::Socket( int nSocket ) : | |||
44 | Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout ) | 45 | Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout ) |
45 | { | 46 | { |
46 | #ifdef WIN32 | 47 | #ifdef WIN32 |
47 | DynamicWinsock2::Winsock2::getInstance(); | 48 | Bu::Winsock2::getInstance(); |
48 | #endif | 49 | #endif |
49 | bActive = false; | 50 | bActive = false; |
50 | 51 | ||
51 | /* Create the socket. */ | 52 | /* Create the socket. */ |
52 | nSocket = DYNLOAD socket( PF_INET, SOCK_STREAM, 0 ); | 53 | nSocket = bu_socket( PF_INET, SOCK_STREAM, 0 ); |
53 | 54 | ||
54 | if( nSocket < 0 ) | 55 | if( nSocket < 0 ) |
55 | { | 56 | { |
56 | throw ExceptionBase("Couldn't create socket.\n"); | 57 | throw ExceptionBase("Couldn't create socket.\n"); |
57 | } | 58 | } |
58 | 59 | ||
59 | // These lines set the socket to non-blocking, a good thing? | 60 | setBlocking( false ); |
60 | #ifndef WIN32 | ||
61 | int flags; | ||
62 | flags = fcntl(nSocket, F_GETFL, 0); | ||
63 | flags |= O_NONBLOCK; | ||
64 | if (fcntl(nSocket, F_SETFL, flags) < 0) | ||
65 | { | ||
66 | throw Bu::SocketException("Couldn't set socket options.\n"); | ||
67 | } | ||
68 | #else | ||
69 | //------------------------- | ||
70 | // Set the socket I/O mode: In this case FIONBIO | ||
71 | // enables or disables the blocking mode for the | ||
72 | // socket based on the numerical value of iMode. | ||
73 | // If iMode = 0, blocking is enabled; | ||
74 | // If iMode != 0, non-blocking mode is enabled. | ||
75 | u_long iMode = 1; | ||
76 | DYNLOAD ioctlsocket(nSocket, FIONBIO, &iMode); | ||
77 | #endif | ||
78 | 61 | ||
79 | /* Connect to the server. */ | 62 | /* Connect to the server. */ |
80 | //printf("Resolving hostname (%s)...\n", sAddr ); | 63 | //printf("Resolving hostname (%s)...\n", sAddr ); |
@@ -89,19 +72,14 @@ Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout ) | |||
89 | sprintf( ibuf, "%d", nPort ); | 72 | sprintf( ibuf, "%d", nPort ); |
90 | 73 | ||
91 | int ret; | 74 | int ret; |
92 | if( (ret = DYNLOAD getaddrinfo( | 75 | if( (ret = bu_getaddrinfo( |
93 | sAddr.getStr(), ibuf, &aiHints, &pAddr )) != 0 ) | 76 | sAddr.getStr(), ibuf, &aiHints, &pAddr )) != 0 ) |
94 | { | 77 | { |
95 | #ifdef WIN32 | ||
96 | throw Bu::SocketException("Couldn't resolve hostname %s (%d).\n", | ||
97 | sAddr.getStr(), DYNLOAD WSAGetLastError()); | ||
98 | #else | ||
99 | throw Bu::SocketException("Couldn't resolve hostname %s (%s).\n", | 78 | throw Bu::SocketException("Couldn't resolve hostname %s (%s).\n", |
100 | sAddr.getStr(), DYNLOAD gai_strerror(ret)); | 79 | sAddr.getStr(), bu_gai_strerror(ret)); |
101 | #endif | ||
102 | } | 80 | } |
103 | 81 | ||
104 | DYNLOAD connect( | 82 | bu_connect( |
105 | nSocket, | 83 | nSocket, |
106 | pAddr->ai_addr, | 84 | pAddr->ai_addr, |
107 | pAddr->ai_addrlen | 85 | pAddr->ai_addrlen |
@@ -109,7 +87,7 @@ Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout ) | |||
109 | 87 | ||
110 | sAddress = pAddr->ai_canonname; | 88 | sAddress = pAddr->ai_canonname; |
111 | 89 | ||
112 | DYNLOAD freeaddrinfo( pAddr ); | 90 | bu_freeaddrinfo( pAddr ); |
113 | } | 91 | } |
114 | 92 | ||
115 | bActive = true; | 93 | bActive = true; |
@@ -130,7 +108,7 @@ Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout ) | |||
130 | tv.tv_sec = nTimeout; | 108 | tv.tv_sec = nTimeout; |
131 | tv.tv_usec = 0; | 109 | tv.tv_usec = 0; |
132 | 110 | ||
133 | retval = DYNLOAD select( nSocket+1, &rfds, &wfds, &efds, &tv ); | 111 | retval = bu_select( nSocket+1, &rfds, &wfds, &efds, &tv ); |
134 | 112 | ||
135 | if( retval == 0 ) | 113 | if( retval == 0 ) |
136 | { | 114 | { |
@@ -156,75 +134,20 @@ void Bu::Socket::close() | |||
156 | bActive = false; | 134 | bActive = false; |
157 | } | 135 | } |
158 | 136 | ||
159 | /* | ||
160 | void Bu::Socket::read() | ||
161 | { | ||
162 | char buffer[RBS]; | ||
163 | int nbytes; | ||
164 | int nTotalRead=0; | ||
165 | |||
166 | for(;;) | ||
167 | { | ||
168 | //memset( buffer, 0, RBS ); | ||
169 | |||
170 | nbytes = ::read( nSocket, buffer, RBS ); | ||
171 | if( nbytes < 0 && errno != 0 && errno != EAGAIN ) | ||
172 | { | ||
173 | //printf("errno: %d, %s\n", errno, strerror( errno ) ); | ||
174 | //perror("readInput"); | ||
175 | throw SocketException( | ||
176 | SocketException::cRead, | ||
177 | "Read error: %s", | ||
178 | strerror( errno ) | ||
179 | ); | ||
180 | } | ||
181 | else | ||
182 | { | ||
183 | if( nbytes <= 0 ) | ||
184 | break; | ||
185 | nTotalRead += nbytes; | ||
186 | sReadBuf.append( buffer, nbytes ); | ||
187 | if( nbytes < RBS ) | ||
188 | { | ||
189 | break; | ||
190 | } | ||
191 | |||
192 | // New test, if data is divisible by RBS bytes on some libs the | ||
193 | // read could block, this keeps it from happening. | ||
194 | { | ||
195 | fd_set rfds; | ||
196 | FD_ZERO(&rfds); | ||
197 | FD_SET(nSocket, &rfds); | ||
198 | struct timeval tv = { 0, 0 }; | ||
199 | int retval = select( nSocket+1, &rfds, NULL, NULL, &tv ); | ||
200 | if( retval == -1 ) | ||
201 | throw SocketException( | ||
202 | SocketException::cBadRead, | ||
203 | "Bad Read error" | ||
204 | ); | ||
205 | if( !FD_ISSET( nSocket, &rfds ) ) | ||
206 | break; | ||
207 | } | ||
208 | } | ||
209 | } | ||
210 | }*/ | ||
211 | |||
212 | size_t Bu::Socket::read( void *pBuf, size_t nBytes ) | 137 | size_t Bu::Socket::read( void *pBuf, size_t nBytes ) |
213 | { | 138 | { |
214 | #ifdef WIN32 | 139 | #ifdef WIN32 |
215 | int nRead = TEMP_FAILURE_RETRY( | 140 | int nRead = TEMP_FAILURE_RETRY( |
216 | DYNLOAD recv( nSocket, (char *) pBuf, nBytes, 0 ) ); | 141 | bu_recv( nSocket, (char *) pBuf, nBytes, 0 ) ); |
217 | #else | 142 | #else |
218 | int nRead = TEMP_FAILURE_RETRY( ::read( nSocket, pBuf, nBytes ) ); | 143 | int nRead = TEMP_FAILURE_RETRY( ::read( nSocket, pBuf, nBytes ) ); |
219 | #endif | 144 | #endif |
220 | if( nRead < 0 ) | 145 | if( nRead < 0 ) |
221 | { | 146 | { |
222 | #ifdef WIN32 | 147 | #ifdef WIN32 |
223 | int iWSAError = DYNLOAD WSAGetLastError(); | 148 | int iWSAError = bu_WSAGetLastError(); |
224 | if( iWSAError == WSAEWOULDBLOCK ) | 149 | if( iWSAError == WSAEWOULDBLOCK ) |
225 | return 0; | 150 | return 0; |
226 | printf( "WSAGetLastError: %d\n", iWSAError ); | ||
227 | return 0; | ||
228 | #else | 151 | #else |
229 | if( errno == EAGAIN ) | 152 | if( errno == EAGAIN ) |
230 | return 0; | 153 | return 0; |
@@ -259,7 +182,7 @@ size_t Bu::Socket::read( void *pBuf, size_t nBytes, | |||
259 | { | 182 | { |
260 | tv.tv_sec = nSec; | 183 | tv.tv_sec = nSec; |
261 | tv.tv_usec = nUSec; | 184 | tv.tv_usec = nUSec; |
262 | DYNLOAD select( nSocket+1, &rfds, NULL, NULL, &tv ); | 185 | bu_select( nSocket+1, &rfds, NULL, NULL, &tv ); |
263 | nRead += read( ((char *)pBuf)+nRead, nBytes-nRead ); | 186 | nRead += read( ((char *)pBuf)+nRead, nBytes-nRead ); |
264 | if( nRead >= nBytes ) | 187 | if( nRead >= nBytes ) |
265 | break; | 188 | break; |
@@ -282,13 +205,19 @@ size_t Bu::Socket::write( const void *pBuf, size_t nBytes ) | |||
282 | { | 205 | { |
283 | #ifdef WIN32 | 206 | #ifdef WIN32 |
284 | int nWrote = TEMP_FAILURE_RETRY( | 207 | int nWrote = TEMP_FAILURE_RETRY( |
285 | DYNLOAD send( nSocket, (const char *) pBuf, nBytes, 0 ) ); | 208 | bu_send( nSocket, (const char *) pBuf, nBytes, 0 ) ); |
286 | #else | 209 | #else |
287 | int nWrote = TEMP_FAILURE_RETRY( ::write( nSocket, pBuf, nBytes ) ); | 210 | int nWrote = TEMP_FAILURE_RETRY( ::write( nSocket, pBuf, nBytes ) ); |
288 | #endif | 211 | #endif |
289 | if( nWrote < 0 ) | 212 | if( nWrote < 0 ) |
290 | { | 213 | { |
214 | #ifdef WIN32 | ||
215 | int iWSAError = bu_WSAGetLastError(); | ||
216 | if( iWSAError == WSAEWOULDBLOCK ) | ||
217 | return 0; | ||
218 | #else | ||
291 | if( errno == EAGAIN ) return 0; | 219 | if( errno == EAGAIN ) return 0; |
220 | #endif | ||
292 | throw SocketException( SocketException::cWrite, strerror(errno) ); | 221 | throw SocketException( SocketException::cWrite, strerror(errno) ); |
293 | } | 222 | } |
294 | return nWrote; | 223 | return nWrote; |
@@ -318,7 +247,7 @@ size_t Bu::Socket::write( const void *pBuf, size_t nBytes, uint32_t nSec, uint32 | |||
318 | { | 247 | { |
319 | tv.tv_sec = nSec; | 248 | tv.tv_sec = nSec; |
320 | tv.tv_usec = nUSec; | 249 | tv.tv_usec = nUSec; |
321 | DYNLOAD select( nSocket+1, NULL, &wfds, NULL, &tv ); | 250 | bu_select( nSocket+1, NULL, &wfds, NULL, &tv ); |
322 | nWrote += write( ((char *)pBuf)+nWrote, nBytes-nWrote ); | 251 | nWrote += write( ((char *)pBuf)+nWrote, nBytes-nWrote ); |
323 | if( nWrote >= nBytes ) | 252 | if( nWrote >= nBytes ) |
324 | break; | 253 | break; |
@@ -368,17 +297,14 @@ bool Bu::Socket::canRead() | |||
368 | FD_ZERO(&rfds); | 297 | FD_ZERO(&rfds); |
369 | FD_SET(nSocket, &rfds); | 298 | FD_SET(nSocket, &rfds); |
370 | struct timeval tv = { 0, 0 }; | 299 | struct timeval tv = { 0, 0 }; |
371 | int retval = DYNLOAD select( nSocket+1, &rfds, NULL, NULL, &tv ); | 300 | int retval = bu_select( nSocket+1, &rfds, NULL, NULL, &tv ); |
372 | if( retval == -1 ) | 301 | if( retval == -1 ) |
373 | throw SocketException( | 302 | throw SocketException( |
374 | SocketException::cBadRead, | 303 | SocketException::cBadRead, |
375 | "Bad Read error" | 304 | "Bad Read error" |
376 | ); | 305 | ); |
377 | #ifdef WIN32 | 306 | |
378 | if( !DynamicWinsock2::DYN_FD_ISSET( nSocket, &rfds ) ) | ||
379 | #else | ||
380 | if( !FD_ISSET( nSocket, &rfds ) ) | 307 | if( !FD_ISSET( nSocket, &rfds ) ) |
381 | #endif | ||
382 | return false; | 308 | return false; |
383 | return true; | 309 | return true; |
384 | } | 310 | } |
@@ -389,17 +315,13 @@ bool Bu::Socket::canWrite() | |||
389 | FD_ZERO(&wfds); | 315 | FD_ZERO(&wfds); |
390 | FD_SET(nSocket, &wfds); | 316 | FD_SET(nSocket, &wfds); |
391 | struct timeval tv = { 0, 0 }; | 317 | struct timeval tv = { 0, 0 }; |
392 | int retval = DYNLOAD select( nSocket+1, NULL, &wfds, NULL, &tv ); | 318 | int retval = bu_select( nSocket+1, NULL, &wfds, NULL, &tv ); |
393 | if( retval == -1 ) | 319 | if( retval == -1 ) |
394 | throw SocketException( | 320 | throw SocketException( |
395 | SocketException::cBadRead, | 321 | SocketException::cBadRead, |
396 | "Bad Read error" | 322 | "Bad Read error" |
397 | ); | 323 | ); |
398 | #ifdef WIN32 | ||
399 | if( !DynamicWinsock2::DYN_FD_ISSET( nSocket, &wfds ) ) | ||
400 | #else | ||
401 | if( !FD_ISSET( nSocket, &wfds ) ) | 324 | if( !FD_ISSET( nSocket, &wfds ) ) |
402 | #endif | ||
403 | return false; | 325 | return false; |
404 | return true; | 326 | return true; |
405 | } | 327 | } |
@@ -447,7 +369,7 @@ void Bu::Socket::setBlocking( bool bBlocking ) | |||
447 | // socket based on the numerical value of iMode. | 369 | // socket based on the numerical value of iMode. |
448 | // If iMode = 0, blocking is enabled; | 370 | // If iMode = 0, blocking is enabled; |
449 | // If iMode != 0, non-blocking mode is enabled. | 371 | // If iMode != 0, non-blocking mode is enabled. |
450 | DYNLOAD ioctlsocket(nSocket, FIONBIO, &iMode); | 372 | bu_ioctlsocket(nSocket, FIONBIO, &iMode); |
451 | #endif | 373 | #endif |
452 | } | 374 | } |
453 | 375 | ||
@@ -465,15 +387,8 @@ void Bu::Socket::setAddress() | |||
465 | struct sockaddr_in addr; | 387 | struct sockaddr_in addr; |
466 | socklen_t len = sizeof(addr); | 388 | socklen_t len = sizeof(addr); |
467 | addr.sin_family = AF_INET; | 389 | addr.sin_family = AF_INET; |
468 | // getsockname( nSocket, (sockaddr *)(&addr), &len ); | 390 | bu_getpeername( nSocket, (sockaddr *)(&addr), &len ); |
469 | DYNLOAD getpeername( nSocket, (sockaddr *)(&addr), &len ); | 391 | sAddress = bu_inet_ntoa( addr.sin_addr ); |
470 | #ifdef WIN32 | ||
471 | DYNLOAD inet_ntoa( sAddress, addr.sin_addr ); | ||
472 | #else | ||
473 | char buf[150]; | ||
474 | sprintf( buf, "%s", inet_ntoa( addr.sin_addr ) ); | ||
475 | sAddress = buf; | ||
476 | #endif | ||
477 | } | 392 | } |
478 | 393 | ||
479 | Bu::FString Bu::Socket::getAddress() const | 394 | Bu::FString Bu::Socket::getAddress() const |
@@ -485,3 +400,4 @@ Bu::Socket::operator int() const | |||
485 | { | 400 | { |
486 | return nSocket; | 401 | return nSocket; |
487 | } | 402 | } |
403 | |||