summaryrefslogtreecommitdiff
path: root/src/socket.cpp
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2009-01-16 23:55:53 +0000
committerMike Buland <eichlan@xagasoft.com>2009-01-16 23:55:53 +0000
commit8c1f4d7bace6ff2c99d546cedaba890b349e88f8 (patch)
treee5c6e29deaaa7db42fbc75d0fdef32457bb0c8f2 /src/socket.cpp
parent0a43e790cf9798948ab989abe88f890813c935df (diff)
downloadlibbu++-8c1f4d7bace6ff2c99d546cedaba890b349e88f8.tar.gz
libbu++-8c1f4d7bace6ff2c99d546cedaba890b349e88f8.tar.bz2
libbu++-8c1f4d7bace6ff2c99d546cedaba890b349e88f8.tar.xz
libbu++-8c1f4d7bace6ff2c99d546cedaba890b349e88f8.zip
I...think that's a little better. Wow, function pointers in windows have a
lot of problems. This may require a little more research, but basically, you can't just call them inline wherever you'd like. I managed to get it to work by providing simple one line wrapper functions for each function we acquired as a pointer. Crazy mess. Anyway, it should load the library just once now, and Bu::Socket looks a little bit cleaner, but not a heck of a lot. I also added some more docs and removed the author references.
Diffstat (limited to 'src/socket.cpp')
-rw-r--r--src/socket.cpp146
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 ) :
44Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout ) 45Bu::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/*
160void 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
212size_t Bu::Socket::read( void *pBuf, size_t nBytes ) 137size_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
479Bu::FString Bu::Socket::getAddress() const 394Bu::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