diff options
Diffstat (limited to 'cppe/src')
-rw-r--r-- | cppe/src/IceE/Network.cpp | 104 | ||||
-rw-r--r-- | cppe/src/IceE/Network.h | 6 | ||||
-rw-r--r-- | cppe/src/TcpTransport/Transceiver.cpp | 5 |
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(); |