diff options
Diffstat (limited to 'src/socket.cpp')
-rw-r--r-- | src/socket.cpp | 77 |
1 files changed, 73 insertions, 4 deletions
diff --git a/src/socket.cpp b/src/socket.cpp index 531d8ac..1e9a2f9 100644 --- a/src/socket.cpp +++ b/src/socket.cpp | |||
@@ -11,16 +11,21 @@ | |||
11 | #include <stdlib.h> | 11 | #include <stdlib.h> |
12 | #include <unistd.h> | 12 | #include <unistd.h> |
13 | #include <sys/types.h> | 13 | #include <sys/types.h> |
14 | #include <sys/socket.h> | ||
15 | #include <sys/time.h> | 14 | #include <sys/time.h> |
16 | #include <netinet/in.h> | ||
17 | #include <netdb.h> | ||
18 | #include <arpa/inet.h> | ||
19 | #include <errno.h> | 15 | #include <errno.h> |
20 | #include <fcntl.h> | 16 | #include <fcntl.h> |
21 | #include "socket.h" | 17 | #include "socket.h" |
22 | #include "osx_compatibility.h" | 18 | #include "osx_compatibility.h" |
23 | 19 | ||
20 | #ifndef WIN32 | ||
21 | #include <sys/socket.h> | ||
22 | #include <netinet/in.h> | ||
23 | #include <netdb.h> | ||
24 | #include <arpa/inet.h> | ||
25 | #else | ||
26 | #include <Winsock2.h> | ||
27 | #endif | ||
28 | |||
24 | #define RBS (1024*2) | 29 | #define RBS (1024*2) |
25 | 30 | ||
26 | namespace Bu { subExceptionDef( SocketException ) } | 31 | namespace Bu { subExceptionDef( SocketException ) } |
@@ -46,6 +51,7 @@ Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout ) | |||
46 | } | 51 | } |
47 | 52 | ||
48 | // These lines set the socket to non-blocking, a good thing? | 53 | // These lines set the socket to non-blocking, a good thing? |
54 | #ifndef WIN32 | ||
49 | int flags; | 55 | int flags; |
50 | flags = fcntl(nSocket, F_GETFL, 0); | 56 | flags = fcntl(nSocket, F_GETFL, 0); |
51 | flags |= O_NONBLOCK; | 57 | flags |= O_NONBLOCK; |
@@ -53,6 +59,16 @@ Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout ) | |||
53 | { | 59 | { |
54 | throw Bu::SocketException("Couldn't set socket options.\n"); | 60 | throw Bu::SocketException("Couldn't set socket options.\n"); |
55 | } | 61 | } |
62 | #else | ||
63 | //------------------------- | ||
64 | // Set the socket I/O mode: In this case FIONBIO | ||
65 | // enables or disables the blocking mode for the | ||
66 | // socket based on the numerical value of iMode. | ||
67 | // If iMode = 0, blocking is enabled; | ||
68 | // If iMode != 0, non-blocking mode is enabled. | ||
69 | u_long iMode = 1; | ||
70 | ioctlsocket(nSocket, FIONBIO, &iMode); | ||
71 | #endif | ||
56 | 72 | ||
57 | /* Connect to the server. */ | 73 | /* Connect to the server. */ |
58 | //printf("Resolving hostname (%s)...\n", sAddr ); | 74 | //printf("Resolving hostname (%s)...\n", sAddr ); |
@@ -115,7 +131,9 @@ void Bu::Socket::close() | |||
115 | { | 131 | { |
116 | if( bActive ) | 132 | if( bActive ) |
117 | { | 133 | { |
134 | #ifndef WIN32 | ||
118 | fsync( nSocket ); | 135 | fsync( nSocket ); |
136 | #endif | ||
119 | ::close( nSocket ); | 137 | ::close( nSocket ); |
120 | } | 138 | } |
121 | bActive = false; | 139 | bActive = false; |
@@ -176,7 +194,11 @@ void Bu::Socket::read() | |||
176 | 194 | ||
177 | size_t Bu::Socket::read( void *pBuf, size_t nBytes ) | 195 | size_t Bu::Socket::read( void *pBuf, size_t nBytes ) |
178 | { | 196 | { |
197 | #ifndef WIN32 | ||
179 | int nRead = TEMP_FAILURE_RETRY( ::read( nSocket, pBuf, nBytes ) ); | 198 | int nRead = TEMP_FAILURE_RETRY( ::read( nSocket, pBuf, nBytes ) ); |
199 | #else | ||
200 | int nRead = ::read( nSocket, pBuf, nBytes ); | ||
201 | #endif | ||
180 | if( nRead < 0 ) | 202 | if( nRead < 0 ) |
181 | { | 203 | { |
182 | throw SocketException( SocketException::cRead, strerror(errno) ); | 204 | throw SocketException( SocketException::cRead, strerror(errno) ); |
@@ -194,9 +216,15 @@ size_t Bu::Socket::read( void *pBuf, size_t nBytes, | |||
194 | FD_ZERO(&rfds); | 216 | FD_ZERO(&rfds); |
195 | FD_SET(nSocket, &rfds); | 217 | FD_SET(nSocket, &rfds); |
196 | 218 | ||
219 | #ifndef WIN32 | ||
197 | gettimeofday( &nt, NULL ); | 220 | gettimeofday( &nt, NULL ); |
198 | nt.tv_sec += nSec; | 221 | nt.tv_sec += nSec; |
199 | nt.tv_usec += nUSec; | 222 | nt.tv_usec += nUSec; |
223 | #else | ||
224 | DWORD dwStart = GetTickCount(); | ||
225 | uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000)); | ||
226 | DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver; | ||
227 | #endif | ||
200 | 228 | ||
201 | for(;;) | 229 | for(;;) |
202 | { | 230 | { |
@@ -206,18 +234,28 @@ size_t Bu::Socket::read( void *pBuf, size_t nBytes, | |||
206 | nRead += read( ((char *)pBuf)+nRead, nBytes-nRead ); | 234 | nRead += read( ((char *)pBuf)+nRead, nBytes-nRead ); |
207 | if( nRead >= nBytes ) | 235 | if( nRead >= nBytes ) |
208 | break; | 236 | break; |
237 | #ifndef WIN32 | ||
209 | gettimeofday( &ct, NULL ); | 238 | gettimeofday( &ct, NULL ); |
210 | if( (ct.tv_sec > nt.tv_sec) || | 239 | if( (ct.tv_sec > nt.tv_sec) || |
211 | (ct.tv_sec == nt.tv_sec && | 240 | (ct.tv_sec == nt.tv_sec && |
212 | ct.tv_usec >= nt.tv_usec) ) | 241 | ct.tv_usec >= nt.tv_usec) ) |
213 | break; | 242 | break; |
243 | #else | ||
244 | DWORD dwNow = GetTickCount(); | ||
245 | if( dwNow > dwEnd ) | ||
246 | break; | ||
247 | #endif | ||
214 | } | 248 | } |
215 | return nRead; | 249 | return nRead; |
216 | } | 250 | } |
217 | 251 | ||
218 | size_t Bu::Socket::write( const void *pBuf, size_t nBytes ) | 252 | size_t Bu::Socket::write( const void *pBuf, size_t nBytes ) |
219 | { | 253 | { |
254 | #ifndef WIN32 | ||
220 | int nWrote = TEMP_FAILURE_RETRY( ::write( nSocket, pBuf, nBytes ) ); | 255 | int nWrote = TEMP_FAILURE_RETRY( ::write( nSocket, pBuf, nBytes ) ); |
256 | #else | ||
257 | int nWrote = ::write( nSocket, pBuf, nBytes ); | ||
258 | #endif | ||
221 | if( nWrote < 0 ) | 259 | if( nWrote < 0 ) |
222 | { | 260 | { |
223 | if( errno == EAGAIN ) return 0; | 261 | if( errno == EAGAIN ) return 0; |
@@ -235,9 +273,15 @@ size_t Bu::Socket::write( const void *pBuf, size_t nBytes, uint32_t nSec, uint32 | |||
235 | FD_ZERO(&wfds); | 273 | FD_ZERO(&wfds); |
236 | FD_SET(nSocket, &wfds); | 274 | FD_SET(nSocket, &wfds); |
237 | 275 | ||
276 | #ifndef WIN32 | ||
238 | gettimeofday( &nt, NULL ); | 277 | gettimeofday( &nt, NULL ); |
239 | nt.tv_sec += nSec; | 278 | nt.tv_sec += nSec; |
240 | nt.tv_usec += nUSec; | 279 | nt.tv_usec += nUSec; |
280 | #else | ||
281 | DWORD dwStart = GetTickCount(); | ||
282 | uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000)); | ||
283 | DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver; | ||
284 | #endif | ||
241 | 285 | ||
242 | for(;;) | 286 | for(;;) |
243 | { | 287 | { |
@@ -247,11 +291,17 @@ size_t Bu::Socket::write( const void *pBuf, size_t nBytes, uint32_t nSec, uint32 | |||
247 | nWrote += write( ((char *)pBuf)+nWrote, nBytes-nWrote ); | 291 | nWrote += write( ((char *)pBuf)+nWrote, nBytes-nWrote ); |
248 | if( nWrote >= nBytes ) | 292 | if( nWrote >= nBytes ) |
249 | break; | 293 | break; |
294 | #ifndef WIN32 | ||
250 | gettimeofday( &ct, NULL ); | 295 | gettimeofday( &ct, NULL ); |
251 | if( (ct.tv_sec > nt.tv_sec) || | 296 | if( (ct.tv_sec > nt.tv_sec) || |
252 | (ct.tv_sec == nt.tv_sec && | 297 | (ct.tv_sec == nt.tv_sec && |
253 | ct.tv_usec >= nt.tv_usec) ) | 298 | ct.tv_usec >= nt.tv_usec) ) |
254 | break; | 299 | break; |
300 | #else | ||
301 | DWORD dwNow = GetTickCount(); | ||
302 | if( dwNow > dwEnd ) | ||
303 | break; | ||
304 | #endif | ||
255 | } | 305 | } |
256 | return nWrote; | 306 | return nWrote; |
257 | } | 307 | } |
@@ -337,6 +387,7 @@ bool Bu::Socket::isBlocking() | |||
337 | 387 | ||
338 | void Bu::Socket::setBlocking( bool bBlocking ) | 388 | void Bu::Socket::setBlocking( bool bBlocking ) |
339 | { | 389 | { |
390 | #ifndef WIN32 | ||
340 | if( bBlocking ) | 391 | if( bBlocking ) |
341 | { | 392 | { |
342 | fcntl( nSocket, F_SETFL, fcntl( nSocket, F_GETFL, 0 ) & ~O_NONBLOCK ); | 393 | fcntl( nSocket, F_SETFL, fcntl( nSocket, F_GETFL, 0 ) & ~O_NONBLOCK ); |
@@ -345,6 +396,20 @@ void Bu::Socket::setBlocking( bool bBlocking ) | |||
345 | { | 396 | { |
346 | fcntl( nSocket, F_SETFL, fcntl( nSocket, F_GETFL, 0 ) | O_NONBLOCK ); | 397 | fcntl( nSocket, F_SETFL, fcntl( nSocket, F_GETFL, 0 ) | O_NONBLOCK ); |
347 | } | 398 | } |
399 | #else | ||
400 | u_long iMode; | ||
401 | if( bBlocking ) | ||
402 | iMode = 0; | ||
403 | else | ||
404 | iMode = 1; | ||
405 | //------------------------- | ||
406 | // Set the socket I/O mode: In this case FIONBIO | ||
407 | // enables or disables the blocking mode for the | ||
408 | // socket based on the numerical value of iMode. | ||
409 | // If iMode = 0, blocking is enabled; | ||
410 | // If iMode != 0, non-blocking mode is enabled. | ||
411 | ioctlsocket(nSocket, FIONBIO, &iMode); | ||
412 | #endif | ||
348 | } | 413 | } |
349 | 414 | ||
350 | void Bu::Socket::flush() | 415 | void Bu::Socket::flush() |
@@ -356,6 +421,10 @@ bool Bu::Socket::isOpen() | |||
356 | return bActive; | 421 | return bActive; |
357 | } | 422 | } |
358 | 423 | ||
424 | #ifdef WIN32 | ||
425 | typedef int socklen_t; | ||
426 | #endif | ||
427 | |||
359 | void Bu::Socket::setAddress() | 428 | void Bu::Socket::setAddress() |
360 | { | 429 | { |
361 | struct sockaddr_in addr; | 430 | struct sockaddr_in addr; |