DWORD Socket::getOutputTimeout() { DWORD timeout = 0; #if defined(WIN32) || defined(WIN64) getSocketOption( SO_SNDTIMEO, timeout ); #endif return timeout; }
bool CPPTcpClientSocket::connect(short port, unsigned int addr, int timeout, bool spin){ std::lock_guard<std::mutex> lockR(recvLock), lockS(sendLock); m_port = port; m_addr = addr; struct sockaddr_in remote; memset(&remote, 0, sizeof(remote)); remote.sin_family = AF_INET; remote.sin_addr.s_addr = m_addr; remote.sin_port = htons(m_port); double tremaining = timeout; auto start = std::chrono::system_clock::now(); bool success = false; do{ if (!open()){ break; } setBlocking(false, false); if (::connect(m_sock, (struct sockaddr *)&remote, sizeof(remote)) == 0){ success = true; break; } if (errno != EINPROGRESS){ break; } struct pollfd pfd = {m_sock, POLLWRNORM, 0}; if (poll(&pfd, 1, (int)tremaining) > 0){ int optionValue = -1; socklen_t optionLength = sizeof(optionValue); if (getSocketOption(SOL_SOCKET, SO_ERROR, (void *)&optionValue, &optionLength, false) && optionValue == 0){ success = true; break; } } std::chrono::duration<double, std::milli> dur = std::chrono::system_clock::now() - start; tremaining = timeout - dur.count(); std::this_thread::sleep_for(std::chrono::milliseconds(10)); ::shutdown(m_sock, SHUT_RDWR); ::close(m_sock); m_sock = -1; if (!spin) break; }while((tremaining > 0.0 || timeout < 0) && !sigClose); setBlocking(true, false); if (success) return true; if (m_sock != -1){ ::shutdown(m_sock, SHUT_RDWR); ::close(m_sock); m_sock=-1; } return false; }
static jobject OSNetworkSystem_getSocketOption(JNIEnv* env, jobject, jobject fileDescriptor, jint option) { NetFd fd(env, fileDescriptor); if (fd.isClosed()) { return NULL; } int family = getSocketAddressFamily(fd.get()); if (family != AF_INET && family != AF_INET6) { jniThrowSocketException(env, EAFNOSUPPORT); return NULL; } switch (option) { case JAVASOCKOPT_TCP_NODELAY: return getSocketOption_Boolean(env, fd, IPPROTO_TCP, TCP_NODELAY); case JAVASOCKOPT_SO_SNDBUF: return getSocketOption_Integer(env, fd, SOL_SOCKET, SO_SNDBUF); case JAVASOCKOPT_SO_RCVBUF: return getSocketOption_Integer(env, fd, SOL_SOCKET, SO_RCVBUF); case JAVASOCKOPT_SO_BROADCAST: return getSocketOption_Boolean(env, fd, SOL_SOCKET, SO_BROADCAST); case JAVASOCKOPT_SO_REUSEADDR: return getSocketOption_Boolean(env, fd, SOL_SOCKET, SO_REUSEADDR); case JAVASOCKOPT_SO_KEEPALIVE: return getSocketOption_Boolean(env, fd, SOL_SOCKET, SO_KEEPALIVE); case JAVASOCKOPT_SO_OOBINLINE: return getSocketOption_Boolean(env, fd, SOL_SOCKET, SO_OOBINLINE); case JAVASOCKOPT_IP_TOS: if (family == AF_INET) { return getSocketOption_Integer(env, fd, IPPROTO_IP, IP_TOS); } else { return getSocketOption_Integer(env, fd, IPPROTO_IPV6, IPV6_TCLASS); } case JAVASOCKOPT_SO_LINGER: { linger lingr; bool ok = getSocketOption(env, fd, SOL_SOCKET, SO_LINGER, &lingr); if (!ok) { return NULL; // We already threw. } else if (!lingr.l_onoff) { return booleanValueOf(env, false); } else { return integerValueOf(env, lingr.l_linger); } } case JAVASOCKOPT_SO_TIMEOUT: { timeval timeout; bool ok = getSocketOption(env, fd, SOL_SOCKET, SO_RCVTIMEO, &timeout); return ok ? integerValueOf(env, toMs(timeout)) : NULL; } #ifdef ENABLE_MULTICAST case JAVASOCKOPT_IP_MULTICAST_IF: { // Although setsockopt(2) can take an ip_mreqn for IP_MULTICAST_IF, getsockopt(2) // always returns an in_addr. sockaddr_storage ss; memset(&ss, 0, sizeof(ss)); ss.ss_family = AF_INET; // This call is IPv4-only. sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(&ss); if (!getSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_IF, &sa->sin_addr)) { return NULL; } return socketAddressToInetAddress(env, &ss); } case JAVASOCKOPT_IP_MULTICAST_IF2: if (family == AF_INET) { // The caller's asking for an interface index, but that's not how IPv4 works. // Our Java should never get here, because we'll try IP_MULTICAST_IF first and // that will satisfy us. jniThrowSocketException(env, EAFNOSUPPORT); } else { return getSocketOption_Integer(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_IF); } case JAVASOCKOPT_IP_MULTICAST_LOOP: if (family == AF_INET) { // Although IPv6 was cleaned up to use int, IPv4 multicast loopback uses a byte. u_char loopback; bool ok = getSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loopback); return ok ? booleanValueOf(env, loopback) : NULL; } else { return getSocketOption_Boolean(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); } case JAVASOCKOPT_MULTICAST_TTL: if (family == AF_INET) { // Although IPv6 was cleaned up to use int, and IPv4 non-multicast TTL uses int, // IPv4 multicast TTL uses a byte. u_char ttl; bool ok = getSocketOption(env, fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl); return ok ? integerValueOf(env, ttl) : NULL; } else { return getSocketOption_Integer(env, fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); } #else case JAVASOCKOPT_MULTICAST_TTL: case JAVASOCKOPT_IP_MULTICAST_IF: case JAVASOCKOPT_IP_MULTICAST_IF2: case JAVASOCKOPT_IP_MULTICAST_LOOP: jniThrowException(env, "java/lang/UnsupportedOperationException", NULL); return NULL; #endif // def ENABLE_MULTICAST default: jniThrowSocketException(env, ENOPROTOOPT); return NULL; } }
static jobject getSocketOption_Integer(JNIEnv* env, const NetFd& fd, int level, int option) { int value; return getSocketOption(env, fd, level, option, &value) ? integerValueOf(env, value) : NULL; }
DWORD Socket::getConnectionTime() { DWORD connectionTime; getSocketOption( SO_CONNECT_TIME, connectionTime ); return connectionTime; }
DWORD Socket::getInputTimeout() { DWORD timeout; getSocketOption(SO_RCVTIMEO, timeout); return timeout; }
bool Socket::isKeepAlive() { DWORD keepAlive = 0; getSocketOption(SO_KEEPALIVE, keepAlive); return keepAlive != 0; }
bool Socket::isRoutingEnabled() { DWORD enabled; getSocketOption(SO_DONTROUTE, enabled); return enabled != 0; }
USHORT Socket::getLingerTime() { linger ln; getSocketOption(SO_LINGER, ln); return ln.l_linger; }