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 = &in;	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 + -
显示快捷键?