Example #1
0
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;
}
Example #2
0
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 */