plaindatagramsocketimpl_md.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,016 行 · 第 1/5 页

C
2,016
字号
/* * @(#)PlainDatagramSocketImpl_md.c	1.31 06/05/03 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation.  *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt).  *  * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA  *  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions.  */#include <errno.h>#include <netinet/in.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#ifdef __linux__#include <sys/utsname.h>#include <netinet/ip.h>#define IPV6_MULTICAST_IF 17#ifndef SO_BSDCOMPAT#define SO_BSDCOMPAT  14#endif#endif#ifndef IPTOS_TOS_MASK#define IPTOS_TOS_MASK 0x1e#endif#ifndef IPTOS_PREC_MASK#define IPTOS_PREC_MASK 0xe0#endif #include "jvm.h"#include "jni_util.h"#include "net_util.h"#include "java_net_InetAddress.h"#include "java_net_Inet4Address.h"#include "java_net_Inet6Address.h"#include "java_net_SocketOptions.h"#include "java_net_PlainDatagramSocketImpl.h"#include "java_net_NetworkInterface.h"/************************************************************************ * PlainDatagramSocketImpl */#include "jni_statics.h"static jboolean isOldKernel;/* * Returns a java.lang.Integer based on 'i' */static jobject createInteger(JNIEnv *env, int i) {    static jclass i_class;    static jmethodID i_ctrID;    if (i_class == NULL) { 	jclass c = (*env)->FindClass(env, "java/lang/Integer");	CHECK_NULL_RETURN(c, NULL);        i_ctrID = (*env)->GetMethodID(env, c, "<init>", "(I)V");	CHECK_NULL_RETURN(i_ctrID, NULL);	i_class = (*env)->NewGlobalRef(env, c);	CHECK_NULL_RETURN(i_class, NULL);    }    return ( (*env)->NewObject(env, i_class, i_ctrID, i) );}/* * Returns a java.lang.Boolean based on 'b' */static jobject createBoolean(JNIEnv *env, int b) {    static jclass b_class;    static jmethodID b_ctrID;    if (b_class == NULL) {        jclass c = (*env)->FindClass(env, "java/lang/Boolean");	CHECK_NULL_RETURN(c, NULL);        b_ctrID = (*env)->GetMethodID(env, c, "<init>", "(Z)V");	CHECK_NULL_RETURN(b_ctrID, NULL);        b_class = (*env)->NewGlobalRef(env, c);	CHECK_NULL_RETURN(b_class, NULL);    }    return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) );}/* * Returns the fd for a PlainDatagramSocketImpl or -1 * if closed. */static int getFD(JNIEnv *env, jobject this) {    jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID));    if (fdObj == NULL) {        return -1;    }    return (*env)->GetIntField(env, fdObj, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID));}/* Do we need this any longer??? * the maximum buffer size. Used for setting * SendBufferSize and ReceiveBufferSize. */static const int max_buffer_size = 64 * 1024;/* * Class:     java_net_PlainDatagramSocketImpl * Method:    init * Signature: ()V */JNIEXPORT void JNICALLJava_java_net_PlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {    struct utsname sysinfo;    JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID)     	= (*env)->GetFieldID(env, cls, "fd", "Ljava/io/FileDescriptor;");    CHECK_NULL(JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID));    JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_timeoutID)     	= (*env)->GetFieldID(env, cls, "timeout", "I");    CHECK_NULL(JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_timeoutID));    JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_trafficClassID)         = (*env)->GetFieldID(env, cls, "trafficClass", "I");    CHECK_NULL(JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_trafficClassID));    JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_localPortID)     	= (*env)->GetFieldID(env, cls, "localPort", "I");    CHECK_NULL(JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_localPortID));    JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_connected)        = (*env)->GetFieldID(env, cls, "connected", "Z");    CHECK_NULL(JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_connected));    JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_connectedAddress)        = (*env)->GetFieldID(env, cls, "connectedAddress", "Ljava/net/InetAddress;");    CHECK_NULL(JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_connectedAddress));    JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_connectedPort)        = (*env)->GetFieldID(env, cls, "connectedPort", "I");    CHECK_NULL(JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_connectedPort));    JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID)     	= NET_GetFileDescriptorID(env);    CHECK_NULL(JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID));    Java_java_net_InetAddress_init(env, 0);    Java_java_net_Inet4Address_init(env, 0);    Java_java_net_Inet6Address_init(env, 0);    Java_java_net_NetworkInterface_init(env, 0);    /*     * We need to determine if this is a 2.2 kernel.     */    if (uname(&sysinfo) == 0) {        sysinfo.release[3] = '\0';        isOldKernel = (strcmp(sysinfo.release, "2.2") == 0);    } else {	/* 	 * uname failed - move to plan B and examine /proc/version	 * If this fails assume that /proc has changed and that	 * this must be new /proc format and hence new kernel.	 */ 	FILE *fP;	isOldKernel = JNI_FALSE;	if ((fP = fopen("/proc/version", "r")) != NULL) {	    char ver[25];	    if (fgets(ver, sizeof(ver), fP) != NULL) {		isOldKernel = (strstr(ver, "2.2.") != NULL);	    }	    fclose(fP);	}    }#ifdef AF_INET6    JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_multicastInterfaceID ) =        (*env)->GetFieldID(env, cls, "multicastInterface", "I");    CHECK_NULL(JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_multicastInterfaceID));    JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_loopbackID) =        (*env)->GetFieldID(env, cls, "loopbackMode", "Z");    CHECK_NULL(JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_loopbackID));    JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_ttlID) =         (*env)->GetFieldID(env, cls, "ttl", "I");    CHECK_NULL(JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_ttlID));#endif}/* * Class:     java_net_PlainDatagramSocketImpl * Method:    bind * Signature: (ILjava/net/InetAddress;)V */JNIEXPORT void JNICALLJava_java_net_PlainDatagramSocketImpl_bind(JNIEnv *env, jobject this,					   jint localport, jobject iaObj) {    /* fdObj is the FileDescriptor field on this */    jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID));    /* fd is an int field on fdObj */    int fd;    int len = 0;    SOCKADDR him;    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 is null.");	return;    }        /* bind - pick a port number for local addr*/    NET_InetAddressToSockaddr(env, iaObj, localport, (struct sockaddr *)&him, &len);    if (NET_Bind(fd, (struct sockaddr *)&him, len) < 0)  {	if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||    	    errno == EPERM || errno == EACCES) {            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",                                         "Bind failed");	} else {	    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",                                         "Bind failed");	}	return;    }         /* intialize the local port */    if (localport == 0) {	/* Now that we're a connected socket, let's extract the port number	 * that the system chose for us and store it in the Socket object.  	 */	if (JVM_GetSockName(fd, (struct sockaddr *)&him, &len) == -1) {	    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",                            "Error getting socket name");	    return;	}	localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);	(*env)->SetIntField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_localPortID), localport);    } else {	(*env)->SetIntField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_localPortID), localport);    }}/* * Class:     java_net_PlainDatagramSocketImpl * Method:    connect0 * Signature: (Ljava/net/InetAddress;I)V */JNIEXPORT void JNICALLJava_java_net_PlainDatagramSocketImpl_connect0(JNIEnv *env, jobject this,					       jobject address, jint port) {    /*The object's field */    jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID));    /* The fdObj'fd */    jint fd;    /* The packetAddress address, family and port */    SOCKADDR rmtaddr;    int len = 0;     if (IS_NULL(fdObj)) {	JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",			"Socket closed");	return;    }    fd = (*env)->GetIntField(env, fdObj, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID));        if (IS_NULL(address)) {	JNU_ThrowNullPointerException(env, "address");	return;    }    NET_InetAddressToSockaddr(env, address, port, (struct sockaddr *)&rmtaddr, &len);    if (isOldKernel) {	int t = 0;        setsockopt(fd, SOL_SOCKET, SO_BSDCOMPAT, (char*) &t, sizeof(int));    } else     { 	if (JVM_Connect(fd, (struct sockaddr *)&rmtaddr, len) == -1) {            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",                            "Connection problem encountered: No network connection detected.");	    return;	}    }}/* * Class:     java_net_PlainDatagramSocketImpl * Method:    disconnect0 * Signature: ()V */JNIEXPORT void JNICALLJava_java_net_PlainDatagramSocketImpl_disconnect0(JNIEnv *env, jobject this) {    /* The object's field */    jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID));    /* The fdObj'fd */    jint fd;    SOCKADDR addr;    int len;    if (IS_NULL(fdObj)) {        return;    }     fd = (*env)->GetIntField(env, fdObj, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID));    if (isOldKernel) {	int t = 1;        setsockopt(fd, SOL_SOCKET, SO_BSDCOMPAT, (char*) &t, sizeof(int));    } else {        memset(&addr, 0, sizeof(addr));#ifdef AF_INET6        if (ipv6_available()) {            struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)&addr;            him6->sin6_family = AF_UNSPEC;            len = sizeof(struct sockaddr_in6);        } else#endif        {            struct sockaddr_in *him4 = (struct sockaddr_in*)&addr;            him4->sin_family = AF_UNSPEC;            len = sizeof(struct sockaddr_in);        }        JVM_Connect(fd, (struct sockaddr *)&addr, len);    }}/* * Class:     java_net_PlainDatagramSocketImpl * Method:    send * Signature: (Ljava/net/DatagramPacket;)V */JNIEXPORT void JNICALLJava_java_net_PlainDatagramSocketImpl_send(JNIEnv *env, jobject this,					   jobject packet) {    char BUF[MAX_BUFFER_LEN];    char *fullPacket = NULL;    int ret, mallocedPacket = JNI_FALSE;    /* The object's field */    jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID));    jint trafficClass = (*env)->GetIntField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl,  pdsi_trafficClassID));    jbyteArray packetBuffer;    jobject packetAddress;    jint packetBufferOffset, packetBufferLen, packetPort;    jboolean connected;    /* The fdObj'fd */    jint fd;    SOCKADDR rmtaddr, *rmtaddrP=&rmtaddr;    int len;    if (IS_NULL(fdObj)) {	JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",			"Socket closed");	return;    }    fd = (*env)->GetIntField(env, fdObj, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID));    if (IS_NULL(packet)) {	JNU_ThrowNullPointerException(env, "packet");	return;    }    connected = (*env)->GetBooleanField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_connected));    packetBuffer = (*env)->GetObjectField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_bufID));    packetAddress = (*env)->GetObjectField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_addressID));    if (IS_NULL(packetBuffer) || IS_NULL(packetAddress)) {	JNU_ThrowNullPointerException(env, "null buffer || null address");	return;    }    packetBufferOffset = (*env)->GetIntField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_offsetID));    packetBufferLen = (*env)->GetIntField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_lengthID));    if (connected && !isOldKernel) {	/* arg to NET_Sendto () null in this case */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?