static PRStatus PR_CALLBACK SocketSetSockOpt( PRFileDesc *fd, PRSockOption optname, const void* optval, PRInt32 optlen) { PRInt32 level, name; PRStatus rv; /* * PR_SockOpt_Nonblocking is a special case that does not * translate to a setsockopt call. */ if (PR_SockOpt_Nonblocking == optname) { PRBool fNonblocking = *((PRIntn *) optval) ? PR_TRUE : PR_FALSE; PR_ASSERT(sizeof(PRIntn) == optlen); #ifdef WINNT PR_ASSERT((fd->secret->md.io_model_committed == PR_FALSE) || (fd->secret->nonblocking == fNonblocking)); if (fd->secret->md.io_model_committed && (fd->secret->nonblocking != fNonblocking)) { /* * On NT, once we have associated a socket with the io * completion port, we can't disassociate it. So we * can't change the nonblocking option of the socket * afterwards. */ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } #endif fd->secret->nonblocking = fNonblocking; return PR_SUCCESS; } rv = _PR_MapOptionName(optname, &level, &name); if (PR_SUCCESS == rv) { if (PR_SockOpt_Linger == optname) { struct linger linger; linger.l_onoff = ((PRLinger*)(optval))->polarity ? 1 : 0; linger.l_linger = PR_IntervalToSeconds( ((PRLinger*)(optval))->linger); rv = _PR_MD_SETSOCKOPT( fd, level, name, (char *) &linger, sizeof(linger)); } else { rv = _PR_MD_SETSOCKOPT( fd, level, name, optval, optlen); } } return rv; }
PRStatus PR_CALLBACK _PR_SocketSetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data) { PRStatus rv; PRInt32 level, name; /* * PR_SockOpt_Nonblocking is a special case that does not * translate to a setsockopt call. */ if (PR_SockOpt_Nonblocking == data->option) { #ifdef WINNT PR_ASSERT((fd->secret->md.io_model_committed == PR_FALSE) || (fd->secret->nonblocking == data->value.non_blocking)); if (fd->secret->md.io_model_committed && (fd->secret->nonblocking != data->value.non_blocking)) { /* * On NT, once we have associated a socket with the io * completion port, we can't disassociate it. So we * can't change the nonblocking option of the socket * afterwards. */ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } #endif fd->secret->nonblocking = data->value.non_blocking; 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; linger.l_onoff = data->value.linger.polarity; linger.l_linger = PR_IntervalToSeconds(data->value.linger.linger); rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&linger, sizeof(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 value = (data->value.reuse_addr) ? 1 : 0; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&value, sizeof(value)); break; } case PR_SockOpt_McastLoopback: { #ifdef WIN32 /* Winsock */ BOOL bool; #else PRUint8 bool; #endif bool = data->value.mcast_loopback ? 1 : 0; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&bool, sizeof(bool)); break; } case PR_SockOpt_RecvBufferSize: case PR_SockOpt_SendBufferSize: case PR_SockOpt_MaxSegment: { PRIntn value = data->value.recv_buffer_size; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&value, sizeof(value)); break; } case PR_SockOpt_IpTimeToLive: case PR_SockOpt_IpTypeOfService: { /* These options should really be an int (or PRIntn). */ rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&data->value.ip_ttl, sizeof(PRUintn)); break; } case PR_SockOpt_McastTimeToLive: { #ifdef WIN32 /* Winsock */ int ttl; #else PRUint8 ttl; #endif ttl = data->value.mcast_ttl; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&ttl, sizeof(ttl)); break; } #ifdef IP_ADD_MEMBERSHIP case PR_SockOpt_AddMember: case PR_SockOpt_DropMember: { struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = data->value.add_member.mcaddr.inet.ip; mreq.imr_interface.s_addr = data->value.add_member.ifaddr.inet.ip; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&mreq, sizeof(mreq)); break; } #endif /* IP_ADD_MEMBERSHIP */ case PR_SockOpt_McastInterface: { /* This option is a struct in_addr. */ rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&data->value.mcast_if.inet.ip, sizeof(data->value.mcast_if.inet.ip)); break; } default: PR_NOT_REACHED("Unknown socket option"); break; } } return rv; } /* _PR_SocketSetSocketOption */