plaindatagramsocketimpl_md.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,016 行 · 第 1/5 页
C
2,016 行
return; } addr = (*env)->GetObjectArrayElement(env, addrArray, 0); in.s_addr = htonl((*env)->GetIntField(env, addr, ia_addressID)); if (JVM_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&in, sizeof(in)) < 0) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error setting socket option"); } return; } }}/* * Class: java_net_PlainDatagramSocketImpl * Method: socketSetOption * Signature: (ILjava/lang/Object;)V */JNIEXPORT void JNICALLJava_java_net_PlainDatagramSocketImpl_socketSetOption(JNIEnv *env, jobject this, jint opt, jobject value) { int fd; int level, optname, optlen = 0; union { int i; char c; } optval; /* * Check that socket hasn't been closed */ fd = getFD(env, this); if (fd < 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); return; } /* * Check argument has been provided */ if (IS_NULL(value)) { JNU_ThrowNullPointerException(env, "value argument"); return; } /* * Setting the multicast interface handled seperately */ if (opt == java_net_SocketOptions_IP_MULTICAST_IF || opt == java_net_SocketOptions_IP_MULTICAST_IF2) { setMulticastInterface(env, this, fd, opt, value); return; } /* * 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; } switch (opt) { case java_net_SocketOptions_SO_SNDBUF : case java_net_SocketOptions_SO_RCVBUF : case java_net_SocketOptions_IP_TOS : { jclass cls; jfieldID fid; cls = (*env)->FindClass(env, "java/lang/Integer"); CHECK_NULL(cls); fid = (*env)->GetFieldID(env, cls, "value", "I"); CHECK_NULL(fid); optval.i = (*env)->GetIntField(env, value, fid); optlen = sizeof(optval.i); break; } case java_net_SocketOptions_SO_REUSEADDR: case java_net_SocketOptions_SO_BROADCAST: case java_net_SocketOptions_IP_MULTICAST_LOOP: { jclass cls; jfieldID fid; jboolean on; cls = (*env)->FindClass(env, "java/lang/Boolean"); CHECK_NULL(cls); fid = (*env)->GetFieldID(env, cls, "value", "Z"); CHECK_NULL(fid); on = (*env)->GetBooleanField(env, value, fid); if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP) { /* * IP_MULTICAST_LOOP may be mapped to IPPROTO (arg * type 'char') or IPPROTO_V6 (arg type 'int'). * * In addition setLoopbackMode(true) disables * IP_MULTICAST_LOOP - doesn't enable it. */ if (level == IPPROTO_IP) { optval.c = (!on ? 1 : 0); optlen = sizeof(optval.c); } else { optval.i = (!on ? 1 : 0); optlen = sizeof(optval.i); } } else { /* SO_REUSEADDR or SO_BROADCAST */ optval.i = (on ? 1 : 0); optlen = sizeof(optval.i); } break; } default : JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket option not supported by PlainDatagramSocketImp"); break; } if (NET_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error setting socket option"); return; } /* * Can't query IPV6_MULTICAST_LOOP on Linux 2.2 kernel so * store it in impl so that we can simulate getsockopt. */#if defined(__linux__) && defined(AF_INET6) if (isOldKernel && level == IPPROTO_IPV6 && optname == IPV6_MULTICAST_LOOP) { (*env)->SetBooleanField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_loopbackID), (optval.c ? JNI_FALSE :JNI_TRUE)); } #endif}/* * Return the multicast interface: * * SocketOptions.IP_MULTICAST_IF * IPv4: Query IPPROTO_IP/IP_MULTICAST_IF * Create InetAddress * IP_MULTICAST_IF returns struct ip_mreqn on 2.2 * kernel but struct in_addr on 2.4 kernel * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF or * obtain from impl is Linux 2.2 kernel * If index == 0 return InetAddress representing * anyLocalAddress. * If index > 0 query NetworkInterface by index * and returns addrs[0] * * SocketOptions.IP_MULTICAST_IF2 * IPv4: Query IPPROTO_IP/IP_MULTICAST_IF * Query NetworkInterface by IP address and * return the NetworkInterface that the address * is bound too. * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF * (except Linux .2 kernel) * Query NetworkInterface by index and * return NetworkInterface. */jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, jint opt) { jboolean isIPV4 = JNI_TRUE;#ifdef AF_INET6 if (ipv6_available()) { isIPV4 = JNI_FALSE; }#endif /* * IPv4 implementation */ if (isIPV4) { static jclass inet4_class; static jmethodID inet4_ctrID; static jfieldID inet4_addrID; static jclass ni_class; static jmethodID ni_ctrID; static jfieldID ni_indexID; static jfieldID ni_addrsID; jobjectArray addrArray; jobject addr; jobject ni; struct in_addr in; struct in_addr *inP = ∈ int len = sizeof(struct in_addr); struct ip_mreqn mreqn; if (isOldKernel) { inP = (struct in_addr *)&mreqn; len = sizeof(struct ip_mreqn); } if (JVM_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char *)inP, &len) < 0) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error getting socket option"); return NULL; } /* * Construct and populate an Inet4Address */ if (inet4_class == NULL) { jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); CHECK_NULL_RETURN(c, NULL); inet4_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V"); CHECK_NULL_RETURN(inet4_ctrID, NULL); inet4_addrID = (*env)->GetFieldID(env, c, "address", "I"); CHECK_NULL_RETURN(inet4_addrID, NULL); inet4_class = (*env)->NewGlobalRef(env, c); CHECK_NULL_RETURN(inet4_class, NULL); } addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0); CHECK_NULL_RETURN(addr, NULL); (*env)->SetIntField(env, addr, inet4_addrID, (isOldKernel ? ntohl(mreqn.imr_address.s_addr) : ntohl(in.s_addr)) ); /* * For IP_MULTICAST_IF return InetAddress */ if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { return addr; } /* * For IP_MULTICAST_IF2 we get the NetworkInterface for * this address and return it */ if (ni_class == NULL) { jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); CHECK_NULL_RETURN(c, NULL); ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V"); CHECK_NULL_RETURN(ni_ctrID, NULL); ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); CHECK_NULL_RETURN(ni_indexID, NULL); ni_addrsID = (*env)->GetFieldID(env, c, "addrs", "[Ljava/net/InetAddress;"); CHECK_NULL_RETURN(ni_addrsID, NULL); ni_class = (*env)->NewGlobalRef(env, c); CHECK_NULL_RETURN(ni_class, NULL); } ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr); if (ni) { return ni; } /* * The address doesn't appear to be bound at any known * NetworkInterface. Therefore we construct a NetworkInterface * with this address. */ ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0); CHECK_NULL_RETURN(ni, NULL); (*env)->SetIntField(env, ni, ni_indexID, -1); addrArray = (*env)->NewObjectArray(env, 1, inet4_class, NULL); CHECK_NULL_RETURN(addrArray, NULL); (*env)->SetObjectArrayElement(env, addrArray, 0, addr); (*env)->SetObjectField(env, ni, ni_addrsID, addrArray); return ni; }#ifdef AF_INET6 /* * IPv6 implementation */ assert ((opt == java_net_SocketOptions_IP_MULTICAST_IF) || (opt == java_net_SocketOptions_IP_MULTICAST_IF2)); { static jclass ni_class; static jmethodID ni_ctrID; static jfieldID ni_indexID; static jfieldID ni_addrsID; static jclass ia_class; static jmethodID ia_anyLocalAddressID; int index; int len = sizeof(index); jobjectArray addrArray; jobject addr; jobject ni; /* * Linux 2.2 kernel doesn't support IPV6_MULTICAST_IF socke option * so use cached 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) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error getting socket option"); return NULL; } } if (ni_class == NULL) { jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); CHECK_NULL_RETURN(c, NULL); ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V"); CHECK_NULL_RETURN(ni_ctrID, NULL); ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); CHECK_NULL_RETURN(ni_indexID, NULL); ni_addrsID = (*env)->GetFieldID(env, c, "addrs", "[Ljava/net/InetAddress;"); CHECK_NULL_RETURN(ni_addrsID, NULL); ia_class = (*env)->FindClass(env, "java/net/InetAddress"); CHECK_NULL_RETURN(ia_class, NULL); ia_class = (*env)->NewGlobalRef(env, ia_class); CHECK_NULL_RETURN(ia_class, NULL); ia_anyLocalAddressID = (*env)->GetStaticMethodID(env, ia_class, "anyLocalAddress", "()Ljava/net/InetAddress;"); CHECK_NULL_RETURN(ia_anyLocalAddressID, NULL); ni_class = (*env)->NewGlobalRef(env, c); CHECK_NULL_RETURN(ni_class, NULL); } /* * If multicast to a specific interface then return the * interface (for IF2) or the any address on that interface * (for IF). */ if (index > 0) { ni = Java_java_net_NetworkInterface_getByIndex(env, ni_class, index); if (ni == NULL) { char errmsg[255]; sprintf(errmsg, "IPV6_MULTICAST_IF returned index to unrecognized interface: %d", index); JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg); return NULL; } /* * For IP_MULTICAST_IF2 return the NetworkInterface */ if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) { return ni; } /* * For IP_MULTICAST_IF return addrs[0] */ addrArray = (*env)->GetObjectField(env, ni, ni_addrsID); if ((*env)->GetArrayLength(env, addrArray) < 1) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "IPV6_MULTICAST_IF returned interface without IP bindings"); return NULL; } addr = (*env)->GetObjectArrayElement(env, addrArray, 0); return addr; } /* * Multicast to any address - return anyLocalAddress * or a NetworkInterface with addrs[0] set to anyLocalAddress */ addr = (*env)->CallStaticObjectMethod(env, ia_class, ia_anyLocalAddressID, NULL); if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { return addr; } ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0); CHECK_NULL_RETURN(ni, NULL); (*env)->SetIntField(env, ni, ni_indexID, -1); addrArray = (*env)->NewObjectArray(env, 1, ia_class, NULL); CHECK_NULL_RETURN(addrArray, NULL); (*env)->SetObjectArrayElement(env, addrArray, 0, addr); (*env)->SetObjectField(env, ni, ni_addrsID, addrArray); return ni;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?