summaryrefslogtreecommitdiff
path: root/cppe/src
diff options
context:
space:
mode:
Diffstat (limited to 'cppe/src')
-rw-r--r--cppe/src/IceE/Network.cpp104
-rw-r--r--cppe/src/IceE/Network.h6
-rw-r--r--cppe/src/TcpTransport/Transceiver.cpp5
3 files changed, 114 insertions, 1 deletions
diff --git a/cppe/src/IceE/Network.cpp b/cppe/src/IceE/Network.cpp
index 01a24ab1735..f01e4bcd8cc 100644
--- a/cppe/src/IceE/Network.cpp
+++ b/cppe/src/IceE/Network.cpp
@@ -1148,3 +1148,107 @@ repeatListen:
}
#endif
+
+#ifdef _WIN32
+
+vector<struct sockaddr_in>
+IceInternal::getLocalAddresses()
+{
+ vector<struct sockaddr_in> result;
+ try
+ {
+ SOCKET fd = createSocket();
+
+ 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
diff --git a/cppe/src/IceE/Network.h b/cppe/src/IceE/Network.h
index 21e9311a50e..56274e88f64 100644
--- a/cppe/src/IceE/Network.h
+++ b/cppe/src/IceE/Network.h
@@ -105,6 +105,12 @@ ICEE_API std::string lastErrorToString();
ICEE_API std::string fdToString(SOCKET);
ICEE_API std::string addrToString(const struct sockaddr_in&);
+#ifdef _WIN32
+ICEE_API std::vector<struct sockaddr_in> getLocalAddresses();
+ICEE_API bool isLocalAddress(const struct sockaddr_in&);
+ICEE_API bool isPeerLocal(SOCKET);
+#endif
+
}
#endif
diff --git a/cppe/src/TcpTransport/Transceiver.cpp b/cppe/src/TcpTransport/Transceiver.cpp
index f27a8189a20..ac3fb02dcd7 100644
--- a/cppe/src/TcpTransport/Transceiver.cpp
+++ b/cppe/src/TcpTransport/Transceiver.cpp
@@ -95,7 +95,7 @@ IceInternal::Transceiver::write(Buffer& buf, int timeout)
//
// Limit packet size to avoid performance problems on WIN32
//
- if(packetSize > 64 * 1024)
+ if(_isPeerLocal && packetSize > 64 * 1024)
{
packetSize = 64 * 1024;
}
@@ -427,6 +427,9 @@ IceInternal::Transceiver::Transceiver(const InstancePtr& instance, SOCKET fd) :
_logger(instance->logger()),
_fd(fd),
_desc(fdToString(fd))
+#ifdef _WIN32
+ , _isPeerLocal(isPeerLocal(fd))
+#endif
{
#ifdef _WIN32_WCE
_event = WSACreateEvent();