summaryrefslogtreecommitdiff
path: root/cpp/src/Ice/Network.cpp
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2005-06-30 09:44:39 +0000
committerBenoit Foucher <benoit@zeroc.com>2005-06-30 09:44:39 +0000
commit34d41333b3b1e104a0796b15c687061ef4560b8e (patch)
tree352393e3f845e3633b735d1b7432356f7c8badd6 /cpp/src/Ice/Network.cpp
parentMake install fixes (diff)
downloadice-34d41333b3b1e104a0796b15c687061ef4560b8e.tar.bz2
ice-34d41333b3b1e104a0796b15c687061ef4560b8e.tar.xz
ice-34d41333b3b1e104a0796b15c687061ef4560b8e.zip
Merged fix from branch (throughput performance issue on Win32)
Diffstat (limited to 'cpp/src/Ice/Network.cpp')
-rw-r--r--cpp/src/Ice/Network.cpp117
1 files changed, 117 insertions, 0 deletions
diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp
index 00eba6393ca..6c3f9126bc9 100644
--- a/cpp/src/Ice/Network.cpp
+++ b/cpp/src/Ice/Network.cpp
@@ -7,9 +7,21 @@
//
// **********************************************************************
+#ifdef _WIN32
+//
+// Prevents windows.h from including winsock.h
+//
+# define WIN32_LEAN_AND_MEAN 1
+#endif
+
#include <Ice/Network.h>
#include <Ice/LocalException.h>
+#ifdef _WIN32
+# include <winsock2.h>
+#endif
+
+
using namespace std;
using namespace Ice;
using namespace IceInternal;
@@ -1193,3 +1205,108 @@ IceInternal::addrToString(const struct sockaddr_in& addr)
s << inet_ntoa(addr.sin_addr) << ':' << ntohs(addr.sin_port);
return s.str();
}
+
+#ifdef _WIN32
+
+vector<struct sockaddr_in>
+IceInternal::getLocalAddresses()
+{
+ vector<struct sockaddr_in> result;
+ try
+ {
+ SOCKET fd = createSocket(false);
+
+ vector<unsigned char> buffer;
+ buffer.resize(1024);
+ unsigned long len = 0;
+ DWORD rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, &buffer[0], buffer.size(), &len, 0, 0);
+ if(rs == SOCKET_ERROR)
+ {
+ //
+ // If the buffer wasn't big enough, resize it to the
+ // required length and try again.
+ //
+ if(getSocketErrno() == WSAEFAULT)
+ {
+ buffer.resize(len);
+ rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, &buffer[0], buffer.size(), &len, 0, 0);
+ }
+
+ if(rs == SOCKET_ERROR)
+ {
+ closeSocket(fd);
+ SocketException ex(__FILE__, __LINE__);
+ ex.error = getSocketErrno();
+ throw ex;
+ }
+ }
+
+ //
+ // Add the local interface addresses.
+ //
+ SOCKET_ADDRESS_LIST* addrs = reinterpret_cast<SOCKET_ADDRESS_LIST*>(&buffer[0]);
+ for (int i = 0; i < addrs->iAddressCount; ++i)
+ {
+ result.push_back(*reinterpret_cast<struct sockaddr_in*>(addrs->Address[i].lpSockaddr));
+ }
+
+ //
+ // Add the loopback interface address.
+ //
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(0);
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ result.push_back(addr);
+
+ closeSocket(fd);
+ }
+ catch(const Ice::LocalException&)
+ {
+ //
+ // TODO: Warning?
+ //
+ }
+ return result;
+}
+
+bool
+IceInternal::isLocalAddress(const struct sockaddr_in& addr)
+{
+ struct sockaddr_in addr0 = addr;
+ addr0.sin_port = htons(0); // Local interface addresses have the port set to 0.
+ vector<struct sockaddr_in> localAddrs = getLocalAddresses();
+ for(vector<struct sockaddr_in>::const_iterator p = localAddrs.begin(); p != localAddrs.end(); ++p)
+ {
+ if(compareAddress(addr0, *p))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+IceInternal::isPeerLocal(SOCKET fd)
+{
+ socklen_t remoteLen = static_cast<socklen_t>(sizeof(struct sockaddr_in));
+ struct sockaddr_in remoteAddr;
+ if(getpeername(fd, reinterpret_cast<struct sockaddr*>(&remoteAddr), &remoteLen) == SOCKET_ERROR)
+ {
+ if(notConnected())
+ {
+ return false;
+ }
+ else
+ {
+ closeSocket(fd);
+ SocketException ex(__FILE__, __LINE__);
+ ex.error = getSocketErrno();
+ throw ex;
+ }
+ }
+ return isLocalAddress(remoteAddr);
+}
+
+#endif