📄 macsockotpt.c
字号:
return; case T_PASSCON: // State is now T_DATAXFER // OTAccept() complete, receiving endpoint in T_DATAXFER state // cookie = OTAccept() resRef parameter break; case T_RESET: // Protocol has been reset PR_ASSERT(!"T_RESET Not implemented"); return; // Async Completion Events case T_BINDCOMPLETE: case T_UNBINDCOMPLETE: case T_ACCEPTCOMPLETE: case T_OPTMGMTCOMPLETE: case T_GETPROTADDRCOMPLETE: readThread = secret->md.misc.thread; secret->md.misc.thread = NULL; secret->md.misc.cookie = cookie; break;// case T_OPENCOMPLETE: // we open endpoints in synchronous mode// case T_REPLYCOMPLETE:// case T_DISCONNECTCOMPLETE: // we don't call OTSndDisconnect()// case T_RESOLVEADDRCOMPLETE:// case T_GETINFOCOMPLETE:// case T_SYNCCOMPLETE:// case T_MEMORYRELEASED: // only if OTAckSends() called on endpoint// case T_REGNAMECOMPLETE:// case T_DELNAMECOMPLETE:// case T_LKUPNAMECOMPLETE:// case T_LKUPNAMERESULT: // OpenTptInternet.h// case T_DNRSTRINGTOADDRCOMPLETE: // DNS is handled by dnsContext in DNSNotifierRoutine()// case T_DNRADDRTONAMECOMPLETE:// case T_DNRSYSINFOCOMPLETE:// case T_DNRMAILEXCHANGECOMPLETE:// case T_DNRQUERYCOMPLETE: default: // we should probably have a bit more sophisticated handling of kOTSystemSleep, etc. // PR_ASSERT(code != 0); return; } if (readThread) WakeUpNotifiedThread(readThread, result); if (writeThread && (writeThread != readThread)) WakeUpNotifiedThread(writeThread, result);}static OSErr CreateSocket(int type, EndpointRef *endpoint){ OSStatus err; PRThread *me = _PR_MD_CURRENT_THREAD(); char * configName; OTConfiguration *config; EndpointRef ep; // for now we just create the endpoint // we'll make it asynchronous and give it a notifier routine in _MD_makenonblock() switch (type){ case SOCK_STREAM: configName = kTCPName; break; case SOCK_DGRAM: configName = kUDPName; break; } config = OTCreateConfiguration(configName); ep = OT_OPEN_ENDPOINT(config, 0, NULL, &err); if (err != kOTNoError) goto ErrorExit; *endpoint = ep; PR_ASSERT(*endpoint != NULL); return kOTNoError;ErrorExit: return err;}// Errors returned:// kOTXXXX - OT returned error// EPROTONOSUPPORT - bad socket type/protocol// ENOBUFS - not enough space for another socket, or failure in socket creation routinePRInt32 _MD_socket(int domain, int type, int protocol){ OSStatus err; EndpointRef endpoint; _MD_FinishInitNetAccess(); // We only deal with internet domain if (domain != AF_INET) { err = kEPROTONOSUPPORTErr; goto ErrorExit; } // We only know about tcp & udp if ((type != SOCK_STREAM) && (type != SOCK_DGRAM)) { err = kEPROTONOSUPPORTErr; goto ErrorExit; } // Convert default types to specific types. if (protocol == 0) { if (type == SOCK_DGRAM) protocol = IPPROTO_UDP; else if (type == SOCK_STREAM) protocol = IPPROTO_TCP; } // Only support default protocol for tcp if ((type == SOCK_STREAM) && (protocol != IPPROTO_TCP)) { err = kEPROTONOSUPPORTErr; goto ErrorExit; } // Only support default protocol for udp if ((type == SOCK_DGRAM) && (protocol != IPPROTO_UDP)) { err = kEPROTONOSUPPORTErr; goto ErrorExit; } // Create a socket, we might run out of memory err = CreateSocket(type, &endpoint); if (err != kOTNoError) goto ErrorExit; PR_ASSERT((PRInt32)endpoint != -1); return ((PRInt32)endpoint);ErrorExit: macsock_map_error(err); return -1;}// Errors:// EBADF -- bad socket id// EFAULT -- bad address formatPRInt32 _MD_bind(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen){ OSStatus err; EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd; TBind bindReq; PRThread *me = _PR_MD_CURRENT_THREAD(); PRUint32 retryCount = 0; if (endpoint == NULL) { err = kEBADFErr; goto ErrorExit; } if (addr == NULL) { err = kEFAULTErr; goto ErrorExit; } /* * There seems to be a bug with OT related to OTBind failing with kOTNoAddressErr even though * a proper legal address was supplied. This happens very rarely and just retrying the * operation after a certain time (less than 1 sec. does not work) seems to succeed. */TryAgain: // setup our request bindReq.addr.len = addrlen; bindReq.addr.maxlen = addrlen; bindReq.addr.buf = (UInt8*) addr; bindReq.qlen = 1; PR_Lock(fd->secret->md.miscLock); PrepareForAsyncCompletion(me, fd->secret->md.osfd); fd->secret->md.misc.thread = me; err = OTBind(endpoint, &bindReq, NULL); 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; return kOTNoError;ErrorExit: if ((err == kOTNoAddressErr) && (++retryCount <= 4)) { unsigned long finalTicks; Delay(100,&finalTicks); goto TryAgain; } macsock_map_error(err); return -1;}// Errors:// EBADF -- bad socket idPRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog){ PRInt32 osfd = fd->secret->md.osfd; OSStatus err = 0; EndpointRef endpoint = (EndpointRef) osfd; TBind bindReq; PRNetAddr addr; PRThread *me = _PR_MD_CURRENT_THREAD(); if ((fd == NULL) || (endpoint == NULL)) { err = EBADF; goto ErrorExit; } if (backlog == 0) backlog = 1; if (endpoint == NULL) { err = EBADF; goto ErrorExit; } addr.inet.family = AF_INET; addr.inet.port = addr.inet.ip = 0; bindReq.addr.maxlen = PR_NETADDR_SIZE (&addr); bindReq.addr.len = 0; bindReq.addr.buf = (UInt8*) &addr; bindReq.qlen = 0; PrepareForAsyncCompletion(me, fd->secret->md.osfd); fd->secret->md.misc.thread = me; // tell notifier routine what to wake up err = OTGetProtAddress(endpoint, &bindReq, NULL); if (err != kOTNoError) goto ErrorExit; WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); err = me->md.osErrCode; if (err != kOTNoError) goto ErrorExit; PrepareForAsyncCompletion(me, fd->secret->md.osfd); fd->secret->md.misc.thread = me; // tell notifier routine what to wake up err = OTUnbind(endpoint); if (err != kOTNoError) goto ErrorExit; WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); err = me->md.osErrCode; if (err != kOTNoError) goto ErrorExit; /* tell the notifier func that we are interested in pending connections */ fd->secret->md.doListen = PR_TRUE; /* accept up to (backlog) pending connections at any one time */ bindReq.qlen = backlog; PrepareForAsyncCompletion(me, fd->secret->md.osfd); fd->secret->md.misc.thread = me; // tell notifier routine what to wake up err = OTBind(endpoint, &bindReq, NULL); if (err != kOTNoError) goto ErrorExit; WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); err = me->md.osErrCode; if (err != kOTNoError) { // If OTBind failed, we're really not ready to listen after all. fd->secret->md.doListen = PR_FALSE; goto ErrorExit; } return kOTNoError;ErrorExit: me->io_pending = PR_FALSE; // clear pending wait state if any macsock_map_error(err); return -1;}// Errors:// EBADF -- bad socket idPRInt32 _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen){ OSStatus err; EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd; TBind bindReq; PRThread *me = _PR_MD_CURRENT_THREAD(); if (endpoint == NULL) { err = kEBADFErr; goto ErrorExit; } if (addr == NULL) { err = kEFAULTErr; goto ErrorExit; } bindReq.addr.len = *addrlen; bindReq.addr.maxlen = *addrlen; bindReq.addr.buf = (UInt8*) addr; bindReq.qlen = 0; PR_Lock(fd->secret->md.miscLock); PrepareForAsyncCompletion(me, fd->secret->md.osfd); fd->secret->md.misc.thread = me; err = OTGetProtAddress(endpoint, &bindReq, NULL); 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; *addrlen = PR_NETADDR_SIZE(addr); return kOTNoError;ErrorExit: macsock_map_error(err); return -1;}PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, 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)]; 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 = sizeof(TOption); opt->level = level; opt->name = optname; opt->status = 0; cmd.opt.len = sizeof(TOption); cmd.opt.maxlen = sizeof(optionBuffer); cmd.opt.buf = (UInt8*)optionBuffer; cmd.flags = T_CURRENT; 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; } PR_ASSERT(opt->status == T_SUCCESS); switch (optname) { case SO_LINGER: *((t_linger*)optval) = *((t_linger*)&opt->value); *optlen = sizeof(t_linger); break; case SO_REUSEADDR: case TCP_NODELAY: case SO_KEEPALIVE: case SO_RCVBUF: case SO_SNDBUF: *((PRIntn*)optval) = *((PRIntn*)&opt->value); *optlen = sizeof(PRIntn); break; case IP_MULTICAST_LOOP: *((PRUint8*)optval) = *((PRIntn*)&opt->value); *optlen = sizeof(PRUint8); break; case IP_TTL: *((PRUintn*)optval) = *((PRUint8*)&opt->value); *optlen = sizeof(PRUintn); break; case IP_MULTICAST_TTL:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -