static PRInt32 PR_CALLBACK SocketRecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) { PRInt32 rv; PRUint32 al; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } al = sizeof(PRNetAddr); rv = _PR_MD_RECVFROM(fd, buf, amount, flags, addr, &al, timeout); #ifdef _PR_INET6 if (addr && (AF_INET6 == addr->raw.family)) addr->raw.family = PR_AF_INET6; #endif return rv; }
static PRInt32 PR_CALLBACK FileWrite(PRFileDesc *fd, const void *buf, PRInt32 amount) { PRInt32 rv = 0; PRInt32 temp, count; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); rv = -1; } if (rv != 0) return rv; count = 0; while (amount > 0) { temp = _PR_MD_WRITE(fd, buf, amount); if (temp < 0) { count = -1; break; } count += temp; if (fd->secret->nonblocking) { break; } buf = (const void*) ((const char*)buf + temp); amount -= temp; } PR_LOG(_pr_io_lm, PR_LOG_MAX, ("write -> %d", count)); return count; }
static PRInt32 PR_CALLBACK SocketAcceptRead(PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout) { PRInt32 rv; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } /* The socket must be in blocking mode. */ if (sd->secret->nonblocking) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } *nd = NULL; #if defined(WINNT) { PROsfd newSock; PRNetAddr *raddrCopy; if (raddr == NULL) { raddr = &raddrCopy; } rv = _PR_MD_ACCEPT_READ(sd, &newSock, raddr, buf, amount, timeout); if (rv < 0) { rv = -1; } else { /* Successfully accepted and read; create the new PRFileDesc */ *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods()); if (*nd == 0) { _PR_MD_CLOSE_SOCKET(newSock); /* PR_AllocFileDesc() has invoked PR_SetError(). */ rv = -1; } else { (*nd)->secret->md.io_model_committed = PR_TRUE; (*nd)->secret->md.accepted_socket = PR_TRUE; memcpy(&(*nd)->secret->md.peer_addr, *raddr, PR_NETADDR_SIZE(*raddr)); #ifdef _PR_INET6 if (AF_INET6 == *raddr->raw.family) *raddr->raw.family = PR_AF_INET6; #endif } } } #else rv = PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout); #endif return rv; }
PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead_WithTimeoutCallback( PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout, _PR_AcceptTimeoutCallback callback, void *callbackArg) { PRInt32 rv; PROsfd newSock; PRThread *me = _PR_MD_CURRENT_THREAD(); PRNetAddr *raddrCopy; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } *nd = NULL; if (raddr == NULL) { raddr = &raddrCopy; } rv = _PR_MD_FAST_ACCEPT_READ(sd, &newSock, raddr, buf, amount, timeout, PR_TRUE, callback, callbackArg); if (rv < 0) { rv = -1; } else { /* Successfully accepted and read; create the new PRFileDesc */ *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods()); if (*nd == 0) { _PR_MD_CLOSE_SOCKET(newSock); /* PR_AllocFileDesc() has invoked PR_SetError(). */ rv = -1; } else { (*nd)->secret->md.io_model_committed = PR_TRUE; (*nd)->secret->md.accepted_socket = PR_TRUE; memcpy(&(*nd)->secret->md.peer_addr, *raddr, PR_NETADDR_SIZE(*raddr)); #ifdef _PR_INET6 if (AF_INET6 == *raddr->raw.family) *raddr->raw.family = PR_AF_INET6; #endif #ifdef _PR_NEED_SECRET_AF (*nd)->secret->af = sd->secret->af; #endif } } return rv; }
static PRInt32 PR_CALLBACK SocketSendTo( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) { PRInt32 temp, count; const PRNetAddr *addrp = addr; #if defined(_PR_INET6) PRNetAddr addrCopy; #endif PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); #if defined(_PR_INET6) if (addr->raw.family == PR_AF_INET6) { addrCopy = *addr; addrCopy.raw.family = AF_INET6; addrp = &addrCopy; } #endif count = 0; while (amount > 0) { temp = _PR_MD_SENDTO(fd, buf, amount, flags, addrp, PR_NETADDR_SIZE(addr), timeout); if (temp < 0) { count = -1; break; } count += temp; if (fd->secret->nonblocking) { break; } buf = (const void*) ((const char*)buf + temp); amount -= temp; } return count; }
PR_IMPLEMENT(PRFileDesc*) PR_NTFast_Accept(PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) { PROsfd osfd; PRFileDesc *fd2; PRIntn al; PRThread *me = _PR_MD_CURRENT_THREAD(); PRNetAddr addrCopy; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return 0; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return 0; } if (addr == NULL) { addr = &addrCopy; } al = PR_NETADDR_SIZE(addr); osfd = _PR_MD_FAST_ACCEPT(fd, addr, &al, timeout, PR_TRUE, NULL, NULL); if (osfd == -1) { return 0; } fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods()); if (!fd2) { _PR_MD_CLOSE_SOCKET(osfd); } else { fd2->secret->nonblocking = fd->secret->nonblocking; fd2->secret->md.io_model_committed = PR_TRUE; PR_ASSERT(al == PR_NETADDR_SIZE(addr)); fd2->secret->md.accepted_socket = PR_TRUE; memcpy(&fd2->secret->md.peer_addr, addr, al); #ifdef _PR_INET6 if (AF_INET6 == addr->raw.family) addr->raw.family = PR_AF_INET6; #endif #ifdef _PR_NEED_SECRET_AF fd2->secret->af = fd->secret->af; #endif } return fd2; }
static PRInt32 PR_CALLBACK SocketTransmitFile(PRFileDesc *sd, PRFileDesc *fd, const void *headers, PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout) { PRInt32 rv; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } #if defined(WINNT) rv = _PR_MD_TRANSMITFILE( sd, fd, headers, hlen, flags, timeout); if (rv < 0) { rv = -1; } if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) { /* * This should be kept the same as SocketClose, except * that _PR_MD_CLOSE_SOCKET(sd->secret->md.osfd) should * not be called because the socket will be recycled. */ sd->secret->state = _PR_FILEDESC_CLOSED; PR_FreeFileDesc(sd); } #else #if defined(XP_UNIX) /* * On HPUX11, we could call _PR_HPUXTransmitFile(), but that * would require that we not override the malloc() functions. */ rv = _PR_UnixTransmitFile(sd, fd, headers, hlen, flags, timeout); #else /* XP_UNIX */ rv = _PR_EmulateTransmitFile(sd, fd, headers, hlen, flags, timeout); #endif /* XP_UNIX */ #endif /* WINNT */ return rv; }
static PRInt32 PR_CALLBACK SocketSend(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PRInt32 temp, count; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } count = 0; while (amount > 0) { PR_LOG(_pr_io_lm, PR_LOG_MAX, ("send: fd=%p osfd=%" PR_PRIdOSFD " buf=%p amount=%d", fd, fd->secret->md.osfd, buf, amount)); temp = _PR_MD_SEND(fd, buf, amount, flags, timeout); if (temp < 0) { count = -1; break; } count += temp; if (fd->secret->nonblocking) { break; } buf = (const void*) ((const char*)buf + temp); amount -= temp; } PR_LOG(_pr_io_lm, PR_LOG_MAX, ("send -> %d", count)); return count; }
static PRInt32 PR_CALLBACK SocketRecv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PRInt32 rv; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } PR_LOG(_pr_io_lm, PR_LOG_MAX, ("recv: fd=%p osfd=%d buf=%p amount=%d", fd, fd->secret->md.osfd, buf, amount)); rv = _PR_MD_RECV(fd, buf, amount, flags, timeout); PR_LOG(_pr_io_lm, PR_LOG_MAX, ("recv -> %d, error = %d, os error = %d", rv, PR_GetError(), PR_GetOSError())); return rv; }
static PRInt32 PR_CALLBACK SocketSendFile( PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { PRInt32 rv; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } /* The socket must be in blocking mode. */ if (sd->secret->nonblocking) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } #if defined(WINNT) rv = _PR_MD_SENDFILE(sd, sfd, flags, timeout); if ((rv >= 0) && (flags == PR_TRANSMITFILE_CLOSE_SOCKET)) { /* * This should be kept the same as SocketClose, except * that _PR_MD_CLOSE_SOCKET(sd->secret->md.osfd) should * not be called because the socket will be recycled. */ PR_FreeFileDesc(sd); } #else rv = PR_EmulateSendFile(sd, sfd, flags, timeout); #endif /* WINNT */ return rv; }
static PRInt32 PR_CALLBACK FileRead(PRFileDesc *fd, void *buf, PRInt32 amount) { PRInt32 rv = 0; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); rv = -1; } if (rv == -1) return rv; rv = _PR_MD_READ(fd, buf, amount); if (rv < 0) { PR_ASSERT(rv == -1); } PR_LOG(_pr_io_lm, PR_LOG_MAX, ("read -> %d", rv)); return rv; }
static PRInt32 PR_CALLBACK SocketWritev(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { PRThread *me = _PR_MD_CURRENT_THREAD(); int w = 0; const PRIOVec *tmp_iov; #define LOCAL_MAXIOV 8 PRIOVec local_iov[LOCAL_MAXIOV]; PRIOVec *iov_copy = NULL; int tmp_out; int index, iov_cnt; int count=0, sz = 0; /* 'count' is the return value. */ if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } /* * Assume the first writev will succeed. Copy iov's only on * failure. */ tmp_iov = iov; for (index = 0; index < iov_size; index++) sz += iov[index].iov_len; iov_cnt = iov_size; while (sz > 0) { w = _PR_MD_WRITEV(fd, tmp_iov, iov_cnt, timeout); if (w < 0) { count = -1; break; } count += w; if (fd->secret->nonblocking) { break; } sz -= w; if (sz > 0) { /* find the next unwritten vector */ for ( index = 0, tmp_out = count; tmp_out >= iov[index].iov_len; tmp_out -= iov[index].iov_len, index++){;} /* nothing to execute */ if (tmp_iov == iov) { /* * The first writev failed so we * must copy iov's around. * Avoid calloc/free if there * are few enough iov's. */ if (iov_size - index <= LOCAL_MAXIOV) iov_copy = local_iov; else if ((iov_copy = (PRIOVec *) PR_CALLOC((iov_size - index) * sizeof *iov_copy)) == NULL) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } tmp_iov = iov_copy; } PR_ASSERT(tmp_iov == iov_copy); /* fill in the first partial read */ iov_copy[0].iov_base = &(((char *)iov[index].iov_base)[tmp_out]); iov_copy[0].iov_len = iov[index].iov_len - tmp_out; index++; /* copy the remaining vectors */ for (iov_cnt=1; index<iov_size; iov_cnt++, index++) { iov_copy[iov_cnt].iov_base = iov[index].iov_base; iov_copy[iov_cnt].iov_len = iov[index].iov_len; } } } if (iov_copy != local_iov) PR_DELETE(iov_copy); return count; }
static PRInt32 PR_CALLBACK SocketRecv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PRInt32 rv; PRThread *me = _PR_MD_CURRENT_THREAD(); if ((flags != 0) && (flags != PR_MSG_PEEK)) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } PR_LOG(_pr_io_lm, PR_LOG_MAX, ("recv: fd=%p osfd=%" PR_PRIdOSFD " buf=%p amount=%d flags=%d", fd, fd->secret->md.osfd, buf, amount, flags)); #ifdef _PR_HAVE_PEEK_BUFFER if (fd->secret->peekBytes != 0) { rv = (amount < fd->secret->peekBytes) ? amount : fd->secret->peekBytes; memcpy(buf, fd->secret->peekBuffer, rv); if (flags == 0) { /* consume the bytes in the peek buffer */ fd->secret->peekBytes -= rv; if (fd->secret->peekBytes != 0) { memmove(fd->secret->peekBuffer, fd->secret->peekBuffer + rv, fd->secret->peekBytes); } } return rv; } /* allocate peek buffer, if necessary */ if ((PR_MSG_PEEK == flags) && _PR_FD_NEED_EMULATE_MSG_PEEK(fd)) { PR_ASSERT(0 == fd->secret->peekBytes); /* impose a max size on the peek buffer */ if (amount > _PR_PEEK_BUFFER_MAX) { amount = _PR_PEEK_BUFFER_MAX; } if (fd->secret->peekBufSize < amount) { if (fd->secret->peekBuffer) { PR_Free(fd->secret->peekBuffer); } fd->secret->peekBufSize = amount; fd->secret->peekBuffer = PR_Malloc(amount); if (NULL == fd->secret->peekBuffer) { fd->secret->peekBufSize = 0; PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } } } #endif rv = _PR_MD_RECV(fd, buf, amount, flags, timeout); PR_LOG(_pr_io_lm, PR_LOG_MAX, ("recv -> %d, error = %d, os error = %d", rv, PR_GetError(), PR_GetOSError())); #ifdef _PR_HAVE_PEEK_BUFFER if ((PR_MSG_PEEK == flags) && _PR_FD_NEED_EMULATE_MSG_PEEK(fd)) { if (rv > 0) { memcpy(fd->secret->peekBuffer, buf, rv); fd->secret->peekBytes = rv; } } #endif return rv; }
static PRFileDesc* PR_CALLBACK SocketAccept(PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) { PROsfd osfd; PRFileDesc *fd2; PRUint32 al; PRThread *me = _PR_MD_CURRENT_THREAD(); #ifdef WINNT PRNetAddr addrCopy; #endif if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return 0; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return 0; } #ifdef WINNT if (addr == NULL) { addr = &addrCopy; } #endif al = sizeof(PRNetAddr); osfd = _PR_MD_ACCEPT(fd, addr, &al, timeout); if (osfd == -1) return 0; fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods()); if (!fd2) { _PR_MD_CLOSE_SOCKET(osfd); return NULL; } fd2->secret->nonblocking = fd->secret->nonblocking; fd2->secret->inheritable = fd->secret->inheritable; #ifdef WINNT if (!fd2->secret->nonblocking && fd2->secret->inheritable != _PR_TRI_TRUE) { /* * The new socket has been associated with an I/O * completion port. There is no going back. */ fd2->secret->md.io_model_committed = PR_TRUE; } PR_ASSERT(al == PR_NETADDR_SIZE(addr)); fd2->secret->md.accepted_socket = PR_TRUE; memcpy(&fd2->secret->md.peer_addr, addr, al); #endif /* * On some platforms, the new socket created by accept() * inherits the nonblocking (or overlapped io) attribute * of the listening socket. As an optimization, these * platforms can skip the following _PR_MD_MAKE_NONBLOCK * call. */ #if !defined(SOLARIS) && !defined(IRIX) && !defined(WINNT) _PR_MD_MAKE_NONBLOCK(fd2); #endif #ifdef _PR_INET6 if (addr && (AF_INET6 == addr->raw.family)) addr->raw.family = PR_AF_INET6; #endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, al) == PR_TRUE); return fd2; }
static PRInt32 PR_CALLBACK SocketWritev(PRFileDesc *fd, PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { PRThread *me = _PR_MD_CURRENT_THREAD(); int w = 0; PRIOVec *tmp_iov = NULL; int tmp_out; int index, iov_cnt; int count=0, sz = 0; /* 'count' is the return value. */ #if defined(XP_UNIX) struct timeval tv, *tvp; fd_set wd; FD_ZERO(&wd); if (timeout == PR_INTERVAL_NO_TIMEOUT) tvp = NULL; else if (timeout != PR_INTERVAL_NO_WAIT) { tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; } #endif if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } tmp_iov = (PRIOVec *)PR_CALLOC(iov_size * sizeof(PRIOVec)); if (!tmp_iov) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } for (index=0; index<iov_size; index++) { sz += iov[index].iov_len; tmp_iov[index].iov_base = iov[index].iov_base; tmp_iov[index].iov_len = iov[index].iov_len; } iov_cnt = iov_size; while (sz > 0) { w = _PR_MD_WRITEV(fd, tmp_iov, iov_cnt, timeout); if (w < 0) { count = -1; break; } count += w; if (fd->secret->nonblocking) { break; } sz -= w; if (sz > 0) { /* find the next unwritten vector */ for ( index = 0, tmp_out = count; tmp_out >= iov[index].iov_len; tmp_out -= iov[index].iov_len, index++){;} /* nothing to execute */ /* fill in the first partial read */ tmp_iov[0].iov_base = &(((char *)iov[index].iov_base)[tmp_out]); tmp_iov[0].iov_len = iov[index].iov_len - tmp_out; index++; /* copy the remaining vectors */ for (iov_cnt=1; index<iov_size; iov_cnt++, index++) { tmp_iov[iov_cnt].iov_base = iov[index].iov_base; tmp_iov[iov_cnt].iov_len = iov[index].iov_len; } } } if (tmp_iov) PR_DELETE(tmp_iov); return count; }