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 + -
显示快捷键?