Bug 387954 – fix NT version of PR_Accept on IPv6 listen socket. r=wtc

git-svn-id: svn://10.0.0.236/trunk@230916 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
nelson%bolyard.com 2007-07-25 06:45:08 +00:00
parent 95ba970f9d
commit d824c01c5c
6 changed files with 55 additions and 24 deletions

View File

@ -101,6 +101,7 @@ struct ip_mreq {
#define _PR_STAT_HAS_ONLY_ST_ATIME
#define _PR_NO_LARGE_FILES
#define _PR_STRICT_ADDR_LEN
#define _PR_NEED_SECRET_AF
/* IPv6 support */
#ifdef _SOCKADDR_LEN

View File

@ -124,6 +124,7 @@ struct _md_sockaddr_in6 {
#define _PR_PEEK_BUFFER_MAX (32 * 1024)
#define _PR_FD_NEED_EMULATE_MSG_PEEK(fd) \
(!(fd)->secret->nonblocking && (fd)->secret->inheritable != _PR_TRI_TRUE)
#define _PR_NEED_SECRET_AF
/* --- Common User-Thread/Native-Thread Definitions --------------------- */

View File

@ -1745,12 +1745,10 @@ struct PRFilePrivate {
* append mode. See Bugzilla 4090, 276330. */
#endif
_MDFileDesc md;
#ifdef _PR_STRICT_ADDR_LEN
PRUint16 af; /* If the platform requires passing the exact
* length of the sockaddr structure for the
* address family of the socket to socket
* functions like accept(), we need to save
* the address family of the socket. */
#ifdef _PR_NEED_SECRET_AF
PRUint16 af; /* If the platform's implementation of accept()
* requires knowing the address family of the
* socket, we save the address family here. */
#endif
};

View File

@ -199,6 +199,13 @@ PRFileDesc *fd;
if (fd != NULL) {
_PR_MD_MAKE_NONBLOCK(fd);
_PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
#ifdef _PR_NEED_SECRET_AF
/* this means we can only import IPv4 sockets here.
* but this is what the function in ptio.c does.
* We need a way to import IPv6 sockets, too.
*/
fd->secret->af = AF_INET;
#endif
} else
_PR_MD_CLOSE_SOCKET(osfd);
return(fd);
@ -513,6 +520,9 @@ PRIntervalTime timeout)
#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;
@ -943,6 +953,9 @@ PRIntervalTime timeout)
#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
}
}
@ -994,6 +1007,9 @@ void *callbackArg)
#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
}
}
@ -1324,6 +1340,9 @@ PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
fd = NULL;
}
}
#endif
#ifdef _PR_NEED_SECRET_AF
fd->secret->af = domain;
#endif
} else
_PR_MD_CLOSE_SOCKET(osfd);

View File

@ -64,8 +64,10 @@ static PRThread *_pr_io_completion_thread;
#define RECYCLE_SIZE 512
static struct _MDLock _pr_recycle_lock;
static PRInt32 _pr_recycle_array[RECYCLE_SIZE];
static PRInt32 _pr_recycle_tail = 0;
static PRInt32 _pr_recycle_INET_array[RECYCLE_SIZE];
static PRInt32 _pr_recycle_INET_tail = 0;
static PRInt32 _pr_recycle_INET6_array[RECYCLE_SIZE];
static PRInt32 _pr_recycle_INET6_tail = 0;
__declspec(thread) PRThread *_pr_io_restarted_io = NULL;
DWORD _pr_io_restartedIOIndex; /* The thread local storage slot for each
@ -965,15 +967,20 @@ _PR_MD_INIT_IO()
* second argument.
*/
static SOCKET
_md_get_recycled_socket()
_md_get_recycled_socket(int af)
{
SOCKET rv;
int af = AF_INET;
_MD_LOCK(&_pr_recycle_lock);
if (_pr_recycle_tail) {
_pr_recycle_tail--;
rv = _pr_recycle_array[_pr_recycle_tail];
if (af == AF_INET && _pr_recycle_INET_tail) {
_pr_recycle_INET_tail--;
rv = _pr_recycle_INET_array[_pr_recycle_INET_tail];
_MD_UNLOCK(&_pr_recycle_lock);
return rv;
}
if (af == AF_INET6 && _pr_recycle_INET6_tail) {
_pr_recycle_INET6_tail--;
rv = _pr_recycle_INET6_array[_pr_recycle_INET6_tail];
_MD_UNLOCK(&_pr_recycle_lock);
return rv;
}
@ -991,14 +998,19 @@ _md_get_recycled_socket()
* Add a socket to the recycle bin.
*/
static void
_md_put_recycled_socket(SOCKET newsock)
_md_put_recycled_socket(SOCKET newsock, int af)
{
PR_ASSERT(_pr_recycle_tail >= 0);
PR_ASSERT(_pr_recycle_INET_tail >= 0);
PR_ASSERT(_pr_recycle_INET6_tail >= 0);
_MD_LOCK(&_pr_recycle_lock);
if (_pr_recycle_tail < RECYCLE_SIZE) {
_pr_recycle_array[_pr_recycle_tail] = newsock;
_pr_recycle_tail++;
if (af == AF_INET && _pr_recycle_INET_tail < RECYCLE_SIZE) {
_pr_recycle_INET_array[_pr_recycle_INET_tail] = newsock;
_pr_recycle_INET_tail++;
_MD_UNLOCK(&_pr_recycle_lock);
} else if (af == AF_INET6 && _pr_recycle_INET6_tail < RECYCLE_SIZE) {
_pr_recycle_INET6_array[_pr_recycle_INET6_tail] = newsock;
_pr_recycle_INET6_tail++;
_MD_UNLOCK(&_pr_recycle_lock);
} else {
_MD_UNLOCK(&_pr_recycle_lock);
@ -1327,7 +1339,7 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
}
}
accept_sock = _md_get_recycled_socket();
accept_sock = _md_get_recycled_socket(fd->secret->af);
if (accept_sock == INVALID_SOCKET)
return -1;
@ -1357,7 +1369,7 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
&bytes,
&(me->md.overlapped.overlapped));
if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING)) {
if ( (rv == 0) && ((err = WSAGetLastError()) != ERROR_IO_PENDING)) {
/* Argh! The IO failed */
closesocket(accept_sock);
_PR_THREAD_LOCK(me);
@ -1450,7 +1462,7 @@ _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PROsfd *newSock, PRNetAddr **raddr,
sd->secret->md.io_model_committed = PR_TRUE;
}
*newSock = _md_get_recycled_socket();
*newSock = _md_get_recycled_socket(sd->secret->af);
if (*newSock == INVALID_SOCKET)
return -1;
@ -1700,7 +1712,7 @@ _PR_MD_SENDFILE(PRFileDesc *sock, PRSendFileData *sfd,
}
if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
_md_put_recycled_socket(sock->secret->md.osfd);
_md_put_recycled_socket(sock->secret->md.osfd, sock->secret->af);
}
PR_ASSERT(me->io_pending == PR_FALSE);

View File

@ -3465,7 +3465,7 @@ PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
fd = pt_SetMethods(osfd, ftype, PR_FALSE, PR_FALSE);
if (fd == NULL) close(osfd);
}
#ifdef _PR_STRICT_ADDR_LEN
#ifdef _PR_NEED_SECRET_AF
if (fd != NULL) fd->secret->af = domain;
#endif
#if defined(_PR_INET6_PROBE) || !defined(_PR_INET6)
@ -4456,7 +4456,7 @@ PR_IMPLEMENT(PRFileDesc*) PR_ImportTCPSocket(PRInt32 osfd)
if (!_pr_initialized) _PR_ImplicitInitialization();
fd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_FALSE, PR_TRUE);
if (NULL == fd) close(osfd);
#ifdef _PR_STRICT_ADDR_LEN
#ifdef _PR_NEED_SECRET_AF
if (NULL != fd) fd->secret->af = PF_INET;
#endif
return fd;