📄 macsockotpt.c
字号:
*((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 + -