2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 * Description: Socket/Naming manipulation functions
20 * Based on: Various Jserv files
24 * @author Gal Shachor <shachor@il.ibm.com>
25 * @author Mladen Turk <mturk@apache.org>
26 * @version $Revision: 1125651 $
30 #include "jk_connect.h"
34 #include "apr_network_io.h"
35 #include "apr_errno.h"
36 #include "apr_general.h"
37 #include "apr_pools.h"
38 static apr_pool_t *jk_apr_pool = NULL;
41 #ifdef HAVE_SYS_FILIO_H
42 /* FIONREAD on Solaris et al. */
43 #include <sys/filio.h>
46 /* Use poll instead select */
50 #if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
51 #define JK_IS_SOCKET_ERROR(x) ((x) == SOCKET_ERROR)
52 #define JK_GET_SOCKET_ERRNO() errno = WSAGetLastError() - WSABASEERR
54 #define JK_IS_SOCKET_ERROR(x) ((x) == -1)
55 #define JK_GET_SOCKET_ERRNO() ((void)0)
58 #if defined(NETWARE) && defined(__NOVELL_LIBC__)
59 #define USE_SOCK_CLOEXEC
62 /* our compiler cant deal with char* <-> const char* ... */
63 #if defined(NETWARE) && !defined(__NOVELL_LIBC__)
64 typedef char* SET_TYPE;
66 typedef const char* SET_TYPE;
69 /** Set socket to blocking
70 * @param sd socket to manipulate
71 * @return errno: fcntl returns -1 (!WIN32)
72 * pseudo errno: ioctlsocket returns SOCKET_ERROR (WIN32)
75 static int soblock(jk_sock_t sd)
77 /* BeOS uses setsockopt at present for non blocking... */
78 #if defined (WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
80 if (JK_IS_SOCKET_ERROR(ioctlsocket(sd, FIONBIO, &on))) {
81 JK_GET_SOCKET_ERRNO();
87 fd_flags = fcntl(sd, F_GETFL, 0);
88 #if defined(O_NONBLOCK)
89 fd_flags &= ~O_NONBLOCK;
90 #elif defined(O_NDELAY)
91 fd_flags &= ~O_NDELAY;
92 #elif defined(FNDELAY)
95 #error Please teach JK how to make sockets blocking on your platform.
97 if (fcntl(sd, F_SETFL, fd_flags) == -1) {
100 #endif /* WIN32 || (NETWARE && __NOVELL_LIBC__) */
104 /** Set socket to non-blocking
105 * @param sd socket to manipulate
106 * @return errno: fcntl returns -1 (!WIN32)
107 * pseudo errno: ioctlsocket returns SOCKET_ERROR (WIN32)
110 static int sononblock(jk_sock_t sd)
112 #if defined (WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
114 if (JK_IS_SOCKET_ERROR(ioctlsocket(sd, FIONBIO, &on))) {
115 JK_GET_SOCKET_ERRNO();
121 fd_flags = fcntl(sd, F_GETFL, 0);
122 #if defined(O_NONBLOCK)
123 fd_flags |= O_NONBLOCK;
124 #elif defined(O_NDELAY)
125 fd_flags |= O_NDELAY;
126 #elif defined(FNDELAY)
129 #error Please teach JK how to make sockets non-blocking on your platform.
131 if (fcntl(sd, F_SETFL, fd_flags) == -1) {
134 #endif /* WIN32 || (NETWARE && __NOVELL_LIBC__) */
138 #if defined (WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
139 /* WIN32 implementation */
140 /** Non-blocking socket connect
141 * @param sd socket to connect
142 * @param addr address to connect to
143 * @param timeout connect timeout in seconds
144 * (<=0: no timeout=blocking)
146 * @return -1: some kind of error occured
147 * SOCKET_ERROR: no timeout given and error
148 * during blocking connect
151 static int nb_connect(jk_sock_t sd, struct sockaddr *addr, int timeout, jk_logger_t *l)
158 rc = connect(sd, addr, sizeof(struct sockaddr_in));
163 if ((rc = sononblock(sd))) {
167 if (JK_IS_SOCKET_ERROR(connect(sd, addr, sizeof(struct sockaddr_in)))) {
169 fd_set wfdset, efdset;
171 if ((rc = WSAGetLastError()) != WSAEWOULDBLOCK) {
177 /* wait for the connect to complete or timeout */
183 tv.tv_sec = timeout / 1000;
184 tv.tv_usec = (timeout % 1000) * 1000;
186 rc = select((int)sd + 1, NULL, &wfdset, &efdset, &tv);
187 if (JK_IS_SOCKET_ERROR(rc) || rc == 0) {
188 rc = WSAGetLastError();
194 /* Evaluate the efdset */
195 if (FD_ISSET(sd, &efdset)) {
196 /* The connect failed. */
197 int rclen = (int)sizeof(rc);
198 if (getsockopt(sd, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen))
212 #elif !defined(NETWARE)
213 /* POSIX implementation */
214 /** Non-blocking socket connect
215 * @param sd socket to connect
216 * @param addr address to connect to
217 * @param timeout connect timeout in seconds
218 * (<=0: no timeout=blocking)
220 * @return -1: some kind of error occured
223 static int nb_connect(jk_sock_t sd, struct sockaddr *addr, int timeout, jk_logger_t *l)
230 if (sononblock(sd)) {
236 rc = connect(sd, addr, sizeof(struct sockaddr_in));
237 } while (rc == -1 && errno == EINTR);
239 if ((rc == -1) && (errno == EINPROGRESS || errno == EALREADY)
243 socklen_t rclen = (socklen_t)sizeof(rc);
247 tv.tv_sec = timeout / 1000;
248 tv.tv_usec = (timeout % 1000) * 1000;
249 rc = select(sd + 1, NULL, &wfdset, NULL, &tv);
260 if (!FD_ISSET(sd, &wfdset) ||
261 (getsockopt(sd, SOL_SOCKET, SO_ERROR,
262 (char *)&rc, &rclen) < 0) || rc) {
267 #endif /* SO_ERROR */
269 /* Not sure we can be already connected */
270 if (rc == -1 && errno == EISCONN)
277 /* NETWARE implementation - blocking for now */
278 /** Non-blocking socket connect
279 * @param sd socket to connect
280 * @param addr address to connect to
281 * @param timeout connect timeout in seconds (ignored!)
283 * @return -1: some kind of error occured
286 static int nb_connect(jk_sock_t sd, struct sockaddr *addr, int timeout, jk_logger_t *l)
292 rc = connect(sd, addr, sizeof(struct sockaddr_in));
302 * i5/OS V5R4 need EBCDIC for its runtime calls but APR/APACHE works in UTF
304 in_addr_t jk_inet_addr(const char * addrstr)
309 ptr = (char *)malloc(strlen(addrstr) + 1);
310 jk_ascii2ebcdic((char *)addrstr, ptr);
311 addr = inet_addr(ptr);
319 /** Resolve the host IP
320 * @param host host or ip address
322 * @param rc return value pointer
324 * @return JK_FALSE: some kind of error occured
327 int jk_resolve(const char *host, int port, struct sockaddr_in *rc,
328 void *pool, jk_logger_t *l)
331 struct in_addr laddr;
335 memset(rc, 0, sizeof(struct sockaddr_in));
337 rc->sin_port = htons((short)port);
338 rc->sin_family = AF_INET;
340 /* Check if we only have digits in the string */
341 for (x = 0; host[x] != '\0'; x++) {
342 if (!isdigit((int)(host[x])) && host[x] != '.') {
347 /* If we found also characters we should make name to IP resolution */
348 if (host[x] != '\0') {
351 apr_sockaddr_t *remote_sa, *temp_sa;
355 if (apr_pool_create(&jk_apr_pool, (apr_pool_t *)pool) != APR_SUCCESS) {
360 apr_pool_clear(jk_apr_pool);
361 if (apr_sockaddr_info_get
362 (&remote_sa, host, APR_UNSPEC, (apr_port_t) port, 0, jk_apr_pool)
368 /* Since we are only handling AF_INET (IPV4) address (in_addr_t) */
369 /* make sure we find one of those. */
371 while ((NULL != temp_sa) && (AF_INET != temp_sa->family))
372 temp_sa = temp_sa->next;
374 /* if temp_sa is set, we have a valid address otherwise, just return */
382 apr_sockaddr_ip_get(&remote_ipaddr, remote_sa);
384 laddr.s_addr = jk_inet_addr(remote_ipaddr);
388 /* XXX : WARNING : We should really use gethostbyname_r in multi-threaded env */
389 /* Fortunatly when APR is available, ie under Apache 2.0, we use it */
390 #if defined(NETWARE) && !defined(__NOVELL_LIBC__)
391 struct hostent *hoste = gethostbyname((char*)host);
393 struct hostent *hoste = gethostbyname(host);
400 laddr = *((struct in_addr *)hoste->h_addr_list[0]);
402 #endif /* HAVE_APR */
405 /* If we found only digits we use inet_addr() */
406 laddr.s_addr = jk_inet_addr(host);
408 memcpy(&(rc->sin_addr), &laddr, sizeof(laddr));
414 /** Connect to Tomcat
415 * @param addr address to connect to
416 * @param keepalive should we set SO_KEEPALIVE (if !=0)
417 * @param timeout connect timeout in seconds
418 * (<=0: no timeout=blocking)
419 * @param sock_buf size of send and recv buffer
422 * @return JK_INVALID_SOCKET: some kind of error occured
423 * created socket: success
424 * @remark Cares about errno
426 jk_sock_t jk_open_socket(struct sockaddr_in *addr, int keepalive,
427 int timeout, int connect_timeout,
428 int sock_buf, jk_logger_t *l)
442 #if defined(SOCK_CLOEXEC) && defined(USE_SOCK_CLOEXEC)
443 flags |= SOCK_CLOEXEC;
445 sd = socket(AF_INET, SOCK_STREAM | flags, 0);
446 if (!IS_VALID_SOCKET(sd)) {
447 JK_GET_SOCKET_ERRNO();
448 jk_log(l, JK_LOG_ERROR,
449 "socket() failed (errno=%d)", errno);
451 return JK_INVALID_SOCKET;
453 #if defined(FD_CLOEXEC) && !defined(USE_SOCK_CLOEXEC)
454 if ((flags = fcntl(sd, F_GETFD)) == -1) {
455 JK_GET_SOCKET_ERRNO();
456 jk_log(l, JK_LOG_ERROR,
457 "fcntl() failed (errno=%d)", errno);
458 jk_close_socket(sd, l);
460 return JK_INVALID_SOCKET;
463 if (fcntl(sd, F_SETFD, flags) == -1) {
464 JK_GET_SOCKET_ERRNO();
465 jk_log(l, JK_LOG_ERROR,
466 "fcntl() failed (errno=%d)", errno);
467 jk_close_socket(sd, l);
469 return JK_INVALID_SOCKET;
473 /* Disable Nagle algorithm */
474 if (setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (SET_TYPE)&set,
476 JK_GET_SOCKET_ERRNO();
477 jk_log(l, JK_LOG_ERROR,
478 "failed setting TCP_NODELAY (errno=%d)", errno);
479 jk_close_socket(sd, l);
481 return JK_INVALID_SOCKET;
483 if (JK_IS_DEBUG_LEVEL(l))
484 jk_log(l, JK_LOG_DEBUG,
485 "socket TCP_NODELAY set to On");
487 #if defined(WIN32) && !defined(NETWARE)
489 struct tcp_keepalive ka = { 0 }, ks = { 0 };
491 ka.keepalivetime = timeout * 10000;
493 ka.keepalivetime = 60 * 10000; /* 10 minutes */
494 ka.keepaliveinterval = 1000;
496 if (WSAIoctl(sd, SIO_KEEPALIVE_VALS, &ka, sizeof(ka),
497 &ks, sizeof(ks), &dw, NULL, NULL)) {
498 JK_GET_SOCKET_ERRNO();
499 jk_log(l, JK_LOG_ERROR,
500 "failed setting SIO_KEEPALIVE_VALS (errno=%d)", errno);
501 jk_close_socket(sd, l);
503 return JK_INVALID_SOCKET;
505 if (JK_IS_DEBUG_LEVEL(l))
506 jk_log(l, JK_LOG_DEBUG,
507 "socket SO_KEEPALIVE set to %d seconds",
508 ka.keepalivetime / 1000);
511 if (setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, (SET_TYPE)&set,
513 JK_GET_SOCKET_ERRNO();
514 jk_log(l, JK_LOG_ERROR,
515 "failed setting SO_KEEPALIVE (errno=%d)", errno);
516 jk_close_socket(sd, l);
518 return JK_INVALID_SOCKET;
520 if (JK_IS_DEBUG_LEVEL(l))
521 jk_log(l, JK_LOG_DEBUG,
522 "socket SO_KEEPALIVE set to On");
528 /* Set socket send buffer size */
529 if (setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (SET_TYPE)&set,
531 JK_GET_SOCKET_ERRNO();
532 jk_log(l, JK_LOG_ERROR,
533 "failed setting SO_SNDBUF (errno=%d)", errno);
534 jk_close_socket(sd, l);
536 return JK_INVALID_SOCKET;
539 /* Set socket receive buffer size */
540 if (setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (SET_TYPE)&set,
542 JK_GET_SOCKET_ERRNO();
543 jk_log(l, JK_LOG_ERROR,
544 "failed setting SO_RCVBUF (errno=%d)", errno);
545 jk_close_socket(sd, l);
547 return JK_INVALID_SOCKET;
549 if (JK_IS_DEBUG_LEVEL(l))
550 jk_log(l, JK_LOG_DEBUG,
551 "socket SO_SNDBUF and SO_RCVBUF set to %d",
556 #if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
557 int tmout = timeout * 1000;
558 setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO,
559 (const char *) &tmout, sizeof(int));
560 setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO,
561 (const char *) &tmout, sizeof(int));
562 JK_GET_SOCKET_ERRNO();
563 #elif defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO) && defined(SO_SNDTIMEO) && defined(USE_SO_SNDTIMEO)
567 setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO,
568 (const void *) &tv, sizeof(tv));
569 setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO,
570 (const void *) &tv, sizeof(tv));
572 if (JK_IS_DEBUG_LEVEL(l))
573 jk_log(l, JK_LOG_DEBUG,
574 "timeout %d set for socket=%d",
578 /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
579 * sending data to a dead peer. Possibly also existing and in use on other BSD
583 if (setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, (const char *)&set,
585 JK_GET_SOCKET_ERRNO();
586 jk_log(l, JK_LOG_ERROR,
587 "failed setting SO_NOSIGPIPE (errno=%d)", errno);
588 jk_close_socket(sd, l);
590 return JK_INVALID_SOCKET;
594 /* Make hard closesocket by disabling lingering */
595 li.l_linger = li.l_onoff = 0;
596 if (setsockopt(sd, SOL_SOCKET, SO_LINGER, (SET_TYPE)&li,
598 JK_GET_SOCKET_ERRNO();
599 jk_log(l, JK_LOG_ERROR,
600 "failed setting SO_LINGER (errno=%d)", errno);
601 jk_close_socket(sd, l);
603 return JK_INVALID_SOCKET;
606 /* Tries to connect to Tomcat (continues trying while error is EINTR) */
607 if (JK_IS_DEBUG_LEVEL(l))
608 jk_log(l, JK_LOG_DEBUG,
609 "trying to connect socket %d to %s", sd,
610 jk_dump_hinfo(addr, buf));
612 /* Need more infos for BSD 4.4 and Unix 98 defines, for now only
613 iSeries when Unix98 is required at compil time */
614 #if (_XOPEN_SOURCE >= 520) && defined(AS400)
615 ((struct sockaddr *)addr)->sa_len = sizeof(struct sockaddr_in);
617 ret = nb_connect(sd, (struct sockaddr *)addr, connect_timeout, l);
618 #if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
619 if (JK_IS_SOCKET_ERROR(ret)) {
620 JK_GET_SOCKET_ERRNO();
624 /* Check if we are connected */
626 jk_log(l, JK_LOG_INFO,
627 "connect to %s failed (errno=%d)",
628 jk_dump_hinfo(addr, buf), errno);
629 jk_close_socket(sd, l);
630 sd = JK_INVALID_SOCKET;
633 if (JK_IS_DEBUG_LEVEL(l))
634 jk_log(l, JK_LOG_DEBUG, "socket %d [%s] connected",
635 sd, jk_dump_sinfo(sd, buf));
642 * @param sd socket to close
644 * @return -1: some kind of error occured (!WIN32)
645 * SOCKET_ERROR: some kind of error occured (WIN32)
647 * @remark Does not change errno
649 int jk_close_socket(jk_sock_t sd, jk_logger_t *l)
656 if (!IS_VALID_SOCKET(sd)) {
662 #if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
663 rc = closesocket(sd) ? -1 : 0;
667 } while (JK_IS_SOCKET_ERROR(rc) && (errno == EINTR || errno == EAGAIN));
674 #ifndef MAX_SECS_TO_LINGER
675 #define MAX_SECS_TO_LINGER 2
677 #define MS_TO_LINGER 500
678 #define MS_TO_LINGER_LAST 2
680 #ifndef MAX_LINGER_BYTES
681 #define MAX_LINGER_BYTES 32768
686 #define SHUT_WR SD_SEND
694 #define SHUT_RD SD_RECEIVE
700 /** Drain and close the socket
701 * @param sd socket to close
703 * @return -1: socket to close is invalid
704 * -1: some kind of error occured (!WIN32)
705 * SOCKET_ERROR: some kind of error occured (WIN32)
707 * @remark Does not change errno
709 int jk_shutdown_socket(jk_sock_t sd, jk_logger_t *l)
718 int timeout = MS_TO_LINGER;
719 time_t start = time(NULL);
723 if (!IS_VALID_SOCKET(sd)) {
729 if (JK_IS_DEBUG_LEVEL(l)) {
730 sb = jk_dump_sinfo(sd, buf);
731 jk_log(l, JK_LOG_DEBUG, "About to shutdown socket %d [%s]",
734 /* Shut down the socket for write, which will send a FIN
737 if (shutdown(sd, SHUT_WR)) {
738 rc = jk_close_socket(sd, l);
739 if (JK_IS_DEBUG_LEVEL(l))
740 jk_log(l, JK_LOG_DEBUG,
741 "Failed sending SHUT_WR for socket %d [%s]",
750 if (jk_is_input_event(sd, timeout, l)) {
751 /* Do a restartable read on the socket
752 * draining out all the data currently in the socket buffer.
755 #if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
756 rc = recv(sd, &dummy[0], sizeof(dummy), 0);
757 if (JK_IS_SOCKET_ERROR(rc))
758 JK_GET_SOCKET_ERRNO();
760 rc = read(sd, &dummy[0], sizeof(dummy));
764 } while (JK_IS_SOCKET_ERROR(rc) && (errno == EINTR || errno == EAGAIN));
768 * Bail out from the loop.
774 /* Error or timeout (reason is logged within jk_is_input_event)
775 * Exit the drain loop
780 if (rp < sizeof(dummy)) {
781 if (timeout > MS_TO_LINGER_LAST) {
782 /* Try one last time with a short timeout
784 timeout = MS_TO_LINGER_LAST;
787 /* We have read less then size of buffer
788 * It's a good chance there will be no more data
791 if ((rc = sononblock(sd))) {
792 rc = jk_close_socket(sd, l);
793 if (JK_IS_DEBUG_LEVEL(l))
794 jk_log(l, JK_LOG_DEBUG,
795 "error setting socket %d [%s] to nonblocking",
801 if (JK_IS_DEBUG_LEVEL(l))
802 jk_log(l, JK_LOG_DEBUG,
803 "shutting down the read side of socket %d [%s]",
805 shutdown(sd, SHUT_RD);
808 timeout = MS_TO_LINGER;
809 } while ((rd < MAX_LINGER_BYTES) && (difftime(time(NULL), start) < MAX_SECS_TO_LINGER));
811 rc = jk_close_socket(sd, l);
812 if (JK_IS_DEBUG_LEVEL(l))
813 jk_log(l, JK_LOG_DEBUG,
814 "Shutdown socket %d [%s] and read %d lingering bytes in %d sec.",
815 sd, sb, rd, (int)difftime(time(NULL), start));
822 * @param sd socket to use
823 * @param b buffer containing the data
824 * @param len length to send
826 * @return negative errno: write returns a fatal -1 (!WIN32)
827 * negative pseudo errno: send returns SOCKET_ERROR (WIN32)
828 * JK_SOCKET_EOF: no bytes could be sent
829 * >0: success, provided number of bytes send
830 * @remark Always closes socket in case of error
831 * @remark Cares about errno
832 * @bug this fails on Unixes if len is too big for the underlying
835 int jk_tcp_socket_sendfull(jk_sock_t sd, const unsigned char *b, int len, jk_logger_t *l)
845 #if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
846 wr = send(sd, (const char*)(b + sent),
848 if (JK_IS_SOCKET_ERROR(wr))
849 JK_GET_SOCKET_ERRNO();
851 wr = write(sd, b + sent, len - sent);
853 } while (JK_IS_SOCKET_ERROR(wr) && (errno == EINTR || errno == EAGAIN));
855 if (JK_IS_SOCKET_ERROR(wr)) {
857 jk_shutdown_socket(sd, l);
858 err = (errno > 0) ? -errno : errno;
863 jk_shutdown_socket(sd, l);
865 return JK_SOCKET_EOF;
874 /** receive a message
875 * @param sd socket to use
876 * @param b buffer to store the data
877 * @param len length to receive
879 * @return negative errno: read returns a fatal -1 (!WIN32)
880 * negative pseudo errno: recv returns SOCKET_ERROR (WIN32)
881 * JK_SOCKET_EOF: no bytes could be read
882 * >0: success, requested number of bytes received
883 * @remark Always closes socket in case of error
884 * @remark Cares about errno
886 int jk_tcp_socket_recvfull(jk_sock_t sd, unsigned char *b, int len, jk_logger_t *l)
894 while (rdlen < len) {
896 #if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
897 rd = recv(sd, (char *)b + rdlen,
899 if (JK_IS_SOCKET_ERROR(rd))
900 JK_GET_SOCKET_ERRNO();
902 rd = read(sd, (char *)b + rdlen, len - rdlen);
904 } while (JK_IS_SOCKET_ERROR(rd) && errno == EINTR);
906 if (JK_IS_SOCKET_ERROR(rd)) {
907 int err = (errno > 0) ? -errno : errno;
908 jk_shutdown_socket(sd, l);
910 return (err == 0) ? JK_SOCKET_EOF : err;
913 jk_shutdown_socket(sd, l);
915 return JK_SOCKET_EOF;
925 * dump a sockaddr_in in A.B.C.D:P in ASCII buffer
928 char *jk_dump_hinfo(struct sockaddr_in *saddr, char *buf)
930 unsigned long laddr = (unsigned long)htonl(saddr->sin_addr.s_addr);
931 unsigned short lport = (unsigned short)htons(saddr->sin_port);
933 sprintf(buf, "%d.%d.%d.%d:%d",
934 (int)(laddr >> 24), (int)((laddr >> 16) & 0xff),
935 (int)((laddr >> 8) & 0xff), (int)(laddr & 0xff), (int)lport);
940 char *jk_dump_sinfo(jk_sock_t sd, char *buf)
942 struct sockaddr_in rsaddr;
943 struct sockaddr_in lsaddr;
946 salen = sizeof(struct sockaddr);
947 if (getsockname(sd, (struct sockaddr *)&lsaddr, &salen) == 0) {
948 salen = sizeof(struct sockaddr);
949 if (getpeername(sd, (struct sockaddr *)&rsaddr, &salen) == 0) {
950 unsigned long laddr = (unsigned long)htonl(lsaddr.sin_addr.s_addr);
951 unsigned short lport = (unsigned short)htons(lsaddr.sin_port);
952 unsigned long raddr = (unsigned long)htonl(rsaddr.sin_addr.s_addr);
953 unsigned short rport = (unsigned short)htons(rsaddr.sin_port);
954 sprintf(buf, "%d.%d.%d.%d:%d -> %d.%d.%d.%d:%d",
955 (int)(laddr >> 24), (int)((laddr >> 16) & 0xff),
956 (int)((laddr >> 8) & 0xff), (int)(laddr & 0xff), (int)lport,
957 (int)(raddr >> 24), (int)((raddr >> 16) & 0xff),
958 (int)((raddr >> 8) & 0xff), (int)(raddr & 0xff), (int)rport);
962 sprintf(buf, "error=%d", errno);
966 /** Wait for input event on socket until timeout
967 * @param sd socket to use
968 * @param timeout wait timeout in milliseconds
970 * @return JK_FALSE: Timeout expired without something to read
971 * JK_FALSE: Error during waiting
973 * @remark Does not close socket in case of error
974 * to allow for iterative waiting
975 * @remark Cares about errno
978 int jk_is_input_event(jk_sock_t sd, int timeout, jk_logger_t *l)
993 rc = poll(&fds, 1, timeout);
994 } while (rc < 0 && errno == EINTR);
997 if (JK_IS_DEBUG_LEVEL(l)) {
998 jk_log(l, JK_LOG_DEBUG,
999 "timeout during poll on socket %d [%s] (timeout=%d)",
1000 sd, jk_dump_sinfo(sd, buf), timeout);
1002 /* Timeout. Set the errno to timeout */
1009 if (JK_IS_DEBUG_LEVEL(l)) {
1010 jk_log(l, JK_LOG_DEBUG,
1011 "error during poll on socket %d [%s] (errno=%d)",
1012 sd, jk_dump_sinfo(sd, buf), errno);
1018 if ((fds.revents & (POLLERR | POLLHUP))) {
1019 save_errno = fds.revents & (POLLERR | POLLHUP);
1020 if (JK_IS_DEBUG_LEVEL(l)) {
1021 jk_log(l, JK_LOG_DEBUG,
1022 "error event during poll on socket %d [%s] (event=%d)",
1023 sd, jk_dump_sinfo(sd, buf), save_errno);
1034 int jk_is_input_event(jk_sock_t sd, int timeout, jk_logger_t *l)
1047 tv.tv_sec = timeout / 1000;
1048 tv.tv_usec = (timeout % 1000) * 1000;
1051 rc = select((int)sd + 1, &rset, NULL, NULL, &tv);
1052 } while (rc < 0 && errno == EINTR);
1055 if (JK_IS_DEBUG_LEVEL(l)) {
1056 jk_log(l, JK_LOG_DEBUG,
1057 "timeout during select on socket %d [%s] (timeout=%d)",
1058 sd, jk_dump_sinfo(sd, buf), timeout);
1060 /* Timeout. Set the errno to timeout */
1061 #if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
1062 errno = WSAETIMEDOUT - WSABASEERR;
1071 if (JK_IS_DEBUG_LEVEL(l)) {
1072 jk_log(l, JK_LOG_DEBUG,
1073 "error during select on socket %d [%s] (errno=%d)",
1074 sd, jk_dump_sinfo(sd, buf), errno);
1086 /** Test if a socket is still connected
1087 * @param sd socket to use
1089 * @return JK_FALSE: failure
1091 * @remark Always closes socket in case of error
1092 * @remark Cares about errno
1095 int jk_is_socket_connected(jk_sock_t sd, jk_logger_t *l)
1104 fds.events = POLLIN;
1107 rc = poll(&fds, 1, 0);
1108 } while (rc < 0 && errno == EINTR);
1111 /* If we get a timeout, then we are still connected */
1115 else if (rc == 1 && fds.revents == POLLIN) {
1118 rc = (int)recvfrom(sd, &buf, 1, MSG_PEEK, NULL, NULL);
1119 } while (rc < 0 && errno == EINTR);
1121 /* There is at least one byte to read. */
1126 jk_shutdown_socket(sd, l);
1133 int jk_is_socket_connected(jk_sock_t sd, jk_logger_t *l)
1145 /* Initially test the socket without any blocking.
1151 rc = select((int)sd + 1, &fd, NULL, NULL, &tv);
1152 JK_GET_SOCKET_ERRNO();
1153 /* Wait one microsecond on next select, if EINTR */
1156 } while (JK_IS_SOCKET_ERROR(rc) && errno == EINTR);
1160 /* If we get a timeout, then we are still connected */
1165 #if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
1167 rc = ioctlsocket(sd, FIONREAD, &nr);
1169 if (WSAGetLastError() == 0)
1172 JK_GET_SOCKET_ERRNO();
1176 rc = ioctl(sd, FIONREAD, (void*)&nr);
1178 if (rc == 0 && nr != 0) {
1182 JK_GET_SOCKET_ERRNO();
1184 jk_shutdown_socket(sd, l);