~ubuntu-branches/ubuntu/oneiric/libapache-mod-jk/oneiric

« back to all changes in this revision

Viewing changes to jk/native/common/jk_connect.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2006-08-05 16:30:53 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060805163053-myf66gm6j1a21ps6
Tags: 1:1.2.18-1ubuntu1
Merge from Debian unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright 1999-2004 The Apache Software Foundation
3
 
 *
4
 
 *  Licensed under the Apache License, Version 2.0 (the "License");
5
 
 *  you may not use this file except in compliance with the License.
6
 
 *  You may obtain a copy of the License at
7
 
 *
8
 
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 
 *
10
 
 *  Unless required by applicable law or agreed to in writing, software
11
 
 *  distributed under the License is distributed on an "AS IS" BASIS,
12
 
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 
 *  See the License for the specific language governing permissions and
14
 
 *  limitations under the License.
15
 
 */
16
 
 
17
 
/*
18
 
 * Description: Socket/Naming manipulation functions
19
 
 * Based on:    Various Jserv files
20
 
 */
21
 
/**
22
 
 * @package jk_connect
23
 
 * @author      Gal Shachor <shachor@il.ibm.com>
24
 
 * @author      Mladen Turk <mturk@apache.org>
25
 
 * @version     $Revision: 1.61 $
26
 
 */
27
 
 
28
 
 
29
 
#include "jk_connect.h"
30
 
#include "jk_util.h"
31
 
 
32
 
#ifdef HAVE_APR
33
 
#include "apr_network_io.h"
34
 
#include "apr_errno.h"
35
 
#include "apr_general.h"
36
 
#include "apr_pools.h"
37
 
static apr_pool_t *jk_apr_pool = NULL;
38
 
#endif
39
 
 
40
 
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
41
 
#define JK_IS_SOCKET_ERROR(x) ((x) == SOCKET_ERROR)
42
 
#define JK_GET_SOCKET_ERRNO() errno = WSAGetLastError() - WSABASEERR
43
 
#else
44
 
#define JK_IS_SOCKET_ERROR(x) ((x) == -1)
45
 
#define JK_GET_SOCKET_ERRNO() ((void)0)
46
 
#endif /* WIN32 */
47
 
 
48
 
/* our compiler cant deal with char* <-> const char* ... */
49
 
#if defined(NETWARE) && !defined(__NOVELL_LIBC__)
50
 
typedef char* SET_TYPE;
51
 
#else
52
 
typedef const char* SET_TYPE;
53
 
#endif
54
 
 
55
 
static int soblock(int sd)
56
 
{
57
 
/* BeOS uses setsockopt at present for non blocking... */
58
 
#ifndef WIN32
59
 
    int fd_flags;
60
 
 
61
 
    fd_flags = fcntl(sd, F_GETFL, 0);
62
 
#if defined(O_NONBLOCK)
63
 
    fd_flags &= ~O_NONBLOCK;
64
 
#elif defined(O_NDELAY)
65
 
    fd_flags &= ~O_NDELAY;
66
 
#elif defined(FNDELAY)
67
 
    fd_flags &= ~FNDELAY;
68
 
#else
69
 
#error Please teach JK how to make sockets blocking on your platform.
70
 
#endif
71
 
    if (fcntl(sd, F_SETFL, fd_flags) == -1) {
72
 
        return errno;
73
 
    }
74
 
#else
75
 
    u_long on = 0;
76
 
    if (ioctlsocket(sd, FIONBIO, &on) == SOCKET_ERROR) {
77
 
        errno = WSAGetLastError() - WSABASEERR;
78
 
        return errno;
79
 
    }
80
 
#endif /* WIN32 */
81
 
    return 0;
82
 
}
83
 
 
84
 
static int sononblock(int sd)
85
 
{
86
 
#ifndef WIN32
87
 
    int fd_flags;
88
 
 
89
 
    fd_flags = fcntl(sd, F_GETFL, 0);
90
 
#if defined(O_NONBLOCK)
91
 
    fd_flags |= O_NONBLOCK;
92
 
#elif defined(O_NDELAY)
93
 
    fd_flags |= O_NDELAY;
94
 
#elif defined(FNDELAY)
95
 
    fd_flags |= FNDELAY;
96
 
#else
97
 
#error Please teach JK how to make sockets non-blocking on your platform.
98
 
#endif
99
 
    if (fcntl(sd, F_SETFL, fd_flags) == -1) {
100
 
        return errno;
101
 
    }
102
 
#else
103
 
    u_long on = 1;
104
 
    if (ioctlsocket(sd, FIONBIO, &on) == SOCKET_ERROR) {
105
 
        errno = WSAGetLastError() - WSABASEERR;
106
 
        return errno;
107
 
    }
108
 
#endif /* WIN32 */
109
 
    return 0;
110
 
}
111
 
 
112
 
#if defined (WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
113
 
/* WIN32 implementation */
114
 
static int nb_connect(int sock, struct sockaddr *addr, int timeout)
115
 
{
116
 
    int rc;
117
 
    if (timeout < 1)
118
 
        return connect(sock, addr, sizeof(struct sockaddr_in));
119
 
 
120
 
    if ((rc = sononblock(sock)))
121
 
        return -1;
122
 
    if (connect(sock, addr, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
123
 
        struct timeval tv;
124
 
        fd_set wfdset, efdset;
125
 
 
126
 
        if ((rc = WSAGetLastError()) != WSAEWOULDBLOCK) {
127
 
            soblock(sock);
128
 
            WSASetLastError(rc);
129
 
            return -1;
130
 
        }
131
 
        /* wait for the connect to complete or timeout */
132
 
        FD_ZERO(&wfdset);
133
 
        FD_SET(sock, &wfdset);
134
 
        FD_ZERO(&efdset);
135
 
        FD_SET(sock, &efdset);
136
 
 
137
 
        tv.tv_sec  = timeout;
138
 
        tv.tv_usec = 0;
139
 
        rc = select(FD_SETSIZE+1, NULL, &wfdset, &efdset, &tv);
140
 
        if (rc == SOCKET_ERROR || rc == 0) {
141
 
            rc = WSAGetLastError();
142
 
            soblock(sock);
143
 
            WSASetLastError(rc);
144
 
            return -1;
145
 
        }
146
 
        /* Evaluate the efdset */
147
 
        if (FD_ISSET(sock, &efdset)) {
148
 
            /* The connect failed. */
149
 
            int rclen = sizeof(rc);
150
 
            if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen))
151
 
                rc = 0;
152
 
            soblock(sock);
153
 
            if (rc)
154
 
                WSASetLastError(rc);
155
 
            return -1;
156
 
        }
157
 
    }
158
 
    soblock(sock);
159
 
    return 0;
160
 
}
161
 
 
162
 
#elif !defined(NETWARE)
163
 
/* POSIX implementation */
164
 
static int nb_connect(int sock, struct sockaddr *addr, int timeout)
165
 
{
166
 
    int rc = 0;
167
 
 
168
 
    if (timeout > 0) {
169
 
        if (sononblock(sock))
170
 
            return -1;
171
 
    }
172
 
    do {
173
 
        rc = connect(sock, addr, sizeof(struct sockaddr_in));
174
 
    } while (rc == -1 && errno == EINTR);
175
 
 
176
 
    if ((rc == -1) && (errno == EINPROGRESS || errno == EALREADY)
177
 
                   && (timeout > 0)) {
178
 
        fd_set wfdset;
179
 
        struct timeval tv;
180
 
        int rclen = sizeof(rc);
181
 
 
182
 
        FD_ZERO(&wfdset);
183
 
        FD_SET(sock, &wfdset);
184
 
        tv.tv_sec  = timeout;
185
 
        tv.tv_usec = 0;
186
 
        rc = select(sock+1, NULL, &wfdset, NULL, &tv);
187
 
        if (rc <= 0) {
188
 
            /* Save errno */
189
 
            int err = errno;
190
 
            soblock(sock);
191
 
            errno = err;
192
 
            return -1;
193
 
        }
194
 
        rc = 0;
195
 
#ifdef SO_ERROR
196
 
        if (!FD_ISSET(sock, &wfdset) ||
197
 
            (getsockopt(sock, SOL_SOCKET, SO_ERROR,
198
 
                        (char *)&rc, &rclen) < 0) || rc) {
199
 
            if (rc)
200
 
                errno = rc;
201
 
            rc = -1;
202
 
        }
203
 
#endif /* SO_ERROR */
204
 
    }
205
 
    /* Not sure we can be already connected */
206
 
    if (rc == -1 && errno == EISCONN)
207
 
        rc = 0;
208
 
    soblock(sock);
209
 
    return rc;
210
 
}
211
 
#else
212
 
/* NETWARE implementation - blocking for now */
213
 
static int nb_connect(int sock, struct sockaddr *addr, int timeout)
214
 
{
215
 
    return connect(sock, addr, sizeof(struct sockaddr_in));
216
 
}
217
 
#endif
218
 
 
219
 
/** resolve the host IP */
220
 
 
221
 
int jk_resolve(const char *host, int port, struct sockaddr_in *rc)
222
 
{
223
 
    int x;
224
 
    struct in_addr laddr;
225
 
 
226
 
    memset(rc, 0, sizeof(struct sockaddr_in));
227
 
 
228
 
    rc->sin_port = htons((short)port);
229
 
    rc->sin_family = AF_INET;
230
 
 
231
 
    /* Check if we only have digits in the string */
232
 
    for (x = 0; host[x] != '\0'; x++) {
233
 
        if (!isdigit(host[x]) && host[x] != '.') {
234
 
            break;
235
 
        }
236
 
    }
237
 
 
238
 
    /* If we found also characters we shoud make name to IP resolution */
239
 
    if (host[x] != '\0') {
240
 
 
241
 
#ifdef HAVE_APR
242
 
        apr_sockaddr_t *remote_sa, *temp_sa;
243
 
        char *remote_ipaddr;
244
 
 
245
 
        if (!jk_apr_pool) {
246
 
            if (apr_pool_create(&jk_apr_pool, NULL) != APR_SUCCESS)
247
 
                return JK_FALSE;
248
 
        }
249
 
        if (apr_sockaddr_info_get
250
 
            (&remote_sa, host, APR_UNSPEC, (apr_port_t) port, 0, jk_apr_pool)
251
 
            != APR_SUCCESS)
252
 
            return JK_FALSE;
253
 
 
254
 
        /* Since we are only handling AF_INET (IPV4) address (in_addr_t) */
255
 
        /* make sure we find one of those.                               */
256
 
        temp_sa = remote_sa;
257
 
        while ((NULL != temp_sa) && (AF_INET != temp_sa->family))
258
 
            temp_sa = temp_sa->next;
259
 
 
260
 
        /* if temp_sa is set, we have a valid address otherwise, just return */
261
 
        if (NULL != temp_sa)
262
 
            remote_sa = temp_sa;
263
 
        else
264
 
            return JK_FALSE;
265
 
 
266
 
        apr_sockaddr_ip_get(&remote_ipaddr, remote_sa);
267
 
        laddr.s_addr = inet_addr(remote_ipaddr);
268
 
 
269
 
#else /* HAVE_APR */
270
 
 
271
 
        /* XXX : WARNING : We should really use gethostbyname_r in multi-threaded env */
272
 
        /* Fortunatly when APR is available, ie under Apache 2.0, we use it */
273
 
#if defined(NETWARE) && !defined(__NOVELL_LIBC__)
274
 
        struct hostent *hoste = gethostbyname((char*)host);
275
 
#else
276
 
        struct hostent *hoste = gethostbyname(host);
277
 
#endif
278
 
        if (!hoste) {
279
 
            return JK_FALSE;
280
 
        }
281
 
 
282
 
        laddr = *((struct in_addr *)hoste->h_addr_list[0]);
283
 
 
284
 
#endif /* HAVE_APR */
285
 
    }
286
 
    else {
287
 
        /* If we found only digits we use inet_addr() */
288
 
        laddr.s_addr = inet_addr(host);
289
 
    }
290
 
    memcpy(&(rc->sin_addr), &laddr, sizeof(laddr));
291
 
 
292
 
    return JK_TRUE;
293
 
}
294
 
 
295
 
/** connect to Tomcat */
296
 
 
297
 
int jk_open_socket(struct sockaddr_in *addr, int keepalive,
298
 
                   int timeout, int sock_buf, jk_logger_t *l)
299
 
{
300
 
    char buf[32];
301
 
    int sock;
302
 
    int set = 1;
303
 
    int ret = 0;
304
 
#ifdef SO_LINGER
305
 
    struct linger li;
306
 
#endif
307
 
 
308
 
    JK_TRACE_ENTER(l);
309
 
 
310
 
    sock = socket(AF_INET, SOCK_STREAM, 0);
311
 
    if (sock < 0) {
312
 
        JK_GET_SOCKET_ERRNO();
313
 
        jk_log(l, JK_LOG_ERROR,
314
 
               "socket() failed with errno=%d", errno);
315
 
        JK_TRACE_EXIT(l);
316
 
        return -1;
317
 
    }
318
 
    /* Disable Nagle algorithm */
319
 
    if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (SET_TYPE)&set,
320
 
                   sizeof(set))) {
321
 
        jk_log(l, JK_LOG_ERROR,
322
 
                "failed setting TCP_NODELAY with errno=%d", errno);
323
 
        jk_close_socket(sock);
324
 
        JK_TRACE_EXIT(l);
325
 
        return -1;
326
 
    }
327
 
    if (JK_IS_DEBUG_LEVEL(l))
328
 
        jk_log(l, JK_LOG_DEBUG,
329
 
               "socket TCP_NODELAY set to On");
330
 
    if (keepalive) {
331
 
        set = 1;
332
 
        if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (SET_TYPE)&set,
333
 
                       sizeof(set))) {
334
 
            jk_log(l, JK_LOG_ERROR,
335
 
                   "failed setting SO_KEEPALIVE with errno=%d", errno);
336
 
            jk_close_socket(sock);
337
 
            JK_TRACE_EXIT(l);
338
 
            return -1;
339
 
        }
340
 
        if (JK_IS_DEBUG_LEVEL(l))
341
 
            jk_log(l, JK_LOG_DEBUG,
342
 
                   "socket SO_KEEPALIVE set to On");
343
 
    }
344
 
 
345
 
    if (sock_buf > 0) {
346
 
        set = sock_buf;
347
 
        /* Set socket send buffer size */
348
 
        if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (SET_TYPE)&set,
349
 
                        sizeof(set))) {
350
 
            JK_GET_SOCKET_ERRNO();
351
 
            jk_log(l, JK_LOG_ERROR,
352
 
                    "failed setting SO_SNDBUF with errno=%d", errno);
353
 
            jk_close_socket(sock);
354
 
            JK_TRACE_EXIT(l);
355
 
            return -1;
356
 
        }
357
 
        set = sock_buf;
358
 
        /* Set socket receive buffer size */
359
 
        if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (SET_TYPE)&set,
360
 
                                sizeof(set))) {
361
 
            JK_GET_SOCKET_ERRNO();
362
 
            jk_log(l, JK_LOG_ERROR,
363
 
                    "failed setting SO_RCVBUF with errno=%d", errno);
364
 
            jk_close_socket(sock);
365
 
            JK_TRACE_EXIT(l);
366
 
            return -1;
367
 
        }
368
 
        if (JK_IS_DEBUG_LEVEL(l))
369
 
            jk_log(l, JK_LOG_DEBUG,
370
 
                   "socket SO_SNDBUF and  SO_RCVBUF set to %d",
371
 
                   sock_buf);
372
 
    }
373
 
 
374
 
    if (timeout > 0) {
375
 
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
376
 
        int tmout = timeout * 1000;
377
 
        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
378
 
                   (const char *) &tmout, sizeof(int));
379
 
        setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
380
 
                   (const char *) &tmout, sizeof(int));
381
 
#elif defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO) && defined(SO_SNDTIMEO) && defined(USE_SO_SNDTIMEO)
382
 
        struct timeval tv;
383
 
        tv.tv_sec  = timeout;
384
 
        tv.tv_usec = 0;
385
 
        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
386
 
                   (const void *) &tv, sizeof(tv));
387
 
        setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
388
 
                   (const void *) &tv, sizeof(tv));
389
 
#endif
390
 
        if (JK_IS_DEBUG_LEVEL(l))
391
 
            jk_log(l, JK_LOG_DEBUG,
392
 
                   "timeout %d set for socket=%d",
393
 
                   timeout, sock);
394
 
    }
395
 
#ifdef SO_NOSIGPIPE
396
 
    /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
397
 
     * sending data to a dead peer. Possibly also existing and in use on other BSD
398
 
     * systems?
399
 
    */
400
 
    set = 1;
401
 
    if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (const char *)&set,
402
 
                   sizeof(int))) {
403
 
        JK_GET_SOCKET_ERRNO();
404
 
        jk_log(l, JK_LOG_ERROR,
405
 
                "failed setting SO_NOSIGPIPE with errno=%d", errno);
406
 
        jk_close_socket(sock);
407
 
        JK_TRACE_EXIT(l);
408
 
        return -1;
409
 
    }
410
 
#endif
411
 
#ifdef SO_LINGER
412
 
    /* Make hard closesocket by disabling lingering */
413
 
    li.l_linger = li.l_onoff = 0;
414
 
    if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (SET_TYPE)&li,
415
 
                   sizeof(li))) {
416
 
        JK_GET_SOCKET_ERRNO();
417
 
        jk_log(l, JK_LOG_ERROR,
418
 
                "failed setting SO_LINGER with errno=%d", errno);
419
 
        jk_close_socket(sock);
420
 
        JK_TRACE_EXIT(l);
421
 
        return -1;
422
 
    }
423
 
#endif
424
 
    /* Tries to connect to Tomcat (continues trying while error is EINTR) */
425
 
    if (JK_IS_DEBUG_LEVEL(l))
426
 
        jk_log(l, JK_LOG_DEBUG,
427
 
                "trying to connect socket %d to %s", sock,
428
 
                jk_dump_hinfo(addr, buf));
429
 
 
430
 
/* Need more infos for BSD 4.4 and Unix 98 defines, for now only
431
 
iSeries when Unix98 is required at compil time */
432
 
#if (_XOPEN_SOURCE >= 520) && defined(AS400)
433
 
    ((struct sockaddr *)addr)->sa_len = sizeof(struct sockaddr_in);
434
 
#endif
435
 
    ret = nb_connect(sock, (struct sockaddr *)addr, timeout);
436
 
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
437
 
    if (ret == SOCKET_ERROR) {
438
 
        errno = WSAGetLastError() - WSABASEERR;
439
 
    }
440
 
#endif /* WIN32 */
441
 
 
442
 
    /* Check if we are connected */
443
 
    if (ret) {
444
 
        jk_log(l, JK_LOG_INFO,
445
 
               "connect to %s failed with errno=%d",
446
 
               jk_dump_hinfo(addr, buf), errno);
447
 
        jk_close_socket(sock);
448
 
        sock = -1;
449
 
    }
450
 
    else {
451
 
        if (JK_IS_DEBUG_LEVEL(l))
452
 
            jk_log(l, JK_LOG_DEBUG, "socket %d connected to %s",
453
 
                   sock, jk_dump_hinfo(addr, buf));
454
 
    }
455
 
    JK_TRACE_EXIT(l);
456
 
    return sock;
457
 
}
458
 
 
459
 
/** close the socket */
460
 
 
461
 
int jk_close_socket(int s)
462
 
{
463
 
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
464
 
    if (s != INVALID_SOCKET)
465
 
        return closesocket(s) ? -1 : 0;
466
 
#else
467
 
    if (s != -1)
468
 
        return close(s);
469
 
#endif
470
 
 
471
 
    return -1;
472
 
}
473
 
 
474
 
#ifndef MAX_SECS_TO_LINGER
475
 
#define MAX_SECS_TO_LINGER 16
476
 
#endif
477
 
#define SECONDS_TO_LINGER  1
478
 
 
479
 
#ifndef SHUT_WR
480
 
#ifdef SD_SEND
481
 
#define SHUT_WR SD_SEND
482
 
#else
483
 
#define SHUT_WR 0x01
484
 
#endif
485
 
#endif
486
 
int jk_shutdown_socket(int s)
487
 
{
488
 
    unsigned char dummy[512];
489
 
    int nbytes;
490
 
    int ttl = 0;
491
 
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
492
 
    int tmout = SECONDS_TO_LINGER * 1000;
493
 
    if (s == INVALID_SOCKET)
494
 
#else
495
 
    struct timeval tv;
496
 
    if (s < 0)
497
 
#endif
498
 
        return -1;
499
 
 
500
 
    /* Shut down the socket for write, which will send a FIN
501
 
     * to the peer.
502
 
     */
503
 
    if (shutdown(s, SHUT_WR)) {
504
 
        return jk_close_socket(s);
505
 
    }
506
 
#if defined(WIN32)  || (defined(NETWARE) && defined(__NOVELL_LIBC__))
507
 
    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO,
508
 
               (const char *) &tmout, sizeof(int));
509
 
#elif defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO)
510
 
    tv.tv_sec  = SECONDS_TO_LINGER;
511
 
    tv.tv_usec = 0;
512
 
    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO,
513
 
               (const void *) &tv, sizeof(tv));
514
 
#endif
515
 
    /* Read all data from the peer until we reach "end-of-file" (FIN
516
 
     * from peer) or we've exceeded our overall timeout. If the client does
517
 
     * not send us bytes within12 second, close the connection.
518
 
     */
519
 
    while (1) {
520
 
        nbytes = jk_tcp_socket_recvfull(s, dummy, sizeof(dummy));
521
 
        if (nbytes <= 0)
522
 
            break;
523
 
        ttl += SECONDS_TO_LINGER;
524
 
        if (ttl > MAX_SECS_TO_LINGER)
525
 
            break;
526
 
    }
527
 
    return jk_close_socket(s);
528
 
}
529
 
 
530
 
/** send a long message
531
 
 * @param sd  opened socket.
532
 
 * @param b   buffer containing the data.
533
 
 * @param len length to send.
534
 
 * @return    -2: send returned 0 ? what this that ?
535
 
 *            -3: send failed.
536
 
 *            >0: total size send.
537
 
 * @bug       this fails on Unixes if len is too big for the underlying
538
 
 *             protocol.
539
 
 */
540
 
int jk_tcp_socket_sendfull(int sd, const unsigned char *b, int len)
541
 
{
542
 
    int sent = 0;
543
 
    int wr;
544
 
 
545
 
    while (sent < len) {
546
 
        do {
547
 
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
548
 
            wr = send(sd, (const char*)(b + sent),
549
 
                      len - sent, 0);
550
 
            if (wr == SOCKET_ERROR)
551
 
                errno = WSAGetLastError() - WSABASEERR;
552
 
#else
553
 
            wr = write(sd, b + sent, len - sent);
554
 
#endif
555
 
        } while (wr == -1 && (errno == EINTR || errno == EAGAIN));
556
 
 
557
 
        if (wr == -1)
558
 
            return (errno > 0) ? -errno : errno;
559
 
        else if (wr == 0)
560
 
            return JK_SOCKET_EOF;
561
 
        sent += wr;
562
 
    }
563
 
 
564
 
    return sent;
565
 
}
566
 
 
567
 
/** receive len bytes. Used in ajp_common.
568
 
 * @param sd  opened socket.
569
 
 * @param b   buffer to store the data.
570
 
 * @param len length to receive.
571
 
 * @return    <0: receive failed or connection closed.
572
 
 *            >0: length of the received data.
573
 
 */
574
 
int jk_tcp_socket_recvfull(int sd, unsigned char *b, int len)
575
 
{
576
 
    int rdlen = 0;
577
 
    int rd;
578
 
 
579
 
    while (rdlen < len) {
580
 
        do {
581
 
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
582
 
            rd = recv(sd, (char *)b + rdlen,
583
 
                      len - rdlen, 0);
584
 
            /* Assuming SOCKET_ERROR is -1 on NETWARE too */
585
 
            if (rd == SOCKET_ERROR)
586
 
                errno = WSAGetLastError() - WSABASEERR;
587
 
#else
588
 
            rd = read(sd, (char *)b + rdlen, len - rdlen);
589
 
#endif
590
 
        } while (rd == -1 && (errno == EINTR || errno == EAGAIN));
591
 
 
592
 
        if (rd == -1)
593
 
            return (errno > 0) ? -errno : errno;
594
 
        else if (rd == 0)
595
 
            return JK_SOCKET_EOF;
596
 
        rdlen += rd;
597
 
    }
598
 
 
599
 
    return rdlen;
600
 
}
601
 
 
602
 
/**
603
 
 * dump a sockaddr_in in A.B.C.D:P in ASCII buffer
604
 
 *
605
 
 */
606
 
char *jk_dump_hinfo(struct sockaddr_in *saddr, char *buf)
607
 
{
608
 
    unsigned long laddr = (unsigned long)htonl(saddr->sin_addr.s_addr);
609
 
    unsigned short lport = (unsigned short)htons(saddr->sin_port);
610
 
 
611
 
    sprintf(buf, "%d.%d.%d.%d:%d",
612
 
            (int)(laddr >> 24), (int)((laddr >> 16) & 0xff),
613
 
            (int)((laddr >> 8) & 0xff), (int)(laddr & 0xff), (int)lport);
614
 
 
615
 
    return buf;
616
 
}
617
 
 
618
 
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
619
 
int jk_is_socket_connected(int sd)
620
 
{
621
 
    fd_set fd;
622
 
    struct timeval tv;
623
 
    int rc;
624
 
 
625
 
    FD_ZERO(&fd);
626
 
    FD_SET(sd, &fd);
627
 
 
628
 
    /* Wait one microsecond */
629
 
    tv.tv_sec  = 0;
630
 
    tv.tv_usec = 1;
631
 
 
632
 
    /* If we get a timeout, then we are still connected */
633
 
    if ((rc = select(1, &fd, NULL, NULL, &tv)) == 0) {
634
 
        errno = 0;
635
 
        return 1;
636
 
    }
637
 
    else {
638
 
        if (rc == SOCKET_ERROR)
639
 
            errno = WSAGetLastError() - WSABASEERR;
640
 
        else
641
 
            errno = EOF;
642
 
        return 0;
643
 
    }
644
 
}
645
 
#else
646
 
int jk_is_socket_connected(int sd)
647
 
{
648
 
    char test_buffer[1];
649
 
    int  rd;
650
 
    int  saved_errno;
651
 
 
652
 
    errno = 0;
653
 
    /* Set socket to nonblocking */
654
 
    if (sononblock(sd) != 0)
655
 
        return 0;
656
 
    do {
657
 
        rd = read(sd, test_buffer, 1);
658
 
    } while (rd == -1 && errno == EINTR);
659
 
    saved_errno = errno;
660
 
    soblock(sd);
661
 
    if (rd == -1 && saved_errno == EWOULDBLOCK) {
662
 
    errno = 0;
663
 
        return 1;
664
 
    }
665
 
    else {
666
 
        errno = saved_errno ? saved_errno : EOF;
667
 
        return 0;
668
 
    }
669
 
}
670
 
#endif