Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; c-basic-offset: 4 -*- */
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 <signal.h>
9 #include <unistd.h>
10 #include <memory.h>
11 #include <fcntl.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <sys/time.h>
15 #include <sys/ioctl.h>
17 /*
18 * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
19 * PRInt32* pointer to a _PRSockLen_t* pointer.
20 */
21 #define _PRSockLen_t int
24 /*
25 ** Global lock variable used to bracket calls into rusty libraries that
26 ** aren't thread safe (like libc, libX, etc).
27 */
28 static PRLock *_pr_rename_lock = NULL;
29 static PRMonitor *_pr_Xfe_mon = NULL;
31 #define READ_FD 1
32 #define WRITE_FD 2
34 /*
35 ** This is a support routine to handle "deferred" i/o on sockets.
36 ** It uses "select", so it is subject to all of the BeOS limitations
37 ** (only READ notification, only sockets)
38 */
40 /*
41 * socket_io_wait --
42 *
43 * wait for socket i/o, periodically checking for interrupt
44 *
45 */
47 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
48 PRIntervalTime timeout)
49 {
50 PRInt32 rv = -1;
51 struct timeval tv;
52 PRThread *me = _PR_MD_CURRENT_THREAD();
53 PRIntervalTime epoch, now, elapsed, remaining;
54 PRBool wait_for_remaining;
55 PRInt32 syserror;
56 fd_set rd_wr;
58 switch (timeout) {
59 case PR_INTERVAL_NO_WAIT:
60 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
61 break;
62 case PR_INTERVAL_NO_TIMEOUT:
63 /*
64 * This is a special case of the 'default' case below.
65 * Please see the comments there.
66 */
67 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
68 tv.tv_usec = 0;
69 FD_ZERO(&rd_wr);
70 do {
71 FD_SET(osfd, &rd_wr);
72 if (fd_type == READ_FD)
73 rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
74 else
75 rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
76 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
77 #ifdef BONE_VERSION
78 _PR_MD_MAP_SELECT_ERROR(syserror);
79 #else
80 if (syserror == EBADF) {
81 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
82 } else {
83 PR_SetError(PR_UNKNOWN_ERROR, syserror);
84 }
85 #endif
86 break;
87 }
88 if (_PR_PENDING_INTERRUPT(me)) {
89 me->flags &= ~_PR_INTERRUPT;
90 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
91 rv = -1;
92 break;
93 }
94 } while (rv == 0 || (rv == -1 && syserror == EINTR));
95 break;
96 default:
97 now = epoch = PR_IntervalNow();
98 remaining = timeout;
99 FD_ZERO(&rd_wr);
100 do {
101 /*
102 * We block in _MD_SELECT for at most
103 * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
104 * so that there is an upper limit on the delay
105 * before the interrupt bit is checked.
106 */
107 wait_for_remaining = PR_TRUE;
108 tv.tv_sec = PR_IntervalToSeconds(remaining);
109 if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
110 wait_for_remaining = PR_FALSE;
111 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
112 tv.tv_usec = 0;
113 } else {
114 tv.tv_usec = PR_IntervalToMicroseconds(
115 remaining -
116 PR_SecondsToInterval(tv.tv_sec));
117 }
118 FD_SET(osfd, &rd_wr);
119 if (fd_type == READ_FD)
120 rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
121 else
122 rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
123 /*
124 * we don't consider EINTR a real error
125 */
126 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
127 #ifdef BONE_VERSION
128 _PR_MD_MAP_SELECT_ERROR(syserror);
129 #else
130 if (syserror == EBADF) {
131 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
132 } else {
133 PR_SetError(PR_UNKNOWN_ERROR, syserror);
134 }
135 #endif
136 break;
137 }
138 if (_PR_PENDING_INTERRUPT(me)) {
139 me->flags &= ~_PR_INTERRUPT;
140 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
141 rv = -1;
142 break;
143 }
144 /*
145 * We loop again if _MD_SELECT timed out or got interrupted
146 * by a signal, and the timeout deadline has not passed yet.
147 */
148 if (rv == 0 || (rv == -1 && syserror == EINTR)) {
149 /*
150 * If _MD_SELECT timed out, we know how much time
151 * we spent in blocking, so we can avoid a
152 * PR_IntervalNow() call.
153 */
154 if (rv == 0) {
155 if (wait_for_remaining) {
156 now += remaining;
157 } else {
158 now += PR_SecondsToInterval(tv.tv_sec)
159 + PR_MicrosecondsToInterval(tv.tv_usec);
160 }
161 } else {
162 now = PR_IntervalNow();
163 }
164 elapsed = (PRIntervalTime) (now - epoch);
165 if (elapsed >= timeout) {
166 PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
167 rv = -1;
168 break;
169 } else {
170 remaining = timeout - elapsed;
171 }
172 }
173 } while (rv == 0 || (rv == -1 && syserror == EINTR));
174 break;
175 }
176 return(rv);
177 }
179 PRInt32
180 _MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags,
181 PRIntervalTime timeout)
182 {
183 PRInt32 osfd = fd->secret->md.osfd;
184 PRInt32 rv, err;
185 PRThread *me = _PR_MD_CURRENT_THREAD();
187 #ifndef BONE_VERSION
188 if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_READ) {
189 _PR_MD_MAP_RECV_ERROR(EPIPE);
190 return -1;
191 }
192 #endif
194 #ifdef BONE_VERSION
195 /*
196 ** Gah, stupid hack. If reading a zero amount, instantly return success.
197 ** BONE beta 6 returns EINVAL for reads of zero bytes, which parts of
198 ** mozilla use to check for socket availability.
199 */
201 if( 0 == amount ) return(0);
202 #endif
204 while ((rv = recv(osfd, buf, amount, flags)) == -1) {
205 err = _MD_ERRNO();
207 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
208 if (fd->secret->nonblocking) {
209 break;
210 }
211 /* If socket was supposed to be blocking,
212 wait a while for the condition to be
213 satisfied. */
214 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
215 goto done;
216 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
217 continue;
219 } else
220 break;
221 }
223 if (rv < 0) {
224 _PR_MD_MAP_RECV_ERROR(err);
225 }
227 done:
228 return(rv);
229 }
231 PRInt32
232 _MD_recvfrom (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
233 PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
234 {
235 PRInt32 osfd = fd->secret->md.osfd;
236 PRInt32 rv, err;
237 PRThread *me = _PR_MD_CURRENT_THREAD();
239 while ((*addrlen = PR_NETADDR_SIZE(addr)),
240 ((rv = recvfrom(osfd, buf, amount, flags,
241 (struct sockaddr *) addr,
242 (_PRSockLen_t *)addrlen)) == -1)) {
243 err = _MD_ERRNO();
245 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
246 if (fd->secret->nonblocking) {
247 break;
248 }
249 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
250 goto done;
252 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
253 continue;
254 } else {
255 break;
256 }
257 }
259 if (rv < 0) {
260 _PR_MD_MAP_RECVFROM_ERROR(err);
261 }
263 done:
264 #ifdef _PR_HAVE_SOCKADDR_LEN
265 if (rv != -1) {
266 /* ignore the sa_len field of struct sockaddr */
267 if (addr) {
268 addr->raw.family = ((struct sockaddr *) addr)->sa_family;
269 }
270 }
271 #endif /* _PR_HAVE_SOCKADDR_LEN */
272 return(rv);
273 }
275 PRInt32
276 _MD_send (PRFileDesc *fd, const void *buf, PRInt32 amount, PRInt32 flags,
277 PRIntervalTime timeout)
278 {
279 PRInt32 osfd = fd->secret->md.osfd;
280 PRInt32 rv, err;
281 PRThread *me = _PR_MD_CURRENT_THREAD();
283 #ifndef BONE_VERSION
284 if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_WRITE)
285 {
286 _PR_MD_MAP_SEND_ERROR(EPIPE);
287 return -1;
288 }
289 #endif
291 while ((rv = send(osfd, buf, amount, flags)) == -1) {
292 err = _MD_ERRNO();
294 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
295 if (fd->secret->nonblocking) {
296 break;
297 }
299 #ifndef BONE_VERSION
300 if( _PR_PENDING_INTERRUPT(me)) {
302 me->flags &= ~_PR_INTERRUPT;
303 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
304 return -1;
305 }
307 /* in UNIX implementations, you could do a socket_io_wait here.
308 * but since BeOS doesn't yet support WRITE notification in select,
309 * you're spanked.
310 */
311 snooze( 10000L );
312 continue;
313 #else /* BONE_VERSION */
314 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
315 goto done;
316 #endif
318 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
319 continue;
321 } else {
322 break;
323 }
324 }
326 #ifdef BONE_VERSION
327 /*
328 * optimization; if bytes sent is less than "amount" call
329 * select before returning. This is because it is likely that
330 * the next writev() call will return EWOULDBLOCK.
331 */
332 if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
333 && (timeout != PR_INTERVAL_NO_WAIT)) {
334 if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
335 rv = -1;
336 goto done;
337 }
338 }
339 #endif /* BONE_VERSION */
341 if (rv < 0) {
342 _PR_MD_MAP_SEND_ERROR(err);
343 }
345 #ifdef BONE_VERSION
346 done:
347 #endif
348 return(rv);
349 }
351 PRInt32
352 _MD_sendto (PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
353 const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
354 {
355 PRInt32 osfd = fd->secret->md.osfd;
356 PRInt32 rv, err;
357 PRThread *me = _PR_MD_CURRENT_THREAD();
358 #ifdef _PR_HAVE_SOCKADDR_LEN
359 PRNetAddr addrCopy;
361 addrCopy = *addr;
362 ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
363 ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
365 while ((rv = sendto(osfd, buf, amount, flags,
366 (struct sockaddr *) &addrCopy, addrlen)) == -1) {
367 #else
368 while ((rv = sendto(osfd, buf, amount, flags,
369 (struct sockaddr *) addr, addrlen)) == -1) {
370 #endif
371 err = _MD_ERRNO();
373 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
374 if (fd->secret->nonblocking) {
375 break;
376 }
378 #ifdef BONE_VERSION
379 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
380 goto done;
381 #endif
382 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
383 continue;
385 } else {
386 break;
387 }
388 }
390 if (rv < 0) {
391 _PR_MD_MAP_SENDTO_ERROR(err);
392 }
394 #ifdef BONE_VERSION
395 done:
396 #endif
397 return(rv);
398 }
400 #ifdef BONE_VERSION
402 PRInt32 _MD_writev(
403 PRFileDesc *fd, const PRIOVec *iov,
404 PRInt32 iov_size, PRIntervalTime timeout)
405 {
406 PRInt32 rv, err;
407 PRThread *me = _PR_MD_CURRENT_THREAD();
408 PRInt32 index, amount = 0;
409 PRInt32 osfd = fd->secret->md.osfd;
410 struct iovec osiov[PR_MAX_IOVECTOR_SIZE];
412 /* Ensured by PR_Writev */
413 PR_ASSERT(iov_size <= PR_MAX_IOVECTOR_SIZE);
415 /*
416 * We can't pass iov to writev because PRIOVec and struct iovec
417 * may not be binary compatible. Make osiov a copy of iov and
418 * pass osiov to writev.
419 */
420 for (index = 0; index < iov_size; index++) {
421 osiov[index].iov_base = iov[index].iov_base;
422 osiov[index].iov_len = iov[index].iov_len;
423 }
425 /*
426 * Calculate the total number of bytes to be sent; needed for
427 * optimization later.
428 * We could avoid this if this number was passed in; but it is
429 * probably not a big deal because iov_size is usually small (less than
430 * 3)
431 */
432 if (!fd->secret->nonblocking) {
433 for (index=0; index<iov_size; index++) {
434 amount += iov[index].iov_len;
435 }
436 }
438 while ((rv = writev(osfd, osiov, iov_size)) == -1) {
439 err = _MD_ERRNO();
440 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
441 if (fd->secret->nonblocking) {
442 break;
443 }
444 if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
445 goto done;
447 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
448 continue;
449 } else {
450 break;
451 }
452 }
454 /*
455 * optimization; if bytes sent is less than "amount" call
456 * select before returning. This is because it is likely that
457 * the next writev() call will return EWOULDBLOCK.
458 */
459 if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
460 && (timeout != PR_INTERVAL_NO_WAIT)) {
461 if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
462 rv = -1;
463 goto done;
464 }
465 }
468 if (rv < 0) {
469 _PR_MD_MAP_WRITEV_ERROR(err);
470 }
471 done:
472 return(rv);
473 }
475 #endif /* BONE_VERSION */
477 PRInt32
478 _MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
479 PRIntervalTime timeout)
480 {
481 PRInt32 osfd = fd->secret->md.osfd;
482 PRInt32 rv, err;
483 PRThread *me = _PR_MD_CURRENT_THREAD();
485 while ((rv = accept(osfd, (struct sockaddr *) addr,
486 (_PRSockLen_t *)addrlen)) == -1) {
487 err = _MD_ERRNO();
489 if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
490 if (fd->secret->nonblocking) {
491 break;
492 }
493 /* If it's SUPPOSED to be a blocking thread, wait
494 * a while to see if the triggering condition gets
495 * satisfied.
496 */
497 /* Assume that we're always using a native thread */
498 if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
499 goto done;
500 } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
501 continue;
502 } else {
503 break;
504 }
505 }
506 if (rv < 0) {
507 _PR_MD_MAP_ACCEPT_ERROR(err);
508 } else if (addr != NULL) {
509 /* bug 134099 */
510 err = getpeername(rv, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
511 }
512 done:
513 #ifdef _PR_HAVE_SOCKADDR_LEN
514 if (rv != -1) {
515 /* Mask off the first byte of struct sockaddr (the length field) */
516 if (addr) {
517 addr->raw.family = ((struct sockaddr *) addr)->sa_family;
518 }
519 }
520 #endif /* _PR_HAVE_SOCKADDR_LEN */
521 return(rv);
522 }
524 PRInt32
525 _MD_connect (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
526 PRIntervalTime timeout)
527 {
528 PRInt32 rv, err;
529 PRThread *me = _PR_MD_CURRENT_THREAD();
530 PRInt32 osfd = fd->secret->md.osfd;
532 #ifndef BONE_VERSION
533 fd->secret->md.connectValueValid = PR_FALSE;
534 #endif
535 #ifdef _PR_HAVE_SOCKADDR_LEN
536 PRNetAddr addrCopy;
538 addrCopy = *addr;
539 ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
540 ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
541 #endif
543 /* (Copied from unix.c)
544 * We initiate the connection setup by making a nonblocking connect()
545 * call. If the connect() call fails, there are two cases we handle
546 * specially:
547 * 1. The connect() call was interrupted by a signal. In this case
548 * we simply retry connect().
549 * 2. The NSPR socket is nonblocking and connect() fails with
550 * EINPROGRESS. We first wait until the socket becomes writable.
551 * Then we try to find out whether the connection setup succeeded
552 * or failed.
553 */
555 retry:
556 #ifdef _PR_HAVE_SOCKADDR_LEN
557 if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) {
558 #else
559 if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
560 #endif
561 err = _MD_ERRNO();
562 #ifndef BONE_VERSION
563 fd->secret->md.connectReturnValue = rv;
564 fd->secret->md.connectReturnError = err;
565 fd->secret->md.connectValueValid = PR_TRUE;
566 #endif
567 if( err == EINTR ) {
569 if( _PR_PENDING_INTERRUPT(me)) {
571 me->flags &= ~_PR_INTERRUPT;
572 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
573 return -1;
574 }
575 #ifndef BONE_VERSION
576 snooze( 100000L );
577 #endif
578 goto retry;
579 }
581 #ifndef BONE_VERSION
582 if(!fd->secret->nonblocking && ((err == EINPROGRESS) || (err==EAGAIN) || (err==EALREADY))) {
584 /*
585 ** There's no timeout on this connect, but that's not
586 ** a big deal, since the connect times out anyways
587 ** after 30 seconds. Just sleep for 1/10th of a second
588 ** and retry until we go through or die.
589 */
591 if( _PR_PENDING_INTERRUPT(me)) {
592 me->flags &= ~_PR_INTERRUPT;
593 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
594 return -1;
595 }
597 goto retry;
598 }
600 if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) {
601 PR_Lock(_connectLock);
602 if (connectCount < sizeof(connectList)/sizeof(connectList[0])) {
603 connectList[connectCount].osfd = osfd;
604 memcpy(&connectList[connectCount].addr, addr, addrlen);
605 connectList[connectCount].addrlen = addrlen;
606 connectList[connectCount].timeout = timeout;
607 connectCount++;
608 PR_Unlock(_connectLock);
609 _PR_MD_MAP_CONNECT_ERROR(err);
610 } else {
611 PR_Unlock(_connectLock);
612 PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
613 }
614 return rv;
615 }
616 #else /* BONE_VERSION */
617 if(!fd->secret->nonblocking && (err == EINTR)) {
619 rv = socket_io_wait(osfd, WRITE_FD, timeout);
620 if (rv == -1) {
621 return -1;
622 }
624 PR_ASSERT(rv == 1);
625 if (_PR_PENDING_INTERRUPT(me)) {
626 me->flags &= ~_PR_INTERRUPT;
627 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
628 return -1;
629 }
630 err = _MD_beos_get_nonblocking_connect_error(osfd);
631 if (err != 0) {
632 _PR_MD_MAP_CONNECT_ERROR(err);
633 return -1;
634 }
635 return 0;
636 }
637 #endif
639 _PR_MD_MAP_CONNECT_ERROR(err);
640 }
642 return rv;
643 }
645 PRInt32
646 _MD_bind (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
647 {
648 PRInt32 rv, err;
649 #ifdef _PR_HAVE_SOCKADDR_LEN
650 PRNetAddr addrCopy;
652 addrCopy = *addr;
653 ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
654 ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
655 rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen);
656 #else
657 rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
658 #endif
659 if (rv < 0) {
660 err = _MD_ERRNO();
661 _PR_MD_MAP_BIND_ERROR(err);
662 }
664 return(rv);
665 }
667 PRInt32
668 _MD_listen (PRFileDesc *fd, PRIntn backlog)
669 {
670 PRInt32 rv, err;
672 #ifndef BONE_VERSION
673 /* Bug workaround! Setting listen to 0 on Be accepts no connections.
674 ** On most UN*Xes this sets the default.
675 */
677 if( backlog == 0 ) backlog = 5;
678 #endif
680 rv = listen(fd->secret->md.osfd, backlog);
681 if (rv < 0) {
682 err = _MD_ERRNO();
683 _PR_MD_MAP_LISTEN_ERROR(err);
684 }
686 return(rv);
687 }
689 PRInt32
690 _MD_shutdown (PRFileDesc *fd, PRIntn how)
691 {
692 PRInt32 rv, err;
694 #ifndef BONE_VERSION
695 if (how == PR_SHUTDOWN_SEND)
696 fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE;
697 else if (how == PR_SHUTDOWN_RCV)
698 fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ;
699 else if (how == PR_SHUTDOWN_BOTH) {
700 fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ);
701 }
703 return 0;
704 #else /* BONE_VERSION */
705 rv = shutdown(fd->secret->md.osfd, how);
706 if (rv < 0) {
707 err = _MD_ERRNO();
708 _PR_MD_MAP_SHUTDOWN_ERROR(err);
709 }
710 return(rv);
711 #endif
712 }
714 PRInt32
715 _MD_socketpair (int af, int type, int flags, PRInt32 *osfd)
716 {
717 return PR_NOT_IMPLEMENTED_ERROR;
718 }
720 PRInt32
721 _MD_close_socket (PRInt32 osfd)
722 {
723 #ifdef BONE_VERSION
724 close( osfd );
725 #else
726 closesocket( osfd );
727 #endif
728 }
730 PRStatus
731 _MD_getsockname (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
732 {
733 PRInt32 rv, err;
735 rv = getsockname(fd->secret->md.osfd,
736 (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
737 #ifdef _PR_HAVE_SOCKADDR_LEN
738 if (rv == 0) {
739 /* ignore the sa_len field of struct sockaddr */
740 if (addr) {
741 addr->raw.family = ((struct sockaddr *) addr)->sa_family;
742 }
743 }
744 #endif /* _PR_HAVE_SOCKADDR_LEN */
745 if (rv < 0) {
746 err = _MD_ERRNO();
747 _PR_MD_MAP_GETSOCKNAME_ERROR(err);
748 }
750 return rv==0?PR_SUCCESS:PR_FAILURE;
751 }
753 PRStatus
754 _MD_getpeername (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
755 {
756 PRInt32 rv, err;
758 rv = getpeername(fd->secret->md.osfd,
759 (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
761 #ifdef _PR_HAVE_SOCKADDR_LEN
762 if (rv == 0) {
763 /* ignore the sa_len field of struct sockaddr */
764 if (addr) {
765 addr->raw.family = ((struct sockaddr *) addr)->sa_family;
766 }
767 }
768 #endif /* _PR_HAVE_SOCKADDR_LEN */
770 if (rv < 0) {
771 err = _MD_ERRNO();
772 _PR_MD_MAP_GETPEERNAME_ERROR(err);
773 }
774 return rv==0?PR_SUCCESS:PR_FAILURE;
775 }
777 PRStatus
778 _MD_getsockopt (PRFileDesc *fd, PRInt32 level,
779 PRInt32 optname, char* optval, PRInt32* optlen)
780 {
781 PRInt32 rv, err;
783 rv = getsockopt(fd->secret->md.osfd, level, optname,
784 optval, (_PRSockLen_t *)optlen);
785 if (rv < 0) {
786 err = _MD_ERRNO();
787 _PR_MD_MAP_GETSOCKOPT_ERROR(err);
788 }
790 return rv==0?PR_SUCCESS:PR_FAILURE;
791 }
793 PRStatus
794 _MD_setsockopt (PRFileDesc *fd, PRInt32 level,
795 PRInt32 optname, const char* optval, PRInt32 optlen)
796 {
797 PRInt32 rv, err;
799 rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
800 if (rv < 0) {
801 err = _MD_ERRNO();
802 _PR_MD_MAP_SETSOCKOPT_ERROR(err);
803 }
804 return rv==0?PR_SUCCESS:PR_FAILURE;
805 }
807 PRInt32
808 _MD_accept_read (PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr,
809 void *buf, PRInt32 amount, PRIntervalTime timeout)
810 {
811 return PR_NOT_IMPLEMENTED_ERROR;
812 }
814 #ifndef BONE_VERSION
815 PRInt32
816 _MD_socket (int af, int type, int flags)
817 {
818 PRInt32 osfd, err;
820 osfd = socket( af, type, 0 );
822 if( -1 == osfd ) {
824 err = _MD_ERRNO();
825 _PR_MD_MAP_SOCKET_ERROR( err );
826 }
828 return( osfd );
829 }
830 #else
831 PRInt32
832 _MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
833 {
834 PRInt32 osfd, err;
836 osfd = socket(domain, type, proto);
838 if (osfd == -1) {
839 err = _MD_ERRNO();
840 _PR_MD_MAP_SOCKET_ERROR(err);
841 }
843 return(osfd);
844 }
845 #endif
847 PRInt32
848 _MD_socketavailable (PRFileDesc *fd)
849 {
850 #ifdef BONE_VERSION
851 PRInt32 result;
853 if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) {
854 _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());
855 return -1;
856 }
857 return result;
858 #else
859 return PR_NOT_IMPLEMENTED_ERROR;
860 #endif
861 }
863 PRInt32
864 _MD_get_socket_error (void)
865 {
866 return PR_NOT_IMPLEMENTED_ERROR;
867 }
869 PRStatus
870 _MD_gethostname (char *name, PRUint32 namelen)
871 {
872 PRInt32 rv, err;
874 rv = gethostname(name, namelen);
875 if (rv == 0)
876 {
877 err = _MD_ERRNO();
878 _PR_MD_MAP_GETHOSTNAME_ERROR(err);
879 return PR_FAILURE;
880 }
881 return PR_SUCCESS;
882 }
884 #ifndef BONE_VERSION
885 PRInt32
886 _MD_beos_get_nonblocking_connect_error(PRFileDesc *fd)
887 {
888 int rv;
889 int flags = 0;
891 rv = recv(fd->secret->md.osfd, NULL, 0, flags);
892 PR_ASSERT(-1 == rv || 0 == rv);
893 if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) {
894 return errno;
895 }
896 return 0; /* no error */
897 }
898 #else
899 PRInt32
900 _MD_beos_get_nonblocking_connect_error(int osfd)
901 {
902 return PR_NOT_IMPLEMENTED_ERROR;
903 // int err;
904 // _PRSockLen_t optlen = sizeof(err);
905 // if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) {
906 // return errno;
907 // } else {
908 // return err;
909 // }
910 }
911 #endif /* BONE_VERSION */