📄 ptio.c
字号:
*out_flags = 0; return in_flags;} /* pt_Poll */static PRInt32 pt_Recv( PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout){ PRInt32 syserrno, bytes = -1; PRIntn osflags; if (0 == flags) osflags = 0; else if (PR_MSG_PEEK == flags) osflags = MSG_PEEK; else { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return bytes; } if (pt_TestAbort()) return bytes; /* recv() is a much slower call on pre-2.6 Solaris than read(). */#if defined(SOLARIS) if (0 == osflags) bytes = read(fd->secret->md.osfd, buf, amount); else bytes = recv(fd->secret->md.osfd, buf, amount, osflags);#else bytes = recv(fd->secret->md.osfd, buf, amount, osflags);#endif syserrno = errno; if ((bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) && (!fd->secret->nonblocking)) { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = buf; op.arg3.amount = amount; op.arg4.flags = osflags; op.timeout = timeout; op.function = pt_recv_cont; op.event = POLLIN | POLLPRI; bytes = pt_Continue(&op); syserrno = op.syserrno; } } if (bytes < 0) pt_MapError(_PR_MD_MAP_RECV_ERROR, syserrno); return bytes;} /* pt_Recv */static PRInt32 pt_SocketRead(PRFileDesc *fd, void *buf, PRInt32 amount){ return pt_Recv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);} /* pt_SocketRead */static PRInt32 pt_Send( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout){ PRInt32 syserrno, bytes = -1; PRBool fNeedContinue = PR_FALSE;#if defined(SOLARIS) PRInt32 tmp_amount = amount;#endif /* * Under HP-UX DCE threads, pthread.h includes dce/cma_ux.h, * which has the following: * # define send cma_send * extern int cma_send (int , void *, int, int ); * So we need to cast away the 'const' of argument #2 for send(). */#if defined (HPUX) && defined(_PR_DCETHREADS)#define PT_SENDBUF_CAST (void *)#else#define PT_SENDBUF_CAST#endif if (pt_TestAbort()) return bytes; /* * On pre-2.6 Solaris, send() is much slower than write(). * On 2.6 and beyond, with in-kernel sockets, send() and * write() are fairly equivalent in performance. */#if defined(SOLARIS) PR_ASSERT(0 == flags);retry: bytes = write(fd->secret->md.osfd, PT_SENDBUF_CAST buf, tmp_amount);#else bytes = send(fd->secret->md.osfd, PT_SENDBUF_CAST buf, amount, flags);#endif syserrno = errno;#if defined(SOLARIS) /* * The write system call has been reported to return the ERANGE error * on occasion. Try to write in smaller chunks to workaround this bug. */ if ((bytes == -1) && (syserrno == ERANGE)) { if (tmp_amount > 1) { tmp_amount = tmp_amount/2; /* half the bytes */ goto retry; } }#endif if ( (bytes >= 0) && (bytes < amount) && (!fd->secret->nonblocking) ) { if (PR_INTERVAL_NO_WAIT == timeout) { bytes = -1; syserrno = ETIMEDOUT; } else { buf = (char *) buf + bytes; amount -= bytes; fNeedContinue = PR_TRUE; } } if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) && (!fd->secret->nonblocking) ) { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else { bytes = 0; fNeedContinue = PR_TRUE; } } if (fNeedContinue == PR_TRUE) { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; op.arg4.flags = flags; op.timeout = timeout; op.result.code = bytes; /* initialize the number sent */ op.function = pt_send_cont; op.event = POLLOUT | POLLPRI; bytes = pt_Continue(&op); syserrno = op.syserrno; } if (bytes == -1) pt_MapError(_PR_MD_MAP_SEND_ERROR, syserrno); return bytes;} /* pt_Send */static PRInt32 pt_SocketWrite(PRFileDesc *fd, const void *buf, PRInt32 amount){ return pt_Send(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);} /* pt_SocketWrite */static PRInt32 pt_SendTo( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout){ PRInt32 syserrno, bytes = -1; PRBool fNeedContinue = PR_FALSE; 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 bytes; PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);#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; bytes = sendto( fd->secret->md.osfd, buf, amount, flags, (struct sockaddr*)&addrCopy, addr_len);#else bytes = sendto( fd->secret->md.osfd, buf, amount, flags, (struct sockaddr*)addrp, addr_len);#endif syserrno = errno; if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) && (!fd->secret->nonblocking) ) { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else fNeedContinue = PR_TRUE; } if (fNeedContinue == PR_TRUE) { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; op.arg4.flags = flags;#ifdef _PR_HAVE_SOCKADDR_LEN op.arg5.addr = (PRNetAddr*)&addrCopy;#else op.arg5.addr = (PRNetAddr*)addr;#endif op.timeout = timeout; op.result.code = 0; /* initialize the number sent */ op.function = pt_sendto_cont; op.event = POLLOUT | POLLPRI; bytes = pt_Continue(&op); syserrno = op.syserrno; } if (bytes < 0) pt_MapError(_PR_MD_MAP_SENDTO_ERROR, syserrno); return bytes;} /* pt_SendTo */static PRInt32 pt_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout){ PRBool fNeedContinue = PR_FALSE; PRInt32 syserrno, bytes = -1; pt_SockLen addr_len = sizeof(PRNetAddr); if (pt_TestAbort()) return bytes; bytes = recvfrom( fd->secret->md.osfd, buf, amount, flags, (struct sockaddr*)addr, &addr_len); syserrno = errno; if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) && (!fd->secret->nonblocking) ) { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else fNeedContinue = PR_TRUE; } if (fNeedContinue == PR_TRUE) { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = buf; op.arg3.amount = amount; op.arg4.flags = flags; op.arg5.addr = addr; op.timeout = timeout; op.function = pt_recvfrom_cont; op.event = POLLIN | POLLPRI; bytes = pt_Continue(&op); syserrno = op.syserrno; }#ifdef _PR_HAVE_SOCKADDR_LEN if (bytes >= 0) { /* 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 if (bytes < 0) pt_MapError(_PR_MD_MAP_RECVFROM_ERROR, syserrno); return bytes;} /* pt_RecvFrom */#ifdef AIX#ifndef HAVE_SEND_FILEstatic pthread_once_t pt_aix_sendfile_once_block = PTHREAD_ONCE_INIT;static void pt_aix_sendfile_init_routine(void){ void *handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); pt_aix_sendfile_fptr = (ssize_t (*)()) dlsym(handle, "send_file"); dlclose(handle);}/* * pt_AIXDispatchSendFile */static PRInt32 pt_AIXDispatchSendFile(PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout){ int rv; rv = pthread_once(&pt_aix_sendfile_once_block, pt_aix_sendfile_init_routine); PR_ASSERT(0 == rv); if (pt_aix_sendfile_fptr) { return pt_AIXSendFile(sd, sfd, flags, timeout); } else { return PR_EmulateSendFile(sd, sfd, flags, timeout); }}#endif /* !HAVE_SEND_FILE *//* * pt_AIXSendFile * * Send file sfd->fd across socket sd. If specified, header and trailer * buffers are sent before and after the file, respectively. * * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file * * return number of bytes sent or -1 on error * * This implementation takes advantage of the send_file() system * call available in AIX 4.3.2. */static PRInt32 pt_AIXSendFile(PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout){ struct sf_parms sf_struct; uint_t send_flags; ssize_t rv; int syserrno; PRInt32 count; unsigned long long saved_file_offset; long long saved_file_bytes; sf_struct.header_data = (void *) sfd->header; /* cast away the 'const' */ sf_struct.header_length = sfd->hlen; sf_struct.file_descriptor = sfd->fd->secret->md.osfd; sf_struct.file_size = 0; sf_struct.file_offset = sfd->file_offset; if (sfd->file_nbytes == 0) sf_struct.file_bytes = -1; else sf_struct.file_bytes = sfd->file_nbytes; sf_struct.trailer_data = (void *) sfd->trailer; sf_struct.trailer_length = sfd->tlen; sf_struct.bytes_sent = 0; saved_file_offset = sf_struct.file_offset; saved_file_bytes = sf_struct.file_bytes; send_flags = 0; /* flags processed at the end */ /* The first argument to send_file() is int*. */ PR_ASSERT(sizeof(int) == sizeof(sd->secret->md.osfd)); do { rv = AIX_SEND_FILE(&sd->secret->md.osfd, &sf_struct, send_flags); } while (rv == -1 && (syserrno = errno) == EINTR); if (rv == -1) { if (syserrno == EAGAIN || syserrno == EWOULDBLOCK) { count = 0; /* Not a real error. Need to continue. */ } else { count = -1; } } else { count = sf_struct.bytes_sent; /* * A bug in AIX 4.3.2 prevents the 'file_bytes' field from * being updated. So, 'file_bytes' is maintained by NSPR to * avoid conflict when this bug is fixed in AIX, in the future. */ if (saved_file_bytes != -1) saved_file_bytes -= (sf_struct.file_offset - saved_file_offset); sf_struct.file_bytes = saved_file_bytes; } if ((rv == 1) || ((rv == -1) && (count == 0))) { pt_Continuation op; op.arg1.osfd = sd->secret->md.osfd; op.arg2.buffer = &sf_struct; op.arg4.flags = send_flags; op.result.code = count; op.timeout = timeout; op.function = pt_aix_sendfile_cont; op.event = POLLOUT | POLLPRI; count = pt_Continue(&op); syserrno = op.syserrno; } if (count == -1) { pt_MapError(_MD_aix_map_sendfile_error, syserrno); return -1; } if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) { PR_Close(sd); } PR_ASSERT(count == (sfd->hlen + sfd->tlen + ((sfd->file_nbytes == 0) ? sf_struct.file_size - sfd->file_offset : sfd->file_nbytes))); return count;}#endif /* AIX */#ifdef HPUX11/* * pt_HPUXSendFile * * Send file sfd->fd across socket sd. If specified, header and trailer * buffers are sent before and after the file, respectively. * * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file * * return number of bytes sent or -1 on error * * This implementation takes advantage of the sendfile() system * call available in HP-UX B.11.00. */static PRInt32 pt_HPUXSendFile(PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout){ struct stat statbuf; size_t nbytes_to_send, file_nbytes_to_send; struct iovec hdtrl[2]; /* optional header and trailer buffers */ int send_flags; PRInt32 count; int syserrno; if (sfd->file_nbytes == 0) { /* Get file size */ if (fstat(sfd->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -