~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/nsprpub/pr/src/md/beos/bnet.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

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