plaindatagramsocketimpl_md.c

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

C
2,016
字号
	len = 0;	rmtaddrP = 0;    } else {	packetPort = (*env)->GetIntField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_portID));	NET_InetAddressToSockaddr(env, packetAddress, packetPort, (struct sockaddr *)&rmtaddr, &len);    }    if (packetBufferLen > MAX_BUFFER_LEN) {	/* When JNI-ifying the JDK's IO routines, we turned	 * read's and write's of byte arrays of size greater	 * than 2048 bytes into several operations of size 2048.	 * This saves a malloc()/memcpy()/free() for big	 * buffers.  This is OK for file IO and TCP, but that	 * strategy violates the semantics of a datagram protocol.	 * (one big send) != (several smaller sends).  So here	 * we *must* alloc the buffer.  Note it needn't be bigger	 * than 65,536 (0xFFFF) the max size of an IP packet.	 * Anything bigger should be truncated anyway.	 *	 * We may want to use a smarter allocation scheme at some	 * point.	 */	if (packetBufferLen > MAX_PACKET_LEN) {	    packetBufferLen = MAX_PACKET_LEN;	}	fullPacket = (char *)malloc(packetBufferLen);	if (!fullPacket) {	    JNU_ThrowOutOfMemoryError(env, "heap allocation failed");	    return;	} else {	    mallocedPacket = JNI_TRUE;	}    } else {	fullPacket = &(BUF[0]);    }    (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, packetBufferLen,			       (jbyte *)fullPacket);#ifdef AF_INET6    if (trafficClass != 0 && ipv6_available()) {	NET_SetTrafficClass((struct sockaddr *)&rmtaddr, trafficClass);    }#endif /* AF_INET6 */    /*     * Send the datagram.      *     * If we are connected it's possible that sendto will return     * ECONNREFUSED indicating that an ICMP port unreachable has     * received.     */    ret = NET_SendTo(fd, fullPacket, packetBufferLen, 0, 		     (struct sockaddr *)rmtaddrP, len);    if (ret < 0) {	switch (ret) {	    case JVM_IO_ERR :		if (errno == ECONNREFUSED) {		    JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",                            "ICMP Port Unreachable");		} else {		    NET_ThrowByNameWithLastError(env, "java/io/IOException", "sendto failed");		}		break;	    case JVM_IO_INTR:	        JNU_ThrowByName(env, "java/io/InterruptedIOException",			        "operation interrupted");		break;	}    }    if (mallocedPacket) {	free(fullPacket);    }    return;}/* * Class:     java_net_PlainDatagramSocketImpl * Method:    peek * Signature: (Ljava/net/InetAddress;)I */JNIEXPORT jint JNICALLJava_java_net_PlainDatagramSocketImpl_peek(JNIEnv *env, jobject this,					   jobject addressObj) {    jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID));    jint timeout = (*env)->GetIntField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_timeoutID));    jint fd;    ssize_t n;    SOCKADDR remote_addr;    int len;    char buf[1];    jint family;    jobject iaObj;    int port;    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));    }    if (IS_NULL(addressObj)) {	JNU_ThrowNullPointerException(env, "Null address in peek()");    }    if (timeout) {	int ret = NET_Timeout(fd, timeout);        if (ret == 0) {            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",			    "Peek timed out");	    return ret;	} else if (ret == JVM_IO_ERR) {	    if (errno == EBADF) {                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");            } else {                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Peek failed");             } 	    return ret;	} else if (ret == JVM_IO_INTR) {	    JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",			    "operation interrupted");	    return ret;	/* WARNING: SHOULD WE REALLY RETURN -2??? */	}    }    len = SOCKADDR_LEN;    n = NET_RecvFrom(fd, buf, 1, MSG_PEEK,		     (struct sockaddr *)&remote_addr, &len);    if (n == JVM_IO_ERR) {        if (errno == ECONNREFUSED) {	    JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",			    "ICMP Port Unreachable");	} else {	    if (errno == EBADF) {                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");            } else {                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Peek failed");            }	}        return 0;    } else if (n == JVM_IO_INTR) {	JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);        return 0;    }    iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&remote_addr, &port);    family = (*env)->GetIntField(env, iaObj, JNI_STATIC(java_net_InetAddress, ia_familyID)) == IPv4? AF_INET : AF_INET6;    if (family == AF_INET) { /* this api can't handle IPV6 addresses */	int address = (*env)->GetIntField(env, iaObj, JNI_STATIC(java_net_InetAddress, ia_addressID));	(*env)->SetIntField(env, addressObj, JNI_STATIC(java_net_InetAddress, ia_addressID), address);    }    return port;}JNIEXPORT jint JNICALLJava_java_net_PlainDatagramSocketImpl_peekData(JNIEnv *env, jobject this,					   jobject packet) {    char BUF[MAX_BUFFER_LEN];    char *fullPacket = NULL;    int mallocedPacket = JNI_FALSE;    jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID));    jint timeout = (*env)->GetIntField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_timeoutID));    jbyteArray packetBuffer;    jint packetBufferOffset, packetBufferLen;    int fd;    int n;    SOCKADDR remote_addr;    int len;    int port;    if (IS_NULL(fdObj)) {	JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",			"Socket closed");	return -1;    }    fd = (*env)->GetIntField(env, fdObj, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID));    if (IS_NULL(packet)) {	JNU_ThrowNullPointerException(env, "packet");	return -1;    }    packetBuffer = (*env)->GetObjectField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_bufID));    if (IS_NULL(packetBuffer)) {	JNU_ThrowNullPointerException(env, "packet buffer");        return -1;    }    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 (timeout) {	int ret = NET_Timeout(fd, timeout);        if (ret == 0) {            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",			    "Receive timed out");	    return -1;	} else if (ret == JVM_IO_ERR) {            if (errno == EBADF) {                JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");            } else {                NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");            }	    return -1;	} else if (ret == JVM_IO_INTR) {	    JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",			    "operation interrupted");	    return -1;	}    }    if (packetBufferLen > MAX_BUFFER_LEN) {	/* When JNI-ifying the JDK's IO routines, we turned	 * read's and write's of byte arrays of size greater	 * than 2048 bytes into several operations of size 2048.	 * This saves a malloc()/memcpy()/free() for big	 * buffers.  This is OK for file IO and TCP, but that	 * strategy violates the semantics of a datagram protocol.	 * (one big send) != (several smaller sends).  So here	 * we *must* alloc the buffer.  Note it needn't be bigger	 * than 65,536 (0xFFFF) the max size of an IP packet.	 * anything bigger is truncated anyway.	 *	 * We may want to use a smarter allocation scheme at some	 * point.	 */	if (packetBufferLen > MAX_PACKET_LEN) {	    packetBufferLen = MAX_PACKET_LEN;	}	fullPacket = (char *)malloc(packetBufferLen);	if (!fullPacket) {	    JNU_ThrowOutOfMemoryError(env, "heap allocation failed");	    return -1;	} else {	    mallocedPacket = JNI_TRUE;	}    } else {	fullPacket = &(BUF[0]);    }    len = SOCKADDR_LEN;    n = NET_RecvFrom(fd, fullPacket, packetBufferLen, MSG_PEEK,		     (struct sockaddr *)&remote_addr, &len);    /* truncate the data if the packet's length is too small */    if (n > packetBufferLen) {	n = packetBufferLen;    }    if (n == JVM_IO_ERR) {#ifdef __solaris__         if (errno == ECONNREFUSED) {            int orig_errno = errno;	    (void) recv(fd, fullPacket, 1, 0);            errno = orig_errno;        }#endif	if (errno == ECONNREFUSED) {	    JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",			    "ICMP Port Unreachable");	} else {	    if (errno == EBADF) {                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");            } else {                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");            }	}	(*env)->SetIntField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_offsetID), 0);	(*env)->SetIntField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_lengthID), 0);    } else if (n == JVM_IO_INTR) {	JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",			"operation interrupted");	(*env)->SetIntField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_offsetID), 0);	(*env)->SetIntField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_lengthID), 0);    } else {	/*	 * success - fill in received address...	 *	 * REMIND: Fill in an int on the packet, and create inetadd	 * object in Java, as a performance improvement. Also	 * construct the inetadd object lazily.	 */        jobject packetAddress;        /*         * Check if there is an InetAddress already associated with this         * packet. If so we check if it is the same source address. We         * can't update any existing InetAddress because it is immutable         */        packetAddress = (*env)->GetObjectField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_addressID));        if (packetAddress != NULL) {            if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&remote_addr, packetAddress)) {                /* force a new InetAddress to be created */                packetAddress = NULL;            }        }	if (packetAddress == NULL) {	    packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&remote_addr, &port);	    /* stuff the new Inetaddress in the packet */	    (*env)->SetObjectField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_addressID), packetAddress);	} else { 	    /* only get the new port number */ 	    port = NET_GetPortFromSockaddr((struct sockaddr *)&remote_addr);  	}	/* and fill in the data, remote address/port and such */	(*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n,				   (jbyte *)fullPacket);	(*env)->SetIntField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_portID), port);	(*env)->SetIntField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_lengthID), n);    }    if (mallocedPacket) {	free(fullPacket);    }    return port;}/* * Class:     java_net_PlainDatagramSocketImpl * Method:    receive * Signature: (Ljava/net/DatagramPacket;)V */JNIEXPORT void JNICALLJava_java_net_PlainDatagramSocketImpl_receive(JNIEnv *env, jobject this,					      jobject packet) {    char BUF[MAX_BUFFER_LEN];    char *fullPacket = NULL;    int mallocedPacket = JNI_FALSE;    jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID));    jint timeout = (*env)->GetIntField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_timeoutID));    jbyteArray packetBuffer;    jint packetBufferOffset, packetBufferLen;    int fd;    int n;    SOCKADDR remote_addr;    int len;    jboolean retry;    jboolean connected = JNI_FALSE;    jobject connectedAddress = 0;    jint connectedPort = 0;    jlong prevTime = 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(packet)) {	JNU_ThrowNullPointerException(env, "packet");	return;    }    packetBuffer = (*env)->GetObjectField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_bufID));    if (IS_NULL(packetBuffer)) {	JNU_ThrowNullPointerException(env, "packet buffer");        return;    }    packetBufferOffset = (*env)->GetIntField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_offsetID));    packetBufferLen = (*env)->GetIntField(env, packet, JNI_STATIC(java_net_DatagramPacket, dp_bufLengthID));    if (packetBufferLen > MAX_BUFFER_LEN) {	/* When JNI-ifying the JDK's IO routines, we turned	 * read's and write's of byte arrays of size greater	 * than 2048 bytes into several operations of size 2048.	 * This saves a malloc()/memcpy()/free() for big	 * buffers.  This is OK for file IO and TCP, but that	 * strategy violates the semantics of a datagram protocol.	 * (one big send) != (several smaller sends).  So here	 * we *must* alloc the buffer.  Note it needn't be bigger	 * than 65,536 (0xFFFF) the max size of an IP packet.	 * anything bigger is truncated anyway.	 *	 * We may want to use a smarter allocation scheme at some	 * point.	 */	if (packetBufferLen > MAX_PACKET_LEN) {	    packetBufferLen = MAX_PACKET_LEN;	}	fullPacket = (char *)malloc(packetBufferLen);	if (!fullPacket) {	    JNU_ThrowOutOfMemoryError(env, "heap allocation failed");	    return;	} else {	    mallocedPacket = JNI_TRUE;	}    } else {

⌨️ 快捷键说明

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