- 论坛徽章:
- 0
|
本帖最后由 wliang511 于 2011-11-09 23:10 编辑
纠结了很多天了,跟一个问题跟到这里,但是觉得google又不可能犯这么低级的错误...请大家指出我愚蠢的地方吧
android 2.2 froyo版本
在froyo\dalvik\libcore\luni\src\main\native\org_apache_harmony_luni_platform_OSNetworkSystem.cpp中(这里只贴出相关的2个case语句):
我们暂时只看IPV4的部分:
在case JAVASOCKOPT_IP_MULTICAST_IF中,getsockopt(...,....,...,&sockval,...)语句之后有sockval.ss_family的引用,因此这个sockval至少是
一个大小大于4个字节的结构体,从紧接的代码socketAddressToInetAddress()中可以看出内核应该返回的sockval为struct sockaddr_in类型
在case JAVASOCKOPT_IP_MULTICAST_IF2,AF_INET时,很明显getsockopt(...,....,...,&sockval,...)返回的sockval类型必须是struct ip_mreqn类型
但是从内核代码\kernel\net\ipv4\ip_sockglue.c中
case IP_MULTICAST_IF中可以看到,getsockopt明明只支持返回类型为struct in_addr的结构体
这,问题究竟在哪里呢?
froyo\dalvik\libcore\luni\src\main\native\org_apache_harmony_luni_platform_OSNetworkSystem.cpp:
- static jobject osNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz,
- jobject fileDescriptor, jint anOption) {
- // LOGD("ENTER getSocketOptionImpl");
- int intValue = 0;
- socklen_t intSize = sizeof(int);
- int result;
- struct sockaddr_storage sockVal;
- socklen_t sockSize = sizeof(sockVal);
- int handle;
- if (!jniGetFd(env, fileDescriptor, handle)) {
- return 0;
- }
- switch ((int) anOption & 0xffff) {
- case JAVASOCKOPT_IP_MULTICAST_IF: {
- if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
- return NULL;
- }
- result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
- &sockVal, &sockSize);
- if (result == -1) {
- jniThrowSocketException(env, errno);
- return NULL;
- }
- if (sockVal.ss_family != AF_INET) {
- // Java expects an AF_INET INADDR_ANY, but Linux just returns AF_UNSPEC.
- jbyteArray inAddrAny = env->NewByteArray(4); // { 0, 0, 0, 0 }
- return byteArrayToInetAddress(env, inAddrAny);
- }
- return socketAddressToInetAddress(env, &sockVal);
- }
- case JAVASOCKOPT_IP_MULTICAST_IF2: {
- if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
- return NULL;
- }
- struct ip_mreqn multicastRequest;
- int interfaceIndex = 0;
- socklen_t optionLength;
- int addressFamily = getSocketAddressFamily(handle);
- switch (addressFamily) {
- case AF_INET:
- optionLength = sizeof(multicastRequest);
- result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
- &multicastRequest, &optionLength);
- if (result == 0)
- interfaceIndex = multicastRequest.imr_ifindex;
- break;
- case AF_INET6:
- optionLength = sizeof(interfaceIndex);
- result = getsockopt(handle, IPPROTO_IPV6, IPV6_MULTICAST_IF,
- &interfaceIndex, &optionLength);
- break;
- default:
- jniThrowSocketException(env, EAFNOSUPPORT);
- return NULL;
- }
- if (0 != result) {
- jniThrowSocketException(env, errno);
- return NULL;
- }
- return newJavaLangInteger(env, interfaceIndex);
- }
- }
- }
复制代码 但是从内核代码\kernel\net\ipv4\ip_sockglue.c中
case IP_MULTICAST_IF中可以看到,getsockopt明明只支持返回类型为struct in_addr的结构体
kernel\net\ipv4\ip_sockglue.c:
- /*
- * Get the options. Note for future reference. The GET of IP options gets the
- * _received_ ones. The set sets the _sent_ ones.
- */
- static int do_ip_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen)
- {
- struct inet_sock *inet = inet_sk(sk);
- int val;
- int len;
- if (level != SOL_IP)
- return -EOPNOTSUPP;
- if (ip_mroute_opt(optname))
- return ip_mroute_getsockopt(sk,optname,optval,optlen);
- if (get_user(len,optlen))
- return -EFAULT;
- if (len < 0)
- return -EINVAL;
- lock_sock(sk);
- switch (optname) {
- case IP_MULTICAST_IF:
- {
- struct in_addr addr;
- len = min_t(unsigned int, len, sizeof(struct in_addr));
- addr.s_addr = inet->mc_addr;
- release_sock(sk);
- if (put_user(len, optlen))
- return -EFAULT;
- if (copy_to_user(optval, &addr, len))
- return -EFAULT;
- return 0;
- }
- }
- }
复制代码 |
|