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