📄 macsockotpt.c
字号:
*readReady = fd->secret->md.readReady && (availableData > 0); *exceptReady = fd->secret->md.exceptReady; resultOT = OTGetEndpointState((EndpointRef)fd->secret->md.osfd); switch (resultOT) { case T_IDLE: case T_UNBND: // the socket is not connected. Emulating BSD sockets, // we mark it readable and writable. The next PR_Read // or PR_Write will then fail. Usually, in this situation, // fd->secret->md.exceptReady is also set, and returned if // anyone is polling for it. *readReady = PR_FALSE; *writeReady = PR_FALSE; break; case T_DATAXFER: // data transfer *writeReady = fd->secret->md.writeReady; break; case T_INREL: // incoming orderly release *writeReady = fd->secret->md.writeReady; break; case T_OUTCON: // outgoing connection pending case T_INCON: // incoming connection pending case T_OUTREL: // outgoing orderly release default: *writeReady = PR_FALSE; } return *readReady || *writeReady || *exceptReady;}// check to see if any of the poll descriptors have data available// for reading or writing, by calling their poll methods (layered IO).static PRInt32 CheckPollDescMethods(PRPollDesc *pds, PRIntn npds, PRInt16 *outReadFlags, PRInt16 *outWriteFlags){ PRInt32 ready = 0; PRPollDesc *pd, *epd; PRInt16 *readFlag, *writeFlag; for (pd = pds, epd = pd + npds, readFlag = outReadFlags, writeFlag = outWriteFlags; pd < epd; pd++, readFlag++, writeFlag++) { PRInt16 in_flags_read = 0, in_flags_write = 0; PRInt16 out_flags_read = 0, out_flags_write = 0; if (NULL == pd->fd || pd->in_flags == 0) continue; if (pd->in_flags & PR_POLL_READ) { in_flags_read = (pd->fd->methods->poll)( pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read); } if (pd->in_flags & PR_POLL_WRITE) { in_flags_write = (pd->fd->methods->poll)( pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write); } if ((0 != (in_flags_read & out_flags_read)) || (0 != (in_flags_write & out_flags_write))) { ready += 1; /* some layer has buffer input */ pd->out_flags = out_flags_read | out_flags_write; } *readFlag = in_flags_read; *writeFlag = in_flags_write; } return ready;}// check to see if any of OT endpoints of the poll descriptors have data available// for reading or writing.static PRInt32 CheckPollDescEndpoints(PRPollDesc *pds, PRIntn npds, const PRInt16 *inReadFlags, const PRInt16 *inWriteFlags){ PRInt32 ready = 0; PRPollDesc *pd, *epd; const PRInt16 *readFlag, *writeFlag; for (pd = pds, epd = pd + npds, readFlag = inReadFlags, writeFlag = inWriteFlags; pd < epd; pd++, readFlag++, writeFlag++) { PRFileDesc *bottomFD; PRBool readReady, writeReady, exceptReady; PRInt16 in_flags_read = *readFlag; PRInt16 in_flags_write = *writeFlag; if (NULL == pd->fd || pd->in_flags == 0) continue; bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); /* bottomFD can be NULL for pollable sockets */ if (bottomFD) { if (_PR_FILEDESC_OPEN == bottomFD->secret->state) { pd->out_flags = 0; /* pre-condition */ if (GetState(bottomFD, &readReady, &writeReady, &exceptReady)) { if (readReady) { if (in_flags_read & PR_POLL_READ) pd->out_flags |= PR_POLL_READ; if (in_flags_write & PR_POLL_READ) pd->out_flags |= PR_POLL_WRITE; } if (writeReady) { if (in_flags_read & PR_POLL_WRITE) pd->out_flags |= PR_POLL_READ; if (in_flags_write & PR_POLL_WRITE) pd->out_flags |= PR_POLL_WRITE; } if (exceptReady && (pd->in_flags & PR_POLL_EXCEPT)) { pd->out_flags |= PR_POLL_EXCEPT; } if (0 != pd->out_flags) ready++; } } else /* bad state */ { ready += 1; /* this will cause an abrupt return */ pd->out_flags = PR_POLL_NVAL; /* bogii */ } } } return ready;}// see how many of the poll descriptors are readystatic PRInt32 CountReadyPollDescs(PRPollDesc *pds, PRIntn npds){ PRInt32 ready = 0; PRPollDesc *pd, *epd; for (pd = pds, epd = pd + npds; pd < epd; pd++) { if (pd->out_flags) ready ++; } return ready;}// set or clear the poll thread on the poll descriptorsstatic void SetDescPollThread(PRPollDesc *pds, PRIntn npds, PRThread* thread){ PRInt32 ready = 0; PRPollDesc *pd, *epd; for (pd = pds, epd = pd + npds; pd < epd; pd++) { if (pd->fd) { PRFileDesc *bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); if (bottomFD && (_PR_FILEDESC_OPEN == bottomFD->secret->state)) { if (pd->in_flags & PR_POLL_READ) { PR_ASSERT(thread == NULL || bottomFD->secret->md.read.thread == NULL); bottomFD->secret->md.read.thread = thread; } if (pd->in_flags & PR_POLL_WRITE) { // it's possible for the writing thread to be non-null during // a non-blocking connect, so we assert that we're on // the same thread, or the thread is null. // Note that it's strictly possible for the connect and poll // to be on different threads, so ideally we need to assert // that if md.write.thread is non-null, there is a non-blocking // connect in progress. PR_ASSERT(thread == NULL || (bottomFD->secret->md.write.thread == NULL || bottomFD->secret->md.write.thread == thread)); bottomFD->secret->md.write.thread = thread; } } } }}#define DESCRIPTOR_FLAGS_ARRAY_SIZE 32PRInt32 _MD_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout){ PRInt16 readFlagsArray[DESCRIPTOR_FLAGS_ARRAY_SIZE]; PRInt16 writeFlagsArray[DESCRIPTOR_FLAGS_ARRAY_SIZE]; PRInt16 *readFlags = readFlagsArray; PRInt16 *writeFlags = writeFlagsArray; PRInt16 *ioFlags = NULL; PRThread *thread = _PR_MD_CURRENT_THREAD(); PRInt32 ready; if (npds > DESCRIPTOR_FLAGS_ARRAY_SIZE) { // we allocate a single double-size array. The first half is used // for read flags, and the second half for write flags. ioFlags = (PRInt16*)PR_Malloc(sizeof(PRInt16) * npds * 2); if (!ioFlags) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } readFlags = ioFlags; writeFlags = &ioFlags[npds]; } if (timeout != PR_INTERVAL_NO_WAIT) { intn is; // we have to be outside the lock when calling this, since // it can call arbitrary user code (including other socket // entry points) (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags); _PR_INTSOFF(is); PR_Lock(thread->md.asyncIOLock); PrepareForAsyncCompletion(thread, 0); SetDescPollThread(pds, npds, thread); (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags); PR_Unlock(thread->md.asyncIOLock); _PR_FAST_INTSON(is); ready = CountReadyPollDescs(pds, npds); if (ready == 0) { WaitOnThisThread(thread, timeout); // since we may have been woken by a pollable event firing, // we have to check both poll methods and endpoints. (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags); (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags); ready = CountReadyPollDescs(pds, npds); } thread->io_pending = PR_FALSE; SetDescPollThread(pds, npds, NULL); } else { (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags); (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags); ready = CountReadyPollDescs(pds, npds); } if (readFlags != readFlagsArray) PR_Free(ioFlags); return ready;}void _MD_initfiledesc(PRFileDesc *fd){ // Allocate a PR_Lock to arbitrate miscellaneous OT calls for this endpoint between threads // We presume that only one thread will be making Read calls (Recv/Accept) and that only // one thread will be making Write calls (Send/Connect) on the endpoint at a time. if (fd->methods->file_type == PR_DESC_SOCKET_TCP || fd->methods->file_type == PR_DESC_SOCKET_UDP ) { PR_ASSERT(fd->secret->md.miscLock == NULL); fd->secret->md.miscLock = PR_NewLock(); PR_ASSERT(fd->secret->md.miscLock != NULL); fd->secret->md.orderlyDisconnect = PR_FALSE; fd->secret->md.readReady = PR_FALSE; // let's not presume we have data ready to read fd->secret->md.writeReady = PR_TRUE; // let's presume we can write unless we hear otherwise fd->secret->md.exceptReady = PR_FALSE; }}void _MD_freefiledesc(PRFileDesc *fd){ if (fd->secret->md.miscLock) { PR_ASSERT(fd->methods->file_type == PR_DESC_SOCKET_TCP || fd->methods->file_type == PR_DESC_SOCKET_UDP); PR_DestroyLock(fd->secret->md.miscLock); fd->secret->md.miscLock = NULL; } else { PR_ASSERT(fd->methods->file_type != PR_DESC_SOCKET_TCP && PR_DESC_SOCKET_TCP != PR_DESC_SOCKET_UDP); }}// _MD_makenonblock is also used for sockets meant to be used for blocking I/O,// in order to install the notifier routine for async completion.void _MD_makenonblock(PRFileDesc *fd){ // We simulate non-blocking mode using async mode rather // than put the endpoint in non-blocking mode. // We need to install the PRFileDesc as the contextPtr for the NotifierRoutine, but it // didn't exist at the time the endpoint was created. It does now though... ProviderRef endpointRef = (ProviderRef)fd->secret->md.osfd; OSStatus err; // Install fd->secret as the contextPtr for the Notifier function associated with this // endpoint. We use this instead of the fd itself because: // (a) in cases where you import I/O layers, the containing // fd changes, but the secret structure does not; // (b) the notifier func refers only to the secret data structure // anyway. err = OTInstallNotifier(endpointRef, NotifierRoutineUPP, fd->secret); PR_ASSERT(err == kOTNoError); // Now that we have a NotifierRoutine installed, we can make the endpoint asynchronous err = OTSetAsynchronous(endpointRef); PR_ASSERT(err == kOTNoError);}void _MD_initfdinheritable(PRFileDesc *fd, PRBool imported){ /* XXX this function needs to be implemented */ fd->secret->inheritable = _PR_TRI_UNKNOWN;}void _MD_queryfdinheritable(PRFileDesc *fd){ /* XXX this function needs to be implemented */ PR_ASSERT(0);}PR_IMPLEMENT(PRInt32) _MD_shutdown(PRFileDesc *fd, PRIntn how){#pragma unused (fd, how)/* Just succeed silently!!! */return (0);}PR_IMPLEMENT(PRStatus) _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen){ PRThread *me = _PR_MD_CURRENT_THREAD(); EndpointRef ep = (EndpointRef) fd->secret->md.osfd; InetAddress inetAddr; TBind peerAddr; OSErr err; if (*addrlen < sizeof(InetAddress)) { err = (OSErr) kEINVALErr; goto ErrorExit; } peerAddr.addr.maxlen = sizeof(InetAddress); peerAddr.addr.len = 0; peerAddr.addr.buf = (UInt8*) &inetAddr; peerAddr.qlen = 0; PrepareForAsyncCompletion(me, fd->secret->md.osfd); fd->secret->md.misc.thread = me; // tell notifier routine what to wake up err = OTGetProtAddress(ep, NULL, &peerAddr); if (err != kOTNoError) goto ErrorExit; WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); err = me->md.osErrCode; if ((err == kOTNoError) && (peerAddr.addr.len < sizeof(InetAddress))) err = kEBADFErr; // we don't understand the address we got if (err != kOTNoError) goto ErrorExit; // Translate the OT peer information into an NSPR address. addr->inet.family = AF_INET; addr->inet.port = (PRUint16) inetAddr.fPort; addr->inet.ip = (PRUint32) inetAddr.fHost; *addrlen = PR_NETADDR_SIZE(addr); // return the amount of data obtained return PR_SUCCESS;ErrorExit: macsock_map_error(err); return PR_FAILURE;}PR_IMPLEMENT(unsigned long) inet_addr(const char *cp){ OSStatus err; InetHost host; _MD_FinishInitNetAccess(); err = OTInetStringToHost((char*) cp, &host); if (err != kOTNoError) return -1; return host;}static char *sAliases[1] = {NULL};static struct hostent sHostEnt = {NULL, &sAliases[0], AF_INET, sizeof (long), NULL};static InetHostInfo sHostInfo;static InetHost *sAddresses[kMaxHostAddrs+1];PR_IMPLEMENT(struct hostent *) gethostbyname(const char * name){ OSStatus err; PRUint32 index; PRThread *me = _PR_MD_CURRENT_THREAD(); _MD_FinishInitNetAccess(); me->io_pending = PR_TRUE; me->io_fd = NULL; me->md.osErrCode = noErr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -