| OLD | NEW |
| (Empty) |
| 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/. */ | |
| 5 | |
| 6 /* Win95 Sockets module | |
| 7 * | |
| 8 */ | |
| 9 | |
| 10 #include "primpl.h" | |
| 11 | |
| 12 #define READ_FD 1 | |
| 13 #define WRITE_FD 2 | |
| 14 #define CONNECT_FD 3 | |
| 15 | |
| 16 static PRInt32 socket_io_wait( | |
| 17 PROsfd osfd, | |
| 18 PRInt32 fd_type, | |
| 19 PRIntervalTime timeout); | |
| 20 | |
| 21 | |
| 22 /* --- SOCKET IO --------------------------------------------------------- */ | |
| 23 | |
| 24 static PRBool socketFixInet6RcvBuf = PR_FALSE; | |
| 25 | |
| 26 void _PR_MD_InitSockets(void) | |
| 27 { | |
| 28 OSVERSIONINFO osvi; | |
| 29 | |
| 30 memset(&osvi, 0, sizeof(osvi)); | |
| 31 osvi.dwOSVersionInfoSize = sizeof(osvi); | |
| 32 GetVersionEx(&osvi); | |
| 33 | |
| 34 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) | |
| 35 { | |
| 36 /* if Windows XP (32-bit) */ | |
| 37 socketFixInet6RcvBuf = PR_TRUE; | |
| 38 } | |
| 39 } | |
| 40 | |
| 41 void _PR_MD_CleanupSockets(void) | |
| 42 { | |
| 43 socketFixInet6RcvBuf = PR_FALSE; | |
| 44 } | |
| 45 | |
| 46 PROsfd | |
| 47 _PR_MD_SOCKET(int af, int type, int flags) | |
| 48 { | |
| 49 SOCKET sock; | |
| 50 u_long one = 1; | |
| 51 | |
| 52 sock = socket(af, type, flags); | |
| 53 | |
| 54 if (sock == INVALID_SOCKET ) | |
| 55 { | |
| 56 _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError()); | |
| 57 return (PROsfd)sock; | |
| 58 } | |
| 59 | |
| 60 /* | |
| 61 ** Make the socket Non-Blocking | |
| 62 */ | |
| 63 if (ioctlsocket( sock, FIONBIO, &one) != 0) | |
| 64 { | |
| 65 PR_SetError(PR_UNKNOWN_ERROR, WSAGetLastError()); | |
| 66 closesocket(sock); | |
| 67 return -1; | |
| 68 } | |
| 69 | |
| 70 if (af == AF_INET6 && socketFixInet6RcvBuf) | |
| 71 { | |
| 72 int bufsize; | |
| 73 int len = sizeof(bufsize); | |
| 74 int rv; | |
| 75 | |
| 76 /* Windows XP 32-bit returns an error on getpeername() for AF_INET6 | |
| 77 * sockets if the receive buffer size is greater than 65535 before | |
| 78 * the connection is initiated. The default receive buffer size may | |
| 79 * be 128000 so fix it here to always be <= 65535. See bug 513659 | |
| 80 * and IBM DB2 support technote "Receive/Send IPv6 Socket Size | |
| 81 * Problem in Windows XP SP2 & SP3". | |
| 82 */ | |
| 83 rv = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, &len); | |
| 84 if (rv == 0 && bufsize > 65535) | |
| 85 { | |
| 86 bufsize = 65535; | |
| 87 setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, len); | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 return (PROsfd)sock; | |
| 92 } | |
| 93 | |
| 94 /* | |
| 95 ** _MD_CloseSocket() -- Close a socket | |
| 96 ** | |
| 97 */ | |
| 98 PRInt32 | |
| 99 _MD_CloseSocket(PROsfd osfd) | |
| 100 { | |
| 101 PRInt32 rv; | |
| 102 | |
| 103 rv = closesocket((SOCKET) osfd ); | |
| 104 if (rv < 0) | |
| 105 _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError()); | |
| 106 | |
| 107 return rv; | |
| 108 } | |
| 109 | |
| 110 PRInt32 | |
| 111 _MD_SocketAvailable(PRFileDesc *fd) | |
| 112 { | |
| 113 PRInt32 result; | |
| 114 | |
| 115 if (ioctlsocket(fd->secret->md.osfd, FIONREAD, &result) < 0) { | |
| 116 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError()); | |
| 117 return -1; | |
| 118 } | |
| 119 return result; | |
| 120 } | |
| 121 | |
| 122 PROsfd _MD_Accept( | |
| 123 PRFileDesc *fd, | |
| 124 PRNetAddr *raddr, | |
| 125 PRUint32 *rlen, | |
| 126 PRIntervalTime timeout ) | |
| 127 { | |
| 128 PROsfd osfd = fd->secret->md.osfd; | |
| 129 SOCKET sock; | |
| 130 PRInt32 rv, err; | |
| 131 | |
| 132 while ((sock = accept(osfd, (struct sockaddr *) raddr, rlen)) == -1) | |
| 133 { | |
| 134 err = WSAGetLastError(); | |
| 135 if ((err == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) | |
| 136 { | |
| 137 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) | |
| 138 { | |
| 139 break; | |
| 140 } | |
| 141 } | |
| 142 else | |
| 143 { | |
| 144 _PR_MD_MAP_ACCEPT_ERROR(err); | |
| 145 break; | |
| 146 } | |
| 147 } | |
| 148 return(sock); | |
| 149 } /* end _MD_accept() */ | |
| 150 | |
| 151 PRInt32 | |
| 152 _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, | |
| 153 PRIntervalTime timeout) | |
| 154 { | |
| 155 PROsfd osfd = fd->secret->md.osfd; | |
| 156 PRInt32 rv; | |
| 157 int err; | |
| 158 | |
| 159 if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1) | |
| 160 { | |
| 161 err = WSAGetLastError(); | |
| 162 if ((!fd->secret->nonblocking) && (err == WSAEWOULDBLOCK)) | |
| 163 { | |
| 164 rv = socket_io_wait(osfd, CONNECT_FD, timeout); | |
| 165 if ( rv < 0 ) | |
| 166 { | |
| 167 return(-1); | |
| 168 } | |
| 169 else | |
| 170 { | |
| 171 PR_ASSERT(rv > 0); | |
| 172 /* it's connected */ | |
| 173 return(0); | |
| 174 } | |
| 175 } | |
| 176 _PR_MD_MAP_CONNECT_ERROR(err); | |
| 177 } | |
| 178 return rv; | |
| 179 } | |
| 180 | |
| 181 PRInt32 | |
| 182 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) | |
| 183 { | |
| 184 PRInt32 rv; | |
| 185 | |
| 186 rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrl
en); | |
| 187 | |
| 188 if (rv == SOCKET_ERROR) { | |
| 189 _PR_MD_MAP_BIND_ERROR(WSAGetLastError()); | |
| 190 return -1; | |
| 191 } | |
| 192 | |
| 193 return 0; | |
| 194 } | |
| 195 | |
| 196 PRInt32 | |
| 197 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog) | |
| 198 { | |
| 199 PRInt32 rv; | |
| 200 | |
| 201 rv = listen(fd->secret->md.osfd, backlog); | |
| 202 | |
| 203 if (rv == SOCKET_ERROR) { | |
| 204 _PR_MD_MAP_DEFAULT_ERROR(WSAGetLastError()); | |
| 205 return -1; | |
| 206 } | |
| 207 | |
| 208 return 0; | |
| 209 } | |
| 210 | |
| 211 PRInt32 | |
| 212 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, | |
| 213 PRIntervalTime timeout) | |
| 214 { | |
| 215 PROsfd osfd = fd->secret->md.osfd; | |
| 216 PRInt32 rv, err; | |
| 217 int osflags; | |
| 218 | |
| 219 if (0 == flags) { | |
| 220 osflags = 0; | |
| 221 } else { | |
| 222 PR_ASSERT(PR_MSG_PEEK == flags); | |
| 223 osflags = MSG_PEEK; | |
| 224 } | |
| 225 while ((rv = recv( osfd, buf, amount, osflags)) == -1) | |
| 226 { | |
| 227 if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) | |
| 228 && (!fd->secret->nonblocking)) | |
| 229 { | |
| 230 rv = socket_io_wait(osfd, READ_FD, timeout); | |
| 231 if ( rv < 0 ) | |
| 232 { | |
| 233 return -1; | |
| 234 } | |
| 235 } | |
| 236 else | |
| 237 { | |
| 238 _PR_MD_MAP_RECV_ERROR(err); | |
| 239 break; | |
| 240 } | |
| 241 } /* end while() */ | |
| 242 return(rv); | |
| 243 } | |
| 244 | |
| 245 PRInt32 | |
| 246 _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, | |
| 247 PRIntervalTime timeout) | |
| 248 { | |
| 249 PROsfd osfd = fd->secret->md.osfd; | |
| 250 PRInt32 rv, err; | |
| 251 PRInt32 bytesSent = 0; | |
| 252 | |
| 253 while(bytesSent < amount ) | |
| 254 { | |
| 255 while ((rv = send( osfd, buf, amount, 0 )) == -1) | |
| 256 { | |
| 257 if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) | |
| 258 && (!fd->secret->nonblocking)) | |
| 259 { | |
| 260 rv = socket_io_wait(osfd, WRITE_FD, timeout); | |
| 261 if ( rv < 0 ) | |
| 262 { | |
| 263 return -1; | |
| 264 } | |
| 265 } | |
| 266 else | |
| 267 { | |
| 268 _PR_MD_MAP_SEND_ERROR(err); | |
| 269 return -1; | |
| 270 } | |
| 271 } | |
| 272 bytesSent += rv; | |
| 273 if (fd->secret->nonblocking) | |
| 274 { | |
| 275 break; | |
| 276 } | |
| 277 if (bytesSent < amount) | |
| 278 { | |
| 279 rv = socket_io_wait(osfd, WRITE_FD, timeout); | |
| 280 if ( rv < 0 ) | |
| 281 { | |
| 282 return -1; | |
| 283 } | |
| 284 } | |
| 285 } | |
| 286 return bytesSent; | |
| 287 } | |
| 288 | |
| 289 PRInt32 | |
| 290 _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, | |
| 291 const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) | |
| 292 { | |
| 293 PROsfd osfd = fd->secret->md.osfd; | |
| 294 PRInt32 rv, err; | |
| 295 PRInt32 bytesSent = 0; | |
| 296 | |
| 297 while(bytesSent < amount) | |
| 298 { | |
| 299 while ((rv = sendto( osfd, buf, amount, 0, (struct sockaddr *) addr, | |
| 300 addrlen)) == -1) | |
| 301 { | |
| 302 if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) | |
| 303 && (!fd->secret->nonblocking)) | |
| 304 { | |
| 305 rv = socket_io_wait(osfd, WRITE_FD, timeout); | |
| 306 if ( rv < 0 ) | |
| 307 { | |
| 308 return -1; | |
| 309 } | |
| 310 } | |
| 311 else | |
| 312 { | |
| 313 _PR_MD_MAP_SENDTO_ERROR(err); | |
| 314 return -1; | |
| 315 } | |
| 316 } | |
| 317 bytesSent += rv; | |
| 318 if (fd->secret->nonblocking) | |
| 319 { | |
| 320 break; | |
| 321 } | |
| 322 if (bytesSent < amount) | |
| 323 { | |
| 324 rv = socket_io_wait(osfd, WRITE_FD, timeout); | |
| 325 if (rv < 0) | |
| 326 { | |
| 327 return -1; | |
| 328 } | |
| 329 } | |
| 330 } | |
| 331 return bytesSent; | |
| 332 } | |
| 333 | |
| 334 PRInt32 | |
| 335 _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, | |
| 336 PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) | |
| 337 { | |
| 338 PROsfd osfd = fd->secret->md.osfd; | |
| 339 PRInt32 rv, err; | |
| 340 | |
| 341 while ((rv = recvfrom( osfd, buf, amount, 0, (struct sockaddr *) addr, | |
| 342 addrlen)) == -1) | |
| 343 { | |
| 344 if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) | |
| 345 && (!fd->secret->nonblocking)) | |
| 346 { | |
| 347 rv = socket_io_wait(osfd, READ_FD, timeout); | |
| 348 if ( rv < 0) | |
| 349 { | |
| 350 return -1; | |
| 351 } | |
| 352 } | |
| 353 else | |
| 354 { | |
| 355 _PR_MD_MAP_RECVFROM_ERROR(err); | |
| 356 break; | |
| 357 } | |
| 358 } | |
| 359 return(rv); | |
| 360 } | |
| 361 | |
| 362 PRInt32 | |
| 363 _PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTi
me timeout) | |
| 364 { | |
| 365 int index; | |
| 366 int sent = 0; | |
| 367 int rv; | |
| 368 | |
| 369 for (index=0; index < iov_size; index++) | |
| 370 { | |
| 371 rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout
); | |
| 372 if (rv > 0) | |
| 373 sent += rv; | |
| 374 if ( rv != iov[index].iov_len ) | |
| 375 { | |
| 376 if (rv < 0) | |
| 377 { | |
| 378 if (fd->secret->nonblocking | |
| 379 && (PR_GetError() == PR_WOULD_BLOCK_ERROR) | |
| 380 && (sent > 0)) | |
| 381 { | |
| 382 return sent; | |
| 383 } | |
| 384 else | |
| 385 { | |
| 386 return -1; | |
| 387 } | |
| 388 } | |
| 389 /* Only a nonblocking socket can have partial sends */ | |
| 390 PR_ASSERT(fd->secret->nonblocking); | |
| 391 return sent; | |
| 392 } | |
| 393 } | |
| 394 return sent; | |
| 395 } | |
| 396 | |
| 397 PRInt32 | |
| 398 _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how) | |
| 399 { | |
| 400 PRInt32 rv; | |
| 401 | |
| 402 rv = shutdown(fd->secret->md.osfd, how); | |
| 403 if (rv < 0) | |
| 404 _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError()); | |
| 405 return rv; | |
| 406 } | |
| 407 | |
| 408 PRStatus | |
| 409 _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len) | |
| 410 { | |
| 411 PRInt32 rv; | |
| 412 | |
| 413 rv = getsockname((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len); | |
| 414 if (rv==0) { | |
| 415 return PR_SUCCESS; | |
| 416 } else { | |
| 417 _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError()); | |
| 418 return PR_FAILURE; | |
| 419 } | |
| 420 } | |
| 421 | |
| 422 PRStatus | |
| 423 _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len) | |
| 424 { | |
| 425 PRInt32 rv; | |
| 426 | |
| 427 rv = getpeername((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len); | |
| 428 if (rv==0) { | |
| 429 return PR_SUCCESS; | |
| 430 } else { | |
| 431 _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError()); | |
| 432 return PR_FAILURE; | |
| 433 } | |
| 434 } | |
| 435 | |
| 436 PRStatus | |
| 437 _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval,
PRInt32* optlen) | |
| 438 { | |
| 439 PRInt32 rv; | |
| 440 | |
| 441 rv = getsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen)
; | |
| 442 if (rv==0) { | |
| 443 return PR_SUCCESS; | |
| 444 } else { | |
| 445 _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); | |
| 446 return PR_FAILURE; | |
| 447 } | |
| 448 } | |
| 449 | |
| 450 PRStatus | |
| 451 _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* op
tval, PRInt32 optlen) | |
| 452 { | |
| 453 PRInt32 rv; | |
| 454 | |
| 455 rv = setsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen)
; | |
| 456 if (rv==0) { | |
| 457 return PR_SUCCESS; | |
| 458 } else { | |
| 459 _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError()); | |
| 460 return PR_FAILURE; | |
| 461 } | |
| 462 } | |
| 463 | |
| 464 void | |
| 465 _MD_MakeNonblock(PRFileDesc *f) | |
| 466 { | |
| 467 return; /* do nothing */ | |
| 468 } | |
| 469 | |
| 470 | |
| 471 | |
| 472 /* | |
| 473 * socket_io_wait -- | |
| 474 * | |
| 475 * Wait for socket i/o, periodically checking for interrupt. | |
| 476 * | |
| 477 * This function returns 1 on success. On failure, it returns | |
| 478 * -1 and sets the error codes. It never returns 0. | |
| 479 */ | |
| 480 #define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5 | |
| 481 | |
| 482 static PRInt32 socket_io_wait( | |
| 483 PROsfd osfd, | |
| 484 PRInt32 fd_type, | |
| 485 PRIntervalTime timeout) | |
| 486 { | |
| 487 PRInt32 rv = -1; | |
| 488 struct timeval tv; | |
| 489 PRThread *me = _PR_MD_CURRENT_THREAD(); | |
| 490 PRIntervalTime elapsed, remaining; | |
| 491 PRBool wait_for_remaining; | |
| 492 fd_set rd_wr, ex; | |
| 493 int err, len; | |
| 494 | |
| 495 switch (timeout) { | |
| 496 case PR_INTERVAL_NO_WAIT: | |
| 497 PR_SetError(PR_IO_TIMEOUT_ERROR, 0); | |
| 498 break; | |
| 499 case PR_INTERVAL_NO_TIMEOUT: | |
| 500 /* | |
| 501 * This is a special case of the 'default' case below. | |
| 502 * Please see the comments there. | |
| 503 */ | |
| 504 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; | |
| 505 tv.tv_usec = 0; | |
| 506 FD_ZERO(&rd_wr); | |
| 507 FD_ZERO(&ex); | |
| 508 do { | |
| 509 FD_SET(osfd, &rd_wr); | |
| 510 FD_SET(osfd, &ex); | |
| 511 switch( fd_type ) | |
| 512 { | |
| 513 case READ_FD: | |
| 514 rv = _MD_SELECT(0, &rd_wr, NULL, NULL, &tv); | |
| 515 break; | |
| 516 case WRITE_FD: | |
| 517 rv = _MD_SELECT(0, NULL, &rd_wr, NULL, &tv); | |
| 518 break; | |
| 519 case CONNECT_FD: | |
| 520 rv = _MD_SELECT(0, NULL, &rd_wr, &ex, &tv); | |
| 521 break; | |
| 522 default: | |
| 523 PR_ASSERT(0); | |
| 524 break; | |
| 525 } /* end switch() */ | |
| 526 if (rv == -1 ) | |
| 527 { | |
| 528 _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); | |
| 529 break; | |
| 530 } | |
| 531 if ( rv > 0 && fd_type == CONNECT_FD ) | |
| 532 { | |
| 533 /* | |
| 534 * Call Sleep(0) to work around a Winsock timing bug. | |
| 535 */ | |
| 536 Sleep(0); | |
| 537 if (FD_ISSET((SOCKET)osfd, &ex)) | |
| 538 { | |
| 539 len = sizeof(err); | |
| 540 if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, | |
| 541 (char *) &err, &len) == SOCKET_ERROR) | |
| 542 { | |
| 543 _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); | |
| 544 return -1; | |
| 545 } | |
| 546 if (err != 0) | |
| 547 _PR_MD_MAP_CONNECT_ERROR(err); | |
| 548 else | |
| 549 PR_SetError(PR_UNKNOWN_ERROR, 0); | |
| 550 return -1; | |
| 551 } | |
| 552 if (FD_ISSET((SOCKET)osfd, &rd_wr)) | |
| 553 { | |
| 554 /* it's connected */ | |
| 555 return 1; | |
| 556 } | |
| 557 PR_ASSERT(0); | |
| 558 } | |
| 559 if (_PR_PENDING_INTERRUPT(me)) { | |
| 560 me->flags &= ~_PR_INTERRUPT; | |
| 561 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); | |
| 562 rv = -1; | |
| 563 break; | |
| 564 } | |
| 565 } while (rv == 0); | |
| 566 break; | |
| 567 default: | |
| 568 remaining = timeout; | |
| 569 FD_ZERO(&rd_wr); | |
| 570 FD_ZERO(&ex); | |
| 571 do { | |
| 572 /* | |
| 573 * We block in _MD_SELECT for at most | |
| 574 * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, | |
| 575 * so that there is an upper limit on the delay | |
| 576 * before the interrupt bit is checked. | |
| 577 */ | |
| 578 wait_for_remaining = PR_TRUE; | |
| 579 tv.tv_sec = PR_IntervalToSeconds(remaining); | |
| 580 if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { | |
| 581 wait_for_remaining = PR_FALSE; | |
| 582 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; | |
| 583 tv.tv_usec = 0; | |
| 584 } else { | |
| 585 tv.tv_usec = PR_IntervalToMicroseconds( | |
| 586 remaining - | |
| 587 PR_SecondsToInterval(tv.tv_sec)); | |
| 588 } | |
| 589 FD_SET(osfd, &rd_wr); | |
| 590 FD_SET(osfd, &ex); | |
| 591 switch( fd_type ) | |
| 592 { | |
| 593 case READ_FD: | |
| 594 rv = _MD_SELECT(0, &rd_wr, NULL, NULL, &tv); | |
| 595 break; | |
| 596 case WRITE_FD: | |
| 597 rv = _MD_SELECT(0, NULL, &rd_wr, NULL, &tv); | |
| 598 break; | |
| 599 case CONNECT_FD: | |
| 600 rv = _MD_SELECT(0, NULL, &rd_wr, &ex, &tv); | |
| 601 break; | |
| 602 default: | |
| 603 PR_ASSERT(0); | |
| 604 break; | |
| 605 } /* end switch() */ | |
| 606 if (rv == -1) | |
| 607 { | |
| 608 _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); | |
| 609 break; | |
| 610 } | |
| 611 if ( rv > 0 && fd_type == CONNECT_FD ) | |
| 612 { | |
| 613 /* | |
| 614 * Call Sleep(0) to work around a Winsock timing bug. | |
| 615 */ | |
| 616 Sleep(0); | |
| 617 if (FD_ISSET((SOCKET)osfd, &ex)) | |
| 618 { | |
| 619 len = sizeof(err); | |
| 620 if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, | |
| 621 (char *) &err, &len) == SOCKET_ERROR) | |
| 622 { | |
| 623 _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); | |
| 624 return -1; | |
| 625 } | |
| 626 if (err != 0) | |
| 627 _PR_MD_MAP_CONNECT_ERROR(err); | |
| 628 else | |
| 629 PR_SetError(PR_UNKNOWN_ERROR, 0); | |
| 630 return -1; | |
| 631 } | |
| 632 if (FD_ISSET((SOCKET)osfd, &rd_wr)) | |
| 633 { | |
| 634 /* it's connected */ | |
| 635 return 1; | |
| 636 } | |
| 637 PR_ASSERT(0); | |
| 638 } | |
| 639 if (_PR_PENDING_INTERRUPT(me)) { | |
| 640 me->flags &= ~_PR_INTERRUPT; | |
| 641 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); | |
| 642 rv = -1; | |
| 643 break; | |
| 644 } | |
| 645 /* | |
| 646 * We loop again if _MD_SELECT timed out and the | |
| 647 * timeout deadline has not passed yet. | |
| 648 */ | |
| 649 if (rv == 0 ) | |
| 650 { | |
| 651 if (wait_for_remaining) { | |
| 652 elapsed = remaining; | |
| 653 } else { | |
| 654 elapsed = PR_SecondsToInterval(tv.tv_sec) | |
| 655 + PR_MicrosecondsToInterval(tv.tv_usec); | |
| 656 } | |
| 657 if (elapsed >= remaining) { | |
| 658 PR_SetError(PR_IO_TIMEOUT_ERROR, 0); | |
| 659 rv = -1; | |
| 660 break; | |
| 661 } else { | |
| 662 remaining = remaining - elapsed; | |
| 663 } | |
| 664 } | |
| 665 } while (rv == 0 ); | |
| 666 break; | |
| 667 } | |
| 668 return(rv); | |
| 669 } /* end socket_io_wait() */ | |
| OLD | NEW |