plaindatagramsocketimpl_md.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,016 行 · 第 1/5 页
C
2,016 行
}#endif}/* * Returns relevant info as a jint. * * Class: java_net_PlainDatagramSocketImpl * Method: socketGetOption * Signature: (I)Ljava/lang/Object; */JNIEXPORT jobject JNICALLJava_java_net_PlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this, jint opt) { int fd; int level, optname, optlen; union { int i; char c; } optval; fd = getFD(env, this); if (fd < 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); return NULL; } /* * Handle IP_MULTICAST_IF seperately */ if (opt == java_net_SocketOptions_IP_MULTICAST_IF || opt == java_net_SocketOptions_IP_MULTICAST_IF2) { return getMulticastInterface(env, this, fd, opt); } /* * SO_BINDADDR implemented using getsockname */ if (opt == java_net_SocketOptions_SO_BINDADDR) { /* find out local IP address */ SOCKADDR him; socklen_t len = 0; int port; jobject iaObj; len = SOCKADDR_LEN; if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error getting socket name"); return NULL; } iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port); return iaObj; } /* * Map the Java level socket option to the platform specific * level and option name. */ if (NET_MapSocketOption(opt, &level, &optname)) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); return NULL; } /* * IP_MULTICAST_LOOP socket option isn't available on Linux 2.2 * kernel with IPv6 so return value stored in impl. */#if defined(AF_INET6) && defined(__linux__) if (isOldKernel && opt == java_net_SocketOptions_IP_MULTICAST_LOOP && level == IPPROTO_IPV6) { int mode = (int)(*env)->GetBooleanField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_loopbackID)); return createBoolean(env, mode); }#endif if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP && level == IPPROTO_IP) { optlen = sizeof(optval.c); } else { optlen = sizeof(optval.i); } if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error getting socket option"); return NULL; } switch (opt) { case java_net_SocketOptions_IP_MULTICAST_LOOP: /* getLoopbackMode() returns true if IP_MULTICAST_LOOP disabled */ if (level == IPPROTO_IP) { return createBoolean(env, (int)!optval.c); } else { return createBoolean(env, !optval.i); } case java_net_SocketOptions_SO_BROADCAST: case java_net_SocketOptions_SO_REUSEADDR: return createBoolean(env, optval.i); case java_net_SocketOptions_SO_SNDBUF: case java_net_SocketOptions_SO_RCVBUF: case java_net_SocketOptions_IP_TOS: return createInteger(env, optval.i); } /* should never rearch here */ return NULL;}/* * Multicast-related calls */JNIEXPORT void JNICALLJava_java_net_PlainDatagramSocketImpl_setTTL(JNIEnv *env, jobject this, jbyte ttl) { jint ittl = ttl; if (ittl < 0) { ittl += 0x100; } Java_java_net_PlainDatagramSocketImpl_setTimeToLive(env, this, (jint)ittl);}/* * Class: java_net_PlainDatagramSocketImpl * Method: setTTL * Signature: (B)V */JNIEXPORT void JNICALLJava_java_net_PlainDatagramSocketImpl_setTimeToLive(JNIEnv *env, jobject this, jint ttl) { jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID)); int fd; /* it is important to cast this to a char, otherwise setsockopt gets confused */ if (IS_NULL(fdObj)) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); return; } else { fd = (*env)->GetIntField(env, fdObj, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID)); } /* setsockopt to be correct ttl */#ifdef AF_INET6 if (ipv6_available()) { if (JVM_SetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&ttl, sizeof(ttl)) < 0) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error setting socket option"); return; } if (isOldKernel) { (*env)->SetIntField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_ttlID), ttl); } } else #endif /* AF_INET6 */ { if (JVM_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)) < 0) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error setting socket option"); } }}/* * Class: java_net_PlainDatagramSocketImpl * Method: getTTL * Signature: ()B */JNIEXPORT jbyte JNICALLJava_java_net_PlainDatagramSocketImpl_getTTL(JNIEnv *env, jobject this) { return (jbyte)Java_java_net_PlainDatagramSocketImpl_getTimeToLive(env, this);}/* * Class: java_net_PlainDatagramSocketImpl * Method: getTTL * Signature: ()B */JNIEXPORT jint JNICALLJava_java_net_PlainDatagramSocketImpl_getTimeToLive(JNIEnv *env, jobject this) { jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID)); jint fd = -1; if (IS_NULL(fdObj)) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); return -1; } else { fd = (*env)->GetIntField(env, fdObj, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID)); } /* getsockopt of ttl */#ifdef AF_INET6 if (ipv6_available()) { int ttl = 0; int len = sizeof(ttl); /* * Linux 2.2 kernel doesn't support IPV6_MULTICAST_HOPS socket option */ if (isOldKernel) { return (*env)->GetIntField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_ttlID)); } if (JVM_GetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&ttl, &len) < 0) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error getting socket option"); return -1; } return (jint)ttl; } else #endif /* AF_INET6 */ { jint ttl = 0; int len = sizeof(ttl); if (JVM_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, &len) < 0) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error getting socket option"); return -1; } return ttl; }}/* * mcast_join_leave: Join or leave a multicast group. * * For IPv4 sockets use IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP socket option * to join/leave multicast group. * * For IPv6 sockets use IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP socket option * to join/leave multicast group. If multicast group is an IPv4 address then * an IPv4-mapped address is used. * * On Linux with IPv6 if we wish to join/leave an IPv4 multicast group then * we must use the IPv4 socket options. This is because the IPv6 socket options * don't support IPv4-mapped addresses. This is true as per 2.2.19 and 2.4.7 * kernel releases. In the future it's possible that IP_ADD_MEMBERSHIP * will be updated to return ENOPROTOOPT if uses with an IPv6 socket (Solaris * already does this). Thus to cater for this we first try with the IPv4 * socket options and if they fail we use the IPv6 socket options. This * seems a reasonable failsafe solution. */static void mcast_join_leave(JNIEnv *env, jobject this, jobject iaObj, jobject niObj, jboolean join) { jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID)); jint fd; jint ipv6_join_leave; if (IS_NULL(fdObj)) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); return; } else { fd = (*env)->GetIntField(env, fdObj, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID)); } if (IS_NULL(iaObj)) { JNU_ThrowNullPointerException(env, "iaObj"); return; } /* * Determine if this is an IPv4 or IPv6 join/leave. */#ifdef AF_INET6 ipv6_join_leave = ipv6_available();#ifdef __linux__ if ((*env)->GetIntField(env, iaObj, JNI_STATIC(java_net_InetAddress, ia_familyID)) == IPv4) { ipv6_join_leave = JNI_FALSE; }#endif#else /* * IPv6 not compiled in */ ipv6_join_leave = JNI_FALSE;#endif /* * For IPv4 join use IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP socket option * * On Linux if IPv4 or IPv6 use IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP */ if (!ipv6_join_leave) {#ifdef __linux__ struct ip_mreqn mname;#else struct ip_mreq mname;#endif int mname_len = 0; /* * joinGroup(InetAddress, NetworkInterface) implementation :- * * Linux/IPv6: use ip_mreqn structure populated with multicast * address and interface index. * * IPv4: use ip_mreq structure populated with multicast * address and first address obtained from * NetworkInterface */ if (niObj != NULL) {#if defined(__linux__) && defined(AF_INET6) if (ipv6_available()) { static jfieldID ni_indexID; if (ni_indexID == NULL) { jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); CHECK_NULL(c); ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); CHECK_NULL(ni_indexID); } mname.imr_multiaddr.s_addr = htonl((*env)->GetIntField(env, iaObj, JNI_STATIC(java_net_InetAddress, ia_addressID))); mname.imr_address.s_addr = 0; mname.imr_ifindex = (*env)->GetIntField(env, niObj, ni_indexID); mname_len = sizeof(struct ip_mreqn); } else #endif { static jfieldID ni_addrsID; jobjectArray addrArray; jobject addr; if (ni_addrsID == NULL) { jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); CHECK_NULL(c); ni_addrsID = (*env)->GetFieldID(env, c, "addrs", "[Ljava/net/InetAddress;"); CHECK_NULL(ni_addrsID); } addrArray = (*env)->GetObjectField(env, niObj, ni_addrsID); if ((*env)->GetArrayLength(env, addrArray) < 1) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "bad argument for IP_ADD_MEMBERSHIP: " "No IP addresses bound to interface"); return; } addr = (*env)->GetObjectArrayElement(env, addrArray, 0); mname.imr_multiaddr.s_addr = htonl((*env)->GetIntField(env, iaObj, JNI_STATIC(java_net_InetAddress, ia_addressID)));#ifdef __linux__ mname.imr_address.s_addr = htonl((*env)->GetIntField(env, addr, JNI_STATIC(java_net_InetAddress, ia_addressID)));#else mname.imr_interface.s_addr = htonl((*env)->GetIntField(env, addr, JNI_STATIC(java_net_InetAddress, ia_addressID)));#endif mname_len = sizeof(struct ip_mreq); } } /* * joinGroup(InetAddress) implementation :- * * Linux/IPv6: use ip_mreqn structure populated with multicast * address and interface index. index obtained * from cached value or IPV6_MULTICAST_IF. * * IPv4: use ip_mreq structure populated with multicast * address and local address obtained from * IP_MULTICAST_IF. On Linux IP_MULTICAST_IF * returns different structure depending on * kernel. */ if (niObj == NULL) {#if defined(__linux__) && defined(AF_INET6) if (ipv6_available()) { int index; int len = sizeof(index); if (isOldKernel) { index = (*env)->GetIntField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_multicastInterfaceID)); } else { if (JVM_GetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char*)&index, &len) < 0) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?