1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/src/io/prsocket.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1794 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "primpl.h" 1.10 + 1.11 +#include <string.h> 1.12 + 1.13 +/************************************************************************/ 1.14 + 1.15 +/* These two functions are only used in assertions. */ 1.16 +#if defined(DEBUG) 1.17 + 1.18 +PRBool IsValidNetAddr(const PRNetAddr *addr) 1.19 +{ 1.20 + if ((addr != NULL) 1.21 +#if defined(XP_UNIX) || defined(XP_OS2) 1.22 + && (addr->raw.family != PR_AF_LOCAL) 1.23 +#endif 1.24 + && (addr->raw.family != PR_AF_INET6) 1.25 + && (addr->raw.family != PR_AF_INET)) { 1.26 + return PR_FALSE; 1.27 + } 1.28 + return PR_TRUE; 1.29 +} 1.30 + 1.31 +static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len) 1.32 +{ 1.33 + /* 1.34 + * The definition of the length of a Unix domain socket address 1.35 + * is not uniform, so we don't check it. 1.36 + */ 1.37 + if ((addr != NULL) 1.38 +#if defined(XP_UNIX) || defined(XP_OS2) 1.39 + && (addr->raw.family != AF_UNIX) 1.40 +#endif 1.41 + && (PR_NETADDR_SIZE(addr) != addr_len)) { 1.42 +#if defined(LINUX) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 1 1.43 + /* 1.44 + * In glibc 2.1, struct sockaddr_in6 is 24 bytes. In glibc 2.2 1.45 + * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id 1.46 + * field and is 28 bytes. It is possible for socket functions 1.47 + * to return an addr_len greater than sizeof(struct sockaddr_in6). 1.48 + * We need to allow that. (Bugzilla bug #77264) 1.49 + */ 1.50 + if ((PR_AF_INET6 == addr->raw.family) 1.51 + && (sizeof(addr->ipv6) == addr_len)) { 1.52 + return PR_TRUE; 1.53 + } 1.54 +#endif 1.55 + /* 1.56 + * The accept(), getsockname(), etc. calls on some platforms 1.57 + * do not set the actual socket address length on return. 1.58 + * In this case, we verifiy addr_len is still the value we 1.59 + * passed in (i.e., sizeof(PRNetAddr)). 1.60 + */ 1.61 +#if defined(QNX) 1.62 + if (sizeof(PRNetAddr) == addr_len) { 1.63 + return PR_TRUE; 1.64 + } 1.65 +#endif 1.66 + return PR_FALSE; 1.67 + } 1.68 + return PR_TRUE; 1.69 +} 1.70 + 1.71 +#endif /* DEBUG */ 1.72 + 1.73 +static PRInt32 PR_CALLBACK SocketWritev(PRFileDesc *fd, const PRIOVec *iov, 1.74 +PRInt32 iov_size, PRIntervalTime timeout) 1.75 +{ 1.76 + PRThread *me = _PR_MD_CURRENT_THREAD(); 1.77 + int w = 0; 1.78 + const PRIOVec *tmp_iov; 1.79 +#define LOCAL_MAXIOV 8 1.80 + PRIOVec local_iov[LOCAL_MAXIOV]; 1.81 + PRIOVec *iov_copy = NULL; 1.82 + int tmp_out; 1.83 + int index, iov_cnt; 1.84 + int count=0, sz = 0; /* 'count' is the return value. */ 1.85 + 1.86 + if (_PR_PENDING_INTERRUPT(me)) { 1.87 + me->flags &= ~_PR_INTERRUPT; 1.88 + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1.89 + return -1; 1.90 + } 1.91 + if (_PR_IO_PENDING(me)) { 1.92 + PR_SetError(PR_IO_PENDING_ERROR, 0); 1.93 + return -1; 1.94 + } 1.95 + 1.96 + /* 1.97 + * Assume the first writev will succeed. Copy iov's only on 1.98 + * failure. 1.99 + */ 1.100 + tmp_iov = iov; 1.101 + for (index = 0; index < iov_size; index++) 1.102 + sz += iov[index].iov_len; 1.103 + 1.104 + iov_cnt = iov_size; 1.105 + 1.106 + while (sz > 0) { 1.107 + 1.108 + w = _PR_MD_WRITEV(fd, tmp_iov, iov_cnt, timeout); 1.109 + if (w < 0) { 1.110 + count = -1; 1.111 + break; 1.112 + } 1.113 + count += w; 1.114 + if (fd->secret->nonblocking) { 1.115 + break; 1.116 + } 1.117 + sz -= w; 1.118 + 1.119 + if (sz > 0) { 1.120 + /* find the next unwritten vector */ 1.121 + for ( index = 0, tmp_out = count; 1.122 + tmp_out >= iov[index].iov_len; 1.123 + tmp_out -= iov[index].iov_len, index++){;} /* nothing to execute */ 1.124 + 1.125 + if (tmp_iov == iov) { 1.126 + /* 1.127 + * The first writev failed so we 1.128 + * must copy iov's around. 1.129 + * Avoid calloc/free if there 1.130 + * are few enough iov's. 1.131 + */ 1.132 + if (iov_size - index <= LOCAL_MAXIOV) 1.133 + iov_copy = local_iov; 1.134 + else if ((iov_copy = (PRIOVec *) PR_CALLOC((iov_size - index) * 1.135 + sizeof *iov_copy)) == NULL) { 1.136 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.137 + return -1; 1.138 + } 1.139 + tmp_iov = iov_copy; 1.140 + } 1.141 + 1.142 + PR_ASSERT(tmp_iov == iov_copy); 1.143 + 1.144 + /* fill in the first partial read */ 1.145 + iov_copy[0].iov_base = &(((char *)iov[index].iov_base)[tmp_out]); 1.146 + iov_copy[0].iov_len = iov[index].iov_len - tmp_out; 1.147 + index++; 1.148 + 1.149 + /* copy the remaining vectors */ 1.150 + for (iov_cnt=1; index<iov_size; iov_cnt++, index++) { 1.151 + iov_copy[iov_cnt].iov_base = iov[index].iov_base; 1.152 + iov_copy[iov_cnt].iov_len = iov[index].iov_len; 1.153 + } 1.154 + } 1.155 + } 1.156 + 1.157 + if (iov_copy != local_iov) 1.158 + PR_DELETE(iov_copy); 1.159 + return count; 1.160 +} 1.161 + 1.162 +/************************************************************************/ 1.163 + 1.164 +PR_IMPLEMENT(PRFileDesc *) PR_ImportTCPSocket(PROsfd osfd) 1.165 +{ 1.166 +PRFileDesc *fd; 1.167 + 1.168 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.169 + fd = PR_AllocFileDesc(osfd, PR_GetTCPMethods()); 1.170 + if (fd != NULL) { 1.171 + _PR_MD_MAKE_NONBLOCK(fd); 1.172 + _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE); 1.173 +#ifdef _PR_NEED_SECRET_AF 1.174 + /* this means we can only import IPv4 sockets here. 1.175 + * but this is what the function in ptio.c does. 1.176 + * We need a way to import IPv6 sockets, too. 1.177 + */ 1.178 + fd->secret->af = AF_INET; 1.179 +#endif 1.180 + } else 1.181 + _PR_MD_CLOSE_SOCKET(osfd); 1.182 + return(fd); 1.183 +} 1.184 + 1.185 +PR_IMPLEMENT(PRFileDesc *) PR_ImportUDPSocket(PROsfd osfd) 1.186 +{ 1.187 +PRFileDesc *fd; 1.188 + 1.189 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.190 + fd = PR_AllocFileDesc(osfd, PR_GetUDPMethods()); 1.191 + if (fd != NULL) { 1.192 + _PR_MD_MAKE_NONBLOCK(fd); 1.193 + _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE); 1.194 + } else 1.195 + _PR_MD_CLOSE_SOCKET(osfd); 1.196 + return(fd); 1.197 +} 1.198 + 1.199 + 1.200 +static const PRIOMethods* PR_GetSocketPollFdMethods(void); 1.201 + 1.202 +PR_IMPLEMENT(PRFileDesc*) PR_CreateSocketPollFd(PROsfd osfd) 1.203 +{ 1.204 + PRFileDesc *fd; 1.205 + 1.206 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.207 + 1.208 + fd = _PR_Getfd(); 1.209 + 1.210 + if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.211 + else 1.212 + { 1.213 + fd->secret->md.osfd = osfd; 1.214 + fd->secret->inheritable = _PR_TRI_FALSE; 1.215 + fd->secret->state = _PR_FILEDESC_OPEN; 1.216 + fd->methods = PR_GetSocketPollFdMethods(); 1.217 + } 1.218 + 1.219 + return fd; 1.220 +} /* PR_CreateSocketPollFD */ 1.221 + 1.222 +PR_IMPLEMENT(PRStatus) PR_DestroySocketPollFd(PRFileDesc *fd) 1.223 +{ 1.224 + if (NULL == fd) 1.225 + { 1.226 + PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); 1.227 + return PR_FAILURE; 1.228 + } 1.229 + fd->secret->state = _PR_FILEDESC_CLOSED; 1.230 + _PR_Putfd(fd); 1.231 + return PR_SUCCESS; 1.232 +} /* PR_DestroySocketPollFd */ 1.233 + 1.234 +static PRStatus PR_CALLBACK SocketConnect( 1.235 + PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) 1.236 +{ 1.237 + PRInt32 rv; /* Return value of _PR_MD_CONNECT */ 1.238 + const PRNetAddr *addrp = addr; 1.239 +#if defined(_PR_INET6) 1.240 + PRNetAddr addrCopy; 1.241 +#endif 1.242 + PRThread *me = _PR_MD_CURRENT_THREAD(); 1.243 + 1.244 + if (_PR_PENDING_INTERRUPT(me)) { 1.245 + me->flags &= ~_PR_INTERRUPT; 1.246 + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1.247 + return PR_FAILURE; 1.248 + } 1.249 +#if defined(_PR_INET6) 1.250 + if (addr->raw.family == PR_AF_INET6) { 1.251 + addrCopy = *addr; 1.252 + addrCopy.raw.family = AF_INET6; 1.253 + addrp = &addrCopy; 1.254 + } 1.255 +#endif 1.256 + 1.257 + rv = _PR_MD_CONNECT(fd, addrp, PR_NETADDR_SIZE(addr), timeout); 1.258 + PR_LOG(_pr_io_lm, PR_LOG_MAX, ("connect -> %d", rv)); 1.259 + if (rv == 0) 1.260 + return PR_SUCCESS; 1.261 + else 1.262 + return PR_FAILURE; 1.263 +} 1.264 + 1.265 +static PRStatus PR_CALLBACK SocketConnectContinue( 1.266 + PRFileDesc *fd, PRInt16 out_flags) 1.267 +{ 1.268 + PROsfd osfd; 1.269 + int err; 1.270 + 1.271 + if (out_flags & PR_POLL_NVAL) { 1.272 + PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); 1.273 + return PR_FAILURE; 1.274 + } 1.275 + if ((out_flags & (PR_POLL_WRITE | PR_POLL_EXCEPT | PR_POLL_ERR)) == 0) { 1.276 + PR_ASSERT(out_flags == 0); 1.277 + PR_SetError(PR_IN_PROGRESS_ERROR, 0); 1.278 + return PR_FAILURE; 1.279 + } 1.280 + 1.281 + osfd = fd->secret->md.osfd; 1.282 + 1.283 +#if defined(XP_UNIX) 1.284 + 1.285 + err = _MD_unix_get_nonblocking_connect_error(osfd); 1.286 + if (err != 0) { 1.287 + _PR_MD_MAP_CONNECT_ERROR(err); 1.288 + return PR_FAILURE; 1.289 + } 1.290 + return PR_SUCCESS; 1.291 + 1.292 +#elif defined(WIN32) || defined(WIN16) 1.293 + 1.294 + if (out_flags & PR_POLL_EXCEPT) { 1.295 + int len = sizeof(err); 1.296 + if (getsockopt(osfd, (int)SOL_SOCKET, SO_ERROR, (char *) &err, &len) 1.297 + == SOCKET_ERROR) { 1.298 + _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); 1.299 + return PR_FAILURE; 1.300 + } 1.301 + if (err != 0) { 1.302 + _PR_MD_MAP_CONNECT_ERROR(err); 1.303 + } else { 1.304 + PR_SetError(PR_UNKNOWN_ERROR, 0); 1.305 + } 1.306 + return PR_FAILURE; 1.307 + } 1.308 + 1.309 + PR_ASSERT(out_flags & PR_POLL_WRITE); 1.310 + return PR_SUCCESS; 1.311 + 1.312 +#elif defined(XP_OS2) 1.313 + 1.314 + err = _MD_os2_get_nonblocking_connect_error(osfd); 1.315 + if (err != 0) { 1.316 + _PR_MD_MAP_CONNECT_ERROR(err); 1.317 + return PR_FAILURE; 1.318 + } 1.319 + return PR_SUCCESS; 1.320 + 1.321 +#elif defined(XP_BEOS) 1.322 + 1.323 +#ifdef BONE_VERSION /* bug 122364 */ 1.324 + /* temporary workaround until getsockopt(SO_ERROR) works in BONE */ 1.325 + if (out_flags & PR_POLL_EXCEPT) { 1.326 + PR_SetError(PR_CONNECT_REFUSED_ERROR, 0); 1.327 + return PR_FAILURE; 1.328 + } 1.329 + PR_ASSERT(out_flags & PR_POLL_WRITE); 1.330 + return PR_SUCCESS; 1.331 +#else 1.332 + err = _MD_beos_get_nonblocking_connect_error(fd); 1.333 + if( err != 0 ) { 1.334 + _PR_MD_MAP_CONNECT_ERROR(err); 1.335 + return PR_FAILURE; 1.336 + } 1.337 + else 1.338 + return PR_SUCCESS; 1.339 +#endif /* BONE_VERSION */ 1.340 + 1.341 +#else 1.342 + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 1.343 + return PR_FAILURE; 1.344 +#endif 1.345 +} 1.346 + 1.347 +PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd) 1.348 +{ 1.349 + /* Find the NSPR layer and invoke its connectcontinue method */ 1.350 + PRFileDesc *bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); 1.351 + 1.352 + if (NULL == bottom) { 1.353 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.354 + return PR_FAILURE; 1.355 + } 1.356 + return SocketConnectContinue(bottom, pd->out_flags); 1.357 +} 1.358 + 1.359 +static PRFileDesc* PR_CALLBACK SocketAccept(PRFileDesc *fd, PRNetAddr *addr, 1.360 +PRIntervalTime timeout) 1.361 +{ 1.362 + PROsfd osfd; 1.363 + PRFileDesc *fd2; 1.364 + PRUint32 al; 1.365 + PRThread *me = _PR_MD_CURRENT_THREAD(); 1.366 +#ifdef WINNT 1.367 + PRNetAddr addrCopy; 1.368 +#endif 1.369 + 1.370 + if (_PR_PENDING_INTERRUPT(me)) { 1.371 + me->flags &= ~_PR_INTERRUPT; 1.372 + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1.373 + return 0; 1.374 + } 1.375 + if (_PR_IO_PENDING(me)) { 1.376 + PR_SetError(PR_IO_PENDING_ERROR, 0); 1.377 + return 0; 1.378 + } 1.379 + 1.380 +#ifdef WINNT 1.381 + if (addr == NULL) { 1.382 + addr = &addrCopy; 1.383 + } 1.384 +#endif 1.385 + al = sizeof(PRNetAddr); 1.386 + osfd = _PR_MD_ACCEPT(fd, addr, &al, timeout); 1.387 + if (osfd == -1) 1.388 + return 0; 1.389 + 1.390 + fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods()); 1.391 + if (!fd2) { 1.392 + _PR_MD_CLOSE_SOCKET(osfd); 1.393 + return NULL; 1.394 + } 1.395 + 1.396 + fd2->secret->nonblocking = fd->secret->nonblocking; 1.397 + fd2->secret->inheritable = fd->secret->inheritable; 1.398 +#ifdef WINNT 1.399 + if (!fd2->secret->nonblocking && fd2->secret->inheritable != _PR_TRI_TRUE) { 1.400 + /* 1.401 + * The new socket has been associated with an I/O 1.402 + * completion port. There is no going back. 1.403 + */ 1.404 + fd2->secret->md.io_model_committed = PR_TRUE; 1.405 + } 1.406 + PR_ASSERT(al == PR_NETADDR_SIZE(addr)); 1.407 + fd2->secret->md.accepted_socket = PR_TRUE; 1.408 + memcpy(&fd2->secret->md.peer_addr, addr, al); 1.409 +#endif 1.410 + 1.411 + /* 1.412 + * On some platforms, the new socket created by accept() 1.413 + * inherits the nonblocking (or overlapped io) attribute 1.414 + * of the listening socket. As an optimization, these 1.415 + * platforms can skip the following _PR_MD_MAKE_NONBLOCK 1.416 + * call. 1.417 + */ 1.418 +#if !defined(SOLARIS) && !defined(IRIX) && !defined(WINNT) 1.419 + _PR_MD_MAKE_NONBLOCK(fd2); 1.420 +#endif 1.421 + 1.422 +#ifdef _PR_INET6 1.423 + if (addr && (AF_INET6 == addr->raw.family)) 1.424 + addr->raw.family = PR_AF_INET6; 1.425 +#endif 1.426 + PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); 1.427 + PR_ASSERT(IsValidNetAddrLen(addr, al) == PR_TRUE); 1.428 + 1.429 + return fd2; 1.430 +} 1.431 + 1.432 +#ifdef WINNT 1.433 +PR_IMPLEMENT(PRFileDesc*) PR_NTFast_Accept(PRFileDesc *fd, PRNetAddr *addr, 1.434 +PRIntervalTime timeout) 1.435 +{ 1.436 + PROsfd osfd; 1.437 + PRFileDesc *fd2; 1.438 + PRIntn al; 1.439 + PRThread *me = _PR_MD_CURRENT_THREAD(); 1.440 + PRNetAddr addrCopy; 1.441 + 1.442 + if (_PR_PENDING_INTERRUPT(me)) { 1.443 + me->flags &= ~_PR_INTERRUPT; 1.444 + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1.445 + return 0; 1.446 + } 1.447 + if (_PR_IO_PENDING(me)) { 1.448 + PR_SetError(PR_IO_PENDING_ERROR, 0); 1.449 + return 0; 1.450 + } 1.451 + 1.452 + if (addr == NULL) { 1.453 + addr = &addrCopy; 1.454 + } 1.455 + al = PR_NETADDR_SIZE(addr); 1.456 + osfd = _PR_MD_FAST_ACCEPT(fd, addr, &al, timeout, PR_TRUE, NULL, NULL); 1.457 + if (osfd == -1) { 1.458 + return 0; 1.459 + } 1.460 + 1.461 + fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods()); 1.462 + if (!fd2) { 1.463 + _PR_MD_CLOSE_SOCKET(osfd); 1.464 + } else { 1.465 + fd2->secret->nonblocking = fd->secret->nonblocking; 1.466 + fd2->secret->md.io_model_committed = PR_TRUE; 1.467 + PR_ASSERT(al == PR_NETADDR_SIZE(addr)); 1.468 + fd2->secret->md.accepted_socket = PR_TRUE; 1.469 + memcpy(&fd2->secret->md.peer_addr, addr, al); 1.470 +#ifdef _PR_INET6 1.471 + if (AF_INET6 == addr->raw.family) 1.472 + addr->raw.family = PR_AF_INET6; 1.473 +#endif 1.474 +#ifdef _PR_NEED_SECRET_AF 1.475 + fd2->secret->af = fd->secret->af; 1.476 +#endif 1.477 + } 1.478 + return fd2; 1.479 +} 1.480 +#endif /* WINNT */ 1.481 + 1.482 + 1.483 +static PRStatus PR_CALLBACK SocketBind(PRFileDesc *fd, const PRNetAddr *addr) 1.484 +{ 1.485 + PRInt32 result; 1.486 + const PRNetAddr *addrp = addr; 1.487 +#if defined(_PR_INET6) 1.488 + PRNetAddr addrCopy; 1.489 +#endif 1.490 + 1.491 + PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); 1.492 + 1.493 +#ifdef XP_UNIX 1.494 + if (addr->raw.family == AF_UNIX) { 1.495 + /* Disallow relative pathnames */ 1.496 + if (addr->local.path[0] != '/') { 1.497 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.498 + return PR_FAILURE; 1.499 + } 1.500 + } 1.501 +#endif /* XP_UNIX */ 1.502 + 1.503 +#if defined(_PR_INET6) 1.504 + if (addr->raw.family == PR_AF_INET6) { 1.505 + addrCopy = *addr; 1.506 + addrCopy.raw.family = AF_INET6; 1.507 + addrp = &addrCopy; 1.508 + } 1.509 +#endif 1.510 + result = _PR_MD_BIND(fd, addrp, PR_NETADDR_SIZE(addr)); 1.511 + if (result < 0) { 1.512 + return PR_FAILURE; 1.513 + } 1.514 + return PR_SUCCESS; 1.515 +} 1.516 + 1.517 +static PRStatus PR_CALLBACK SocketListen(PRFileDesc *fd, PRIntn backlog) 1.518 +{ 1.519 + PRInt32 result; 1.520 + 1.521 + result = _PR_MD_LISTEN(fd, backlog); 1.522 + if (result < 0) { 1.523 + return PR_FAILURE; 1.524 + } 1.525 + return PR_SUCCESS; 1.526 +} 1.527 + 1.528 +static PRStatus PR_CALLBACK SocketShutdown(PRFileDesc *fd, PRIntn how) 1.529 +{ 1.530 + PRInt32 result; 1.531 + 1.532 + result = _PR_MD_SHUTDOWN(fd, how); 1.533 + if (result < 0) { 1.534 + return PR_FAILURE; 1.535 + } 1.536 + return PR_SUCCESS; 1.537 +} 1.538 + 1.539 +static PRInt32 PR_CALLBACK SocketRecv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, 1.540 +PRIntervalTime timeout) 1.541 +{ 1.542 + PRInt32 rv; 1.543 + PRThread *me = _PR_MD_CURRENT_THREAD(); 1.544 + 1.545 + if ((flags != 0) && (flags != PR_MSG_PEEK)) { 1.546 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.547 + return -1; 1.548 + } 1.549 + if (_PR_PENDING_INTERRUPT(me)) { 1.550 + me->flags &= ~_PR_INTERRUPT; 1.551 + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1.552 + return -1; 1.553 + } 1.554 + if (_PR_IO_PENDING(me)) { 1.555 + PR_SetError(PR_IO_PENDING_ERROR, 0); 1.556 + return -1; 1.557 + } 1.558 + 1.559 + PR_LOG(_pr_io_lm, PR_LOG_MAX, 1.560 + ("recv: fd=%p osfd=%" PR_PRIdOSFD " buf=%p amount=%d flags=%d", 1.561 + fd, fd->secret->md.osfd, buf, amount, flags)); 1.562 + 1.563 +#ifdef _PR_HAVE_PEEK_BUFFER 1.564 + if (fd->secret->peekBytes != 0) { 1.565 + rv = (amount < fd->secret->peekBytes) ? 1.566 + amount : fd->secret->peekBytes; 1.567 + memcpy(buf, fd->secret->peekBuffer, rv); 1.568 + if (flags == 0) { 1.569 + /* consume the bytes in the peek buffer */ 1.570 + fd->secret->peekBytes -= rv; 1.571 + if (fd->secret->peekBytes != 0) { 1.572 + memmove(fd->secret->peekBuffer, 1.573 + fd->secret->peekBuffer + rv, 1.574 + fd->secret->peekBytes); 1.575 + } 1.576 + } 1.577 + return rv; 1.578 + } 1.579 + 1.580 + /* allocate peek buffer, if necessary */ 1.581 + if ((PR_MSG_PEEK == flags) && _PR_FD_NEED_EMULATE_MSG_PEEK(fd)) { 1.582 + PR_ASSERT(0 == fd->secret->peekBytes); 1.583 + /* impose a max size on the peek buffer */ 1.584 + if (amount > _PR_PEEK_BUFFER_MAX) { 1.585 + amount = _PR_PEEK_BUFFER_MAX; 1.586 + } 1.587 + if (fd->secret->peekBufSize < amount) { 1.588 + if (fd->secret->peekBuffer) { 1.589 + PR_Free(fd->secret->peekBuffer); 1.590 + } 1.591 + fd->secret->peekBufSize = amount; 1.592 + fd->secret->peekBuffer = PR_Malloc(amount); 1.593 + if (NULL == fd->secret->peekBuffer) { 1.594 + fd->secret->peekBufSize = 0; 1.595 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.596 + return -1; 1.597 + } 1.598 + } 1.599 + } 1.600 +#endif 1.601 + 1.602 + rv = _PR_MD_RECV(fd, buf, amount, flags, timeout); 1.603 + PR_LOG(_pr_io_lm, PR_LOG_MAX, ("recv -> %d, error = %d, os error = %d", 1.604 + rv, PR_GetError(), PR_GetOSError())); 1.605 + 1.606 +#ifdef _PR_HAVE_PEEK_BUFFER 1.607 + if ((PR_MSG_PEEK == flags) && _PR_FD_NEED_EMULATE_MSG_PEEK(fd)) { 1.608 + if (rv > 0) { 1.609 + memcpy(fd->secret->peekBuffer, buf, rv); 1.610 + fd->secret->peekBytes = rv; 1.611 + } 1.612 + } 1.613 +#endif 1.614 + 1.615 + return rv; 1.616 +} 1.617 + 1.618 +static PRInt32 PR_CALLBACK SocketRead(PRFileDesc *fd, void *buf, PRInt32 amount) 1.619 +{ 1.620 + return SocketRecv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT); 1.621 +} 1.622 + 1.623 +static PRInt32 PR_CALLBACK SocketSend(PRFileDesc *fd, const void *buf, PRInt32 amount, 1.624 +PRIntn flags, PRIntervalTime timeout) 1.625 +{ 1.626 + PRInt32 temp, count; 1.627 + PRThread *me = _PR_MD_CURRENT_THREAD(); 1.628 + 1.629 + if (_PR_PENDING_INTERRUPT(me)) { 1.630 + me->flags &= ~_PR_INTERRUPT; 1.631 + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1.632 + return -1; 1.633 + } 1.634 + if (_PR_IO_PENDING(me)) { 1.635 + PR_SetError(PR_IO_PENDING_ERROR, 0); 1.636 + return -1; 1.637 + } 1.638 + 1.639 + count = 0; 1.640 + while (amount > 0) { 1.641 + PR_LOG(_pr_io_lm, PR_LOG_MAX, 1.642 + ("send: fd=%p osfd=%" PR_PRIdOSFD " buf=%p amount=%d", 1.643 + fd, fd->secret->md.osfd, buf, amount)); 1.644 + temp = _PR_MD_SEND(fd, buf, amount, flags, timeout); 1.645 + if (temp < 0) { 1.646 + count = -1; 1.647 + break; 1.648 + } 1.649 + 1.650 + count += temp; 1.651 + if (fd->secret->nonblocking) { 1.652 + break; 1.653 + } 1.654 + buf = (const void*) ((const char*)buf + temp); 1.655 + 1.656 + amount -= temp; 1.657 + } 1.658 + PR_LOG(_pr_io_lm, PR_LOG_MAX, ("send -> %d", count)); 1.659 + return count; 1.660 +} 1.661 + 1.662 +static PRInt32 PR_CALLBACK SocketWrite(PRFileDesc *fd, const void *buf, PRInt32 amount) 1.663 +{ 1.664 + return SocketSend(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT); 1.665 +} 1.666 + 1.667 +static PRStatus PR_CALLBACK SocketClose(PRFileDesc *fd) 1.668 +{ 1.669 + if (!fd || !fd->secret 1.670 + || (fd->secret->state != _PR_FILEDESC_OPEN 1.671 + && fd->secret->state != _PR_FILEDESC_CLOSED)) { 1.672 + PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); 1.673 + return PR_FAILURE; 1.674 + } 1.675 + 1.676 + if (fd->secret->state == _PR_FILEDESC_OPEN) { 1.677 + if (_PR_MD_CLOSE_SOCKET(fd->secret->md.osfd) < 0) { 1.678 + return PR_FAILURE; 1.679 + } 1.680 + fd->secret->state = _PR_FILEDESC_CLOSED; 1.681 + } 1.682 + 1.683 +#ifdef _PR_HAVE_PEEK_BUFFER 1.684 + if (fd->secret->peekBuffer) { 1.685 + PR_ASSERT(fd->secret->peekBufSize > 0); 1.686 + PR_DELETE(fd->secret->peekBuffer); 1.687 + fd->secret->peekBufSize = 0; 1.688 + fd->secret->peekBytes = 0; 1.689 + } 1.690 +#endif 1.691 + 1.692 + PR_FreeFileDesc(fd); 1.693 + return PR_SUCCESS; 1.694 +} 1.695 + 1.696 +static PRInt32 PR_CALLBACK SocketAvailable(PRFileDesc *fd) 1.697 +{ 1.698 + PRInt32 rv; 1.699 +#ifdef _PR_HAVE_PEEK_BUFFER 1.700 + if (fd->secret->peekBytes != 0) { 1.701 + return fd->secret->peekBytes; 1.702 + } 1.703 +#endif 1.704 + rv = _PR_MD_SOCKETAVAILABLE(fd); 1.705 + return rv; 1.706 +} 1.707 + 1.708 +static PRInt64 PR_CALLBACK SocketAvailable64(PRFileDesc *fd) 1.709 +{ 1.710 + PRInt64 rv; 1.711 +#ifdef _PR_HAVE_PEEK_BUFFER 1.712 + if (fd->secret->peekBytes != 0) { 1.713 + LL_I2L(rv, fd->secret->peekBytes); 1.714 + return rv; 1.715 + } 1.716 +#endif 1.717 + LL_I2L(rv, _PR_MD_SOCKETAVAILABLE(fd)); 1.718 + return rv; 1.719 +} 1.720 + 1.721 +static PRStatus PR_CALLBACK SocketSync(PRFileDesc *fd) 1.722 +{ 1.723 + return PR_SUCCESS; 1.724 +} 1.725 + 1.726 +static PRInt32 PR_CALLBACK SocketSendTo( 1.727 + PRFileDesc *fd, const void *buf, PRInt32 amount, 1.728 + PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) 1.729 +{ 1.730 + PRInt32 temp, count; 1.731 + const PRNetAddr *addrp = addr; 1.732 +#if defined(_PR_INET6) 1.733 + PRNetAddr addrCopy; 1.734 +#endif 1.735 + PRThread *me = _PR_MD_CURRENT_THREAD(); 1.736 + 1.737 + if (_PR_PENDING_INTERRUPT(me)) { 1.738 + me->flags &= ~_PR_INTERRUPT; 1.739 + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1.740 + return -1; 1.741 + } 1.742 + if (_PR_IO_PENDING(me)) { 1.743 + PR_SetError(PR_IO_PENDING_ERROR, 0); 1.744 + return -1; 1.745 + } 1.746 + 1.747 + PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); 1.748 +#if defined(_PR_INET6) 1.749 + if (addr->raw.family == PR_AF_INET6) { 1.750 + addrCopy = *addr; 1.751 + addrCopy.raw.family = AF_INET6; 1.752 + addrp = &addrCopy; 1.753 + } 1.754 +#endif 1.755 + 1.756 + count = 0; 1.757 + while (amount > 0) { 1.758 + temp = _PR_MD_SENDTO(fd, buf, amount, flags, 1.759 + addrp, PR_NETADDR_SIZE(addr), timeout); 1.760 + if (temp < 0) { 1.761 + count = -1; 1.762 + break; 1.763 + } 1.764 + count += temp; 1.765 + if (fd->secret->nonblocking) { 1.766 + break; 1.767 + } 1.768 + buf = (const void*) ((const char*)buf + temp); 1.769 + amount -= temp; 1.770 + } 1.771 + return count; 1.772 +} 1.773 + 1.774 +static PRInt32 PR_CALLBACK SocketRecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, 1.775 +PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) 1.776 +{ 1.777 + PRInt32 rv; 1.778 + PRUint32 al; 1.779 + PRThread *me = _PR_MD_CURRENT_THREAD(); 1.780 + 1.781 + if (_PR_PENDING_INTERRUPT(me)) { 1.782 + me->flags &= ~_PR_INTERRUPT; 1.783 + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1.784 + return -1; 1.785 + } 1.786 + if (_PR_IO_PENDING(me)) { 1.787 + PR_SetError(PR_IO_PENDING_ERROR, 0); 1.788 + return -1; 1.789 + } 1.790 + 1.791 + al = sizeof(PRNetAddr); 1.792 + rv = _PR_MD_RECVFROM(fd, buf, amount, flags, addr, &al, timeout); 1.793 +#ifdef _PR_INET6 1.794 + if (addr && (AF_INET6 == addr->raw.family)) 1.795 + addr->raw.family = PR_AF_INET6; 1.796 +#endif 1.797 + return rv; 1.798 +} 1.799 + 1.800 +static PRInt32 PR_CALLBACK SocketAcceptRead(PRFileDesc *sd, PRFileDesc **nd, 1.801 +PRNetAddr **raddr, void *buf, PRInt32 amount, 1.802 +PRIntervalTime timeout) 1.803 +{ 1.804 + PRInt32 rv; 1.805 + PRThread *me = _PR_MD_CURRENT_THREAD(); 1.806 + 1.807 + if (_PR_PENDING_INTERRUPT(me)) { 1.808 + me->flags &= ~_PR_INTERRUPT; 1.809 + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1.810 + return -1; 1.811 + } 1.812 + if (_PR_IO_PENDING(me)) { 1.813 + PR_SetError(PR_IO_PENDING_ERROR, 0); 1.814 + return -1; 1.815 + } 1.816 + /* The socket must be in blocking mode. */ 1.817 + if (sd->secret->nonblocking) { 1.818 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.819 + return -1; 1.820 + } 1.821 + *nd = NULL; 1.822 + 1.823 +#if defined(WINNT) 1.824 + { 1.825 + PROsfd newSock; 1.826 + PRNetAddr *raddrCopy; 1.827 + 1.828 + if (raddr == NULL) { 1.829 + raddr = &raddrCopy; 1.830 + } 1.831 + rv = _PR_MD_ACCEPT_READ(sd, &newSock, raddr, buf, amount, timeout); 1.832 + if (rv < 0) { 1.833 + rv = -1; 1.834 + } else { 1.835 + /* Successfully accepted and read; create the new PRFileDesc */ 1.836 + *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods()); 1.837 + if (*nd == 0) { 1.838 + _PR_MD_CLOSE_SOCKET(newSock); 1.839 + /* PR_AllocFileDesc() has invoked PR_SetError(). */ 1.840 + rv = -1; 1.841 + } else { 1.842 + (*nd)->secret->md.io_model_committed = PR_TRUE; 1.843 + (*nd)->secret->md.accepted_socket = PR_TRUE; 1.844 + memcpy(&(*nd)->secret->md.peer_addr, *raddr, 1.845 + PR_NETADDR_SIZE(*raddr)); 1.846 +#ifdef _PR_INET6 1.847 + if (AF_INET6 == *raddr->raw.family) 1.848 + *raddr->raw.family = PR_AF_INET6; 1.849 +#endif 1.850 + } 1.851 + } 1.852 + } 1.853 +#else 1.854 + rv = PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout); 1.855 +#endif 1.856 + return rv; 1.857 +} 1.858 + 1.859 +#ifdef WINNT 1.860 +PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead(PRFileDesc *sd, PRFileDesc **nd, 1.861 +PRNetAddr **raddr, void *buf, PRInt32 amount, 1.862 +PRIntervalTime timeout) 1.863 +{ 1.864 + PRInt32 rv; 1.865 + PROsfd newSock; 1.866 + PRThread *me = _PR_MD_CURRENT_THREAD(); 1.867 + PRNetAddr *raddrCopy; 1.868 + 1.869 + if (_PR_PENDING_INTERRUPT(me)) { 1.870 + me->flags &= ~_PR_INTERRUPT; 1.871 + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1.872 + return -1; 1.873 + } 1.874 + if (_PR_IO_PENDING(me)) { 1.875 + PR_SetError(PR_IO_PENDING_ERROR, 0); 1.876 + return -1; 1.877 + } 1.878 + *nd = NULL; 1.879 + 1.880 + if (raddr == NULL) { 1.881 + raddr = &raddrCopy; 1.882 + } 1.883 + rv = _PR_MD_FAST_ACCEPT_READ(sd, &newSock, raddr, buf, amount, 1.884 + timeout, PR_TRUE, NULL, NULL); 1.885 + if (rv < 0) { 1.886 + rv = -1; 1.887 + } else { 1.888 + /* Successfully accepted and read; create the new PRFileDesc */ 1.889 + *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods()); 1.890 + if (*nd == 0) { 1.891 + _PR_MD_CLOSE_SOCKET(newSock); 1.892 + /* PR_AllocFileDesc() has invoked PR_SetError(). */ 1.893 + rv = -1; 1.894 + } else { 1.895 + (*nd)->secret->md.io_model_committed = PR_TRUE; 1.896 + (*nd)->secret->md.accepted_socket = PR_TRUE; 1.897 + memcpy(&(*nd)->secret->md.peer_addr, *raddr, 1.898 + PR_NETADDR_SIZE(*raddr)); 1.899 +#ifdef _PR_INET6 1.900 + if (AF_INET6 == *raddr->raw.family) 1.901 + *raddr->raw.family = PR_AF_INET6; 1.902 +#endif 1.903 +#ifdef _PR_NEED_SECRET_AF 1.904 + (*nd)->secret->af = sd->secret->af; 1.905 +#endif 1.906 + } 1.907 + } 1.908 + return rv; 1.909 +} 1.910 + 1.911 +PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead_WithTimeoutCallback( 1.912 +PRFileDesc *sd, PRFileDesc **nd, 1.913 +PRNetAddr **raddr, void *buf, PRInt32 amount, 1.914 +PRIntervalTime timeout, 1.915 +_PR_AcceptTimeoutCallback callback, 1.916 +void *callbackArg) 1.917 +{ 1.918 + PRInt32 rv; 1.919 + PROsfd newSock; 1.920 + PRThread *me = _PR_MD_CURRENT_THREAD(); 1.921 + PRNetAddr *raddrCopy; 1.922 + 1.923 + if (_PR_PENDING_INTERRUPT(me)) { 1.924 + me->flags &= ~_PR_INTERRUPT; 1.925 + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1.926 + return -1; 1.927 + } 1.928 + if (_PR_IO_PENDING(me)) { 1.929 + PR_SetError(PR_IO_PENDING_ERROR, 0); 1.930 + return -1; 1.931 + } 1.932 + *nd = NULL; 1.933 + 1.934 + if (raddr == NULL) { 1.935 + raddr = &raddrCopy; 1.936 + } 1.937 + rv = _PR_MD_FAST_ACCEPT_READ(sd, &newSock, raddr, buf, amount, 1.938 + timeout, PR_TRUE, callback, callbackArg); 1.939 + if (rv < 0) { 1.940 + rv = -1; 1.941 + } else { 1.942 + /* Successfully accepted and read; create the new PRFileDesc */ 1.943 + *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods()); 1.944 + if (*nd == 0) { 1.945 + _PR_MD_CLOSE_SOCKET(newSock); 1.946 + /* PR_AllocFileDesc() has invoked PR_SetError(). */ 1.947 + rv = -1; 1.948 + } else { 1.949 + (*nd)->secret->md.io_model_committed = PR_TRUE; 1.950 + (*nd)->secret->md.accepted_socket = PR_TRUE; 1.951 + memcpy(&(*nd)->secret->md.peer_addr, *raddr, 1.952 + PR_NETADDR_SIZE(*raddr)); 1.953 +#ifdef _PR_INET6 1.954 + if (AF_INET6 == *raddr->raw.family) 1.955 + *raddr->raw.family = PR_AF_INET6; 1.956 +#endif 1.957 +#ifdef _PR_NEED_SECRET_AF 1.958 + (*nd)->secret->af = sd->secret->af; 1.959 +#endif 1.960 + } 1.961 + } 1.962 + return rv; 1.963 +} 1.964 +#endif /* WINNT */ 1.965 + 1.966 +#ifdef WINNT 1.967 +PR_IMPLEMENT(void) 1.968 +PR_NTFast_UpdateAcceptContext(PRFileDesc *socket, PRFileDesc *acceptSocket) 1.969 +{ 1.970 + _PR_MD_UPDATE_ACCEPT_CONTEXT( 1.971 + socket->secret->md.osfd, acceptSocket->secret->md.osfd); 1.972 +} 1.973 +#endif /* WINNT */ 1.974 + 1.975 +static PRInt32 PR_CALLBACK SocketSendFile( 1.976 + PRFileDesc *sd, PRSendFileData *sfd, 1.977 + PRTransmitFileFlags flags, PRIntervalTime timeout) 1.978 +{ 1.979 + PRInt32 rv; 1.980 + PRThread *me = _PR_MD_CURRENT_THREAD(); 1.981 + 1.982 + if (_PR_PENDING_INTERRUPT(me)) { 1.983 + me->flags &= ~_PR_INTERRUPT; 1.984 + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); 1.985 + return -1; 1.986 + } 1.987 + if (_PR_IO_PENDING(me)) { 1.988 + PR_SetError(PR_IO_PENDING_ERROR, 0); 1.989 + return -1; 1.990 + } 1.991 + /* The socket must be in blocking mode. */ 1.992 + if (sd->secret->nonblocking) { 1.993 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.994 + return -1; 1.995 + } 1.996 +#if defined(WINNT) 1.997 + rv = _PR_MD_SENDFILE(sd, sfd, flags, timeout); 1.998 + if ((rv >= 0) && (flags == PR_TRANSMITFILE_CLOSE_SOCKET)) { 1.999 + /* 1.1000 + * This should be kept the same as SocketClose, except 1.1001 + * that _PR_MD_CLOSE_SOCKET(sd->secret->md.osfd) should 1.1002 + * not be called because the socket will be recycled. 1.1003 + */ 1.1004 + PR_FreeFileDesc(sd); 1.1005 + } 1.1006 +#else 1.1007 + rv = PR_EmulateSendFile(sd, sfd, flags, timeout); 1.1008 +#endif /* WINNT */ 1.1009 + 1.1010 + return rv; 1.1011 +} 1.1012 + 1.1013 +static PRInt32 PR_CALLBACK SocketTransmitFile(PRFileDesc *sd, PRFileDesc *fd, 1.1014 +const void *headers, PRInt32 hlen, PRTransmitFileFlags flags, 1.1015 +PRIntervalTime timeout) 1.1016 +{ 1.1017 + PRSendFileData sfd; 1.1018 + 1.1019 + sfd.fd = fd; 1.1020 + sfd.file_offset = 0; 1.1021 + sfd.file_nbytes = 0; 1.1022 + sfd.header = headers; 1.1023 + sfd.hlen = hlen; 1.1024 + sfd.trailer = NULL; 1.1025 + sfd.tlen = 0; 1.1026 + 1.1027 + return(SocketSendFile(sd, &sfd, flags, timeout)); 1.1028 +} 1.1029 + 1.1030 +static PRStatus PR_CALLBACK SocketGetName(PRFileDesc *fd, PRNetAddr *addr) 1.1031 +{ 1.1032 + PRInt32 result; 1.1033 + PRUint32 addrlen; 1.1034 + 1.1035 + addrlen = sizeof(PRNetAddr); 1.1036 + result = _PR_MD_GETSOCKNAME(fd, addr, &addrlen); 1.1037 + if (result < 0) { 1.1038 + return PR_FAILURE; 1.1039 + } 1.1040 +#ifdef _PR_INET6 1.1041 + if (AF_INET6 == addr->raw.family) 1.1042 + addr->raw.family = PR_AF_INET6; 1.1043 +#endif 1.1044 + PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); 1.1045 + PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE); 1.1046 + return PR_SUCCESS; 1.1047 +} 1.1048 + 1.1049 +static PRStatus PR_CALLBACK SocketGetPeerName(PRFileDesc *fd, PRNetAddr *addr) 1.1050 +{ 1.1051 + PRInt32 result; 1.1052 + PRUint32 addrlen; 1.1053 + 1.1054 + addrlen = sizeof(PRNetAddr); 1.1055 + result = _PR_MD_GETPEERNAME(fd, addr, &addrlen); 1.1056 + if (result < 0) { 1.1057 + return PR_FAILURE; 1.1058 + } 1.1059 +#ifdef _PR_INET6 1.1060 + if (AF_INET6 == addr->raw.family) 1.1061 + addr->raw.family = PR_AF_INET6; 1.1062 +#endif 1.1063 + PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); 1.1064 + PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE); 1.1065 + return PR_SUCCESS; 1.1066 +} 1.1067 + 1.1068 +static PRInt16 PR_CALLBACK SocketPoll( 1.1069 + PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) 1.1070 +{ 1.1071 + *out_flags = 0; 1.1072 + return in_flags; 1.1073 +} /* SocketPoll */ 1.1074 + 1.1075 +static PRIOMethods tcpMethods = { 1.1076 + PR_DESC_SOCKET_TCP, 1.1077 + SocketClose, 1.1078 + SocketRead, 1.1079 + SocketWrite, 1.1080 + SocketAvailable, 1.1081 + SocketAvailable64, 1.1082 + SocketSync, 1.1083 + (PRSeekFN)_PR_InvalidInt, 1.1084 + (PRSeek64FN)_PR_InvalidInt64, 1.1085 + (PRFileInfoFN)_PR_InvalidStatus, 1.1086 + (PRFileInfo64FN)_PR_InvalidStatus, 1.1087 + SocketWritev, 1.1088 + SocketConnect, 1.1089 + SocketAccept, 1.1090 + SocketBind, 1.1091 + SocketListen, 1.1092 + SocketShutdown, 1.1093 + SocketRecv, 1.1094 + SocketSend, 1.1095 + (PRRecvfromFN)_PR_InvalidInt, 1.1096 + (PRSendtoFN)_PR_InvalidInt, 1.1097 + SocketPoll, 1.1098 + SocketAcceptRead, 1.1099 + SocketTransmitFile, 1.1100 + SocketGetName, 1.1101 + SocketGetPeerName, 1.1102 + (PRReservedFN)_PR_InvalidInt, 1.1103 + (PRReservedFN)_PR_InvalidInt, 1.1104 + _PR_SocketGetSocketOption, 1.1105 + _PR_SocketSetSocketOption, 1.1106 + SocketSendFile, 1.1107 + SocketConnectContinue, 1.1108 + (PRReservedFN)_PR_InvalidInt, 1.1109 + (PRReservedFN)_PR_InvalidInt, 1.1110 + (PRReservedFN)_PR_InvalidInt, 1.1111 + (PRReservedFN)_PR_InvalidInt 1.1112 +}; 1.1113 + 1.1114 +static PRIOMethods udpMethods = { 1.1115 + PR_DESC_SOCKET_UDP, 1.1116 + SocketClose, 1.1117 + SocketRead, 1.1118 + SocketWrite, 1.1119 + SocketAvailable, 1.1120 + SocketAvailable64, 1.1121 + SocketSync, 1.1122 + (PRSeekFN)_PR_InvalidInt, 1.1123 + (PRSeek64FN)_PR_InvalidInt64, 1.1124 + (PRFileInfoFN)_PR_InvalidStatus, 1.1125 + (PRFileInfo64FN)_PR_InvalidStatus, 1.1126 + SocketWritev, 1.1127 + SocketConnect, 1.1128 + (PRAcceptFN)_PR_InvalidDesc, 1.1129 + SocketBind, 1.1130 + SocketListen, 1.1131 + SocketShutdown, 1.1132 + SocketRecv, 1.1133 + SocketSend, 1.1134 + SocketRecvFrom, 1.1135 + SocketSendTo, 1.1136 + SocketPoll, 1.1137 + (PRAcceptreadFN)_PR_InvalidInt, 1.1138 + (PRTransmitfileFN)_PR_InvalidInt, 1.1139 + SocketGetName, 1.1140 + SocketGetPeerName, 1.1141 + (PRReservedFN)_PR_InvalidInt, 1.1142 + (PRReservedFN)_PR_InvalidInt, 1.1143 + _PR_SocketGetSocketOption, 1.1144 + _PR_SocketSetSocketOption, 1.1145 + (PRSendfileFN)_PR_InvalidInt, 1.1146 + (PRConnectcontinueFN)_PR_InvalidStatus, 1.1147 + (PRReservedFN)_PR_InvalidInt, 1.1148 + (PRReservedFN)_PR_InvalidInt, 1.1149 + (PRReservedFN)_PR_InvalidInt, 1.1150 + (PRReservedFN)_PR_InvalidInt 1.1151 +}; 1.1152 + 1.1153 + 1.1154 +static PRIOMethods socketpollfdMethods = { 1.1155 + (PRDescType) 0, 1.1156 + (PRCloseFN)_PR_InvalidStatus, 1.1157 + (PRReadFN)_PR_InvalidInt, 1.1158 + (PRWriteFN)_PR_InvalidInt, 1.1159 + (PRAvailableFN)_PR_InvalidInt, 1.1160 + (PRAvailable64FN)_PR_InvalidInt64, 1.1161 + (PRFsyncFN)_PR_InvalidStatus, 1.1162 + (PRSeekFN)_PR_InvalidInt, 1.1163 + (PRSeek64FN)_PR_InvalidInt64, 1.1164 + (PRFileInfoFN)_PR_InvalidStatus, 1.1165 + (PRFileInfo64FN)_PR_InvalidStatus, 1.1166 + (PRWritevFN)_PR_InvalidInt, 1.1167 + (PRConnectFN)_PR_InvalidStatus, 1.1168 + (PRAcceptFN)_PR_InvalidDesc, 1.1169 + (PRBindFN)_PR_InvalidStatus, 1.1170 + (PRListenFN)_PR_InvalidStatus, 1.1171 + (PRShutdownFN)_PR_InvalidStatus, 1.1172 + (PRRecvFN)_PR_InvalidInt, 1.1173 + (PRSendFN)_PR_InvalidInt, 1.1174 + (PRRecvfromFN)_PR_InvalidInt, 1.1175 + (PRSendtoFN)_PR_InvalidInt, 1.1176 + SocketPoll, 1.1177 + (PRAcceptreadFN)_PR_InvalidInt, 1.1178 + (PRTransmitfileFN)_PR_InvalidInt, 1.1179 + (PRGetsocknameFN)_PR_InvalidStatus, 1.1180 + (PRGetpeernameFN)_PR_InvalidStatus, 1.1181 + (PRReservedFN)_PR_InvalidInt, 1.1182 + (PRReservedFN)_PR_InvalidInt, 1.1183 + (PRGetsocketoptionFN)_PR_InvalidStatus, 1.1184 + (PRSetsocketoptionFN)_PR_InvalidStatus, 1.1185 + (PRSendfileFN)_PR_InvalidInt, 1.1186 + (PRConnectcontinueFN)_PR_InvalidStatus, 1.1187 + (PRReservedFN)_PR_InvalidInt, 1.1188 + (PRReservedFN)_PR_InvalidInt, 1.1189 + (PRReservedFN)_PR_InvalidInt, 1.1190 + (PRReservedFN)_PR_InvalidInt 1.1191 +}; 1.1192 + 1.1193 +PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods() 1.1194 +{ 1.1195 + return &tcpMethods; 1.1196 +} 1.1197 + 1.1198 +PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods() 1.1199 +{ 1.1200 + return &udpMethods; 1.1201 +} 1.1202 + 1.1203 +static const PRIOMethods* PR_GetSocketPollFdMethods() 1.1204 +{ 1.1205 + return &socketpollfdMethods; 1.1206 +} /* PR_GetSocketPollFdMethods */ 1.1207 + 1.1208 +#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) 1.1209 +PR_EXTERN(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd); 1.1210 + 1.1211 +#if defined(_PR_INET6_PROBE) 1.1212 + 1.1213 +extern PRBool _pr_ipv6_is_present(void); 1.1214 + 1.1215 +PR_IMPLEMENT(PRBool) _pr_test_ipv6_socket() 1.1216 +{ 1.1217 + PROsfd osfd; 1.1218 + 1.1219 + osfd = _PR_MD_SOCKET(AF_INET6, SOCK_STREAM, 0); 1.1220 + if (osfd != -1) { 1.1221 + _PR_MD_CLOSE_SOCKET(osfd); 1.1222 + return PR_TRUE; 1.1223 + } 1.1224 + return PR_FALSE; 1.1225 +} 1.1226 +#endif /* _PR_INET6_PROBE */ 1.1227 + 1.1228 +#endif 1.1229 + 1.1230 +PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto) 1.1231 +{ 1.1232 + PROsfd osfd; 1.1233 + PRFileDesc *fd; 1.1234 + PRInt32 tmp_domain = domain; 1.1235 + 1.1236 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.1237 + if (PR_AF_INET != domain 1.1238 + && PR_AF_INET6 != domain 1.1239 +#if defined(XP_UNIX) || defined(XP_OS2) 1.1240 + && PR_AF_LOCAL != domain 1.1241 +#endif 1.1242 + ) { 1.1243 + PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); 1.1244 + return NULL; 1.1245 + } 1.1246 + 1.1247 +#if defined(_PR_INET6_PROBE) 1.1248 + if (PR_AF_INET6 == domain) 1.1249 + domain = _pr_ipv6_is_present() ? AF_INET6 : AF_INET; 1.1250 +#elif defined(_PR_INET6) 1.1251 + if (PR_AF_INET6 == domain) 1.1252 + domain = AF_INET6; 1.1253 +#else 1.1254 + if (PR_AF_INET6 == domain) 1.1255 + domain = AF_INET; 1.1256 +#endif /* _PR_INET6 */ 1.1257 + osfd = _PR_MD_SOCKET(domain, type, proto); 1.1258 + if (osfd == -1) { 1.1259 + return 0; 1.1260 + } 1.1261 + if (type == SOCK_STREAM) 1.1262 + fd = PR_AllocFileDesc(osfd, PR_GetTCPMethods()); 1.1263 + else 1.1264 + fd = PR_AllocFileDesc(osfd, PR_GetUDPMethods()); 1.1265 + /* 1.1266 + * Make the sockets non-blocking 1.1267 + */ 1.1268 + if (fd != NULL) { 1.1269 + _PR_MD_MAKE_NONBLOCK(fd); 1.1270 + _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE); 1.1271 +#ifdef _PR_NEED_SECRET_AF 1.1272 + fd->secret->af = domain; 1.1273 +#endif 1.1274 +#if defined(_PR_INET6_PROBE) || !defined(_PR_INET6) 1.1275 + /* 1.1276 + * For platforms with no support for IPv6 1.1277 + * create layered socket for IPv4-mapped IPv6 addresses 1.1278 + */ 1.1279 + if (PR_AF_INET6 == tmp_domain && PR_AF_INET == domain) { 1.1280 + if (PR_FAILURE == _pr_push_ipv6toipv4_layer(fd)) { 1.1281 + PR_Close(fd); 1.1282 + fd = NULL; 1.1283 + } 1.1284 + } 1.1285 +#endif 1.1286 + } else 1.1287 + _PR_MD_CLOSE_SOCKET(osfd); 1.1288 + 1.1289 + return fd; 1.1290 +} 1.1291 + 1.1292 +PR_IMPLEMENT(PRFileDesc *) PR_NewTCPSocket(void) 1.1293 +{ 1.1294 + PRInt32 domain = AF_INET; 1.1295 + 1.1296 + return PR_Socket(domain, SOCK_STREAM, 0); 1.1297 +} 1.1298 + 1.1299 +PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket(void) 1.1300 +{ 1.1301 + PRInt32 domain = AF_INET; 1.1302 + 1.1303 + return PR_Socket(domain, SOCK_DGRAM, 0); 1.1304 +} 1.1305 + 1.1306 +PR_IMPLEMENT(PRFileDesc *) PR_OpenTCPSocket(PRIntn af) 1.1307 +{ 1.1308 + return PR_Socket(af, SOCK_STREAM, 0); 1.1309 +} 1.1310 + 1.1311 +PR_IMPLEMENT(PRFileDesc*) PR_OpenUDPSocket(PRIntn af) 1.1312 +{ 1.1313 + return PR_Socket(af, SOCK_DGRAM, 0); 1.1314 +} 1.1315 + 1.1316 +PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *f[]) 1.1317 +{ 1.1318 +#ifdef XP_UNIX 1.1319 + PRInt32 rv, osfd[2]; 1.1320 + 1.1321 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.1322 + 1.1323 + rv = _PR_MD_SOCKETPAIR(AF_UNIX, SOCK_STREAM, 0, osfd); 1.1324 + if (rv == -1) { 1.1325 + return PR_FAILURE; 1.1326 + } 1.1327 + 1.1328 + f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods()); 1.1329 + if (!f[0]) { 1.1330 + _PR_MD_CLOSE_SOCKET(osfd[0]); 1.1331 + _PR_MD_CLOSE_SOCKET(osfd[1]); 1.1332 + /* PR_AllocFileDesc() has invoked PR_SetError(). */ 1.1333 + return PR_FAILURE; 1.1334 + } 1.1335 + f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods()); 1.1336 + if (!f[1]) { 1.1337 + PR_Close(f[0]); 1.1338 + _PR_MD_CLOSE_SOCKET(osfd[1]); 1.1339 + /* PR_AllocFileDesc() has invoked PR_SetError(). */ 1.1340 + return PR_FAILURE; 1.1341 + } 1.1342 + _PR_MD_MAKE_NONBLOCK(f[0]); 1.1343 + _PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE); 1.1344 + _PR_MD_MAKE_NONBLOCK(f[1]); 1.1345 + _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE); 1.1346 + return PR_SUCCESS; 1.1347 +#elif defined(WINNT) 1.1348 + /* 1.1349 + * A socket pair is often used for interprocess communication, 1.1350 + * so we need to make sure neither socket is associated with 1.1351 + * the I/O completion port; otherwise it can't be used by a 1.1352 + * child process. 1.1353 + * 1.1354 + * The default implementation below cannot be used for NT 1.1355 + * because PR_Accept would have associated the I/O completion 1.1356 + * port with the listening and accepted sockets. 1.1357 + */ 1.1358 + SOCKET listenSock; 1.1359 + SOCKET osfd[2]; 1.1360 + struct sockaddr_in selfAddr, peerAddr; 1.1361 + int addrLen; 1.1362 + 1.1363 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.1364 + 1.1365 + osfd[0] = osfd[1] = INVALID_SOCKET; 1.1366 + listenSock = socket(AF_INET, SOCK_STREAM, 0); 1.1367 + if (listenSock == INVALID_SOCKET) { 1.1368 + goto failed; 1.1369 + } 1.1370 + selfAddr.sin_family = AF_INET; 1.1371 + selfAddr.sin_port = 0; 1.1372 + selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* BugZilla: 35408 */ 1.1373 + addrLen = sizeof(selfAddr); 1.1374 + if (bind(listenSock, (struct sockaddr *) &selfAddr, 1.1375 + addrLen) == SOCKET_ERROR) { 1.1376 + goto failed; 1.1377 + } 1.1378 + if (getsockname(listenSock, (struct sockaddr *) &selfAddr, 1.1379 + &addrLen) == SOCKET_ERROR) { 1.1380 + goto failed; 1.1381 + } 1.1382 + if (listen(listenSock, 5) == SOCKET_ERROR) { 1.1383 + goto failed; 1.1384 + } 1.1385 + osfd[0] = socket(AF_INET, SOCK_STREAM, 0); 1.1386 + if (osfd[0] == INVALID_SOCKET) { 1.1387 + goto failed; 1.1388 + } 1.1389 + selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1.1390 + 1.1391 + /* 1.1392 + * Only a thread is used to do the connect and accept. 1.1393 + * I am relying on the fact that connect returns 1.1394 + * successfully as soon as the connect request is put 1.1395 + * into the listen queue (but before accept is called). 1.1396 + * This is the behavior of the BSD socket code. If 1.1397 + * connect does not return until accept is called, we 1.1398 + * will need to create another thread to call connect. 1.1399 + */ 1.1400 + if (connect(osfd[0], (struct sockaddr *) &selfAddr, 1.1401 + addrLen) == SOCKET_ERROR) { 1.1402 + goto failed; 1.1403 + } 1.1404 + /* 1.1405 + * A malicious local process may connect to the listening 1.1406 + * socket, so we need to verify that the accepted connection 1.1407 + * is made from our own socket osfd[0]. 1.1408 + */ 1.1409 + if (getsockname(osfd[0], (struct sockaddr *) &selfAddr, 1.1410 + &addrLen) == SOCKET_ERROR) { 1.1411 + goto failed; 1.1412 + } 1.1413 + osfd[1] = accept(listenSock, (struct sockaddr *) &peerAddr, &addrLen); 1.1414 + if (osfd[1] == INVALID_SOCKET) { 1.1415 + goto failed; 1.1416 + } 1.1417 + if (peerAddr.sin_port != selfAddr.sin_port) { 1.1418 + /* the connection we accepted is not from osfd[0] */ 1.1419 + PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); 1.1420 + goto failed; 1.1421 + } 1.1422 + closesocket(listenSock); 1.1423 + 1.1424 + f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods()); 1.1425 + if (!f[0]) { 1.1426 + closesocket(osfd[0]); 1.1427 + closesocket(osfd[1]); 1.1428 + /* PR_AllocFileDesc() has invoked PR_SetError(). */ 1.1429 + return PR_FAILURE; 1.1430 + } 1.1431 + f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods()); 1.1432 + if (!f[1]) { 1.1433 + PR_Close(f[0]); 1.1434 + closesocket(osfd[1]); 1.1435 + /* PR_AllocFileDesc() has invoked PR_SetError(). */ 1.1436 + return PR_FAILURE; 1.1437 + } 1.1438 + _PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE); 1.1439 + _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE); 1.1440 + return PR_SUCCESS; 1.1441 + 1.1442 +failed: 1.1443 + if (listenSock != INVALID_SOCKET) { 1.1444 + closesocket(listenSock); 1.1445 + } 1.1446 + if (osfd[0] != INVALID_SOCKET) { 1.1447 + closesocket(osfd[0]); 1.1448 + } 1.1449 + if (osfd[1] != INVALID_SOCKET) { 1.1450 + closesocket(osfd[1]); 1.1451 + } 1.1452 + return PR_FAILURE; 1.1453 +#else /* not Unix or NT */ 1.1454 + /* 1.1455 + * default implementation 1.1456 + */ 1.1457 + PRFileDesc *listenSock; 1.1458 + PRNetAddr selfAddr, peerAddr; 1.1459 + PRUint16 port; 1.1460 + 1.1461 + f[0] = f[1] = NULL; 1.1462 + listenSock = PR_NewTCPSocket(); 1.1463 + if (listenSock == NULL) { 1.1464 + goto failed; 1.1465 + } 1.1466 + PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); /* BugZilla: 35408 */ 1.1467 + if (PR_Bind(listenSock, &selfAddr) == PR_FAILURE) { 1.1468 + goto failed; 1.1469 + } 1.1470 + if (PR_GetSockName(listenSock, &selfAddr) == PR_FAILURE) { 1.1471 + goto failed; 1.1472 + } 1.1473 + port = ntohs(selfAddr.inet.port); 1.1474 + if (PR_Listen(listenSock, 5) == PR_FAILURE) { 1.1475 + goto failed; 1.1476 + } 1.1477 + f[0] = PR_NewTCPSocket(); 1.1478 + if (f[0] == NULL) { 1.1479 + goto failed; 1.1480 + } 1.1481 +#ifdef _PR_CONNECT_DOES_NOT_BIND 1.1482 + /* 1.1483 + * If connect does not implicitly bind the socket (e.g., on 1.1484 + * BeOS), we have to bind the socket so that we can get its 1.1485 + * port with getsockname later. 1.1486 + */ 1.1487 + PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); 1.1488 + if (PR_Bind(f[0], &selfAddr) == PR_FAILURE) { 1.1489 + goto failed; 1.1490 + } 1.1491 +#endif 1.1492 + PR_InitializeNetAddr(PR_IpAddrLoopback, port, &selfAddr); 1.1493 + 1.1494 + /* 1.1495 + * Only a thread is used to do the connect and accept. 1.1496 + * I am relying on the fact that PR_Connect returns 1.1497 + * successfully as soon as the connect request is put 1.1498 + * into the listen queue (but before PR_Accept is called). 1.1499 + * This is the behavior of the BSD socket code. If 1.1500 + * connect does not return until accept is called, we 1.1501 + * will need to create another thread to call connect. 1.1502 + */ 1.1503 + if (PR_Connect(f[0], &selfAddr, PR_INTERVAL_NO_TIMEOUT) 1.1504 + == PR_FAILURE) { 1.1505 + goto failed; 1.1506 + } 1.1507 + /* 1.1508 + * A malicious local process may connect to the listening 1.1509 + * socket, so we need to verify that the accepted connection 1.1510 + * is made from our own socket f[0]. 1.1511 + */ 1.1512 + if (PR_GetSockName(f[0], &selfAddr) == PR_FAILURE) { 1.1513 + goto failed; 1.1514 + } 1.1515 + f[1] = PR_Accept(listenSock, &peerAddr, PR_INTERVAL_NO_TIMEOUT); 1.1516 + if (f[1] == NULL) { 1.1517 + goto failed; 1.1518 + } 1.1519 + if (peerAddr.inet.port != selfAddr.inet.port) { 1.1520 + /* the connection we accepted is not from f[0] */ 1.1521 + PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); 1.1522 + goto failed; 1.1523 + } 1.1524 + PR_Close(listenSock); 1.1525 + return PR_SUCCESS; 1.1526 + 1.1527 +failed: 1.1528 + if (listenSock) { 1.1529 + PR_Close(listenSock); 1.1530 + } 1.1531 + if (f[0]) { 1.1532 + PR_Close(f[0]); 1.1533 + } 1.1534 + if (f[1]) { 1.1535 + PR_Close(f[1]); 1.1536 + } 1.1537 + return PR_FAILURE; 1.1538 +#endif 1.1539 +} 1.1540 + 1.1541 +PR_IMPLEMENT(PROsfd) 1.1542 +PR_FileDesc2NativeHandle(PRFileDesc *fd) 1.1543 +{ 1.1544 + if (fd) { 1.1545 + fd = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER); 1.1546 + } 1.1547 + if (!fd) { 1.1548 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.1549 + return -1; 1.1550 + } 1.1551 + return fd->secret->md.osfd; 1.1552 +} 1.1553 + 1.1554 +PR_IMPLEMENT(void) 1.1555 +PR_ChangeFileDescNativeHandle(PRFileDesc *fd, PROsfd handle) 1.1556 +{ 1.1557 + if (fd) 1.1558 + fd->secret->md.osfd = handle; 1.1559 +} 1.1560 + 1.1561 +/* 1.1562 +** Select compatibility 1.1563 +** 1.1564 +*/ 1.1565 + 1.1566 +PR_IMPLEMENT(void) PR_FD_ZERO(PR_fd_set *set) 1.1567 +{ 1.1568 + memset(set, 0, sizeof(PR_fd_set)); 1.1569 +} 1.1570 + 1.1571 +PR_IMPLEMENT(void) PR_FD_SET(PRFileDesc *fh, PR_fd_set *set) 1.1572 +{ 1.1573 + PR_ASSERT( set->hsize < PR_MAX_SELECT_DESC ); 1.1574 + 1.1575 + set->harray[set->hsize++] = fh; 1.1576 +} 1.1577 + 1.1578 +PR_IMPLEMENT(void) PR_FD_CLR(PRFileDesc *fh, PR_fd_set *set) 1.1579 +{ 1.1580 + PRUint32 index, index2; 1.1581 + 1.1582 + for (index = 0; index<set->hsize; index++) 1.1583 + if (set->harray[index] == fh) { 1.1584 + for (index2=index; index2 < (set->hsize-1); index2++) { 1.1585 + set->harray[index2] = set->harray[index2+1]; 1.1586 + } 1.1587 + set->hsize--; 1.1588 + break; 1.1589 + } 1.1590 +} 1.1591 + 1.1592 +PR_IMPLEMENT(PRInt32) PR_FD_ISSET(PRFileDesc *fh, PR_fd_set *set) 1.1593 +{ 1.1594 + PRUint32 index; 1.1595 + for (index = 0; index<set->hsize; index++) 1.1596 + if (set->harray[index] == fh) { 1.1597 + return 1; 1.1598 + } 1.1599 + return 0; 1.1600 +} 1.1601 + 1.1602 +PR_IMPLEMENT(void) PR_FD_NSET(PROsfd fd, PR_fd_set *set) 1.1603 +{ 1.1604 + PR_ASSERT( set->nsize < PR_MAX_SELECT_DESC ); 1.1605 + 1.1606 + set->narray[set->nsize++] = fd; 1.1607 +} 1.1608 + 1.1609 +PR_IMPLEMENT(void) PR_FD_NCLR(PROsfd fd, PR_fd_set *set) 1.1610 +{ 1.1611 + PRUint32 index, index2; 1.1612 + 1.1613 + for (index = 0; index<set->nsize; index++) 1.1614 + if (set->narray[index] == fd) { 1.1615 + for (index2=index; index2 < (set->nsize-1); index2++) { 1.1616 + set->narray[index2] = set->narray[index2+1]; 1.1617 + } 1.1618 + set->nsize--; 1.1619 + break; 1.1620 + } 1.1621 +} 1.1622 + 1.1623 +PR_IMPLEMENT(PRInt32) PR_FD_NISSET(PROsfd fd, PR_fd_set *set) 1.1624 +{ 1.1625 + PRUint32 index; 1.1626 + for (index = 0; index<set->nsize; index++) 1.1627 + if (set->narray[index] == fd) { 1.1628 + return 1; 1.1629 + } 1.1630 + return 0; 1.1631 +} 1.1632 + 1.1633 + 1.1634 +#if !defined(NEED_SELECT) 1.1635 +#include "obsolete/probslet.h" 1.1636 + 1.1637 +#define PD_INCR 20 1.1638 + 1.1639 +static PRPollDesc *_pr_setfd( 1.1640 + PR_fd_set *set, PRInt16 flags, PRPollDesc *polldesc) 1.1641 +{ 1.1642 + PRUintn fsidx, pdidx; 1.1643 + PRPollDesc *poll = polldesc; 1.1644 + 1.1645 + if (NULL == set) return poll; 1.1646 + 1.1647 + /* First set the pr file handle osfds */ 1.1648 + for (fsidx = 0; fsidx < set->hsize; fsidx++) 1.1649 + { 1.1650 + for (pdidx = 0; 1; pdidx++) 1.1651 + { 1.1652 + if ((PRFileDesc*)-1 == poll[pdidx].fd) 1.1653 + { 1.1654 + /* our vector is full - extend and condition it */ 1.1655 + poll = (PRPollDesc*)PR_Realloc( 1.1656 + poll, (pdidx + 1 + PD_INCR) * sizeof(PRPollDesc)); 1.1657 + if (NULL == poll) goto out_of_memory; 1.1658 + memset( 1.1659 + poll + pdidx * sizeof(PRPollDesc), 1.1660 + 0, PD_INCR * sizeof(PRPollDesc)); 1.1661 + poll[pdidx + PD_INCR].fd = (PRFileDesc*)-1; 1.1662 + } 1.1663 + if ((NULL == poll[pdidx].fd) 1.1664 + || (poll[pdidx].fd == set->harray[fsidx])) 1.1665 + { 1.1666 + /* PR_ASSERT(0 == (poll[pdidx].in_flags & flags)); */ 1.1667 + /* either empty or prevously defined */ 1.1668 + poll[pdidx].fd = set->harray[fsidx]; /* possibly redundant */ 1.1669 + poll[pdidx].in_flags |= flags; /* possibly redundant */ 1.1670 + break; 1.1671 + } 1.1672 + } 1.1673 + } 1.1674 + 1.1675 +#if 0 1.1676 + /* Second set the native osfds */ 1.1677 + for (fsidx = 0; fsidx < set->nsize; fsidx++) 1.1678 + { 1.1679 + for (pdidx = 0; ((PRFileDesc*)-1 != poll[pdidx].fd); pdidx++) 1.1680 + { 1.1681 + if ((PRFileDesc*)-1 == poll[pdidx].fd) 1.1682 + { 1.1683 + /* our vector is full - extend and condition it */ 1.1684 + poll = PR_Realloc( 1.1685 + poll, (pdidx + PD_INCR) * sizeof(PRPollDesc)); 1.1686 + if (NULL == poll) goto out_of_memory; 1.1687 + memset( 1.1688 + poll + pdidx * sizeof(PRPollDesc), 1.1689 + 0, PD_INCR * sizeof(PRPollDesc)); 1.1690 + poll[(pdidx + PD_INCR)].fd = (PRFileDesc*)-1; 1.1691 + } 1.1692 + if ((NULL == poll[pdidx].fd) 1.1693 + || (poll[pdidx].fd == set->narray[fsidx])) 1.1694 + { 1.1695 + /* either empty or prevously defined */ 1.1696 + poll[pdidx].fd = set->narray[fsidx]; 1.1697 + PR_ASSERT(0 == (poll[pdidx].in_flags & flags)); 1.1698 + poll[pdidx].in_flags |= flags; 1.1699 + break; 1.1700 + } 1.1701 + } 1.1702 + } 1.1703 +#endif /* 0 */ 1.1704 + 1.1705 + return poll; 1.1706 + 1.1707 +out_of_memory: 1.1708 + if (NULL != polldesc) PR_DELETE(polldesc); 1.1709 + return NULL; 1.1710 +} /* _pr_setfd */ 1.1711 + 1.1712 +#endif /* !defined(NEED_SELECT) */ 1.1713 + 1.1714 +PR_IMPLEMENT(PRInt32) PR_Select( 1.1715 + PRInt32 unused, PR_fd_set *pr_rd, PR_fd_set *pr_wr, 1.1716 + PR_fd_set *pr_ex, PRIntervalTime timeout) 1.1717 +{ 1.1718 + 1.1719 +#if !defined(NEED_SELECT) 1.1720 + PRInt32 npds = 0; 1.1721 + /* 1.1722 + ** Find out how many fds are represented in the three lists. 1.1723 + ** Then allocate a polling descriptor for the logical union 1.1724 + ** (there can't be any overlapping) and call PR_Poll(). 1.1725 + */ 1.1726 + 1.1727 + PRPollDesc *copy, *poll; 1.1728 + 1.1729 + static PRBool warning = PR_TRUE; 1.1730 + if (warning) warning = _PR_Obsolete( "PR_Select()", "PR_Poll()"); 1.1731 + 1.1732 + /* try to get an initial guesss at how much space we need */ 1.1733 + npds = 0; 1.1734 + if ((NULL != pr_rd) && ((pr_rd->hsize + pr_rd->nsize - npds) > 0)) 1.1735 + npds = pr_rd->hsize + pr_rd->nsize; 1.1736 + if ((NULL != pr_wr) && ((pr_wr->hsize + pr_wr->nsize - npds) > 0)) 1.1737 + npds = pr_wr->hsize + pr_wr->nsize; 1.1738 + if ((NULL != pr_ex) && ((pr_ex->hsize + pr_ex->nsize - npds) > 0)) 1.1739 + npds = pr_ex->hsize + pr_ex->nsize; 1.1740 + 1.1741 + if (0 == npds) 1.1742 + { 1.1743 + PR_Sleep(timeout); 1.1744 + return 0; 1.1745 + } 1.1746 + 1.1747 + copy = poll = (PRPollDesc*)PR_Calloc(npds + PD_INCR, sizeof(PRPollDesc)); 1.1748 + if (NULL == poll) goto out_of_memory; 1.1749 + poll[npds + PD_INCR - 1].fd = (PRFileDesc*)-1; 1.1750 + 1.1751 + poll = _pr_setfd(pr_rd, PR_POLL_READ, poll); 1.1752 + if (NULL == poll) goto out_of_memory; 1.1753 + poll = _pr_setfd(pr_wr, PR_POLL_WRITE, poll); 1.1754 + if (NULL == poll) goto out_of_memory; 1.1755 + poll = _pr_setfd(pr_ex, PR_POLL_EXCEPT, poll); 1.1756 + if (NULL == poll) goto out_of_memory; 1.1757 + unused = 0; 1.1758 + while (NULL != poll[unused].fd && (PRFileDesc*)-1 != poll[unused].fd) 1.1759 + { 1.1760 + ++unused; 1.1761 + } 1.1762 + 1.1763 + PR_ASSERT(unused > 0); 1.1764 + npds = PR_Poll(poll, unused, timeout); 1.1765 + 1.1766 + if (npds > 0) 1.1767 + { 1.1768 + /* Copy the results back into the fd sets */ 1.1769 + if (NULL != pr_rd) pr_rd->nsize = pr_rd->hsize = 0; 1.1770 + if (NULL != pr_wr) pr_wr->nsize = pr_wr->hsize = 0; 1.1771 + if (NULL != pr_ex) pr_ex->nsize = pr_ex->hsize = 0; 1.1772 + for (copy = &poll[unused - 1]; copy >= poll; --copy) 1.1773 + { 1.1774 + if (copy->out_flags & PR_POLL_NVAL) 1.1775 + { 1.1776 + PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); 1.1777 + npds = -1; 1.1778 + break; 1.1779 + } 1.1780 + if (copy->out_flags & PR_POLL_READ) 1.1781 + if (NULL != pr_rd) pr_rd->harray[pr_rd->hsize++] = copy->fd; 1.1782 + if (copy->out_flags & PR_POLL_WRITE) 1.1783 + if (NULL != pr_wr) pr_wr->harray[pr_wr->hsize++] = copy->fd; 1.1784 + if (copy->out_flags & PR_POLL_EXCEPT) 1.1785 + if (NULL != pr_ex) pr_ex->harray[pr_ex->hsize++] = copy->fd; 1.1786 + } 1.1787 + } 1.1788 + PR_DELETE(poll); 1.1789 + 1.1790 + return npds; 1.1791 +out_of_memory: 1.1792 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.1793 + return -1; 1.1794 + 1.1795 +#endif /* !defined(NEED_SELECT) */ 1.1796 + 1.1797 +}