summaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/bitstring.h1
-rw-r--r--src/client.h1
-rw-r--r--src/ito.h1
-rw-r--r--src/itoatom.h1
-rw-r--r--src/itocondition.h1
-rw-r--r--src/itocounter.h1
-rw-r--r--src/itomutex.h1
-rw-r--r--src/itoqueue.h1
-rw-r--r--src/itoserver.h1
-rw-r--r--src/linkmessage.h1
-rw-r--r--src/linux_compatibility.h21
-rw-r--r--src/programchain.h6
-rw-r--r--src/programlink.h1
-rw-r--r--src/protocol.h1
-rw-r--r--src/server.h1
-rw-r--r--src/serversocket.cpp29
-rw-r--r--src/serversocket.h1
-rw-r--r--src/singleton.h1
-rw-r--r--src/socket.cpp146
-rw-r--r--src/socket.h27
-rw-r--r--src/win32_compatibility.cpp434
-rw-r--r--src/win32_compatibility.h110
22 files changed, 283 insertions, 505 deletions
diff --git a/src/bitstring.h b/src/bitstring.h
index f124d2d..9f0c719 100644
--- a/src/bitstring.h
+++ b/src/bitstring.h
@@ -14,7 +14,6 @@ namespace Bu
14 * 14 *
15 * For more general and mathematical type interaction see BitStringInt. 15 * For more general and mathematical type interaction see BitStringInt.
16 * 16 *
17 *@author Mike Buland
18 */ 17 */
19 class BitString 18 class BitString
20 { 19 {
diff --git a/src/client.h b/src/client.h
index ae2815b..b11774e 100644
--- a/src/client.h
+++ b/src/client.h
@@ -19,7 +19,6 @@ namespace Bu
19 class ClientLinkFactory; 19 class ClientLinkFactory;
20 20
21 /** 21 /**
22 *@author Mike Buland
23 *@ingroup Serving 22 *@ingroup Serving
24 */ 23 */
25 class Client 24 class Client
diff --git a/src/ito.h b/src/ito.h
index 009d4b1..9829d28 100644
--- a/src/ito.h
+++ b/src/ito.h
@@ -17,7 +17,6 @@ namespace Bu
17 * system in an object oriented sort of way. It allows you to create a 17 * system in an object oriented sort of way. It allows you to create a
18 * class with standard member variables and callable functions that can be 18 * class with standard member variables and callable functions that can be
19 * run in it's own thread, one per class instance. 19 * run in it's own thread, one per class instance.
20 *@author Mike Buland
21 *@ingroup Threading 20 *@ingroup Threading
22 */ 21 */
23 class Ito 22 class Ito
diff --git a/src/itoatom.h b/src/itoatom.h
index 4eaa13c..2791519 100644
--- a/src/itoatom.h
+++ b/src/itoatom.h
@@ -15,7 +15,6 @@
15 15
16/** 16/**
17 * A thread-safe wrapper class. 17 * A thread-safe wrapper class.
18 *@author Mike Buland
19 *@ingroup Threading 18 *@ingroup Threading
20 */ 19 */
21template <class T> 20template <class T>
diff --git a/src/itocondition.h b/src/itocondition.h
index 7300920..8cae427 100644
--- a/src/itocondition.h
+++ b/src/itocondition.h
@@ -34,7 +34,6 @@ namespace Bu
34 * The usage for the triggering thread is much simpler, when it needs to 34 * The usage for the triggering thread is much simpler, when it needs to
35 * tell the others that it's time to grab some data it calls either signal 35 * tell the others that it's time to grab some data it calls either signal
36 * or broadcast. See both of those functions for the difference. 36 * or broadcast. See both of those functions for the difference.
37 *@author Mike Buland
38 *@ingroup Threading 37 *@ingroup Threading
39 */ 38 */
40 class ItoCondition : public ItoMutex 39 class ItoCondition : public ItoMutex
diff --git a/src/itocounter.h b/src/itocounter.h
index 58abe07..afca8da 100644
--- a/src/itocounter.h
+++ b/src/itocounter.h
@@ -15,7 +15,6 @@ namespace Bu
15 /** 15 /**
16 * A simple thread-safe counter class. This is handy for assigning unique 16 * A simple thread-safe counter class. This is handy for assigning unique
17 * IDs to objects that are being created in different threads. 17 * IDs to objects that are being created in different threads.
18 *@author Mike Buland
19 *@ingroup Threading Containers 18 *@ingroup Threading Containers
20 */ 19 */
21 template <class T> 20 template <class T>
diff --git a/src/itomutex.h b/src/itomutex.h
index 0521b81..80930cc 100644
--- a/src/itomutex.h
+++ b/src/itomutex.h
@@ -17,7 +17,6 @@ namespace Bu
17 * except keep all of the functionality together in an OO sorta' way and 17 * except keep all of the functionality together in an OO sorta' way and
18 * keep you from having to worry about cleaning up your mutexes properly, 18 * keep you from having to worry about cleaning up your mutexes properly,
19 * or initing them. 19 * or initing them.
20 *@author Mike Buland
21 *@ingroup Threading 20 *@ingroup Threading
22 */ 21 */
23 class ItoMutex 22 class ItoMutex
diff --git a/src/itoqueue.h b/src/itoqueue.h
index a481f87..3a116e2 100644
--- a/src/itoqueue.h
+++ b/src/itoqueue.h
@@ -22,7 +22,6 @@ namespace Bu
22 * infinite blocking, or with timed blocking, which will return a value if 22 * infinite blocking, or with timed blocking, which will return a value if
23 * something is enqueued within the specified time limit, or NULL if the 23 * something is enqueued within the specified time limit, or NULL if the
24 * time limit is exceded. 24 * time limit is exceded.
25 *@author Mike Buland
26 *@ingroup Threading Containers 25 *@ingroup Threading Containers
27 */ 26 */
28 template <class T> 27 template <class T>
diff --git a/src/itoserver.h b/src/itoserver.h
index 0256f87..bcdd1d1 100644
--- a/src/itoserver.h
+++ b/src/itoserver.h
@@ -45,7 +45,6 @@ namespace Bu
45 * In order to use a Server you must subclass it and implement the pure 45 * In order to use a Server you must subclass it and implement the pure
46 * virtual functions. These allow you to receive notification of events 46 * virtual functions. These allow you to receive notification of events
47 * happening within the server itself, and actually makes it useful. 47 * happening within the server itself, and actually makes it useful.
48 *@author Mike Buland
49 *@ingroup Threading Serving 48 *@ingroup Threading Serving
50 */ 49 */
51 class ItoServer : public Ito 50 class ItoServer : public Ito
diff --git a/src/linkmessage.h b/src/linkmessage.h
index c9abd04..5b8b7e2 100644
--- a/src/linkmessage.h
+++ b/src/linkmessage.h
@@ -17,7 +17,6 @@ namespace Bu
17 * A message to be broadcast accross ProgramLinks in a ProgramChain. Generally 17 * A message to be broadcast accross ProgramLinks in a ProgramChain. Generally
18 * one would make a subclass of this in order to transmit more useful 18 * one would make a subclass of this in order to transmit more useful
19 * information, but sometimes it isn't necesarry. 19 * information, but sometimes it isn't necesarry.
20 *@author Mike Buland
21 */ 20 */
22 class LinkMessage 21 class LinkMessage
23 { 22 {
diff --git a/src/linux_compatibility.h b/src/linux_compatibility.h
new file mode 100644
index 0000000..67016a7
--- /dev/null
+++ b/src/linux_compatibility.h
@@ -0,0 +1,21 @@
1#ifdef __linux__
2
3#define bu_inet_ntoa inet_ntoa
4#define bu_inet_addr inet_addr
5#define bu_select select
6#define bu_socket socket
7#define bu_htons htons
8#define bu_htonl htonl
9#define bu_gethostbyname gethostbyname
10#define bu_freeaddrinfo freeaddrinfo
11#define bu_getaddrinfo getaddrinfo
12#define bu_connect connect
13#define bu_getpeername getpeername
14#define bu_setsockopt setsockopt
15#define bu_bind bind
16#define bu_listen listen
17#define bu_accept accept
18
19#define bu_gai_strerror gai_strerror
20
21#endif
diff --git a/src/programchain.h b/src/programchain.h
index bd4f658..c50e1c2 100644
--- a/src/programchain.h
+++ b/src/programchain.h
@@ -17,7 +17,6 @@ namespace Bu
17 /** 17 /**
18 * The Program Chain links together program "chunks" to more easily facilitate 18 * The Program Chain links together program "chunks" to more easily facilitate
19 * a generalized program loop with modular extensions. 19 * a generalized program loop with modular extensions.
20 *@author Mike Buland
21 */ 20 */
22 class ProgramChain 21 class ProgramChain
23 { 22 {
@@ -36,7 +35,6 @@ namespace Bu
36 * Adds a link to the end of the chain. 35 * Adds a link to the end of the chain.
37 *@param pLink A pointer to the link to add to the chain. 36 *@param pLink A pointer to the link to add to the chain.
38 *@returns True if adding the link was successful, otherwise false 37 *@returns True if adding the link was successful, otherwise false
39 *@author Mike Buland
40 */ 38 */
41 bool addLink( Bu::ProgramLink *pLink ); 39 bool addLink( Bu::ProgramLink *pLink );
42 40
@@ -46,14 +44,12 @@ namespace Bu
46 * name, apparently. 44 * name, apparently.
47 *@returns A pointer to the specified ProgramLink, or NULL if none were 45 *@returns A pointer to the specified ProgramLink, or NULL if none were
48 * found matching your criteria. 46 * found matching your criteria.
49 *@author Mike Buland
50 */ 47 */
51 class ProgramLink *getLink( const char *lpName ); 48 class ProgramLink *getLink( const char *lpName );
52 49
53 /** 50 /**
54 * Gets the very first link in the chain. 51 * Gets the very first link in the chain.
55 *@returns A pointer to the first link in the chain. 52 *@returns A pointer to the first link in the chain.
56 *@author Mike Buland
57 */ 53 */
58 class ProgramLink *getBaseLink(); 54 class ProgramLink *getBaseLink();
59 55
@@ -62,7 +58,6 @@ namespace Bu
62 * over the operation of the chain. 58 * over the operation of the chain.
63 *@returns true if every link returned true. If at least one link returns 59 *@returns true if every link returned true. If at least one link returns
64 * false, then returns false. 60 * false, then returns false.
65 *@author Mike Buland
66 */ 61 */
67 bool execChainOnce(); 62 bool execChainOnce();
68 63
@@ -72,7 +67,6 @@ namespace Bu
72 * a link returns a false value. 67 * a link returns a false value.
73 *@returns False, always. It returns true unless a link returned false, 68 *@returns False, always. It returns true unless a link returned false,
74 * but loops until a link does return false. 69 * but loops until a link does return false.
75 *@author Mike Buland
76 **/ 70 **/
77 bool enterChainLoop(); 71 bool enterChainLoop();
78 72
diff --git a/src/programlink.h b/src/programlink.h
index dfbbdb5..d34a3df 100644
--- a/src/programlink.h
+++ b/src/programlink.h
@@ -16,7 +16,6 @@ namespace Bu
16 /** 16 /**
17 * Program Link is the base class for any object that will be a piece of the 17 * Program Link is the base class for any object that will be a piece of the
18 * main program chain loop. 18 * main program chain loop.
19 *@author Mike Buland
20 */ 19 */
21 class ProgramLink 20 class ProgramLink
22 { 21 {
diff --git a/src/protocol.h b/src/protocol.h
index 64e5ca7..6009fe5 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -17,7 +17,6 @@ namespace Bu
17 class Client; 17 class Client;
18 18
19 /** 19 /**
20 *@author Mike Buland
21 *@ingroup Serving 20 *@ingroup Serving
22 */ 21 */
23 class Protocol 22 class Protocol
diff --git a/src/server.h b/src/server.h
index 55de081..315248b 100644
--- a/src/server.h
+++ b/src/server.h
@@ -41,7 +41,6 @@ namespace Bu
41 * In order to use a Server you must subclass it and implement the pure 41 * In order to use a Server you must subclass it and implement the pure
42 * virtual functions. These allow you to receive notification of events 42 * virtual functions. These allow you to receive notification of events
43 * happening within the server itself, and actually makes it useful. 43 * happening within the server itself, and actually makes it useful.
44 *@author Mike Buland
45 *@ingroup Serving 44 *@ingroup Serving
46 */ 45 */
47 class Server 46 class Server
diff --git a/src/serversocket.cpp b/src/serversocket.cpp
index 946d0d3..89fef7e 100644
--- a/src/serversocket.cpp
+++ b/src/serversocket.cpp
@@ -24,6 +24,7 @@
24#include "bu/serversocket.h" 24#include "bu/serversocket.h"
25#include "bu/osx_compatibility.h" 25#include "bu/osx_compatibility.h"
26#include "bu/win32_compatibility.h" 26#include "bu/win32_compatibility.h"
27#include "bu/linux_compatibility.h"
27 28
28namespace Bu { subExceptionDef( ServerSocketException ) } 29namespace Bu { subExceptionDef( ServerSocketException ) }
29 30
@@ -35,11 +36,11 @@ Bu::ServerSocket::ServerSocket( int nPort, int nPoolSize ) :
35 36
36 /* Give the socket a name. */ 37 /* Give the socket a name. */
37 name.sin_family = AF_INET; 38 name.sin_family = AF_INET;
38 name.sin_port = DYNLOAD htons( nPort ); 39 name.sin_port = bu_htons( nPort );
39 40
40 // I think this specifies who we will accept connections from, 41 // I think this specifies who we will accept connections from,
41 // a good thing to make configurable later on 42 // a good thing to make configurable later on
42 name.sin_addr.s_addr = DYNLOAD htonl( INADDR_ANY ); 43 name.sin_addr.s_addr = bu_htonl( INADDR_ANY );
43 44
44 startServer( name, nPoolSize ); 45 startServer( name, nPoolSize );
45} 46}
@@ -53,10 +54,10 @@ Bu::ServerSocket::ServerSocket(const FString &sAddr,int nPort, int nPoolSize) :
53 /* Give the socket a name. */ 54 /* Give the socket a name. */
54 name.sin_family = AF_INET; 55 name.sin_family = AF_INET;
55 56
56 name.sin_port = DYNLOAD htons( nPort ); 57 name.sin_port = bu_htons( nPort );
57 58
58#ifdef WIN32 59#ifdef WIN32
59 name.sin_addr.s_addr = DYNLOAD inet_addr( sAddr.getStr() ); 60 name.sin_addr.s_addr = bu_inet_addr( sAddr.getStr() );
60#else 61#else
61 inet_aton( sAddr.getStr(), &name.sin_addr ); 62 inet_aton( sAddr.getStr(), &name.sin_addr );
62#endif 63#endif
@@ -72,7 +73,7 @@ Bu::ServerSocket::~ServerSocket()
72void Bu::ServerSocket::startServer( struct sockaddr_in &name, int nPoolSize ) 73void Bu::ServerSocket::startServer( struct sockaddr_in &name, int nPoolSize )
73{ 74{
74 /* Create the socket. */ 75 /* Create the socket. */
75 nServer = DYNLOAD socket( PF_INET, SOCK_STREAM, 0 ); 76 nServer = bu_socket( PF_INET, SOCK_STREAM, 0 );
76 77
77 if( nServer < 0 ) 78 if( nServer < 0 )
78 { 79 {
@@ -80,7 +81,7 @@ void Bu::ServerSocket::startServer( struct sockaddr_in &name, int nPoolSize )
80 } 81 }
81 82
82 int opt = 1; 83 int opt = 1;
83 DYNLOAD setsockopt( 84 bu_setsockopt(
84 nServer, 85 nServer,
85 SOL_SOCKET, 86 SOL_SOCKET,
86 SO_REUSEADDR, 87 SO_REUSEADDR,
@@ -88,13 +89,12 @@ void Bu::ServerSocket::startServer( struct sockaddr_in &name, int nPoolSize )
88 sizeof( opt ) 89 sizeof( opt )
89 ); 90 );
90 91
91 if( DYNLOAD bind( 92 if( bu_bind( nServer, (struct sockaddr *) &name, sizeof(name) ) < 0 )
92 nServer, (struct sockaddr *) &name, sizeof(name) ) < 0 )
93 { 93 {
94 throw Bu::ServerSocketException("Couldn't bind to the listen socket."); 94 throw Bu::ServerSocketException("Couldn't bind to the listen socket.");
95 } 95 }
96 96
97 if( DYNLOAD listen( nServer, nPoolSize ) < 0 ) 97 if( bu_listen( nServer, nPoolSize ) < 0 )
98 { 98 {
99 throw Bu::ServerSocketException( 99 throw Bu::ServerSocketException(
100 "Couldn't begin listening to the server socket." 100 "Couldn't begin listening to the server socket."
@@ -121,18 +121,14 @@ int Bu::ServerSocket::accept( int nTimeoutSec, int nTimeoutUSec )
121 xT.tv_usec = nTimeoutUSec; 121 xT.tv_usec = nTimeoutUSec;
122 122
123 if( TEMP_FAILURE_RETRY( 123 if( TEMP_FAILURE_RETRY(
124 DYNLOAD select( nServer+1, &fdRead, NULL, NULL, &xT )) < 0 ) 124 bu_select( nServer+1, &fdRead, NULL, NULL, &xT )) < 0 )
125 { 125 {
126 throw Bu::ServerSocketException( 126 throw Bu::ServerSocketException(
127 "Error scanning for new connections: %s", strerror( errno ) 127 "Error scanning for new connections: %s", strerror( errno )
128 ); 128 );
129 } 129 }
130 130
131#ifdef WIN32
132 if( DynamicWinsock2::DYN_FD_ISSET( nServer, &fdRead ) )
133#else
134 if( FD_ISSET( nServer, &fdRead ) ) 131 if( FD_ISSET( nServer, &fdRead ) )
135#endif
136 { 132 {
137 struct sockaddr_in clientname; 133 struct sockaddr_in clientname;
138 socklen_t size; 134 socklen_t size;
@@ -140,8 +136,7 @@ int Bu::ServerSocket::accept( int nTimeoutSec, int nTimeoutUSec )
140 136
141 size = sizeof( clientname ); 137 size = sizeof( clientname );
142#ifdef WIN32 138#ifdef WIN32
143 nClient = DYNLOAD accept( 139 nClient = bu_accept( nServer, (struct sockaddr *)&clientname, &size);
144 nServer, (struct sockaddr *)&clientname, (int *)&size);
145#else /* not-WIN32 */ 140#else /* not-WIN32 */
146#ifdef __CYGWIN__ 141#ifdef __CYGWIN__
147 nClient = ::accept( nServer, (struct sockaddr *)&clientname, 142 nClient = ::accept( nServer, (struct sockaddr *)&clientname,
@@ -189,7 +184,7 @@ int Bu::ServerSocket::accept( int nTimeoutSec, int nTimeoutUSec )
189 // If iMode = 0, blocking is enabled; 184 // If iMode = 0, blocking is enabled;
190 // If iMode != 0, non-blocking mode is enabled. 185 // If iMode != 0, non-blocking mode is enabled.
191 u_long iMode = 1; 186 u_long iMode = 1;
192 DYNLOAD ioctlsocket(nClient, FIONBIO, &iMode); 187 bu_ioctlsocket(nClient, FIONBIO, &iMode);
193#endif 188#endif
194 } 189 }
195 190
diff --git a/src/serversocket.h b/src/serversocket.h
index 168c5e1..0860972 100644
--- a/src/serversocket.h
+++ b/src/serversocket.h
@@ -32,7 +32,6 @@ namespace Bu
32 * Although the accept function returns an integral file descriptor, it is 32 * Although the accept function returns an integral file descriptor, it is
33 * designed to be used with the Socket class. 33 * designed to be used with the Socket class.
34 * 34 *
35 *@author Mike Buland
36 *@ingroup Serving 35 *@ingroup Serving
37 */ 36 */
38 class ServerSocket 37 class ServerSocket
diff --git a/src/singleton.h b/src/singleton.h
index 7bdf97f..0bcc3f7 100644
--- a/src/singleton.h
+++ b/src/singleton.h
@@ -33,7 +33,6 @@ namespace Bu
33 * You can still add public functions and variables to your new Singleton child 33 * You can still add public functions and variables to your new Singleton child
34 * class, but your constructor should be protected (hence the need for the 34 * class, but your constructor should be protected (hence the need for the
35 * friend decleration). 35 * friend decleration).
36 *@author Mike Buland
37 */ 36 */
38 template <class T> 37 template <class T>
39 class Singleton 38 class Singleton
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
diff --git a/src/socket.h b/src/socket.h
index 572c2ad..f12f79c 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -27,7 +27,32 @@ namespace Bu
27 subExceptionDeclEnd(); 27 subExceptionDeclEnd();
28 28
29 /** 29 /**
30 *@author Mike Buland 30 * Network socket stream class. This class provides a mechanism for
31 * communicating over a network using TCP/IP. It will provide other low
32 * level protocol and addressing support later on, but for now it's just
33 * standard STREAM TCP/IP sockets.
34 *
35 * Unlike system sockets, these sockets are opened by default in
36 * non-blocking mode, you can specify your own timeout for opening a socket,
37 * and a number of non-fatal error messages have been automatically handled
38 * and treated as standard no-data-available-yet situations on read.
39 *
40 * Please note that there is a condition that will occur eventually (at
41 * least on *nix systems) that will trigger a SIGPIPE condition. This
42 * will terminate your program immediately unless handled properly. Most
43 * people doing any connections with Socket will want to put this in their
44 * program somewhere before they use it:
45 *@code
46 #include <signal.h>
47 ...
48 ...
49 ...
50 sigset( SIGPIPE, SIG_IGN ); // do this before you use a Bu::Socket
51 @endcode
52 * When this is done, Bu::Socket will simply throw a broken pipe exception
53 * just like every other error condition, allowing your program to handle
54 * it sanely.
55 *
31 *@ingroup Serving 56 *@ingroup Serving
32 *@ingroup Streams 57 *@ingroup Streams
33 */ 58 */
diff --git a/src/win32_compatibility.cpp b/src/win32_compatibility.cpp
index 54fd56c..b85e869 100644
--- a/src/win32_compatibility.cpp
+++ b/src/win32_compatibility.cpp
@@ -2,352 +2,152 @@
2 2
3#ifdef WIN32 3#ifdef WIN32
4 4
5typedef int (__cdecl *FNDEF_DYN_WSAStartup)(WORD,LPWSADATA); 5#define deffunc( name ) \
6int DynamicWinsock2::WSAStartup( 6 Bu::Winsock2::FNDEF_DYN_ ##name Bu::Winsock2::_fnptr_ ##name = NULL
7 WORD wVersionRequested,LPWSADATA lpWSAData) 7
8char Bu::Winsock2::scode[15];
9
10deffunc( WSAStartup );
11deffunc( WSACleanup );
12deffunc( WSAGetLastError );
13deffunc( inet_ntoa );
14deffunc( inet_addr );
15deffunc( select );
16deffunc( socket );
17deffunc( ioctlsocket );
18deffunc( htons );
19deffunc( htonl );
20deffunc( gethostbyname );
21deffunc( freeaddrinfo );
22deffunc( getaddrinfo );
23deffunc( connect );
24deffunc( getpeername );
25deffunc( setsockopt );
26deffunc( bind );
27deffunc( listen );
28deffunc( accept );
29deffunc( recv );
30deffunc( send );
31deffunc( __WSAFDIsSet );
32
33// Safely get a function from the library
34#define getfunc( name ) \
35 Bu::Winsock2::_fnptr_ ##name = (FNDEF_DYN_ ##name) \
36 GetProcAddress( Ws2_32, #name ); \
37 if( Bu::Winsock2::_fnptr_ ##name == NULL ) { \
38 throw Bu::ExceptionBase("Error loading function " #name " from dll.");\
39 } (void)0
40
41Bu::Winsock2::Winsock2()
8{ 42{
9 int out=0; 43 Ws2_32 = LoadLibrary(TEXT("WS2_32.DLL"));
10 HINSTANCE Ws2_32 = LoadLibrary(TEXT("WS2_32.DLL")); 44
11 if( Ws2_32 != NULL ) 45 getfunc( WSAStartup );
12 { 46 getfunc( WSACleanup );
13 FNDEF_DYN_WSAStartup fn = (FNDEF_DYN_WSAStartup) 47 getfunc( WSAGetLastError );
14 GetProcAddress( Ws2_32, "WSAStartup" ); 48 getfunc( inet_ntoa );
15 if( fn != NULL ) 49 getfunc( inet_addr );
16 out = (fn)(wVersionRequested,lpWSAData); 50 getfunc( select );
17 } 51 getfunc( socket );
18 return out; 52 getfunc( ioctlsocket );
19} 53 getfunc( htons );
54 getfunc( htonl );
55 getfunc( gethostbyname );
56 getfunc( freeaddrinfo );
57 getfunc( getaddrinfo );
58 getfunc( connect );
59 getfunc( getpeername );
60 getfunc( setsockopt );
61 getfunc( bind );
62 getfunc( listen );
63 getfunc( accept );
64 getfunc( recv );
65 getfunc( send );
66 getfunc( __WSAFDIsSet );
20 67
21typedef int (__cdecl *FNDEF_DYN_WSACleanup)(); 68 Bu::Winsock2::WSAStartup( MAKEWORD(2, 2), &wsaData );
22int DynamicWinsock2::WSACleanup()
23{
24 int out=0;
25 HINSTANCE Ws2_32 = LoadLibrary(TEXT("WS2_32.DLL"));
26 if( Ws2_32 != NULL )
27 {
28 FNDEF_DYN_WSACleanup fn = (FNDEF_DYN_WSACleanup)
29 GetProcAddress( Ws2_32, "WSACleanup" );
30 if( fn != NULL )
31 out = (fn)();
32 }
33 return out;
34} 69}
35 70
36//typedef char * (__cdecl *FNDEF_DYN_gai_strerrorA)( int ecode ); 71Bu::Winsock2::~Winsock2()
37typedef int (__cdecl *FNDEF_DYN_WSAGetLastError)(void);
38int DynamicWinsock2::WSAGetLastError()
39{ 72{
40 int out=0; 73 Bu::Winsock2::WSACleanup();
41 HINSTANCE Ws2_32 = LoadLibrary(TEXT("WS2_32.DLL")); 74 FreeLibrary( Ws2_32 );
42 if( Ws2_32 != NULL )
43 {
44 FNDEF_DYN_WSAGetLastError fn = (FNDEF_DYN_WSAGetLastError)
45 GetProcAddress( Ws2_32, "WSAGetLastError" );
46 if( fn != NULL )
47 out = (fn)();
48 }
49 return out;
50} 75}
51 76
52typedef char * (__cdecl *FNDEF_DYN_inet_ntoa)( struct in_addr ); 77char *Bu::Winsock2::gai_strerror( int iCode )
53void DynamicWinsock2::inet_ntoa( Bu::FString &out, struct in_addr addr_in )
54{ 78{
55 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32")); 79 sprintf( scode, "%d", Bu::Winsock2::WSAGetLastError() );
56 if( Ws2_32 != NULL ) 80 return scode;
57 {
58 FNDEF_DYN_inet_ntoa fn = (FNDEF_DYN_inet_ntoa)
59 GetProcAddress( Ws2_32, "inet_ntoa" );
60 if( fn != NULL )
61 out = (fn)( addr_in );
62
63 //We will let windows clean up our dll imports on exit
64 //FreeLibrary( Ws2_32 );
65 }
66} 81}
67 82
68typedef unsigned long (__cdecl *FNDEF_DYN_inet_addr)( const char * ); 83int Bu::Winsock2::WSAStartup( WORD a, LPWSADATA b ) {
69unsigned long DynamicWinsock2::inet_addr( const char *s_in ) 84 return (*Bu::Winsock2::_fnptr_WSAStartup)( a, b );
70{
71 unsigned long out = 0;
72 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
73 if( Ws2_32 != NULL )
74 {
75 FNDEF_DYN_inet_addr fn = (FNDEF_DYN_inet_addr)
76 GetProcAddress( Ws2_32, "inet_addr" );
77 if( fn != NULL )
78 out = (fn)( s_in );
79 }
80 return out;
81} 85}
82 86int Bu::Winsock2::WSACleanup( ) {
83typedef int (__cdecl *FNDEF_DYN_select)( 87 return (*Bu::Winsock2::_fnptr_WSACleanup)();
84 int nfds,fd_set*,fd_set*,fd_set*,const struct timeval*);
85int DynamicWinsock2::select(int nfds, fd_set *readfds, fd_set *writefds,
86 fd_set *exceptfds, const struct timeval *timeout)
87{
88 int out = 0;
89 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
90 if( Ws2_32 != NULL )
91 {
92 FNDEF_DYN_select fn = (FNDEF_DYN_select)
93 GetProcAddress( Ws2_32, "select" );
94 if( fn != NULL )
95 out = (fn)( nfds, readfds, writefds, exceptfds, timeout );
96 }
97 return out;
98} 88}
99 89int Bu::Winsock2::WSAGetLastError( ) {
100typedef SOCKET (__cdecl *FNDEF_DYN_socket)(int,int,int); 90 return (*Bu::Winsock2::_fnptr_WSAGetLastError)();
101SOCKET DynamicWinsock2::socket(int domain, int type, int protocol)
102{
103 SOCKET out = 0;
104 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
105 if( Ws2_32 != NULL )
106 {
107 FNDEF_DYN_socket fn = (FNDEF_DYN_socket)
108 GetProcAddress( Ws2_32, "socket" );
109 if( fn != NULL )
110 out = (fn)( domain, type, protocol );
111 }
112 return out;
113} 91}
114 92char * Bu::Winsock2::inet_ntoa( struct in_addr a ) {
115typedef int (__cdecl *FNDEF_DYN_ioctlsocket)(SOCKET,long,u_long *); 93 return (*Bu::Winsock2::_fnptr_inet_ntoa)( a );
116int DynamicWinsock2::ioctlsocket(SOCKET s, long cmd, u_long *argp)
117{
118 int out = 0;
119 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
120 if( Ws2_32 != NULL )
121 {
122 FNDEF_DYN_ioctlsocket fn = (FNDEF_DYN_ioctlsocket)
123 GetProcAddress( Ws2_32, "ioctlsocket" );
124 if( fn != NULL )
125 out = (fn)( s, cmd, argp );
126 }
127 return out;
128} 94}
129 95unsigned long Bu::Winsock2::inet_addr( const char *s_in ) {
130typedef u_short (__cdecl *FNDEF_DYN_htons)(u_short); 96 return (*Bu::Winsock2::_fnptr_inet_addr)( s_in );
131u_short DynamicWinsock2::htons(u_short in)
132{
133 u_short out = 0;
134 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
135 if( Ws2_32 != NULL )
136 {
137 FNDEF_DYN_htons fn = (FNDEF_DYN_htons)
138 GetProcAddress( Ws2_32, "htons" );
139 if( fn != NULL )
140 out = (fn)( in );
141 }
142 return out;
143} 97}
144 98int Bu::Winsock2::select( int a, fd_set *b, fd_set *c, fd_set *d,
145typedef u_long (__cdecl *FNDEF_DYN_htonl)(u_long); 99 const struct timeval *e ) {
146u_long DynamicWinsock2::htonl(u_long in) 100 return (*Bu::Winsock2::_fnptr_select)( a, b, c, d, e );
147{
148 u_long out = 0;
149 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
150 if( Ws2_32 != NULL )
151 {
152 FNDEF_DYN_htonl fn = (FNDEF_DYN_htonl)
153 GetProcAddress( Ws2_32, "htonl" );
154 if( fn != NULL )
155 out = (fn)( in );
156 }
157 return out;
158} 101}
159 102SOCKET Bu::Winsock2::socket( int domain, int type, int protocol ) {
160typedef struct hostent * (__cdecl *FNDEF_DYN_gethostbyname)(const char *); 103 return (*Bu::Winsock2::_fnptr_socket)( domain, type, protocol );
161struct hostent *DynamicWinsock2::gethostbyname(const char *name)
162{
163 hostent *out = NULL;
164 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
165 if( Ws2_32 != NULL )
166 {
167 FNDEF_DYN_gethostbyname fn = (FNDEF_DYN_gethostbyname)
168 GetProcAddress( Ws2_32, "gethostbyname" );
169 if( fn != NULL )
170 out = (fn)( name );
171 }
172 return out;
173} 104}
174 105int Bu::Winsock2::ioctlsocket( SOCKET s, long cmd, u_long *argp ) {
175typedef void (__cdecl *FNDEF_DYN_freeaddrinfo)(struct addrinfo *); 106 return (*Bu::Winsock2::_fnptr_ioctlsocket)( s, cmd, argp );
176void DynamicWinsock2::freeaddrinfo(struct addrinfo *ai)
177{
178 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
179 if( Ws2_32 != NULL )
180 {
181 FNDEF_DYN_freeaddrinfo fn = (FNDEF_DYN_freeaddrinfo)
182 GetProcAddress( Ws2_32, "freeaddrinfo" );
183 if( fn != NULL )
184 (fn)( ai );
185 }
186} 107}
187 108u_short Bu::Winsock2::htons( u_short in ) {
188typedef int (__cdecl *FNDEF_DYN_getaddrinfo)( 109 return (*Bu::Winsock2::_fnptr_htons)( in );
189 const char*,const char*,const struct addrinfo*,struct addrinfo**); 110}
190int DynamicWinsock2::getaddrinfo( 111u_long Bu::Winsock2::htonl( u_long in ) {
191 const char *nodename, const char *servname, 112 return (*Bu::Winsock2::_fnptr_htonl)( in );
192 const struct addrinfo *hints, struct addrinfo **res )
193{
194 int out = 0;
195 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
196 if( Ws2_32 != NULL )
197 {
198 FNDEF_DYN_getaddrinfo fn = (FNDEF_DYN_getaddrinfo)
199 GetProcAddress( Ws2_32, "getaddrinfo" );
200 if( fn != NULL )
201 out = (fn)( nodename, servname, hints, res );
202 }
203 return out;
204} 113}
205 114struct hostent * Bu::Winsock2::gethostbyname( const char *name ) {
206typedef int (__cdecl *FNDEF_DYN_connect)(SOCKET,const struct sockaddr*,int); 115 return (*Bu::Winsock2::_fnptr_gethostbyname)( name );
207int DynamicWinsock2::connect(
208 SOCKET s, const struct sockaddr *serv_addr, int addrlen)
209{
210 int out = 0;
211 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
212 if( Ws2_32 != NULL )
213 {
214 FNDEF_DYN_connect fn = (FNDEF_DYN_connect)
215 GetProcAddress( Ws2_32, "connect" );
216 if( fn != NULL )
217 out = (fn)( s, serv_addr, addrlen );
218 }
219 return out;
220} 116}
221 117void Bu::Winsock2::freeaddrinfo( struct addrinfo *ai ) {
222typedef int (__cdecl *FNDEF_DYN_getpeername)(SOCKET,struct sockaddr*,int*); 118 return (*Bu::Winsock2::_fnptr_freeaddrinfo)( ai );
223int DynamicWinsock2::getpeername(SOCKET s, struct sockaddr *name, int *namelen)
224{
225 int out = 0;
226 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
227 if( Ws2_32 != NULL )
228 {
229 FNDEF_DYN_getpeername fn = (FNDEF_DYN_getpeername)
230 GetProcAddress( Ws2_32, "getpeername" );
231 if( fn != NULL )
232 out = (fn)( s, name, namelen );
233 }
234 return out;
235} 119}
236 120int Bu::Winsock2::getaddrinfo( const char *a, const char *b,
237typedef int (__cdecl *FNDEF_DYN_setsockopt)(SOCKET,int,int,const char*,int); 121 const struct addrinfo *c, struct addrinfo **d ) {
238int DynamicWinsock2::setsockopt(SOCKET s, int level, int optname, 122 return (*Bu::Winsock2::_fnptr_getaddrinfo)( a, b, c, d );
239 const char *optval, int optlen)
240{
241 int out = 0;
242 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
243 if( Ws2_32 != NULL )
244 {
245 FNDEF_DYN_setsockopt fn = (FNDEF_DYN_setsockopt)
246 GetProcAddress( Ws2_32, "setsockopt" );
247 if( fn != NULL )
248 out = (fn)( s, level, optname, optval, optlen );
249 }
250 return out;
251} 123}
252 124int Bu::Winsock2::connect( SOCKET s, const struct sockaddr *a, int b ) {
253typedef int (__cdecl *FNDEF_DYN_bind)(SOCKET,const struct sockaddr*,int); 125 return (*Bu::Winsock2::_fnptr_connect)( s, a, b );
254int DynamicWinsock2::bind(SOCKET s, const struct sockaddr *my_addr, int addrlen)
255{
256 int out = 0;
257 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
258 if( Ws2_32 != NULL )
259 {
260 FNDEF_DYN_bind fn = (FNDEF_DYN_bind)
261 GetProcAddress( Ws2_32, "bind" );
262 if( fn != NULL )
263 out = (fn)( s, my_addr, addrlen );
264 }
265 return out;
266} 126}
267 127int Bu::Winsock2::getpeername( SOCKET s, struct sockaddr *a, int *b ) {
268typedef int (__cdecl *FNDEF_DYN_listen)(SOCKET,int); 128 return (*Bu::Winsock2::_fnptr_getpeername)( s, a, b);
269int DynamicWinsock2::listen(SOCKET s, int backlog)
270{
271 int out = 0;
272 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
273 if( Ws2_32 != NULL )
274 {
275 FNDEF_DYN_listen fn = (FNDEF_DYN_listen)
276 GetProcAddress( Ws2_32, "listen" );
277 if( fn != NULL )
278 out = (fn)( s, backlog );
279 }
280 return out;
281} 129}
282 130int Bu::Winsock2::setsockopt( SOCKET s, int a, int b,
283typedef SOCKET (__cdecl *FNDEF_DYN_accept)(SOCKET,struct sockaddr*,int*); 131 const char *c, int d ) {
284SOCKET DynamicWinsock2::accept(SOCKET s, struct sockaddr *addr, int *addrlen) 132 return (*Bu::Winsock2::_fnptr_setsockopt)( s, a, b, c, d );
285{
286 SOCKET out = 0;
287 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
288 if( Ws2_32 != NULL )
289 {
290 FNDEF_DYN_accept fn = (FNDEF_DYN_accept)
291 GetProcAddress( Ws2_32, "accept" );
292 if( fn != NULL )
293 out = (fn)( s, addr, addrlen );
294 }
295 return out;
296} 133}
297 134int Bu::Winsock2::bind( SOCKET s, const struct sockaddr *a, int b ) {
298typedef int (__cdecl *FNDEF_DYN_recv)(SOCKET,char*,int,int); 135 return (*Bu::Winsock2::_fnptr_bind)( s, a, b );
299int DynamicWinsock2::recv( SOCKET s, char *buf, int len, int flags )
300{
301 int out = 0;
302 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
303 if( Ws2_32 != NULL )
304 {
305 FNDEF_DYN_recv fn = (FNDEF_DYN_recv)
306 GetProcAddress( Ws2_32, "recv" );
307 if( fn != NULL )
308 out = (fn)( s, buf, len, flags );
309 }
310 return out;
311} 136}
312 137int Bu::Winsock2::listen( SOCKET s, int backlog ) {
313typedef int (__cdecl *FNDEF_DYN_send)(SOCKET,const char*,int,int); 138 return (*Bu::Winsock2::_fnptr_listen)( s, backlog );
314int DynamicWinsock2::send( SOCKET s, const char *buf, int len, int flags )
315{
316 int out = 0;
317 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
318 if( Ws2_32 != NULL )
319 {
320 FNDEF_DYN_send fn = (FNDEF_DYN_send)
321 GetProcAddress( Ws2_32, "send" );
322 if( fn != NULL )
323 out = (fn)( s, buf, len, flags );
324 }
325 return out;
326} 139}
327 140SOCKET Bu::Winsock2::accept( SOCKET s, struct sockaddr *a, int *b ) {
328typedef int (__cdecl *FNDEF_DYN__WSAFDIsSet)(SOCKET,fd_set*); 141 return (*Bu::Winsock2::_fnptr_accept)( s, a, b );
329int DynamicWinsock2::DYN_FD_ISSET(SOCKET s, fd_set *set)
330{
331 int out = 0;
332 HINSTANCE Ws2_32 = LoadLibrary(TEXT("Ws2_32"));
333 if( Ws2_32 != NULL )
334 {
335 FNDEF_DYN__WSAFDIsSet fn = (FNDEF_DYN__WSAFDIsSet)
336 GetProcAddress( Ws2_32, "__WSAFDIsSet" );
337 if( fn != NULL )
338 out = (fn)( s, set );
339 }
340 return out;
341} 142}
342 143int Bu::Winsock2::recv( SOCKET s, char *buf, int len, int flags ) {
343DynamicWinsock2::Winsock2::Winsock2() 144 return (*Bu::Winsock2::_fnptr_recv)( s, buf, len, flags );
344{
345 DynamicWinsock2::WSAStartup( MAKEWORD(2, 2), &wsaData );
346} 145}
347 146int Bu::Winsock2::send( SOCKET s, const char *buf, int len, int flags ) {
348DynamicWinsock2::Winsock2::~Winsock2() 147 return (*Bu::Winsock2::_fnptr_send)( s, buf, len, flags );
349{ 148}
350 DynamicWinsock2::WSACleanup(); 149int Bu::Winsock2::__WSAFDIsSet( SOCKET s, fd_set *set ) {
150 return (*Bu::Winsock2::_fnptr___WSAFDIsSet)( s, set );
351} 151}
352 152
353#endif 153#endif
diff --git a/src/win32_compatibility.h b/src/win32_compatibility.h
index 2d3c52b..36613d1 100644
--- a/src/win32_compatibility.h
+++ b/src/win32_compatibility.h
@@ -9,12 +9,6 @@
9#define WIN32_COMPATIBILITY__H 9#define WIN32_COMPATIBILITY__H
10 10
11#ifdef WIN32 11#ifdef WIN32
12 #define DYNLOAD DynamicWinsock2::
13#else
14 #define DYNLOAD
15#endif
16
17#ifdef WIN32
18 12
19#ifdef __cplusplus 13#ifdef __cplusplus
20extern "C" 14extern "C"
@@ -36,37 +30,19 @@ extern "C"
36 __result; })) 30 __result; }))
37#endif 31#endif
38 32
33#define decltype( ret, name, ... ) \
34 typedef ret (__cdecl *FNDEF_DYN_ ##name)( __VA_ARGS__ ); \
35 static FNDEF_DYN_ ##name _fnptr_ ##name; \
36 static ret name( __VA_ARGS__ )
37
39__extension__ typedef int socklen_t; 38__extension__ typedef int socklen_t;
40 39
41namespace DynamicWinsock2 40#ifdef gai_strerror
42{ 41#undef gai_strerror
43 int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData); 42#endif
44 int WSACleanup(void);
45 int WSAGetLastError();
46 void inet_ntoa( Bu::FString &out, struct in_addr addr_in );
47 unsigned long inet_addr( const char *s_in );
48 int select(int nfds, fd_set *readfds, fd_set *writefds,
49 fd_set *exceptfds, const struct timeval *timeout);
50 SOCKET socket(int domain, int type, int protocol);
51 int ioctlsocket(SOCKET s, long cmd, u_long *argp);
52 u_short htons(u_short in);
53 u_long htonl(u_long in);
54 struct hostent *gethostbyname(const char *name);
55 void freeaddrinfo(struct addrinfo *ai);
56 int getaddrinfo(
57 const char *nodename, const char *servname,
58 const struct addrinfo *hints, struct addrinfo **res );
59 int connect(SOCKET s, const struct sockaddr *serv_addr, int addrlen);
60 int getpeername(SOCKET s, struct sockaddr *name, int *namelen);
61 int setsockopt(SOCKET s, int level, int optname,
62 const char *optval, int optlen);
63 int bind(SOCKET s, const struct sockaddr *my_addr, int addrlen);
64 int listen(SOCKET s, int backlog);
65 SOCKET accept(SOCKET s, struct sockaddr *addr, int *addrlen);
66 int recv( SOCKET s, char *buf, int len, int flags );
67 int send( SOCKET s, const char *buf, int len, int flags );
68 int DYN_FD_ISSET(SOCKET s, fd_set *set);
69 43
44namespace Bu
45{
70 class Winsock2 : public Bu::Singleton<Winsock2> 46 class Winsock2 : public Bu::Singleton<Winsock2>
71 { 47 {
72 friend class Bu::Singleton<Winsock2>; 48 friend class Bu::Singleton<Winsock2>;
@@ -75,11 +51,77 @@ namespace DynamicWinsock2
75 virtual ~Winsock2(); 51 virtual ~Winsock2();
76 52
77 WSADATA wsaData; 53 WSADATA wsaData;
54 HINSTANCE Ws2_32;
78 55
79 public: 56 public:
57 // decltype( return type, function name<, optional parameters> )
58 decltype( int, WSAStartup, WORD, LPWSADATA );
59 decltype( int, WSACleanup );
60 decltype( int, WSAGetLastError );
61 decltype( char *, inet_ntoa, struct in_addr );
62 decltype( unsigned long, inet_addr, const char *s_in );
63 decltype( int, select, int nfds, fd_set *readfds, fd_set *writefds,
64 fd_set *exceptfds, const struct timeval *timeout );
65 decltype( SOCKET, socket, int domain, int type, int protocol );
66 decltype( int, ioctlsocket, SOCKET s, long cmd, u_long *argp );
67 decltype( u_short, htons, u_short in );
68 decltype( u_long, htonl, u_long in );
69 decltype( struct hostent *, gethostbyname, const char *name );
70 decltype( void, freeaddrinfo, struct addrinfo *ai );
71 decltype( int, getaddrinfo, const char *nodename, const char *servname,
72 const struct addrinfo *hints, struct addrinfo **res );
73 decltype( int, connect, SOCKET s, const struct sockaddr *serv_addr,
74 int addrlen );
75 decltype( int, getpeername, SOCKET s, struct sockaddr *name,
76 int *namelen );
77 decltype( int, setsockopt, SOCKET s, int level, int optname,
78 const char *optval, int optlen );
79 decltype( int, bind, SOCKET s, const struct sockaddr *my_addr,
80 int addrlen );
81 decltype( int, listen, SOCKET s, int backlog );
82 decltype( SOCKET, accept, SOCKET s, struct sockaddr *addr,
83 int *addrlen);
84 decltype( int, recv, SOCKET s, char *buf, int len, int flags );
85 decltype( int, send, SOCKET s, const char *buf, int len, int flags );
86 decltype( int, __WSAFDIsSet, SOCKET s, fd_set *set );
87
88 static char scode[15];
89 static char *gai_strerror( int iCode );
80 }; 90 };
81}; 91};
82 92
93#ifdef FD_ISSET
94#undef FD_ISSET
95#endif
96
97#define bu_WSAStartup (*Bu::Winsock2::WSAStartup)
98#define bu_WSACleanup (*Bu::Winsock2::WSACleanup)
99#define bu_WSAGetLastError (*Bu::Winsock2::WSAGetLastError)
100#define bu_inet_ntoa (*Bu::Winsock2::inet_ntoa)
101#define bu_inet_addr (*Bu::Winsock2::inet_addr)
102#define bu_select (*Bu::Winsock2::select)
103#define bu_socket (*Bu::Winsock2::socket)
104#define bu_ioctlsocket (*Bu::Winsock2::ioctlsocket)
105#define bu_htons (*Bu::Winsock2::htons)
106#define bu_htonl (*Bu::Winsock2::htonl)
107#define bu_gethostbyname (*Bu::Winsock2::gethostbyname)
108#define bu_freeaddrinfo (*Bu::Winsock2::freeaddrinfo)
109#define bu_getaddrinfo (*Bu::Winsock2::getaddrinfo)
110#define bu_connect (*Bu::Winsock2::connect)
111#define bu_getpeername (*Bu::Winsock2::getpeername)
112#define bu_setsockopt (*Bu::Winsock2::setsockopt)
113#define bu_bind (*Bu::Winsock2::bind)
114#define bu_listen (*Bu::Winsock2::listen)
115#define bu_accept (*Bu::Winsock2::accept)
116#define bu_recv (*Bu::Winsock2::recv)
117#define bu_send (*Bu::Winsock2::send)
118#define bu___WSAFDIsSet (*Bu::Winsock2::__WSAFDIsSet)
119
120#define FD_ISSET (*Bu::Winsock2::__WSAFDIsSet)
121#define bu_gai_strerror Bu::Winsock2::gai_strerror
122
123#undef decltype
124
83#endif /* WIN32 */ 125#endif /* WIN32 */
84#endif 126#endif
85 127