plaindatagramsocketimpl_md.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,016 行 · 第 1/5 页
C
2,016 行
fullPacket = &(BUF[0]); } /* * On Linux with the 2.2 kernel we simulate connected datagrams by * discarding packets */ if (isOldKernel) { connected = (*env)->GetBooleanField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_connected)); if (connected) { connectedAddress = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_connectedAddress)); connectedPort = (*env)->GetIntField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_connectedPort)); if (timeout) { prevTime = JVM_CurrentTimeMillis(env, 0); } } } do { retry = JNI_FALSE; if (timeout) { int ret = NET_Timeout(fd, timeout); if (ret <= 0) { if (ret == 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "Receive timed out"); } 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"); } } else if (ret == JVM_IO_INTR) { JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", "operation interrupted"); } if (mallocedPacket) { free(fullPacket); } return; } } /* * Security Note: For Linux 2.2 with connected datagrams ensure that * you receive into the stack/heap allocated buffer - do not attempt * to receive directly into DatagramPacket's byte array. * (ie: if the virtual machine support pinning don't use * GetByteArrayElements or a JNI critical section and receive * directly into the byte array) */ len = SOCKADDR_LEN; n = NET_RecvFrom(fd, fullPacket, packetBufferLen, 0, (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) { 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 { int port; jobject packetAddress; /* * If we are connected then we know that the datagram that we have * received is from the address that we are connected too. However * on Linux with 2.2 kernel we have to simulate this behaviour by * discarding any datagrams that aren't from the connected address. */ if (isOldKernel && connected) { if (NET_GetPortFromSockaddr((struct sockaddr *)&remote_addr) != connectedPort || !NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&remote_addr, connectedAddress)) { /* * Discard the datagram as it's not from the connected * address */ retry = JNI_TRUE; /* * Adjust timeout if necessary to ensure that we adhere to * timeout semantics. */ if (timeout) { jlong newTime = JVM_CurrentTimeMillis(env, 0); timeout -= (newTime - prevTime); if (timeout <= 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "Receive timed out"); if (mallocedPacket) { free(fullPacket); } return; } prevTime = newTime; } continue; } } /* * 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. */ /* * 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); } } while (retry); if (mallocedPacket) { free(fullPacket); }}/* * Class: java_net_PlainDatagramSocketImpl * Method: datagramSocketCreate * Signature: ()V */JNIEXPORT void JNICALLJava_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env, jobject this) { jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID)); int fd; int t = 1; if (IS_NULL(fdObj)) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); return; } else {#ifdef AF_INET6 if (ipv6_available()) { fd = JVM_Socket(AF_INET6, SOCK_DGRAM, 0); } else #endif /* AF_INET6 */ { fd = JVM_Socket(AF_INET, SOCK_DGRAM, 0); } } if (fd == JVM_IO_ERR) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error creating socket"); return; } setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*) &t, sizeof(int)); if (isOldKernel) { setsockopt(fd, SOL_SOCKET, SO_BSDCOMPAT, (char*) &t, sizeof(int)); }#ifdef AF_INET6 /* * On Linux for IPv6 sockets we must set the hop limit * to 1 to be compatible with default ttl of 1 for IPv4 sockets. */ if (ipv6_available()) { int ttl = 1; setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ttl, sizeof(ttl)); if (isOldKernel) { (*env)->SetIntField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_ttlID), ttl); } }#endif (*env)->SetIntField(env, fdObj, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID), fd);}/* * Class: java_net_PlainDatagramSocketImpl * Method: datagramSocketClose * Signature: ()V */JNIEXPORT void JNICALLJava_java_net_PlainDatagramSocketImpl_datagramSocketClose(JNIEnv *env, jobject this) { /* * REMIND: PUT A LOCK AROUND THIS CODE */ jobject fdObj = (*env)->GetObjectField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_fdID)); int fd; if (IS_NULL(fdObj)) { return; } fd = (*env)->GetIntField(env, fdObj, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID)); if (fd == -1) { return; } (*env)->SetIntField(env, fdObj, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, IO_fd_fdID), -1); NET_SocketClose(fd);}/* * Sets the multicast interface. * * SocketOptions.IP_MULTICAST_IF :- * value is a InetAddress * IPv4: set outgoing multicast interface using * IPPROTO_IP/IP_MULTICAST_IF * IPv6: Get the index of the interface to which the * InetAddress is bound * Set outgoing multicast interface using * IPPROTO_IPV6/IPV6_MULTICAST_IF * On Linux 2.2 record interface index as can't * query the multicast interface. * * SockOptions.IF_MULTICAST_IF2 :- * value is a NetworkInterface * IPv4: Obtain IP address bound to network interface * (NetworkInterface.addres[0]) * set outgoing multicast interface using * IPPROTO_IP/IP_MULTICAST_IF * IPv6: Obtain NetworkInterface.index * Set outgoing multicast interface using * IPPROTO_IPV6/IPV6_MULTICAST_IF * On Linux 2.2 record interface index as can't * query the multicast interface. * */static void setMulticastInterface(JNIEnv *env, jobject this, int fd, jint opt, jobject value){ if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { /* * value is an InetAddress. * On IPv4 system use IP_MULTICAST_IF socket option * On IPv6 system get the NetworkInterface that this IP * address is bound too and use the IPV6_MULTICAST_IF * option instead of IP_MULTICAST_IF */#ifdef AF_INET6 if (ipv6_available()) { static jclass ni_class; if (ni_class == NULL) { jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); CHECK_NULL(c); ni_class = (*env)->NewGlobalRef(env, c); CHECK_NULL(ni_class); } value = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, value); if (value == NULL) { if (!(*env)->ExceptionOccurred(env)) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "bad argument for IP_MULTICAST_IF" ": address not bound to any interface"); } return; } opt = java_net_SocketOptions_IP_MULTICAST_IF2; } else#endif /* AF_INET6 */ { static jfieldID ia_addressID; struct in_addr in; if (ia_addressID == NULL) { jclass c = (*env)->FindClass(env,"java/net/InetAddress"); CHECK_NULL(c); ia_addressID = (*env)->GetFieldID(env, c, "address", "I"); CHECK_NULL(ia_addressID); } in.s_addr = htonl( (*env)->GetIntField(env, value, 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; } } if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) { /* * value is a NetworkInterface. * On IPv6 system get the index of the interface and use the * IPV6_MULTICAST_IF socket option * On IPv4 system extract addr[0] and use the IP_MULTICAST_IF * option. */#ifdef AF_INET6 if (ipv6_available()) { static jfieldID ni_indexID; int index; if (ni_indexID == NULL) { jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); CHECK_NULL(c); ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); CHECK_NULL(ni_indexID); } index = (*env)->GetIntField(env, value, ni_indexID); if (JVM_SetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (const char*)&index, sizeof(index)) < 0) { if (errno == EINVAL && index > 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "IPV6_MULTICAST_IF failed (interface has IPv4 " "address only?)"); } else { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error setting socket option"); } return; } /* * Linux 2.2 kernel doesn't support IPV6_MULTICAST_IF socket * option so record index for later retrival. */ if (isOldKernel) { (*env)->SetIntField(env, this, JNI_STATIC_MD(java_net_PlainDatagramSocketImpl, pdsi_multicastInterfaceID), (jint)index); } return; } else#endif /* AF_INET6 */ { static jfieldID ni_addrsID; static jfieldID ia_addressID; struct in_addr in; jobjectArray addrArray; jsize len; jobject addr; if (ni_addrsID == NULL) { jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); CHECK_NULL(c); ni_addrsID = (*env)->GetFieldID(env, c, "addrs", "[Ljava/net/InetAddress;"); CHECK_NULL(ni_addrsID); c = (*env)->FindClass(env,"java/net/InetAddress"); CHECK_NULL(c); ia_addressID = (*env)->GetFieldID(env, c, "address", "I"); CHECK_NULL(ia_addressID); } addrArray = (*env)->GetObjectField(env, value, ni_addrsID); len = (*env)->GetArrayLength(env, addrArray); /* * Check that there is at least one address bound to this * interface. */ if (len < 1) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?