nsprpub/pr/src/io/prsocket.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "primpl.h"
     8 #include <string.h>
    10 /************************************************************************/
    12 /* These two functions are only used in assertions. */
    13 #if defined(DEBUG)
    15 PRBool IsValidNetAddr(const PRNetAddr *addr)
    16 {
    17     if ((addr != NULL)
    18 #if defined(XP_UNIX) || defined(XP_OS2)
    19 	    && (addr->raw.family != PR_AF_LOCAL)
    20 #endif
    21 	    && (addr->raw.family != PR_AF_INET6)
    22 	    && (addr->raw.family != PR_AF_INET)) {
    23         return PR_FALSE;
    24     }
    25     return PR_TRUE;
    26 }
    28 static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
    29 {
    30     /*
    31      * The definition of the length of a Unix domain socket address
    32      * is not uniform, so we don't check it.
    33      */
    34     if ((addr != NULL)
    35 #if defined(XP_UNIX) || defined(XP_OS2)
    36             && (addr->raw.family != AF_UNIX)
    37 #endif
    38             && (PR_NETADDR_SIZE(addr) != addr_len)) {
    39 #if defined(LINUX) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 1
    40         /*
    41          * In glibc 2.1, struct sockaddr_in6 is 24 bytes.  In glibc 2.2
    42          * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id
    43          * field and is 28 bytes.  It is possible for socket functions
    44          * to return an addr_len greater than sizeof(struct sockaddr_in6).
    45          * We need to allow that.  (Bugzilla bug #77264)
    46          */
    47         if ((PR_AF_INET6 == addr->raw.family)
    48                 && (sizeof(addr->ipv6) == addr_len)) {
    49             return PR_TRUE;
    50         }
    51 #endif
    52         /*
    53          * The accept(), getsockname(), etc. calls on some platforms
    54          * do not set the actual socket address length on return.
    55          * In this case, we verifiy addr_len is still the value we
    56          * passed in (i.e., sizeof(PRNetAddr)).
    57          */
    58 #if defined(QNX)
    59         if (sizeof(PRNetAddr) == addr_len) {
    60             return PR_TRUE;
    61         }
    62 #endif
    63         return PR_FALSE;
    64     }
    65     return PR_TRUE;
    66 }
    68 #endif /* DEBUG */
    70 static PRInt32 PR_CALLBACK SocketWritev(PRFileDesc *fd, const PRIOVec *iov,
    71 PRInt32 iov_size, PRIntervalTime timeout)
    72 {
    73 	PRThread *me = _PR_MD_CURRENT_THREAD();
    74 	int w = 0;
    75 	const PRIOVec *tmp_iov;
    76 #define LOCAL_MAXIOV    8
    77 	PRIOVec local_iov[LOCAL_MAXIOV];
    78 	PRIOVec *iov_copy = NULL;
    79 	int tmp_out;
    80 	int index, iov_cnt;
    81 	int count=0, sz = 0;    /* 'count' is the return value. */
    83 	if (_PR_PENDING_INTERRUPT(me)) {
    84 		me->flags &= ~_PR_INTERRUPT;
    85 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
    86 		return -1;
    87 	}
    88 	if (_PR_IO_PENDING(me)) {
    89 		PR_SetError(PR_IO_PENDING_ERROR, 0);
    90 		return -1;
    91 	}
    93     /*
    94      * Assume the first writev will succeed.  Copy iov's only on
    95      * failure.
    96      */
    97     tmp_iov = iov;
    98     for (index = 0; index < iov_size; index++)
    99         sz += iov[index].iov_len;
   101 	iov_cnt = iov_size;
   103 	while (sz > 0) {
   105 		w = _PR_MD_WRITEV(fd, tmp_iov, iov_cnt, timeout);
   106 		if (w < 0) {
   107 			count = -1;
   108 			break;
   109 		}
   110 		count += w;
   111 		if (fd->secret->nonblocking) {
   112 			break;
   113 		}
   114 		sz -= w;
   116 		if (sz > 0) {
   117 			/* find the next unwritten vector */
   118 			for ( index = 0, tmp_out = count;
   119 				tmp_out >= iov[index].iov_len;
   120 				tmp_out -= iov[index].iov_len, index++){;} /* nothing to execute */
   122 			if (tmp_iov == iov) {
   123 				/*
   124 				 * The first writev failed so we
   125 				 * must copy iov's around.
   126 				 * Avoid calloc/free if there
   127 				 * are few enough iov's.
   128 				 */
   129 				if (iov_size - index <= LOCAL_MAXIOV)
   130 					iov_copy = local_iov;
   131 				else if ((iov_copy = (PRIOVec *) PR_CALLOC((iov_size - index) *
   132 					sizeof *iov_copy)) == NULL) {
   133 					PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   134 					return -1;
   135 				}
   136 				tmp_iov = iov_copy;
   137 			}
   139 			PR_ASSERT(tmp_iov == iov_copy);
   141 			/* fill in the first partial read */
   142 			iov_copy[0].iov_base = &(((char *)iov[index].iov_base)[tmp_out]);
   143 			iov_copy[0].iov_len = iov[index].iov_len - tmp_out;
   144 			index++;
   146 			/* copy the remaining vectors */
   147 			for (iov_cnt=1; index<iov_size; iov_cnt++, index++) {
   148 				iov_copy[iov_cnt].iov_base = iov[index].iov_base;
   149 				iov_copy[iov_cnt].iov_len = iov[index].iov_len;
   150 			}
   151 		}
   152 	}
   154 	if (iov_copy != local_iov)
   155 		PR_DELETE(iov_copy);
   156 	return count;
   157 }
   159 /************************************************************************/
   161 PR_IMPLEMENT(PRFileDesc *) PR_ImportTCPSocket(PROsfd osfd)
   162 {
   163 PRFileDesc *fd;
   165 	if (!_pr_initialized) _PR_ImplicitInitialization();
   166 	fd = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
   167 	if (fd != NULL) {
   168 		_PR_MD_MAKE_NONBLOCK(fd);
   169 		_PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
   170 #ifdef _PR_NEED_SECRET_AF
   171 		/* this means we can only import IPv4 sockets here.
   172 		 * but this is what the function in ptio.c does.
   173 		 * We need a way to import IPv6 sockets, too.
   174 		 */
   175 		fd->secret->af = AF_INET;
   176 #endif
   177 	} else
   178 		_PR_MD_CLOSE_SOCKET(osfd);
   179 	return(fd);
   180 }
   182 PR_IMPLEMENT(PRFileDesc *) PR_ImportUDPSocket(PROsfd osfd)
   183 {
   184 PRFileDesc *fd;
   186 	if (!_pr_initialized) _PR_ImplicitInitialization();
   187 	fd = PR_AllocFileDesc(osfd, PR_GetUDPMethods());
   188 	if (fd != NULL) {
   189 		_PR_MD_MAKE_NONBLOCK(fd);
   190 		_PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
   191 	} else
   192 		_PR_MD_CLOSE_SOCKET(osfd);
   193 	return(fd);
   194 }
   197 static const PRIOMethods* PR_GetSocketPollFdMethods(void);
   199 PR_IMPLEMENT(PRFileDesc*) PR_CreateSocketPollFd(PROsfd osfd)
   200 {
   201     PRFileDesc *fd;
   203     if (!_pr_initialized) _PR_ImplicitInitialization();
   205     fd = _PR_Getfd();
   207     if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   208     else
   209     {
   210         fd->secret->md.osfd = osfd;
   211         fd->secret->inheritable = _PR_TRI_FALSE;
   212     	fd->secret->state = _PR_FILEDESC_OPEN;
   213         fd->methods = PR_GetSocketPollFdMethods();
   214     }
   216     return fd;
   217 }  /* PR_CreateSocketPollFD */
   219 PR_IMPLEMENT(PRStatus) PR_DestroySocketPollFd(PRFileDesc *fd)
   220 {
   221     if (NULL == fd)
   222     {
   223         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
   224         return PR_FAILURE;
   225     }
   226     fd->secret->state = _PR_FILEDESC_CLOSED;
   227     _PR_Putfd(fd);
   228     return PR_SUCCESS;
   229 }  /* PR_DestroySocketPollFd */
   231 static PRStatus PR_CALLBACK SocketConnect(
   232     PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
   233 {
   234 	PRInt32 rv;    /* Return value of _PR_MD_CONNECT */
   235     const PRNetAddr *addrp = addr;
   236 #if defined(_PR_INET6)
   237 	PRNetAddr addrCopy;
   238 #endif
   239 	PRThread *me = _PR_MD_CURRENT_THREAD();
   241 	if (_PR_PENDING_INTERRUPT(me)) {
   242 		me->flags &= ~_PR_INTERRUPT;
   243 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   244 		return PR_FAILURE;
   245 	}
   246 #if defined(_PR_INET6)
   247 	if (addr->raw.family == PR_AF_INET6) {
   248 		addrCopy = *addr;
   249 		addrCopy.raw.family = AF_INET6;
   250 		addrp = &addrCopy;
   251 	}
   252 #endif
   254 	rv = _PR_MD_CONNECT(fd, addrp, PR_NETADDR_SIZE(addr), timeout);
   255 	PR_LOG(_pr_io_lm, PR_LOG_MAX, ("connect -> %d", rv));
   256 	if (rv == 0)
   257 		return PR_SUCCESS;
   258 	else
   259 		return PR_FAILURE;
   260 }
   262 static PRStatus PR_CALLBACK SocketConnectContinue(
   263     PRFileDesc *fd, PRInt16 out_flags)
   264 {
   265     PROsfd osfd;
   266     int err;
   268     if (out_flags & PR_POLL_NVAL) {
   269         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
   270         return PR_FAILURE;
   271     }
   272     if ((out_flags & (PR_POLL_WRITE | PR_POLL_EXCEPT | PR_POLL_ERR)) == 0) {
   273         PR_ASSERT(out_flags == 0);
   274         PR_SetError(PR_IN_PROGRESS_ERROR, 0);
   275         return PR_FAILURE;
   276     }
   278     osfd = fd->secret->md.osfd;
   280 #if defined(XP_UNIX)
   282     err = _MD_unix_get_nonblocking_connect_error(osfd);
   283     if (err != 0) {
   284         _PR_MD_MAP_CONNECT_ERROR(err);
   285         return PR_FAILURE;
   286     }
   287     return PR_SUCCESS;
   289 #elif defined(WIN32) || defined(WIN16)
   291     if (out_flags & PR_POLL_EXCEPT) {
   292         int len = sizeof(err);
   293         if (getsockopt(osfd, (int)SOL_SOCKET, SO_ERROR, (char *) &err, &len)
   294                 == SOCKET_ERROR) {
   295             _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
   296             return PR_FAILURE;
   297         }
   298         if (err != 0) {
   299             _PR_MD_MAP_CONNECT_ERROR(err);
   300         } else {
   301             PR_SetError(PR_UNKNOWN_ERROR, 0);
   302         }
   303         return PR_FAILURE;
   304     }
   306     PR_ASSERT(out_flags & PR_POLL_WRITE);
   307     return PR_SUCCESS;
   309 #elif defined(XP_OS2)
   311     err = _MD_os2_get_nonblocking_connect_error(osfd);
   312     if (err != 0) {
   313         _PR_MD_MAP_CONNECT_ERROR(err);
   314         return PR_FAILURE;
   315     }
   316     return PR_SUCCESS;
   318 #elif defined(XP_BEOS)
   320 #ifdef BONE_VERSION  /* bug 122364 */
   321     /* temporary workaround until getsockopt(SO_ERROR) works in BONE */
   322     if (out_flags & PR_POLL_EXCEPT) {
   323         PR_SetError(PR_CONNECT_REFUSED_ERROR, 0);
   324         return PR_FAILURE;
   325     }
   326     PR_ASSERT(out_flags & PR_POLL_WRITE);
   327     return PR_SUCCESS;
   328 #else
   329     err = _MD_beos_get_nonblocking_connect_error(fd);
   330     if( err != 0 ) {
   331         _PR_MD_MAP_CONNECT_ERROR(err);
   332         return PR_FAILURE;
   333     }
   334     else
   335         return PR_SUCCESS;
   336 #endif /* BONE_VERSION */
   338 #else
   339     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
   340     return PR_FAILURE;
   341 #endif
   342 }
   344 PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd)
   345 {
   346     /* Find the NSPR layer and invoke its connectcontinue method */
   347     PRFileDesc *bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
   349     if (NULL == bottom) {
   350         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
   351         return PR_FAILURE;
   352     }
   353     return SocketConnectContinue(bottom, pd->out_flags);
   354 }
   356 static PRFileDesc* PR_CALLBACK SocketAccept(PRFileDesc *fd, PRNetAddr *addr,
   357 PRIntervalTime timeout)
   358 {
   359 	PROsfd osfd;
   360 	PRFileDesc *fd2;
   361 	PRUint32 al;
   362 	PRThread *me = _PR_MD_CURRENT_THREAD();
   363 #ifdef WINNT
   364 	PRNetAddr addrCopy;
   365 #endif
   367 	if (_PR_PENDING_INTERRUPT(me)) {
   368 		me->flags &= ~_PR_INTERRUPT;
   369 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   370 		return 0;
   371 	}
   372 	if (_PR_IO_PENDING(me)) {
   373 		PR_SetError(PR_IO_PENDING_ERROR, 0);
   374 		return 0;
   375 	}
   377 #ifdef WINNT
   378 	if (addr == NULL) {
   379 		addr = &addrCopy;
   380 	}
   381 #endif
   382 	al = sizeof(PRNetAddr);
   383 	osfd = _PR_MD_ACCEPT(fd, addr, &al, timeout);
   384 	if (osfd == -1)
   385 		return 0;
   387 	fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
   388 	if (!fd2) {
   389 		_PR_MD_CLOSE_SOCKET(osfd);
   390 		return NULL;
   391 	}
   393 	fd2->secret->nonblocking = fd->secret->nonblocking;
   394 	fd2->secret->inheritable = fd->secret->inheritable;
   395 #ifdef WINNT
   396 	if (!fd2->secret->nonblocking && fd2->secret->inheritable != _PR_TRI_TRUE) {
   397 		/*
   398 		 * The new socket has been associated with an I/O
   399 		 * completion port.  There is no going back.
   400 		 */
   401 		fd2->secret->md.io_model_committed = PR_TRUE;
   402 	}
   403 	PR_ASSERT(al == PR_NETADDR_SIZE(addr));
   404 	fd2->secret->md.accepted_socket = PR_TRUE;
   405 	memcpy(&fd2->secret->md.peer_addr, addr, al);
   406 #endif
   408 	/*
   409 	 * On some platforms, the new socket created by accept()
   410 	 * inherits the nonblocking (or overlapped io) attribute
   411 	 * of the listening socket.  As an optimization, these
   412 	 * platforms can skip the following _PR_MD_MAKE_NONBLOCK
   413 	 * call.
   414 	 */
   415 #if !defined(SOLARIS) && !defined(IRIX) && !defined(WINNT)
   416 	_PR_MD_MAKE_NONBLOCK(fd2);
   417 #endif
   419 #ifdef _PR_INET6
   420 	if (addr && (AF_INET6 == addr->raw.family))
   421         addr->raw.family = PR_AF_INET6;
   422 #endif
   423 	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
   424 	PR_ASSERT(IsValidNetAddrLen(addr, al) == PR_TRUE);
   426 	return fd2;
   427 }
   429 #ifdef WINNT
   430 PR_IMPLEMENT(PRFileDesc*) PR_NTFast_Accept(PRFileDesc *fd, PRNetAddr *addr,
   431 PRIntervalTime timeout)
   432 {
   433 	PROsfd osfd;
   434 	PRFileDesc *fd2;
   435 	PRIntn al;
   436 	PRThread *me = _PR_MD_CURRENT_THREAD();
   437 	PRNetAddr addrCopy;
   439 	if (_PR_PENDING_INTERRUPT(me)) {
   440 		me->flags &= ~_PR_INTERRUPT;
   441 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   442 		return 0;
   443 	}
   444 	if (_PR_IO_PENDING(me)) {
   445 		PR_SetError(PR_IO_PENDING_ERROR, 0);
   446 		return 0;
   447 	}
   449 		if (addr == NULL) {
   450 			addr = &addrCopy;
   451 		}
   452 		al = PR_NETADDR_SIZE(addr);
   453 		osfd = _PR_MD_FAST_ACCEPT(fd, addr, &al, timeout, PR_TRUE, NULL, NULL);
   454 		if (osfd == -1) {
   455 			return 0;
   456 		}
   458 	fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
   459 	if (!fd2) {
   460 		_PR_MD_CLOSE_SOCKET(osfd);
   461 	} else {
   462 		fd2->secret->nonblocking = fd->secret->nonblocking;
   463 		fd2->secret->md.io_model_committed = PR_TRUE;
   464 	        PR_ASSERT(al == PR_NETADDR_SIZE(addr));
   465         	fd2->secret->md.accepted_socket = PR_TRUE;
   466         	memcpy(&fd2->secret->md.peer_addr, addr, al);
   467 #ifdef _PR_INET6
   468 		if (AF_INET6 == addr->raw.family)
   469         	addr->raw.family = PR_AF_INET6;
   470 #endif
   471 #ifdef _PR_NEED_SECRET_AF
   472 		fd2->secret->af = fd->secret->af;
   473 #endif
   474 	}
   475 	return fd2;
   476 }
   477 #endif /* WINNT */
   480 static PRStatus PR_CALLBACK SocketBind(PRFileDesc *fd, const PRNetAddr *addr)
   481 {
   482 	PRInt32 result;
   483     const PRNetAddr *addrp = addr;
   484 #if defined(_PR_INET6)
   485 	PRNetAddr addrCopy;
   486 #endif
   488 	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
   490 #ifdef XP_UNIX
   491 	if (addr->raw.family == AF_UNIX) {
   492 		/* Disallow relative pathnames */
   493 		if (addr->local.path[0] != '/') {
   494 			PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
   495 			return PR_FAILURE;
   496 		}
   497 	}
   498 #endif /* XP_UNIX */
   500 #if defined(_PR_INET6)
   501 	if (addr->raw.family == PR_AF_INET6) {
   502 		addrCopy = *addr;
   503 		addrCopy.raw.family = AF_INET6;
   504 		addrp = &addrCopy;
   505 	}
   506 #endif
   507 	result = _PR_MD_BIND(fd, addrp, PR_NETADDR_SIZE(addr));
   508 	if (result < 0) {
   509 		return PR_FAILURE;
   510 	}
   511 	return PR_SUCCESS;
   512 }
   514 static PRStatus PR_CALLBACK SocketListen(PRFileDesc *fd, PRIntn backlog)
   515 {
   516 	PRInt32 result;
   518 	result = _PR_MD_LISTEN(fd, backlog);
   519 	if (result < 0) {
   520 		return PR_FAILURE;
   521 	}
   522 	return PR_SUCCESS;
   523 }
   525 static PRStatus PR_CALLBACK SocketShutdown(PRFileDesc *fd, PRIntn how)
   526 {
   527 	PRInt32 result;
   529 	result = _PR_MD_SHUTDOWN(fd, how);
   530 	if (result < 0) {
   531 		return PR_FAILURE;
   532 	}
   533 	return PR_SUCCESS;
   534 }
   536 static PRInt32 PR_CALLBACK SocketRecv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
   537 PRIntervalTime timeout)
   538 {
   539 	PRInt32 rv;
   540 	PRThread *me = _PR_MD_CURRENT_THREAD();
   542 	if ((flags != 0) && (flags != PR_MSG_PEEK)) {
   543 		PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
   544 		return -1;
   545 	}
   546 	if (_PR_PENDING_INTERRUPT(me)) {
   547 		me->flags &= ~_PR_INTERRUPT;
   548 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   549 		return -1;
   550 	}
   551 	if (_PR_IO_PENDING(me)) {
   552 		PR_SetError(PR_IO_PENDING_ERROR, 0);
   553 		return -1;
   554 	}
   556 	PR_LOG(_pr_io_lm, PR_LOG_MAX,
   557 		("recv: fd=%p osfd=%" PR_PRIdOSFD " buf=%p amount=%d flags=%d",
   558 		fd, fd->secret->md.osfd, buf, amount, flags));
   560 #ifdef _PR_HAVE_PEEK_BUFFER
   561 	if (fd->secret->peekBytes != 0) {
   562 		rv = (amount < fd->secret->peekBytes) ?
   563 			amount : fd->secret->peekBytes;
   564 		memcpy(buf, fd->secret->peekBuffer, rv);
   565 		if (flags == 0) {
   566 			/* consume the bytes in the peek buffer */
   567 			fd->secret->peekBytes -= rv;
   568 			if (fd->secret->peekBytes != 0) {
   569 				memmove(fd->secret->peekBuffer,
   570 					fd->secret->peekBuffer + rv,
   571 					fd->secret->peekBytes);
   572 			}
   573 		}
   574 		return rv;
   575 	}
   577 	/* allocate peek buffer, if necessary */
   578 	if ((PR_MSG_PEEK == flags) && _PR_FD_NEED_EMULATE_MSG_PEEK(fd)) {
   579 		PR_ASSERT(0 == fd->secret->peekBytes);
   580 		/* impose a max size on the peek buffer */
   581 		if (amount > _PR_PEEK_BUFFER_MAX) {
   582 			amount = _PR_PEEK_BUFFER_MAX;
   583 		}
   584 		if (fd->secret->peekBufSize < amount) {
   585 			if (fd->secret->peekBuffer) {
   586 				PR_Free(fd->secret->peekBuffer);
   587 			}
   588 			fd->secret->peekBufSize = amount;
   589 			fd->secret->peekBuffer = PR_Malloc(amount);
   590 			if (NULL == fd->secret->peekBuffer) {
   591 				fd->secret->peekBufSize = 0;
   592 				PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
   593 				return -1;
   594 			}
   595 		}
   596 	}
   597 #endif
   599 	rv = _PR_MD_RECV(fd, buf, amount, flags, timeout);
   600 	PR_LOG(_pr_io_lm, PR_LOG_MAX, ("recv -> %d, error = %d, os error = %d",
   601 		rv, PR_GetError(), PR_GetOSError()));
   603 #ifdef _PR_HAVE_PEEK_BUFFER
   604 	if ((PR_MSG_PEEK == flags) && _PR_FD_NEED_EMULATE_MSG_PEEK(fd)) {
   605 		if (rv > 0) {
   606 			memcpy(fd->secret->peekBuffer, buf, rv);
   607 			fd->secret->peekBytes = rv;
   608 		}
   609 	}
   610 #endif
   612 	return rv;
   613 }
   615 static PRInt32 PR_CALLBACK SocketRead(PRFileDesc *fd, void *buf, PRInt32 amount)
   616 {
   617 	return SocketRecv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
   618 }
   620 static PRInt32 PR_CALLBACK SocketSend(PRFileDesc *fd, const void *buf, PRInt32 amount,
   621 PRIntn flags, PRIntervalTime timeout)
   622 {
   623 	PRInt32 temp, count;
   624 	PRThread *me = _PR_MD_CURRENT_THREAD();
   626 	if (_PR_PENDING_INTERRUPT(me)) {
   627 		me->flags &= ~_PR_INTERRUPT;
   628 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   629 		return -1;
   630 	}
   631 	if (_PR_IO_PENDING(me)) {
   632 		PR_SetError(PR_IO_PENDING_ERROR, 0);
   633 		return -1;
   634 	}
   636 	count = 0;
   637 	while (amount > 0) {
   638 		PR_LOG(_pr_io_lm, PR_LOG_MAX,
   639 		    ("send: fd=%p osfd=%" PR_PRIdOSFD " buf=%p amount=%d",
   640 		    fd, fd->secret->md.osfd, buf, amount));
   641 		temp = _PR_MD_SEND(fd, buf, amount, flags, timeout);
   642 		if (temp < 0) {
   643 					count = -1;
   644 					break;
   645 				}
   647 		count += temp;
   648 		if (fd->secret->nonblocking) {
   649 			break;
   650 		}
   651 		buf = (const void*) ((const char*)buf + temp);
   653 		amount -= temp;
   654 	}
   655 	PR_LOG(_pr_io_lm, PR_LOG_MAX, ("send -> %d", count));
   656 	return count;
   657 }
   659 static PRInt32 PR_CALLBACK SocketWrite(PRFileDesc *fd, const void *buf, PRInt32 amount)
   660 {
   661 	return SocketSend(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
   662 }
   664 static PRStatus PR_CALLBACK SocketClose(PRFileDesc *fd)
   665 {
   666 	if (!fd || !fd->secret
   667 			|| (fd->secret->state != _PR_FILEDESC_OPEN
   668 			&& fd->secret->state != _PR_FILEDESC_CLOSED)) {
   669 		PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
   670 		return PR_FAILURE;
   671 	}
   673 	if (fd->secret->state == _PR_FILEDESC_OPEN) {
   674 		if (_PR_MD_CLOSE_SOCKET(fd->secret->md.osfd) < 0) {
   675 			return PR_FAILURE;
   676 		}
   677 		fd->secret->state = _PR_FILEDESC_CLOSED;
   678 	}
   680 #ifdef _PR_HAVE_PEEK_BUFFER
   681 	if (fd->secret->peekBuffer) {
   682 		PR_ASSERT(fd->secret->peekBufSize > 0);
   683 		PR_DELETE(fd->secret->peekBuffer);
   684 		fd->secret->peekBufSize = 0;
   685 		fd->secret->peekBytes = 0;
   686 	}
   687 #endif
   689 	PR_FreeFileDesc(fd);
   690 	return PR_SUCCESS;
   691 }
   693 static PRInt32 PR_CALLBACK SocketAvailable(PRFileDesc *fd)
   694 {
   695 	PRInt32 rv;
   696 #ifdef _PR_HAVE_PEEK_BUFFER
   697 	if (fd->secret->peekBytes != 0) {
   698 		return fd->secret->peekBytes;
   699 	}
   700 #endif
   701 	rv =  _PR_MD_SOCKETAVAILABLE(fd);
   702 	return rv;		
   703 }
   705 static PRInt64 PR_CALLBACK SocketAvailable64(PRFileDesc *fd)
   706 {
   707     PRInt64 rv;
   708 #ifdef _PR_HAVE_PEEK_BUFFER
   709     if (fd->secret->peekBytes != 0) {
   710         LL_I2L(rv, fd->secret->peekBytes);
   711         return rv;
   712     }
   713 #endif
   714     LL_I2L(rv, _PR_MD_SOCKETAVAILABLE(fd));
   715 	return rv;		
   716 }
   718 static PRStatus PR_CALLBACK SocketSync(PRFileDesc *fd)
   719 {
   720 	return PR_SUCCESS;
   721 }
   723 static PRInt32 PR_CALLBACK SocketSendTo(
   724     PRFileDesc *fd, const void *buf, PRInt32 amount,
   725     PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout)
   726 {
   727 	PRInt32 temp, count;
   728     const PRNetAddr *addrp = addr;
   729 #if defined(_PR_INET6)
   730 	PRNetAddr addrCopy;
   731 #endif
   732 	PRThread *me = _PR_MD_CURRENT_THREAD();
   734 	if (_PR_PENDING_INTERRUPT(me)) {
   735 		me->flags &= ~_PR_INTERRUPT;
   736 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   737 		return -1;
   738 	}
   739 	if (_PR_IO_PENDING(me)) {
   740 		PR_SetError(PR_IO_PENDING_ERROR, 0);
   741 		return -1;
   742 	}
   744 	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
   745 #if defined(_PR_INET6)
   746 	if (addr->raw.family == PR_AF_INET6) {
   747 		addrCopy = *addr;
   748 		addrCopy.raw.family = AF_INET6;
   749 		addrp = &addrCopy;
   750 	}
   751 #endif
   753 	count = 0;
   754 	while (amount > 0) {
   755 		temp = _PR_MD_SENDTO(fd, buf, amount, flags,
   756 		    addrp, PR_NETADDR_SIZE(addr), timeout);
   757 		if (temp < 0) {
   758 					count = -1;
   759 					break;
   760 				}
   761 		count += temp;
   762 		if (fd->secret->nonblocking) {
   763 			break;
   764 		}
   765 		buf = (const void*) ((const char*)buf + temp);
   766 		amount -= temp;
   767 	}
   768 	return count;
   769 }
   771 static PRInt32 PR_CALLBACK SocketRecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount,
   772 PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
   773 {
   774 	PRInt32 rv;
   775 	PRUint32 al;
   776 	PRThread *me = _PR_MD_CURRENT_THREAD();
   778 	if (_PR_PENDING_INTERRUPT(me)) {
   779 		me->flags &= ~_PR_INTERRUPT;
   780 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   781 		return -1;
   782 	}
   783 	if (_PR_IO_PENDING(me)) {
   784 		PR_SetError(PR_IO_PENDING_ERROR, 0);
   785 		return -1;
   786 	}
   788 	al = sizeof(PRNetAddr);
   789 	rv = _PR_MD_RECVFROM(fd, buf, amount, flags, addr, &al, timeout);
   790 #ifdef _PR_INET6
   791 	if (addr && (AF_INET6 == addr->raw.family))
   792         addr->raw.family = PR_AF_INET6;
   793 #endif
   794 	return rv;
   795 }
   797 static PRInt32 PR_CALLBACK SocketAcceptRead(PRFileDesc *sd, PRFileDesc **nd, 
   798 PRNetAddr **raddr, void *buf, PRInt32 amount,
   799 PRIntervalTime timeout)
   800 {
   801 	PRInt32 rv;
   802 	PRThread *me = _PR_MD_CURRENT_THREAD();
   804 	if (_PR_PENDING_INTERRUPT(me)) {
   805 		me->flags &= ~_PR_INTERRUPT;
   806 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   807 		return -1;
   808 	}
   809 	if (_PR_IO_PENDING(me)) {
   810 		PR_SetError(PR_IO_PENDING_ERROR, 0);
   811 		return -1;
   812 	}
   813 	/* The socket must be in blocking mode. */
   814 	if (sd->secret->nonblocking) {
   815 		PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
   816 		return -1;
   817 	}
   818 	*nd = NULL;
   820 #if defined(WINNT)
   821 	{
   822 	PROsfd newSock;
   823 	PRNetAddr *raddrCopy;
   825 	if (raddr == NULL) {
   826 		raddr = &raddrCopy;
   827 	}
   828 	rv = _PR_MD_ACCEPT_READ(sd, &newSock, raddr, buf, amount, timeout);
   829 	if (rv < 0) {
   830 		rv = -1;
   831 	} else {
   832 		/* Successfully accepted and read; create the new PRFileDesc */
   833 		*nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods());
   834 		if (*nd == 0) {
   835 			_PR_MD_CLOSE_SOCKET(newSock);
   836 			/* PR_AllocFileDesc() has invoked PR_SetError(). */
   837 			rv = -1;
   838 		} else {
   839 			(*nd)->secret->md.io_model_committed = PR_TRUE;
   840 			(*nd)->secret->md.accepted_socket = PR_TRUE;
   841 			memcpy(&(*nd)->secret->md.peer_addr, *raddr,
   842 				PR_NETADDR_SIZE(*raddr));
   843 #ifdef _PR_INET6
   844 			if (AF_INET6 == *raddr->raw.family)
   845         		*raddr->raw.family = PR_AF_INET6;
   846 #endif
   847 		}
   848 	}
   849 	}
   850 #else
   851 	rv = PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout);
   852 #endif
   853 	return rv;
   854 }
   856 #ifdef WINNT
   857 PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead(PRFileDesc *sd, PRFileDesc **nd, 
   858 PRNetAddr **raddr, void *buf, PRInt32 amount,
   859 PRIntervalTime timeout)
   860 {
   861 	PRInt32 rv;
   862 	PROsfd newSock;
   863 	PRThread *me = _PR_MD_CURRENT_THREAD();
   864 	PRNetAddr *raddrCopy;
   866 	if (_PR_PENDING_INTERRUPT(me)) {
   867 		me->flags &= ~_PR_INTERRUPT;
   868 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   869 		return -1;
   870 	}
   871 	if (_PR_IO_PENDING(me)) {
   872 		PR_SetError(PR_IO_PENDING_ERROR, 0);
   873 		return -1;
   874 	}
   875 	*nd = NULL;
   877 	if (raddr == NULL) {
   878 		raddr = &raddrCopy;
   879 	}
   880 	rv = _PR_MD_FAST_ACCEPT_READ(sd, &newSock, raddr, buf, amount, 
   881 	    timeout, PR_TRUE, NULL, NULL);
   882 	if (rv < 0) {
   883 		rv = -1;
   884 	} else {
   885 		/* Successfully accepted and read; create the new PRFileDesc */
   886 		*nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods());
   887 		if (*nd == 0) {
   888 			_PR_MD_CLOSE_SOCKET(newSock);
   889 			/* PR_AllocFileDesc() has invoked PR_SetError(). */
   890 			rv = -1;
   891 		} else {
   892 			(*nd)->secret->md.io_model_committed = PR_TRUE;
   893 			(*nd)->secret->md.accepted_socket = PR_TRUE;
   894 			memcpy(&(*nd)->secret->md.peer_addr, *raddr,
   895 				PR_NETADDR_SIZE(*raddr));
   896 #ifdef _PR_INET6
   897 			if (AF_INET6 == *raddr->raw.family)
   898         		*raddr->raw.family = PR_AF_INET6;
   899 #endif
   900 #ifdef _PR_NEED_SECRET_AF
   901 			(*nd)->secret->af = sd->secret->af;
   902 #endif
   903 		}
   904 	}
   905 	return rv;
   906 }
   908 PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead_WithTimeoutCallback(
   909 PRFileDesc *sd, PRFileDesc **nd, 
   910 PRNetAddr **raddr, void *buf, PRInt32 amount,
   911 PRIntervalTime timeout,
   912 _PR_AcceptTimeoutCallback callback,
   913 void *callbackArg)
   914 {
   915 	PRInt32 rv;
   916 	PROsfd newSock;
   917 	PRThread *me = _PR_MD_CURRENT_THREAD();
   918 	PRNetAddr *raddrCopy;
   920 	if (_PR_PENDING_INTERRUPT(me)) {
   921 		me->flags &= ~_PR_INTERRUPT;
   922 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   923 		return -1;
   924 	}
   925 	if (_PR_IO_PENDING(me)) {
   926 		PR_SetError(PR_IO_PENDING_ERROR, 0);
   927 		return -1;
   928 	}
   929 	*nd = NULL;
   931 	if (raddr == NULL) {
   932 		raddr = &raddrCopy;
   933 	}
   934 	rv = _PR_MD_FAST_ACCEPT_READ(sd, &newSock, raddr, buf, amount,
   935 	    timeout, PR_TRUE, callback, callbackArg);
   936 	if (rv < 0) {
   937 		rv = -1;
   938 	} else {
   939 		/* Successfully accepted and read; create the new PRFileDesc */
   940 		*nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods());
   941 		if (*nd == 0) {
   942 			_PR_MD_CLOSE_SOCKET(newSock);
   943 			/* PR_AllocFileDesc() has invoked PR_SetError(). */
   944 			rv = -1;
   945 		} else {
   946 			(*nd)->secret->md.io_model_committed = PR_TRUE;
   947 			(*nd)->secret->md.accepted_socket = PR_TRUE;
   948 			memcpy(&(*nd)->secret->md.peer_addr, *raddr,
   949 				PR_NETADDR_SIZE(*raddr));
   950 #ifdef _PR_INET6
   951 			if (AF_INET6 == *raddr->raw.family)
   952         		*raddr->raw.family = PR_AF_INET6;
   953 #endif
   954 #ifdef _PR_NEED_SECRET_AF
   955 			(*nd)->secret->af = sd->secret->af;
   956 #endif
   957 		}
   958 	}
   959 	return rv;
   960 }
   961 #endif /* WINNT */
   963 #ifdef WINNT
   964 PR_IMPLEMENT(void)
   965 PR_NTFast_UpdateAcceptContext(PRFileDesc *socket, PRFileDesc *acceptSocket)
   966 {
   967 	_PR_MD_UPDATE_ACCEPT_CONTEXT(
   968 		socket->secret->md.osfd, acceptSocket->secret->md.osfd);
   969 }
   970 #endif /* WINNT */
   972 static PRInt32 PR_CALLBACK SocketSendFile(
   973     PRFileDesc *sd, PRSendFileData *sfd,
   974     PRTransmitFileFlags flags, PRIntervalTime timeout)
   975 {
   976 	PRInt32 rv;
   977 	PRThread *me = _PR_MD_CURRENT_THREAD();
   979 	if (_PR_PENDING_INTERRUPT(me)) {
   980 		me->flags &= ~_PR_INTERRUPT;
   981 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   982 		return -1;
   983 	}
   984 	if (_PR_IO_PENDING(me)) {
   985 		PR_SetError(PR_IO_PENDING_ERROR, 0);
   986 		return -1;
   987 	}
   988 	/* The socket must be in blocking mode. */
   989 	if (sd->secret->nonblocking) {
   990 		PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
   991 		return -1;
   992 	}
   993 #if defined(WINNT)
   994 	rv = _PR_MD_SENDFILE(sd, sfd, flags, timeout);
   995 	if ((rv >= 0) && (flags == PR_TRANSMITFILE_CLOSE_SOCKET)) {
   996 		/*
   997 		 * This should be kept the same as SocketClose, except
   998 		 * that _PR_MD_CLOSE_SOCKET(sd->secret->md.osfd) should
   999 		 * not be called because the socket will be recycled.
  1000 		 */
  1001 		PR_FreeFileDesc(sd);
  1003 #else
  1004 	rv = PR_EmulateSendFile(sd, sfd, flags, timeout);
  1005 #endif	/* WINNT */
  1007 	return rv;
  1010 static PRInt32 PR_CALLBACK SocketTransmitFile(PRFileDesc *sd, PRFileDesc *fd, 
  1011 const void *headers, PRInt32 hlen, PRTransmitFileFlags flags,
  1012 PRIntervalTime timeout)
  1014 	PRSendFileData sfd;
  1016 	sfd.fd = fd;
  1017 	sfd.file_offset = 0;
  1018 	sfd.file_nbytes = 0;
  1019 	sfd.header = headers;
  1020 	sfd.hlen = hlen;
  1021 	sfd.trailer = NULL;
  1022 	sfd.tlen = 0;
  1024 	return(SocketSendFile(sd, &sfd, flags, timeout));
  1027 static PRStatus PR_CALLBACK SocketGetName(PRFileDesc *fd, PRNetAddr *addr)
  1029 	PRInt32 result;
  1030 	PRUint32 addrlen;
  1032 	addrlen = sizeof(PRNetAddr);
  1033 	result = _PR_MD_GETSOCKNAME(fd, addr, &addrlen);
  1034 	if (result < 0) {
  1035 		return PR_FAILURE;
  1037 #ifdef _PR_INET6
  1038 	if (AF_INET6 == addr->raw.family)
  1039         addr->raw.family = PR_AF_INET6;
  1040 #endif
  1041 	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
  1042 	PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE);
  1043 	return PR_SUCCESS;
  1046 static PRStatus PR_CALLBACK SocketGetPeerName(PRFileDesc *fd, PRNetAddr *addr)
  1048 	PRInt32 result;
  1049 	PRUint32 addrlen;
  1051 	addrlen = sizeof(PRNetAddr);
  1052 	result = _PR_MD_GETPEERNAME(fd, addr, &addrlen);
  1053 	if (result < 0) {
  1054 		return PR_FAILURE;
  1056 #ifdef _PR_INET6
  1057 	if (AF_INET6 == addr->raw.family)
  1058         addr->raw.family = PR_AF_INET6;
  1059 #endif
  1060 	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
  1061 	PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE);
  1062 	return PR_SUCCESS;
  1065 static PRInt16 PR_CALLBACK SocketPoll(
  1066     PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
  1068     *out_flags = 0;
  1069     return in_flags;
  1070 }  /* SocketPoll */
  1072 static PRIOMethods tcpMethods = {
  1073 	PR_DESC_SOCKET_TCP,
  1074 	SocketClose,
  1075 	SocketRead,
  1076 	SocketWrite,
  1077 	SocketAvailable,
  1078 	SocketAvailable64,
  1079 	SocketSync,
  1080 	(PRSeekFN)_PR_InvalidInt,
  1081 	(PRSeek64FN)_PR_InvalidInt64,
  1082 	(PRFileInfoFN)_PR_InvalidStatus,
  1083 	(PRFileInfo64FN)_PR_InvalidStatus,
  1084 	SocketWritev,
  1085 	SocketConnect,
  1086 	SocketAccept,
  1087 	SocketBind,
  1088 	SocketListen,
  1089 	SocketShutdown,
  1090 	SocketRecv,
  1091 	SocketSend,
  1092 	(PRRecvfromFN)_PR_InvalidInt,
  1093 	(PRSendtoFN)_PR_InvalidInt,
  1094 	SocketPoll,
  1095 	SocketAcceptRead,
  1096 	SocketTransmitFile,
  1097 	SocketGetName,
  1098 	SocketGetPeerName,
  1099 	(PRReservedFN)_PR_InvalidInt,
  1100 	(PRReservedFN)_PR_InvalidInt,
  1101 	_PR_SocketGetSocketOption,
  1102 	_PR_SocketSetSocketOption,
  1103     SocketSendFile, 
  1104     SocketConnectContinue,
  1105     (PRReservedFN)_PR_InvalidInt, 
  1106     (PRReservedFN)_PR_InvalidInt, 
  1107     (PRReservedFN)_PR_InvalidInt, 
  1108     (PRReservedFN)_PR_InvalidInt
  1109 };
  1111 static PRIOMethods udpMethods = {
  1112 	PR_DESC_SOCKET_UDP,
  1113 	SocketClose,
  1114 	SocketRead,
  1115 	SocketWrite,
  1116 	SocketAvailable,
  1117 	SocketAvailable64,
  1118 	SocketSync,
  1119 	(PRSeekFN)_PR_InvalidInt,
  1120 	(PRSeek64FN)_PR_InvalidInt64,
  1121 	(PRFileInfoFN)_PR_InvalidStatus,
  1122 	(PRFileInfo64FN)_PR_InvalidStatus,
  1123 	SocketWritev,
  1124 	SocketConnect,
  1125 	(PRAcceptFN)_PR_InvalidDesc,
  1126 	SocketBind,
  1127 	SocketListen,
  1128 	SocketShutdown,
  1129 	SocketRecv,
  1130 	SocketSend,
  1131 	SocketRecvFrom,
  1132 	SocketSendTo,
  1133 	SocketPoll,
  1134 	(PRAcceptreadFN)_PR_InvalidInt,
  1135 	(PRTransmitfileFN)_PR_InvalidInt,
  1136 	SocketGetName,
  1137 	SocketGetPeerName,
  1138 	(PRReservedFN)_PR_InvalidInt,
  1139 	(PRReservedFN)_PR_InvalidInt,
  1140 	_PR_SocketGetSocketOption,
  1141 	_PR_SocketSetSocketOption,
  1142     (PRSendfileFN)_PR_InvalidInt, 
  1143     (PRConnectcontinueFN)_PR_InvalidStatus, 
  1144     (PRReservedFN)_PR_InvalidInt, 
  1145     (PRReservedFN)_PR_InvalidInt, 
  1146     (PRReservedFN)_PR_InvalidInt, 
  1147     (PRReservedFN)_PR_InvalidInt
  1148 };
  1151 static PRIOMethods socketpollfdMethods = {
  1152     (PRDescType) 0,
  1153     (PRCloseFN)_PR_InvalidStatus,
  1154     (PRReadFN)_PR_InvalidInt,
  1155     (PRWriteFN)_PR_InvalidInt,
  1156     (PRAvailableFN)_PR_InvalidInt,
  1157     (PRAvailable64FN)_PR_InvalidInt64,
  1158     (PRFsyncFN)_PR_InvalidStatus,
  1159     (PRSeekFN)_PR_InvalidInt,
  1160     (PRSeek64FN)_PR_InvalidInt64,
  1161     (PRFileInfoFN)_PR_InvalidStatus,
  1162     (PRFileInfo64FN)_PR_InvalidStatus,
  1163     (PRWritevFN)_PR_InvalidInt,        
  1164     (PRConnectFN)_PR_InvalidStatus,        
  1165     (PRAcceptFN)_PR_InvalidDesc,        
  1166     (PRBindFN)_PR_InvalidStatus,        
  1167     (PRListenFN)_PR_InvalidStatus,        
  1168     (PRShutdownFN)_PR_InvalidStatus,    
  1169     (PRRecvFN)_PR_InvalidInt,        
  1170     (PRSendFN)_PR_InvalidInt,        
  1171     (PRRecvfromFN)_PR_InvalidInt,    
  1172     (PRSendtoFN)_PR_InvalidInt,        
  1173 	SocketPoll,
  1174     (PRAcceptreadFN)_PR_InvalidInt,   
  1175     (PRTransmitfileFN)_PR_InvalidInt, 
  1176     (PRGetsocknameFN)_PR_InvalidStatus,    
  1177     (PRGetpeernameFN)_PR_InvalidStatus,    
  1178     (PRReservedFN)_PR_InvalidInt,    
  1179     (PRReservedFN)_PR_InvalidInt,    
  1180     (PRGetsocketoptionFN)_PR_InvalidStatus,
  1181     (PRSetsocketoptionFN)_PR_InvalidStatus,
  1182     (PRSendfileFN)_PR_InvalidInt, 
  1183     (PRConnectcontinueFN)_PR_InvalidStatus, 
  1184     (PRReservedFN)_PR_InvalidInt, 
  1185     (PRReservedFN)_PR_InvalidInt, 
  1186     (PRReservedFN)_PR_InvalidInt, 
  1187     (PRReservedFN)_PR_InvalidInt
  1188 };
  1190 PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods()
  1192 	return &tcpMethods;
  1195 PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods()
  1197 	return &udpMethods;
  1200 static const PRIOMethods* PR_GetSocketPollFdMethods()
  1202     return &socketpollfdMethods;
  1203 }  /* PR_GetSocketPollFdMethods */
  1205 #if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
  1206 PR_EXTERN(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd);
  1208 #if defined(_PR_INET6_PROBE)
  1210 extern PRBool _pr_ipv6_is_present(void);
  1212 PR_IMPLEMENT(PRBool) _pr_test_ipv6_socket()
  1214 	PROsfd osfd;
  1216 	osfd = _PR_MD_SOCKET(AF_INET6, SOCK_STREAM, 0);
  1217 	if (osfd != -1) {
  1218 		_PR_MD_CLOSE_SOCKET(osfd);
  1219 		return PR_TRUE;
  1221 	return PR_FALSE;
  1223 #endif	/* _PR_INET6_PROBE */
  1225 #endif
  1227 PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
  1229 	PROsfd osfd;
  1230 	PRFileDesc *fd;
  1231 	PRInt32 tmp_domain = domain;
  1233 	if (!_pr_initialized) _PR_ImplicitInitialization();
  1234 	if (PR_AF_INET != domain
  1235 			&& PR_AF_INET6 != domain
  1236 #if defined(XP_UNIX) || defined(XP_OS2)
  1237 			&& PR_AF_LOCAL != domain
  1238 #endif
  1239 			) {
  1240 		PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
  1241 		return NULL;
  1244 #if defined(_PR_INET6_PROBE)
  1245 	if (PR_AF_INET6 == domain)
  1246 		domain = _pr_ipv6_is_present() ? AF_INET6 : AF_INET;
  1247 #elif defined(_PR_INET6)
  1248 	if (PR_AF_INET6 == domain)
  1249 		domain = AF_INET6;
  1250 #else
  1251 	if (PR_AF_INET6 == domain)
  1252 		domain = AF_INET;
  1253 #endif	/* _PR_INET6 */
  1254 	osfd = _PR_MD_SOCKET(domain, type, proto);
  1255 	if (osfd == -1) {
  1256 		return 0;
  1258 	if (type == SOCK_STREAM)
  1259 		fd = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
  1260 	else
  1261 		fd = PR_AllocFileDesc(osfd, PR_GetUDPMethods());
  1262 	/*
  1263 	 * Make the sockets non-blocking
  1264 	 */
  1265 	if (fd != NULL) {
  1266 		_PR_MD_MAKE_NONBLOCK(fd);
  1267 		_PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE);
  1268 #ifdef _PR_NEED_SECRET_AF
  1269 		fd->secret->af = domain;
  1270 #endif
  1271 #if defined(_PR_INET6_PROBE) || !defined(_PR_INET6)
  1272 		/*
  1273 		 * For platforms with no support for IPv6 
  1274 		 * create layered socket for IPv4-mapped IPv6 addresses
  1275 		 */
  1276 		if (PR_AF_INET6 == tmp_domain && PR_AF_INET == domain) {
  1277 			if (PR_FAILURE == _pr_push_ipv6toipv4_layer(fd)) {
  1278 				PR_Close(fd);
  1279 				fd = NULL;
  1282 #endif
  1283 	} else
  1284 		_PR_MD_CLOSE_SOCKET(osfd);
  1286 	return fd;
  1289 PR_IMPLEMENT(PRFileDesc *) PR_NewTCPSocket(void)
  1291 	PRInt32 domain = AF_INET;
  1293 	return PR_Socket(domain, SOCK_STREAM, 0);
  1296 PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket(void)
  1298 	PRInt32 domain = AF_INET;
  1300 	return PR_Socket(domain, SOCK_DGRAM, 0);
  1303 PR_IMPLEMENT(PRFileDesc *) PR_OpenTCPSocket(PRIntn af)
  1305 	return PR_Socket(af, SOCK_STREAM, 0);
  1308 PR_IMPLEMENT(PRFileDesc*) PR_OpenUDPSocket(PRIntn af)
  1310 	return PR_Socket(af, SOCK_DGRAM, 0);
  1313 PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *f[])
  1315 #ifdef XP_UNIX
  1316 	PRInt32 rv, osfd[2];
  1318 	if (!_pr_initialized) _PR_ImplicitInitialization();
  1320 	rv = _PR_MD_SOCKETPAIR(AF_UNIX, SOCK_STREAM, 0, osfd);
  1321 	if (rv == -1) {
  1322 		return PR_FAILURE;
  1325 	f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods());
  1326 	if (!f[0]) {
  1327 		_PR_MD_CLOSE_SOCKET(osfd[0]);
  1328 		_PR_MD_CLOSE_SOCKET(osfd[1]);
  1329 		/* PR_AllocFileDesc() has invoked PR_SetError(). */
  1330 		return PR_FAILURE;
  1332 	f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods());
  1333 	if (!f[1]) {
  1334 		PR_Close(f[0]);
  1335 		_PR_MD_CLOSE_SOCKET(osfd[1]);
  1336 		/* PR_AllocFileDesc() has invoked PR_SetError(). */
  1337 		return PR_FAILURE;
  1339 	_PR_MD_MAKE_NONBLOCK(f[0]);
  1340 	_PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE);
  1341 	_PR_MD_MAKE_NONBLOCK(f[1]);
  1342 	_PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE);
  1343 	return PR_SUCCESS;
  1344 #elif defined(WINNT)
  1345     /*
  1346      * A socket pair is often used for interprocess communication,
  1347      * so we need to make sure neither socket is associated with
  1348      * the I/O completion port; otherwise it can't be used by a
  1349      * child process.
  1351      * The default implementation below cannot be used for NT
  1352      * because PR_Accept would have associated the I/O completion
  1353      * port with the listening and accepted sockets.
  1354      */
  1355     SOCKET listenSock;
  1356     SOCKET osfd[2];
  1357     struct sockaddr_in selfAddr, peerAddr;
  1358     int addrLen;
  1360     if (!_pr_initialized) _PR_ImplicitInitialization();
  1362     osfd[0] = osfd[1] = INVALID_SOCKET;
  1363     listenSock = socket(AF_INET, SOCK_STREAM, 0);
  1364     if (listenSock == INVALID_SOCKET) {
  1365         goto failed;
  1367     selfAddr.sin_family = AF_INET;
  1368     selfAddr.sin_port = 0;
  1369     selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* BugZilla: 35408 */
  1370     addrLen = sizeof(selfAddr);
  1371     if (bind(listenSock, (struct sockaddr *) &selfAddr,
  1372             addrLen) == SOCKET_ERROR) {
  1373         goto failed;
  1375     if (getsockname(listenSock, (struct sockaddr *) &selfAddr,
  1376             &addrLen) == SOCKET_ERROR) {
  1377         goto failed;
  1379     if (listen(listenSock, 5) == SOCKET_ERROR) {
  1380         goto failed;
  1382     osfd[0] = socket(AF_INET, SOCK_STREAM, 0);
  1383     if (osfd[0] == INVALID_SOCKET) {
  1384         goto failed;
  1386     selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  1388     /*
  1389      * Only a thread is used to do the connect and accept.
  1390      * I am relying on the fact that connect returns
  1391      * successfully as soon as the connect request is put
  1392      * into the listen queue (but before accept is called).
  1393      * This is the behavior of the BSD socket code.  If
  1394      * connect does not return until accept is called, we
  1395      * will need to create another thread to call connect.
  1396      */
  1397     if (connect(osfd[0], (struct sockaddr *) &selfAddr,
  1398             addrLen) == SOCKET_ERROR) {
  1399         goto failed;
  1401     /*
  1402      * A malicious local process may connect to the listening
  1403      * socket, so we need to verify that the accepted connection
  1404      * is made from our own socket osfd[0].
  1405      */
  1406     if (getsockname(osfd[0], (struct sockaddr *) &selfAddr,
  1407             &addrLen) == SOCKET_ERROR) {
  1408         goto failed;
  1410     osfd[1] = accept(listenSock, (struct sockaddr *) &peerAddr, &addrLen);
  1411     if (osfd[1] == INVALID_SOCKET) {
  1412         goto failed;
  1414     if (peerAddr.sin_port != selfAddr.sin_port) {
  1415         /* the connection we accepted is not from osfd[0] */
  1416         PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
  1417         goto failed;
  1419     closesocket(listenSock);
  1421     f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods());
  1422     if (!f[0]) {
  1423         closesocket(osfd[0]);
  1424         closesocket(osfd[1]);
  1425         /* PR_AllocFileDesc() has invoked PR_SetError(). */
  1426         return PR_FAILURE;
  1428     f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods());
  1429     if (!f[1]) {
  1430         PR_Close(f[0]);
  1431         closesocket(osfd[1]);
  1432         /* PR_AllocFileDesc() has invoked PR_SetError(). */
  1433         return PR_FAILURE;
  1435     _PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE);
  1436     _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE);
  1437     return PR_SUCCESS;
  1439 failed:
  1440     if (listenSock != INVALID_SOCKET) {
  1441         closesocket(listenSock);
  1443     if (osfd[0] != INVALID_SOCKET) {
  1444         closesocket(osfd[0]);
  1446     if (osfd[1] != INVALID_SOCKET) {
  1447         closesocket(osfd[1]);
  1449     return PR_FAILURE;
  1450 #else /* not Unix or NT */
  1451     /*
  1452      * default implementation
  1453      */
  1454     PRFileDesc *listenSock;
  1455     PRNetAddr selfAddr, peerAddr;
  1456     PRUint16 port;
  1458     f[0] = f[1] = NULL;
  1459     listenSock = PR_NewTCPSocket();
  1460     if (listenSock == NULL) {
  1461         goto failed;
  1463     PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); /* BugZilla: 35408 */
  1464     if (PR_Bind(listenSock, &selfAddr) == PR_FAILURE) {
  1465         goto failed;
  1467     if (PR_GetSockName(listenSock, &selfAddr) == PR_FAILURE) {
  1468         goto failed;
  1470     port = ntohs(selfAddr.inet.port);
  1471     if (PR_Listen(listenSock, 5) == PR_FAILURE) {
  1472         goto failed;
  1474     f[0] = PR_NewTCPSocket();
  1475     if (f[0] == NULL) {
  1476         goto failed;
  1478 #ifdef _PR_CONNECT_DOES_NOT_BIND
  1479     /*
  1480      * If connect does not implicitly bind the socket (e.g., on
  1481      * BeOS), we have to bind the socket so that we can get its
  1482      * port with getsockname later.
  1483      */
  1484     PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr);
  1485     if (PR_Bind(f[0], &selfAddr) == PR_FAILURE) {
  1486         goto failed;
  1488 #endif
  1489     PR_InitializeNetAddr(PR_IpAddrLoopback, port, &selfAddr);
  1491     /*
  1492      * Only a thread is used to do the connect and accept.
  1493      * I am relying on the fact that PR_Connect returns
  1494      * successfully as soon as the connect request is put
  1495      * into the listen queue (but before PR_Accept is called).
  1496      * This is the behavior of the BSD socket code.  If
  1497      * connect does not return until accept is called, we
  1498      * will need to create another thread to call connect.
  1499      */
  1500     if (PR_Connect(f[0], &selfAddr, PR_INTERVAL_NO_TIMEOUT)
  1501             == PR_FAILURE) {
  1502         goto failed;
  1504     /*
  1505      * A malicious local process may connect to the listening
  1506      * socket, so we need to verify that the accepted connection
  1507      * is made from our own socket f[0].
  1508      */
  1509     if (PR_GetSockName(f[0], &selfAddr) == PR_FAILURE) {
  1510         goto failed;
  1512     f[1] = PR_Accept(listenSock, &peerAddr, PR_INTERVAL_NO_TIMEOUT);
  1513     if (f[1] == NULL) {
  1514         goto failed;
  1516     if (peerAddr.inet.port != selfAddr.inet.port) {
  1517         /* the connection we accepted is not from f[0] */
  1518         PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
  1519         goto failed;
  1521     PR_Close(listenSock);
  1522     return PR_SUCCESS;
  1524 failed:
  1525     if (listenSock) {
  1526         PR_Close(listenSock);
  1528     if (f[0]) {
  1529         PR_Close(f[0]);
  1531     if (f[1]) {
  1532         PR_Close(f[1]);
  1534     return PR_FAILURE;
  1535 #endif
  1538 PR_IMPLEMENT(PROsfd)
  1539 PR_FileDesc2NativeHandle(PRFileDesc *fd)
  1541     if (fd) {
  1542         fd = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER);
  1544     if (!fd) {
  1545         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  1546         return -1;
  1548     return fd->secret->md.osfd;
  1551 PR_IMPLEMENT(void)
  1552 PR_ChangeFileDescNativeHandle(PRFileDesc *fd, PROsfd handle)
  1554 	if (fd)
  1555 		fd->secret->md.osfd = handle;
  1558 /*
  1559 ** Select compatibility
  1560 **
  1561 */
  1563 PR_IMPLEMENT(void) PR_FD_ZERO(PR_fd_set *set)
  1565 	memset(set, 0, sizeof(PR_fd_set));
  1568 PR_IMPLEMENT(void) PR_FD_SET(PRFileDesc *fh, PR_fd_set *set)
  1570 	PR_ASSERT( set->hsize < PR_MAX_SELECT_DESC );
  1572 	set->harray[set->hsize++] = fh;
  1575 PR_IMPLEMENT(void) PR_FD_CLR(PRFileDesc *fh, PR_fd_set *set)
  1577 	PRUint32 index, index2;
  1579 	for (index = 0; index<set->hsize; index++)
  1580 		if (set->harray[index] == fh) {
  1581 			for (index2=index; index2 < (set->hsize-1); index2++) {
  1582 				set->harray[index2] = set->harray[index2+1];
  1584 			set->hsize--;
  1585 			break;
  1589 PR_IMPLEMENT(PRInt32) PR_FD_ISSET(PRFileDesc *fh, PR_fd_set *set)
  1591 	PRUint32 index;
  1592 	for (index = 0; index<set->hsize; index++)
  1593 		if (set->harray[index] == fh) {
  1594 			return 1;
  1596 	return 0;
  1599 PR_IMPLEMENT(void) PR_FD_NSET(PROsfd fd, PR_fd_set *set)
  1601 	PR_ASSERT( set->nsize < PR_MAX_SELECT_DESC );
  1603 	set->narray[set->nsize++] = fd;
  1606 PR_IMPLEMENT(void) PR_FD_NCLR(PROsfd fd, PR_fd_set *set)
  1608 	PRUint32 index, index2;
  1610 	for (index = 0; index<set->nsize; index++)
  1611 		if (set->narray[index] == fd) {
  1612 			for (index2=index; index2 < (set->nsize-1); index2++) {
  1613 				set->narray[index2] = set->narray[index2+1];
  1615 			set->nsize--;
  1616 			break;
  1620 PR_IMPLEMENT(PRInt32) PR_FD_NISSET(PROsfd fd, PR_fd_set *set)
  1622 	PRUint32 index;
  1623 	for (index = 0; index<set->nsize; index++)
  1624 		if (set->narray[index] == fd) {
  1625 			return 1;
  1627 	return 0;
  1631 #if !defined(NEED_SELECT)
  1632 #include "obsolete/probslet.h"
  1634 #define PD_INCR 20
  1636 static PRPollDesc *_pr_setfd(
  1637     PR_fd_set *set, PRInt16 flags, PRPollDesc *polldesc)
  1639     PRUintn fsidx, pdidx;
  1640     PRPollDesc *poll = polldesc;
  1642     if (NULL == set) return poll;
  1644 	/* First set the pr file handle osfds */
  1645 	for (fsidx = 0; fsidx < set->hsize; fsidx++)
  1647 	    for (pdidx = 0; 1; pdidx++)
  1649             if ((PRFileDesc*)-1 == poll[pdidx].fd)
  1651                 /* our vector is full - extend and condition it */
  1652                 poll = (PRPollDesc*)PR_Realloc(
  1653                     poll, (pdidx + 1 + PD_INCR) * sizeof(PRPollDesc));
  1654                 if (NULL == poll) goto out_of_memory;
  1655                 memset(
  1656                     poll + pdidx * sizeof(PRPollDesc),
  1657                     0, PD_INCR * sizeof(PRPollDesc));
  1658                 poll[pdidx + PD_INCR].fd = (PRFileDesc*)-1;
  1660             if ((NULL == poll[pdidx].fd)
  1661             || (poll[pdidx].fd == set->harray[fsidx]))
  1663                 /* PR_ASSERT(0 == (poll[pdidx].in_flags & flags)); */
  1664                 /* either empty or prevously defined */
  1665                 poll[pdidx].fd = set->harray[fsidx];  /* possibly redundant */
  1666                 poll[pdidx].in_flags |= flags;  /* possibly redundant */
  1667                 break;
  1672 #if 0
  1673 	/* Second set the native osfds */
  1674 	for (fsidx = 0; fsidx < set->nsize; fsidx++)
  1676 	    for (pdidx = 0; ((PRFileDesc*)-1 != poll[pdidx].fd); pdidx++)
  1678             if ((PRFileDesc*)-1 == poll[pdidx].fd)
  1680                 /* our vector is full - extend and condition it */
  1681                 poll = PR_Realloc(
  1682                     poll, (pdidx + PD_INCR) * sizeof(PRPollDesc));
  1683                 if (NULL == poll) goto out_of_memory;
  1684                 memset(
  1685                     poll + pdidx * sizeof(PRPollDesc),
  1686                     0, PD_INCR * sizeof(PRPollDesc));
  1687                 poll[(pdidx + PD_INCR)].fd = (PRFileDesc*)-1;
  1689             if ((NULL == poll[pdidx].fd)
  1690             || (poll[pdidx].fd == set->narray[fsidx]))
  1692                 /* either empty or prevously defined */
  1693                 poll[pdidx].fd = set->narray[fsidx];
  1694                 PR_ASSERT(0 == (poll[pdidx].in_flags & flags));
  1695                 poll[pdidx].in_flags |= flags;
  1696                 break;
  1700 #endif /* 0 */
  1702 	return poll;
  1704 out_of_memory:
  1705     if (NULL != polldesc) PR_DELETE(polldesc);
  1706     return NULL;
  1707 }  /* _pr_setfd */
  1709 #endif /* !defined(NEED_SELECT) */
  1711 PR_IMPLEMENT(PRInt32) PR_Select(
  1712     PRInt32 unused, PR_fd_set *pr_rd, PR_fd_set *pr_wr, 
  1713     PR_fd_set *pr_ex, PRIntervalTime timeout)
  1716 #if !defined(NEED_SELECT)
  1717     PRInt32 npds = 0; 
  1718     /*
  1719     ** Find out how many fds are represented in the three lists.
  1720     ** Then allocate a polling descriptor for the logical union
  1721     ** (there can't be any overlapping) and call PR_Poll().
  1722     */
  1724     PRPollDesc *copy, *poll;
  1726     static PRBool warning = PR_TRUE;
  1727     if (warning) warning = _PR_Obsolete( "PR_Select()", "PR_Poll()");
  1729     /* try to get an initial guesss at how much space we need */
  1730     npds = 0;
  1731     if ((NULL != pr_rd) && ((pr_rd->hsize + pr_rd->nsize - npds) > 0))
  1732         npds = pr_rd->hsize + pr_rd->nsize;
  1733     if ((NULL != pr_wr) && ((pr_wr->hsize + pr_wr->nsize - npds) > 0))
  1734         npds = pr_wr->hsize + pr_wr->nsize;
  1735     if ((NULL != pr_ex) && ((pr_ex->hsize + pr_ex->nsize - npds) > 0))
  1736         npds = pr_ex->hsize + pr_ex->nsize;
  1738     if (0 == npds)
  1740         PR_Sleep(timeout);
  1741         return 0;
  1744     copy = poll = (PRPollDesc*)PR_Calloc(npds + PD_INCR, sizeof(PRPollDesc));
  1745     if (NULL == poll) goto out_of_memory;
  1746     poll[npds + PD_INCR - 1].fd = (PRFileDesc*)-1;
  1748     poll = _pr_setfd(pr_rd, PR_POLL_READ, poll);
  1749     if (NULL == poll) goto out_of_memory;
  1750     poll = _pr_setfd(pr_wr, PR_POLL_WRITE, poll);
  1751     if (NULL == poll) goto out_of_memory;
  1752     poll = _pr_setfd(pr_ex, PR_POLL_EXCEPT, poll);
  1753     if (NULL == poll) goto out_of_memory;
  1754     unused = 0;
  1755     while (NULL != poll[unused].fd && (PRFileDesc*)-1 != poll[unused].fd)
  1757         ++unused;
  1760     PR_ASSERT(unused > 0);
  1761     npds = PR_Poll(poll, unused, timeout);
  1763     if (npds > 0)
  1765         /* Copy the results back into the fd sets */
  1766         if (NULL != pr_rd) pr_rd->nsize = pr_rd->hsize = 0;
  1767         if (NULL != pr_wr) pr_wr->nsize = pr_wr->hsize = 0;
  1768         if (NULL != pr_ex) pr_ex->nsize = pr_ex->hsize = 0;
  1769         for (copy = &poll[unused - 1]; copy >= poll; --copy)
  1771             if (copy->out_flags & PR_POLL_NVAL)
  1773                 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
  1774                 npds = -1;
  1775                 break;
  1777             if (copy->out_flags & PR_POLL_READ)
  1778                 if (NULL != pr_rd) pr_rd->harray[pr_rd->hsize++] = copy->fd;
  1779             if (copy->out_flags & PR_POLL_WRITE)
  1780                 if (NULL != pr_wr) pr_wr->harray[pr_wr->hsize++] = copy->fd;
  1781             if (copy->out_flags & PR_POLL_EXCEPT)
  1782                 if (NULL != pr_ex) pr_ex->harray[pr_ex->hsize++] = copy->fd;
  1785     PR_DELETE(poll);
  1787     return npds;
  1788 out_of_memory:
  1789     PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
  1790     return -1;    
  1792 #endif /* !defined(NEED_SELECT) */

mercurial