📄 ptio.c
字号:
/* Ensured by PR_Writev */ PR_ASSERT(iov_len <= PR_MAX_IOVECTOR_SIZE); /* * We can't pass iov to writev because PRIOVec and struct iovec * may not be binary compatible. Make osiov a copy of iov and * pass osiov to writev. We can modify osiov if we need to * continue the operation. */ osiov = osiov_local; osiov_len = iov_len; for (iov_index = 0; iov_index < osiov_len; iov_index++) { osiov[iov_index].iov_base = iov[iov_index].iov_base; osiov[iov_index].iov_len = iov[iov_index].iov_len; } rv = bytes = writev(fd->secret->md.osfd, osiov, osiov_len); syserrno = errno; if (!fd->secret->nonblocking) { if (bytes >= 0) { /* * If we moved some bytes, how does that implicate the * i/o vector list? In other words, exactly where are * we within that array? What are the parameters for * resumption? Maybe we're done! */ for ( ;osiov_len > 0; osiov++, osiov_len--) { if (bytes < osiov->iov_len) { /* this one's not done yet */ osiov->iov_base = (char*)osiov->iov_base + bytes; osiov->iov_len -= bytes; break; /* go off and do that */ } bytes -= osiov->iov_len; /* this one's done cooked */ } PR_ASSERT(osiov_len > 0 || bytes == 0); if (osiov_len > 0) { if (PR_INTERVAL_NO_WAIT == timeout) { rv = -1; syserrno = ETIMEDOUT; } else fNeedContinue = PR_TRUE; } } else if (syserrno == EWOULDBLOCK || syserrno == EAGAIN) { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else { rv = 0; fNeedContinue = PR_TRUE; } } } if (fNeedContinue == PR_TRUE) { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)osiov; op.arg3.amount = osiov_len; op.timeout = timeout; op.result.code = rv; op.function = pt_writev_cont; op.event = POLLOUT | POLLPRI; rv = pt_Continue(&op); syserrno = op.syserrno; } if (rv == -1) pt_MapError(_PR_MD_MAP_WRITEV_ERROR, syserrno); return rv;} /* pt_Writev */static PRInt32 pt_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence){ return _PR_MD_LSEEK(fd, offset, whence);} /* pt_Seek */static PRInt64 pt_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence){ return _PR_MD_LSEEK64(fd, offset, whence);} /* pt_Seek64 */static PRInt32 pt_Available_f(PRFileDesc *fd){ PRInt32 result, cur, end; cur = _PR_MD_LSEEK(fd, 0, PR_SEEK_CUR); if (cur >= 0) end = _PR_MD_LSEEK(fd, 0, PR_SEEK_END); if ((cur < 0) || (end < 0)) { return -1; } result = end - cur; _PR_MD_LSEEK(fd, cur, PR_SEEK_SET); return result;} /* pt_Available_f */static PRInt64 pt_Available64_f(PRFileDesc *fd){ PRInt64 result, cur, end; PRInt64 minus_one; LL_I2L(minus_one, -1); cur = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_CUR); if (LL_GE_ZERO(cur)) end = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_END); if (!LL_GE_ZERO(cur) || !LL_GE_ZERO(end)) return minus_one; LL_SUB(result, end, cur); (void)_PR_MD_LSEEK64(fd, cur, PR_SEEK_SET); return result;} /* pt_Available64_f */static PRInt32 pt_Available_s(PRFileDesc *fd){ PRInt32 rv, bytes = -1; if (pt_TestAbort()) return bytes; rv = ioctl(fd->secret->md.osfd, FIONREAD, &bytes); if (rv == -1) pt_MapError(_PR_MD_MAP_SOCKETAVAILABLE_ERROR, errno); return bytes;} /* pt_Available_s */static PRInt64 pt_Available64_s(PRFileDesc *fd){ PRInt64 rv; LL_I2L(rv, pt_Available_s(fd)); return rv;} /* pt_Available64_s */static PRStatus pt_FileInfo(PRFileDesc *fd, PRFileInfo *info){ PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, info); return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;} /* pt_FileInfo */static PRStatus pt_FileInfo64(PRFileDesc *fd, PRFileInfo64 *info){ PRInt32 rv = _PR_MD_GETOPENFILEINFO64(fd, info); return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;} /* pt_FileInfo64 */static PRStatus pt_Synch(PRFileDesc *fd){ return (NULL == fd) ? PR_FAILURE : PR_SUCCESS;} /* pt_Synch */static PRStatus pt_Fsync(PRFileDesc *fd){ PRIntn rv = -1; if (pt_TestAbort()) return PR_FAILURE; rv = fsync(fd->secret->md.osfd); if (rv < 0) { pt_MapError(_PR_MD_MAP_FSYNC_ERROR, errno); return PR_FAILURE; } return PR_SUCCESS;} /* pt_Fsync */static PRStatus pt_Connect( PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout){ PRIntn rv = -1, syserrno; pt_SockLen addr_len; const PRNetAddr *addrp = addr;#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) PRUint16 md_af = addr->raw.family; PRNetAddr addrCopy;#endif if (pt_TestAbort()) return PR_FAILURE; PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); addr_len = PR_NETADDR_SIZE(addr);#if defined(_PR_INET6) if (addr->raw.family == PR_AF_INET6) { md_af = AF_INET6;#ifndef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; addrCopy.raw.family = AF_INET6; addrp = &addrCopy;#endif }#endif#ifdef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; ((struct sockaddr*)&addrCopy)->sa_len = addr_len; ((struct sockaddr*)&addrCopy)->sa_family = md_af; rv = connect(fd->secret->md.osfd, (struct sockaddr*)&addrCopy, addr_len);#else rv = connect(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len);#endif syserrno = errno; if ((-1 == rv) && (EINPROGRESS == syserrno) && (!fd->secret->nonblocking)) { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd;#ifdef _PR_HAVE_SOCKADDR_LEN op.arg2.buffer = (void*)&addrCopy;#else op.arg2.buffer = (void*)addr;#endif op.arg3.amount = addr_len; op.timeout = timeout; op.function = pt_connect_cont; op.event = POLLOUT | POLLPRI; rv = pt_Continue(&op); syserrno = op.syserrno; } } if (-1 == rv) { pt_MapError(_PR_MD_MAP_CONNECT_ERROR, syserrno); return PR_FAILURE; } return PR_SUCCESS;} /* pt_Connect */static PRStatus pt_ConnectContinue( PRFileDesc *fd, PRInt16 out_flags){ int err; PRInt32 osfd; if (out_flags & PR_POLL_NVAL) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); return PR_FAILURE; } if ((out_flags & (PR_POLL_WRITE | PR_POLL_EXCEPT | PR_POLL_ERR)) == 0) { PR_ASSERT(out_flags == 0); PR_SetError(PR_IN_PROGRESS_ERROR, 0); return PR_FAILURE; } osfd = fd->secret->md.osfd; err = _MD_unix_get_nonblocking_connect_error(osfd); if (err != 0) { _PR_MD_MAP_CONNECT_ERROR(err); return PR_FAILURE; } return PR_SUCCESS;} /* pt_ConnectContinue */PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd){ /* Find the NSPR layer and invoke its connectcontinue method */ PRFileDesc *bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); if (NULL == bottom) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } return pt_ConnectContinue(bottom, pd->out_flags);} /* PR_GetConnectStatus */static PRFileDesc* pt_Accept( PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout){ PRFileDesc *newfd = NULL; PRIntn syserrno, osfd = -1; pt_SockLen addr_len = sizeof(PRNetAddr); if (pt_TestAbort()) return newfd;#ifdef _PR_STRICT_ADDR_LEN if (addr) { /* * Set addr->raw.family just so that we can use the * PR_NETADDR_SIZE macro. */ addr->raw.family = fd->secret->af; addr_len = PR_NETADDR_SIZE(addr); }#endif osfd = accept(fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len); syserrno = errno; if (osfd == -1) { if (fd->secret->nonblocking) goto failed; if (EWOULDBLOCK != syserrno && EAGAIN != syserrno && ECONNABORTED != syserrno) goto failed; else { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = addr; op.arg3.addr_len = &addr_len; op.timeout = timeout; op.function = pt_accept_cont; op.event = POLLIN | POLLPRI; osfd = pt_Continue(&op); syserrno = op.syserrno; } if (osfd < 0) goto failed; } }#ifdef _PR_HAVE_SOCKADDR_LEN /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr*)addr)->sa_family; }#endif /* _PR_HAVE_SOCKADDR_LEN */#ifdef _PR_INET6 if (addr && (AF_INET6 == addr->raw.family)) addr->raw.family = PR_AF_INET6;#endif newfd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_TRUE, PR_FALSE); if (newfd == NULL) close(osfd); /* $$$ whoops! this doesn't work $$$ */ else { PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);#ifdef LINUX /* * On Linux, experiments showed that the accepted sockets * inherit the TCP_NODELAY socket option of the listening * socket. */ newfd->secret->md.tcp_nodelay = fd->secret->md.tcp_nodelay;#endif } return newfd;failed: pt_MapError(_PR_MD_MAP_ACCEPT_ERROR, syserrno); return NULL;} /* pt_Accept */static PRStatus pt_Bind(PRFileDesc *fd, const PRNetAddr *addr){ PRIntn rv; pt_SockLen addr_len; const PRNetAddr *addrp = addr;#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) PRUint16 md_af = addr->raw.family; PRNetAddr addrCopy;#endif if (pt_TestAbort()) return PR_FAILURE; PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); if (addr->raw.family == AF_UNIX) { /* Disallow relative pathnames */ if (addr->local.path[0] != '/') { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } }#if defined(_PR_INET6) if (addr->raw.family == PR_AF_INET6) { md_af = AF_INET6;#ifndef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; addrCopy.raw.family = AF_INET6; addrp = &addrCopy;#endif }#endif addr_len = PR_NETADDR_SIZE(addr);#ifdef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; ((struct sockaddr*)&addrCopy)->sa_len = addr_len; ((struct sockaddr*)&addrCopy)->sa_family = md_af; rv = bind(fd->secret->md.osfd, (struct sockaddr*)&addrCopy, addr_len);#else rv = bind(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len);#endif if (rv == -1) { pt_MapError(_PR_MD_MAP_BIND_ERROR, errno); return PR_FAILURE; } return PR_SUCCESS;} /* pt_Bind */static PRStatus pt_Listen(PRFileDesc *fd, PRIntn backlog){ PRIntn rv; if (pt_TestAbort()) return PR_FAILURE; rv = listen(fd->secret->md.osfd, backlog); if (rv == -1) { pt_MapError(_PR_MD_MAP_LISTEN_ERROR, errno); return PR_FAILURE; } return PR_SUCCESS;} /* pt_Listen */static PRStatus pt_Shutdown(PRFileDesc *fd, PRIntn how){ PRIntn rv = -1; if (pt_TestAbort()) return PR_FAILURE; rv = shutdown(fd->secret->md.osfd, how); if (rv == -1) { pt_MapError(_PR_MD_MAP_SHUTDOWN_ERROR, errno); return PR_FAILURE; } return PR_SUCCESS;} /* pt_Shutdown */static PRInt16 pt_Poll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -