📄 prsocket.c
字号:
_PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE); _PR_MD_MAKE_NONBLOCK(f[1]); _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE); return PR_SUCCESS;#elif defined(WINNT) /* * A socket pair is often used for interprocess communication, * so we need to make sure neither socket is associated with * the I/O completion port; otherwise it can't be used by a * child process. * * The default implementation below cannot be used for NT * because PR_Accept would have associated the I/O completion * port with the listening and accepted sockets. */ SOCKET listenSock; SOCKET osfd[2]; struct sockaddr_in selfAddr, peerAddr; int addrLen; if (!_pr_initialized) _PR_ImplicitInitialization(); osfd[0] = osfd[1] = INVALID_SOCKET; listenSock = socket(AF_INET, SOCK_STREAM, 0); if (listenSock == INVALID_SOCKET) { goto failed; } selfAddr.sin_family = AF_INET; selfAddr.sin_port = 0; selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* BugZilla: 35408 */ addrLen = sizeof(selfAddr); if (bind(listenSock, (struct sockaddr *) &selfAddr, addrLen) == SOCKET_ERROR) { goto failed; } if (getsockname(listenSock, (struct sockaddr *) &selfAddr, &addrLen) == SOCKET_ERROR) { goto failed; } if (listen(listenSock, 5) == SOCKET_ERROR) { goto failed; } osfd[0] = socket(AF_INET, SOCK_STREAM, 0); if (osfd[0] == INVALID_SOCKET) { goto failed; } selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* * Only a thread is used to do the connect and accept. * I am relying on the fact that connect returns * successfully as soon as the connect request is put * into the listen queue (but before accept is called). * This is the behavior of the BSD socket code. If * connect does not return until accept is called, we * will need to create another thread to call connect. */ if (connect(osfd[0], (struct sockaddr *) &selfAddr, addrLen) == SOCKET_ERROR) { goto failed; } /* * A malicious local process may connect to the listening * socket, so we need to verify that the accepted connection * is made from our own socket osfd[0]. */ if (getsockname(osfd[0], (struct sockaddr *) &selfAddr, &addrLen) == SOCKET_ERROR) { goto failed; } osfd[1] = accept(listenSock, (struct sockaddr *) &peerAddr, &addrLen); if (osfd[1] == INVALID_SOCKET) { goto failed; } if (peerAddr.sin_port != selfAddr.sin_port) { /* the connection we accepted is not from osfd[0] */ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); goto failed; } closesocket(listenSock); f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods()); if (!f[0]) { closesocket(osfd[0]); closesocket(osfd[1]); /* PR_AllocFileDesc() has invoked PR_SetError(). */ return PR_FAILURE; } f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods()); if (!f[1]) { PR_Close(f[0]); closesocket(osfd[1]); /* PR_AllocFileDesc() has invoked PR_SetError(). */ return PR_FAILURE; } _PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE); _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE); return PR_SUCCESS;failed: if (listenSock != INVALID_SOCKET) { closesocket(listenSock); } if (osfd[0] != INVALID_SOCKET) { closesocket(osfd[0]); } if (osfd[1] != INVALID_SOCKET) { closesocket(osfd[1]); } return PR_FAILURE;#else /* not Unix or NT */ /* * default implementation */ PRFileDesc *listenSock; PRNetAddr selfAddr, peerAddr; PRUint16 port; f[0] = f[1] = NULL; listenSock = PR_NewTCPSocket(); if (listenSock == NULL) { goto failed; } PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); /* BugZilla: 35408 */ if (PR_Bind(listenSock, &selfAddr) == PR_FAILURE) { goto failed; } if (PR_GetSockName(listenSock, &selfAddr) == PR_FAILURE) { goto failed; } port = ntohs(selfAddr.inet.port); if (PR_Listen(listenSock, 5) == PR_FAILURE) { goto failed; } f[0] = PR_NewTCPSocket(); if (f[0] == NULL) { goto failed; }#ifdef _PR_CONNECT_DOES_NOT_BIND /* * If connect does not implicitly bind the socket (e.g., on * BeOS), we have to bind the socket so that we can get its * port with getsockname later. */ PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); if (PR_Bind(f[0], &selfAddr) == PR_FAILURE) { goto failed; }#endif PR_InitializeNetAddr(PR_IpAddrLoopback, port, &selfAddr); /* * Only a thread is used to do the connect and accept. * I am relying on the fact that PR_Connect returns * successfully as soon as the connect request is put * into the listen queue (but before PR_Accept is called). * This is the behavior of the BSD socket code. If * connect does not return until accept is called, we * will need to create another thread to call connect. */ if (PR_Connect(f[0], &selfAddr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { goto failed; } /* * A malicious local process may connect to the listening * socket, so we need to verify that the accepted connection * is made from our own socket f[0]. */ if (PR_GetSockName(f[0], &selfAddr) == PR_FAILURE) { goto failed; } f[1] = PR_Accept(listenSock, &peerAddr, PR_INTERVAL_NO_TIMEOUT); if (f[1] == NULL) { goto failed; } if (peerAddr.inet.port != selfAddr.inet.port) { /* the connection we accepted is not from f[0] */ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); goto failed; } PR_Close(listenSock); return PR_SUCCESS;failed: if (listenSock) { PR_Close(listenSock); } if (f[0]) { PR_Close(f[0]); } if (f[1]) { PR_Close(f[1]); } return PR_FAILURE;#endif}PR_IMPLEMENT(PRInt32)PR_FileDesc2NativeHandle(PRFileDesc *fd){ if (fd) { fd = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER); } if (!fd) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } return fd->secret->md.osfd;}PR_IMPLEMENT(void)PR_ChangeFileDescNativeHandle(PRFileDesc *fd, PRInt32 handle){ if (fd) fd->secret->md.osfd = handle;}/*** Select compatibility***/PR_IMPLEMENT(void) PR_FD_ZERO(PR_fd_set *set){ memset(set, 0, sizeof(PR_fd_set));}PR_IMPLEMENT(void) PR_FD_SET(PRFileDesc *fh, PR_fd_set *set){ PR_ASSERT( set->hsize < PR_MAX_SELECT_DESC ); set->harray[set->hsize++] = fh;}PR_IMPLEMENT(void) PR_FD_CLR(PRFileDesc *fh, PR_fd_set *set){ PRUint32 index, index2; for (index = 0; index<set->hsize; index++) if (set->harray[index] == fh) { for (index2=index; index2 < (set->hsize-1); index2++) { set->harray[index2] = set->harray[index2+1]; } set->hsize--; break; }}PR_IMPLEMENT(PRInt32) PR_FD_ISSET(PRFileDesc *fh, PR_fd_set *set){ PRUint32 index; for (index = 0; index<set->hsize; index++) if (set->harray[index] == fh) { return 1; } return 0;}PR_IMPLEMENT(void) PR_FD_NSET(PRInt32 fd, PR_fd_set *set){ PR_ASSERT( set->nsize < PR_MAX_SELECT_DESC ); set->narray[set->nsize++] = fd;}PR_IMPLEMENT(void) PR_FD_NCLR(PRInt32 fd, PR_fd_set *set){ PRUint32 index, index2; for (index = 0; index<set->nsize; index++) if (set->narray[index] == fd) { for (index2=index; index2 < (set->nsize-1); index2++) { set->narray[index2] = set->narray[index2+1]; } set->nsize--; break; }}PR_IMPLEMENT(PRInt32) PR_FD_NISSET(PRInt32 fd, PR_fd_set *set){ PRUint32 index; for (index = 0; index<set->nsize; index++) if (set->narray[index] == fd) { return 1; } return 0;}#if !defined(NEED_SELECT)#if !defined(XP_MAC)#include "obsolete/probslet.h"#else#include "probslet.h"#endif#define PD_INCR 20static PRPollDesc *_pr_setfd( PR_fd_set *set, PRInt16 flags, PRPollDesc *polldesc){ PRUintn fsidx, pdidx; PRPollDesc *poll = polldesc; if (NULL == set) return poll; /* First set the pr file handle osfds */ for (fsidx = 0; fsidx < set->hsize; fsidx++) { for (pdidx = 0; 1; pdidx++) { if ((PRFileDesc*)-1 == poll[pdidx].fd) { /* our vector is full - extend and condition it */ poll = (PRPollDesc*)PR_Realloc( poll, (pdidx + 1 + PD_INCR) * sizeof(PRPollDesc)); if (NULL == poll) goto out_of_memory; memset( poll + pdidx * sizeof(PRPollDesc), 0, PD_INCR * sizeof(PRPollDesc)); poll[pdidx + PD_INCR].fd = (PRFileDesc*)-1; } if ((NULL == poll[pdidx].fd) || (poll[pdidx].fd == set->harray[fsidx])) { /* PR_ASSERT(0 == (poll[pdidx].in_flags & flags)); */ /* either empty or prevously defined */ poll[pdidx].fd = set->harray[fsidx]; /* possibly redundant */ poll[pdidx].in_flags |= flags; /* possibly redundant */ break; } } }#if 0 /* Second set the native osfds */ for (fsidx = 0; fsidx < set->nsize; fsidx++) { for (pdidx = 0; ((PRFileDesc*)-1 != poll[pdidx].fd); pdidx++) { if ((PRFileDesc*)-1 == poll[pdidx].fd) { /* our vector is full - extend and condition it */ poll = PR_Realloc( poll, (pdidx + PD_INCR) * sizeof(PRPollDesc)); if (NULL == poll) goto out_of_memory; memset( poll + pdidx * sizeof(PRPollDesc), 0, PD_INCR * sizeof(PRPollDesc)); poll[(pdidx + PD_INCR)].fd = (PRFileDesc*)-1; } if ((NULL == poll[pdidx].fd) || (poll[pdidx].fd == set->narray[fsidx])) { /* either empty or prevously defined */ poll[pdidx].fd = set->narray[fsidx]; PR_ASSERT(0 == (poll[pdidx].in_flags & flags)); poll[pdidx].in_flags |= flags; break; } } }#endif /* 0 */ return poll;out_of_memory: if (NULL != polldesc) PR_DELETE(polldesc); return NULL;} /* _pr_setfd */#endif /* !defined(NEED_SELECT) */PR_IMPLEMENT(PRInt32) PR_Select( PRInt32 unused, PR_fd_set *pr_rd, PR_fd_set *pr_wr, PR_fd_set *pr_ex, PRIntervalTime timeout){#if !defined(NEED_SELECT) PRInt32 npds = 0; /* ** Find out how many fds are represented in the three lists. ** Then allocate a polling descriptor for the logical union ** (there can't be any overlapping) and call PR_Poll(). */ PRPollDesc *copy, *poll; static PRBool warning = PR_TRUE; if (warning) warning = _PR_Obsolete( "PR_Select()", "PR_Poll()"); /* try to get an initial guesss at how much space we need */ npds = 0; if ((NULL != pr_rd) && ((pr_rd->hsize + pr_rd->nsize - npds) > 0)) npds = pr_rd->hsize + pr_rd->nsize; if ((NULL != pr_wr) && ((pr_wr->hsize + pr_wr->nsize - npds) > 0)) npds = pr_wr->hsize + pr_wr->nsize; if ((NULL != pr_ex) && ((pr_ex->hsize + pr_ex->nsize - npds) > 0)) npds = pr_ex->hsize + pr_ex->nsize; if (0 == npds) { PR_Sleep(timeout); return 0; } copy = poll = (PRPollDesc*)PR_Calloc(npds + PD_INCR, sizeof(PRPollDesc)); if (NULL == poll) goto out_of_memory; poll[npds + PD_INCR - 1].fd = (PRFileDesc*)-1; poll = _pr_setfd(pr_rd, PR_POLL_READ, poll); if (NULL == poll) goto out_of_memory; poll = _pr_setfd(pr_wr, PR_POLL_WRITE, poll); if (NULL == poll) goto out_of_memory; poll = _pr_setfd(pr_ex, PR_POLL_EXCEPT, poll); if (NULL == poll) goto out_of_memory; unused = 0; while (NULL != poll[unused].fd && (PRFileDesc*)-1 != poll[unused].fd) { ++unused; } PR_ASSERT(unused > 0); npds = PR_Poll(poll, unused, timeout); if (npds > 0) { /* Copy the results back into the fd sets */ if (NULL != pr_rd) pr_rd->nsize = pr_rd->hsize = 0; if (NULL != pr_wr) pr_wr->nsize = pr_wr->hsize = 0; if (NULL != pr_ex) pr_ex->nsize = pr_ex->hsize = 0; for (copy = &poll[unused - 1]; copy >= poll; --copy) { if (copy->out_flags & PR_POLL_NVAL) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); npds = -1; break; } if (copy->out_flags & PR_POLL_READ) if (NULL != pr_rd) pr_rd->harray[pr_rd->hsize++] = copy->fd; if (copy->out_flags & PR_POLL_WRITE) if (NULL != pr_wr) pr_wr->harray[pr_wr->hsize++] = copy->fd; if (copy->out_flags & PR_POLL_EXCEPT) if (NULL != pr_ex) pr_ex->harray[pr_ex->hsize++] = copy->fd; } } PR_DELETE(poll); return npds;out_of_memory: PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; #endif /* !defined(NEED_SELECT) */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -