⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macsockotpt.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
            *((PRUint8*)optval) = *((PRUint8*)&opt->value);            *optlen = sizeof(PRUint8);            break;        case IP_ADD_MEMBERSHIP:        case IP_DROP_MEMBERSHIP:            {            /* struct ip_mreq and TIPAddMulticast are the same size and optval                is pointing to struct ip_mreq */            *((struct ip_mreq *)optval) = *((struct ip_mreq *)&opt->value);            *optlen = sizeof(struct ip_mreq);            break;            }        case IP_MULTICAST_IF:            {            *((PRUint32*)optval) = *((PRUint32*)&opt->value);            *optlen = sizeof(PRUint32);            break;            }        /*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */        case TCP_MAXSEG:            if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */                *((PRIntn*)optval) = *((PRIntn*)&opt->value);                *optlen = sizeof(PRIntn);            } else { /* it is IP_TOS */                *((PRUintn*)optval) = *((PRUint8*)&opt->value);                *optlen = sizeof(PRUintn);            }            break;        default:            PR_ASSERT(0);            break;        }        return PR_SUCCESS;ErrorExit:    macsock_map_error(err);    return PR_FAILURE;}PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen){    OSStatus err;    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;    TOptMgmt cmd;    TOption *opt;    PRThread *me = _PR_MD_CURRENT_THREAD();    unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData) + 1];        if (endpoint == NULL) {        err = kEBADFErr;        goto ErrorExit;    }        /*     OT wants IPPROTO_IP for level and not XTI_GENERIC.  SO_REUSEADDR and SO_KEEPALIVE     are equated to IP level and TCP level options respectively and hence we need to set     the level correctly.    */    if (level == SOL_SOCKET) {        if (optname == SO_REUSEADDR)            level = IPPROTO_IP;        else if (optname == SO_KEEPALIVE)            level = INET_TCP;    }    opt = (TOption *)&optionBuffer[0];    opt->len = kOTOptionHeaderSize + optlen;    /* special case adjustments for length follow */    if (optname == SO_KEEPALIVE) /* we need to pass the timeout value for OT */        opt->len = kOTOptionHeaderSize + sizeof(t_kpalive);    if (optname == IP_MULTICAST_TTL || optname == IP_TTL) /* it is an unsigned char value */        opt->len = kOTOneByteOptionSize;    if (optname == IP_TOS && level == IPPROTO_IP)        opt->len = kOTOneByteOptionSize;    opt->level = level;    opt->name = optname;    opt->status = 0;        cmd.opt.len = opt->len;    cmd.opt.maxlen = sizeof(optionBuffer);    cmd.opt.buf = (UInt8*)optionBuffer;        optionBuffer[opt->len] = 0;        cmd.flags = T_NEGOTIATE;    switch (optname) {        case SO_LINGER:            *((t_linger*)&opt->value) = *((t_linger*)optval);            break;        case SO_REUSEADDR:        case TCP_NODELAY:        case SO_RCVBUF:        case SO_SNDBUF:            *((PRIntn*)&opt->value) = *((PRIntn*)optval);            break;        case IP_MULTICAST_LOOP:            if (*optval != 0)                opt->value[0] = T_YES;            else                opt->value[0] = T_NO;            break;        case SO_KEEPALIVE:            {            t_kpalive *kpalive = (t_kpalive *)&opt->value;                        kpalive->kp_onoff = *((long*)optval);            kpalive->kp_timeout = 10; /* timeout in minutes */            break;            }        case IP_TTL:            *((unsigned char*)&opt->value) = *((PRUintn*)optval);            break;        case IP_MULTICAST_TTL:            *((unsigned char*)&opt->value) = *optval;            break;        case IP_ADD_MEMBERSHIP:        case IP_DROP_MEMBERSHIP:            {            /* struct ip_mreq and TIPAddMulticast are the same size and optval                is pointing to struct ip_mreq */            *((TIPAddMulticast *)&opt->value) = *((TIPAddMulticast *)optval);            break;            }        case IP_MULTICAST_IF:            {            *((PRUint32*)&opt->value) = *((PRUint32*)optval);            break;            }        /*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */        case TCP_MAXSEG:            if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */                *((PRIntn*)&opt->value) = *((PRIntn*)optval);            } else { /* it is IP_TOS */                *((unsigned char*)&opt->value) = *((PRUintn*)optval);            }            break;        default:            PR_ASSERT(0);            break;        }    	PR_Lock(fd->secret->md.miscLock);    PrepareForAsyncCompletion(me, fd->secret->md.osfd);    	fd->secret->md.misc.thread = me;    err = OTOptionManagement(endpoint, &cmd, &cmd);    if (err != kOTNoError) {	    me->io_pending = PR_FALSE;	    PR_Unlock(fd->secret->md.miscLock);        goto ErrorExit;	}    WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);	PR_Unlock(fd->secret->md.miscLock);    err = me->md.osErrCode;    if (err != kOTNoError)        goto ErrorExit;    if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){        err = kEOPNOTSUPPErr;        goto ErrorExit;    }        if (level == IPPROTO_TCP && optname == TCP_MAXSEG && opt->status == T_READONLY) {        err = kEOPNOTSUPPErr;        goto ErrorExit;    }    PR_ASSERT(opt->status == T_SUCCESS);    return PR_SUCCESS;ErrorExit:    macsock_map_error(err);    return PR_FAILURE;}PRInt32 _MD_socketavailable(PRFileDesc *fd){    PRInt32 osfd = fd->secret->md.osfd;    OSStatus err;    EndpointRef endpoint = (EndpointRef) osfd;    size_t bytes;    if (endpoint == NULL) {        err = kEBADFErr;        goto ErrorExit;    }        bytes = 0;        err = OTCountDataBytes(endpoint, &bytes);    if ((err == kOTLookErr) ||         // Not really errors, we just need to do a read,        (err == kOTNoDataErr))        // or there's nothing there.        err = kOTNoError;            if (err != kOTNoError)        goto ErrorExit;            return bytes;ErrorExit:    macsock_map_error(err);    return -1;}typedef struct RawEndpointAndThread{	PRThread *  thread;	EndpointRef endpoint;} RawEndpointAndThread;// Notification routine for raw endpoints not yet attached to a PRFileDesc.// Async callback routine.// A5 is OK. Cannot allocate memory herestatic pascal void  RawEndpointNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie){    RawEndpointAndThread *endthr = (RawEndpointAndThread *) contextPtr;    PRThread *    thread   = endthr->thread;    EndpointRef * endpoint = endthr->endpoint;    _PRCPU *      cpu      = _PR_MD_CURRENT_CPU();     OSStatus      err;    OTResult	  resultOT;    switch (code)    {// OTLook Events -         case T_LISTEN:        // A connection request is available            PR_ASSERT(!"T_EXDATA not implemented for raw endpoints");            break;			        case T_CONNECT:      // Confirmation of a connect request			// cookie = sndCall parameter from OTConnect()            err = OTRcvConnect(endpoint, NULL);            PR_ASSERT(err == kOTNoError);			// wake up waiting thread            break;        case T_DATA:        // Standard data is available			break;        case T_EXDATA:      // Expedited data is available            PR_ASSERT(!"T_EXDATA Not implemented for raw endpoints");			return;        case T_DISCONNECT:  // A disconnect is available            err = OTRcvDisconnect(endpoint, NULL);            PR_ASSERT(err == kOTNoError);            break;		        case T_ERROR:       // obsolete/unused in library            PR_ASSERT(!"T_ERROR Not implemented for raw endpoints");			return;				        case T_UDERR:       // UDP Send error; clear the error			(void) OTRcvUDErr((EndpointRef) cookie, NULL);            break;        case T_ORDREL:      // An orderly release is available            err = OTRcvOrderlyDisconnect(endpoint);            PR_ASSERT(err == kOTNoError);            break;		        case T_GODATA:   // Flow control lifted on standard data			resultOT = OTLook(endpoint);		// clear T_GODATA event			PR_ASSERT(resultOT == T_GODATA);						// wake up waiting thread, if any            break;        case T_GOEXDATA: // Flow control lifted on expedited data            PR_ASSERT(!"T_GOEXDATA Not implemented");			return;        case T_REQUEST:  // An Incoming request is available            PR_ASSERT(!"T_REQUEST Not implemented");            return;        case T_REPLY:    // An Incoming reply is available            PR_ASSERT(!"T_REPLY Not implemented");            return;        case T_PASSCON:  // State is now T_DATAXFER			// OTAccept() complete, receiving endpoint in T_DATAXFER state			// cookie = OTAccept() resRef parameter			break;            // Async Completion Events        case T_BINDCOMPLETE:        case T_UNBINDCOMPLETE:        case T_ACCEPTCOMPLETE:        case T_OPTMGMTCOMPLETE:        case T_GETPROTADDRCOMPLETE:            break;		// for other OT events, see NotifierRoutine above        default:            return;    }	if (thread) {		thread->md.osErrCode = result;		if (_PR_MD_GET_INTSOFF()) {			thread->md.asyncNotifyPending = PR_TRUE;			cpu->u.missed[cpu->where] |= _PR_MISSED_IO;		} else {			DoneWaitingOnThisThread(thread);		}	}	SignalIdleSemaphore();}PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout){    OSStatus err;    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;    PRThread *me = _PR_MD_CURRENT_THREAD();    TBind bindReq;    PRNetAddr bindAddr;    PRInt32 newosfd = -1;    TCall call;    PRNetAddr callAddr;    RawEndpointAndThread *endthr = NULL;    if (endpoint == NULL) {        err = kEBADFErr;        goto ErrorExit;    }            memset(&call, 0 , sizeof(call));    if (addr != NULL) {        call.addr.maxlen = *addrlen;        call.addr.len = *addrlen;        call.addr.buf = (UInt8*) addr;    } else {        call.addr.maxlen = sizeof(callAddr);        call.addr.len = sizeof(callAddr);        call.addr.buf = (UInt8*) &callAddr;    }	do {	    PrepareForAsyncCompletion(me, fd->secret->md.osfd);	    fd->secret->md.misc.thread = me;	    	    // Perform the listen. 	    err = OTListen (endpoint, &call);	    if (err == kOTNoError)	    	break; // got the call information	    else if ((!fd->secret->nonblocking) && (err == kOTNoDataErr)) {	        WaitOnThisThread(me, timeout);	        err = me->md.osErrCode;	        if ((err != kOTNoError) && (err != kOTNoDataErr))	        	goto ErrorExit;			// we can get kOTNoError here, but still need			// to loop back to call OTListen, in order			// to get call info for OTAccept	    } else {	    	goto ErrorExit; // we're nonblocking, and/or we got an error	    }   	}	while(1);    newosfd = _MD_socket(AF_INET, SOCK_STREAM, 0);    if (newosfd == -1)        return -1;            	// Attach the raw endpoint handler to this endpoint for now.	endthr = (RawEndpointAndThread *) PR_Malloc(sizeof(RawEndpointAndThread));	endthr->thread = me;	endthr->endpoint = (EndpointRef) newosfd;		err = OTInstallNotifier((ProviderRef) newosfd, RawEndpointNotifierRoutineUPP, endthr);    PR_ASSERT(err == kOTNoError);    	err = OTSetAsynchronous((EndpointRef) newosfd);	PR_ASSERT(err == kOTNoError);    // Bind to a local port; let the system assign it.    bindAddr.inet.family = AF_INET;    bindAddr.inet.port = bindAddr.inet.ip = 0;    bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr);    bindReq.addr.len = 0;    bindReq.addr.buf = (UInt8*) &bindAddr;    bindReq.qlen = 0;    PrepareForAsyncCompletion(me, newosfd);        err = OTBind((EndpointRef) newosfd, &bindReq, NULL);    if (err != kOTNoError)        goto ErrorExit;    WaitOnThisThread(me, timeout);    err = me->md.osErrCode;    if (err != kOTNoError)        goto ErrorExit;    PrepareForAsyncCompletion(me, newosfd);        err = OTAccept (endpoint, (EndpointRef) newosfd, &call); 	if ((err != kOTNoError) && (err != kOTNoDataErr))        goto ErrorExit;    WaitOnThisThread(me, timeout);    err = me->md.osErrCode;    if (err != kOTNoError)        goto ErrorExit;    if (addrlen != NULL)        *addrlen = call.addr.len;	// Remove the temporary notifier we installed to set up the new endpoint.	OTRemoveNotifier((EndpointRef) newosfd);	PR_Free(endthr); // free the temporary context we set up for this endpoint    return newosfd;ErrorExit:	me->io_pending = PR_FALSE; // clear pending wait state if any    if (newosfd != -1)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -