static PRStatus PR_CALLBACK SocketGetSockOpt( PRFileDesc *fd, PRSockOption optname, void* optval, PRInt32* optlen) { PRInt32 level, name; PRStatus rv; /* * PR_SockOpt_Nonblocking is a special case that does not * translate to a getsockopt() call */ if (PR_SockOpt_Nonblocking == optname) { PR_ASSERT(sizeof(PRIntn) <= *optlen); *((PRIntn *) optval) = (PRIntn) fd->secret->nonblocking; *optlen = sizeof(PRIntn); return PR_SUCCESS; } rv = _PR_MapOptionName(optname, &level, &name); if (PR_SUCCESS == rv) { if (PR_SockOpt_Linger == optname) { struct linger linger; PRInt32 len = sizeof(linger); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char *) &linger, &len); if (PR_SUCCESS == rv) { ((PRLinger*)(optval))->polarity = linger.l_onoff ? PR_TRUE : PR_FALSE; ((PRLinger*)(optval))->linger = PR_SecondsToInterval( linger.l_linger); *optlen = sizeof(PRLinger); } } else { rv = _PR_MD_GETSOCKOPT( fd, level, name, optval, optlen); } } return rv; }
PRStatus PR_CALLBACK _PR_SocketGetSocketOption(PRFileDesc *fd, PRSocketOptionData *data) { PRStatus rv; PRInt32 length; PRInt32 level, name; /* * PR_SockOpt_Nonblocking is a special case that does not * translate to a getsockopt() call */ if (PR_SockOpt_Nonblocking == data->option) { data->value.non_blocking = fd->secret->nonblocking; return PR_SUCCESS; } rv = _PR_MapOptionName(data->option, &level, &name); if (PR_SUCCESS == rv) { switch (data->option) { case PR_SockOpt_Linger: { #if !defined(XP_BEOS) || defined(BONE_VERSION) struct linger linger; length = sizeof(linger); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char *) &linger, &length); if (PR_SUCCESS == rv) { PR_ASSERT(sizeof(linger) == length); data->value.linger.polarity = (linger.l_onoff) ? PR_TRUE : PR_FALSE; data->value.linger.linger = PR_SecondsToInterval(linger.l_linger); } break; #else PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return PR_FAILURE; #endif } case PR_SockOpt_Reuseaddr: case PR_SockOpt_Keepalive: case PR_SockOpt_NoDelay: case PR_SockOpt_Broadcast: { #ifdef WIN32 /* Winsock */ BOOL value; #else PRIntn value; #endif length = sizeof(value); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&value, &length); if (PR_SUCCESS == rv) data->value.reuse_addr = (0 == value) ? PR_FALSE : PR_TRUE; break; } case PR_SockOpt_McastLoopback: { #ifdef WIN32 /* Winsock */ BOOL bool; #else PRUint8 bool; #endif length = sizeof(bool); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&bool, &length); if (PR_SUCCESS == rv) data->value.mcast_loopback = (0 == bool) ? PR_FALSE : PR_TRUE; break; } case PR_SockOpt_RecvBufferSize: case PR_SockOpt_SendBufferSize: case PR_SockOpt_MaxSegment: { PRIntn value; length = sizeof(value); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&value, &length); if (PR_SUCCESS == rv) data->value.recv_buffer_size = value; break; } case PR_SockOpt_IpTimeToLive: case PR_SockOpt_IpTypeOfService: { /* These options should really be an int (or PRIntn). */ length = sizeof(PRUintn); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&data->value.ip_ttl, &length); break; } case PR_SockOpt_McastTimeToLive: { #ifdef WIN32 /* Winsock */ int ttl; #else PRUint8 ttl; #endif length = sizeof(ttl); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&ttl, &length); if (PR_SUCCESS == rv) data->value.mcast_ttl = ttl; break; } #ifdef IP_ADD_MEMBERSHIP case PR_SockOpt_AddMember: case PR_SockOpt_DropMember: { struct ip_mreq mreq; length = sizeof(mreq); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&mreq, &length); if (PR_SUCCESS == rv) { data->value.add_member.mcaddr.inet.ip = mreq.imr_multiaddr.s_addr; data->value.add_member.ifaddr.inet.ip = mreq.imr_interface.s_addr; } break; } #endif /* IP_ADD_MEMBERSHIP */ case PR_SockOpt_McastInterface: { /* This option is a struct in_addr. */ length = sizeof(data->value.mcast_if.inet.ip); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&data->value.mcast_if.inet.ip, &length); break; } default: PR_NOT_REACHED("Unknown socket option"); break; } } return rv; } /* _PR_SocketGetSocketOption */