/**************************************************************** * * * Copyright 2001, 2010 Fidelity Information Services, Inc * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * * under a license. If you do not know the terms of * * the license, please stop and do not read further. * * * ****************************************************************/ /* get socket routines address */ #include "mdef.h" #include "gtm_netdb.h" #include "gtm_unistd.h" #include #include "gtm_socket.h" #include "gtm_inet.h" #include "gtm_string.h" /* for FD_ZERO */ #include "io.h" #include "iotcp_select.h" #include "iotcproutine.h" GBLDEF tcp_library_struct tcp_routines; int gtm_accept(int socket, struct sockaddr *address, sssize_t *address_len); int gtm_recv(int socket, void *buffer, size_t length, int flags); int gtm_send(int socket, void *buffer, size_t length, int flags); /* * Note - the checks for EINTR in these functions are valid and need to stay in, * because the functions are being assigned to members of the tcp_routines table, * and thus cannot be replaced by EINTR wrapper macros. */ int gtm_accept(int socket, struct sockaddr *address, sssize_t *address_len) { int res; do { res = accept(socket, address, (GTM_SOCKLEN_TYPE *)address_len); } while (-1 == res && EINTR == errno); return(res); } int gtm_connect(int socket, struct sockaddr *address, size_t address_len) { int res, sockerror; GTM_SOCKLEN_TYPE sockerrorlen; fd_set writefds; res = connect(socket, address, (GTM_SOCKLEN_TYPE)address_len); if ((-1 == res) && ((EINTR == errno) || (EINPROGRESS == errno) #if (defined(__osf__) && defined(__alpha)) || defined(__sun) || defined(__vms) || (EWOULDBLOCK == errno) #endif )) {/* connection attempt will continue so wait for completion */ do { /* a plain connect will usually timeout after 75 seconds with ETIMEDOUT */ FD_ZERO(&writefds); FD_SET(socket, &writefds); res = select(socket + 1, NULL, &writefds, NULL, NULL); if (-1 == res && EINTR == errno) continue; if (0 < res) { /* check for socket error */ sockerrorlen = SIZEOF(sockerror); res = getsockopt(socket, SOL_SOCKET, SO_ERROR, &sockerror, &sockerrorlen); if (0 == res && 0 != sockerror) { /* return socket error */ res = -1; errno = sockerror; } } break; } while (TRUE); } else if (-1 == res && EISCONN == errno) res = 0; /* socket is already connected */ return(res); } int gtm_recv(int socket, void *buffer, size_t length, int flags) { int res; do { res = (int)(recv(socket, buffer, (int)(length), flags)); } while (-1 == res && EINTR == errno); return(res); } int gtm_send(int socket, void *buffer, size_t length, int flags) { int res; do { res = (int)(send(socket, buffer, (int)(length), flags)); } while (-1 == res && EINTR == errno); return(res); } int iotcp_fillroutine(void) { if (gtm_accept == tcp_routines.aa_accept) return 0; /* already done */ tcp_routines.aa_accept = gtm_accept; tcp_routines.aa_bind = bind; tcp_routines.aa_close = close; tcp_routines.aa_connect = gtm_connect; tcp_routines.aa_getsockname = getsockname; tcp_routines.aa_getsockopt = getsockopt; #ifndef htons /* if htons is not a macro, assign the routine */ tcp_routines.aa_htons = htons; #endif tcp_routines.aa_inet_addr = INET_ADDR; tcp_routines.aa_inet_ntoa = INET_NTOA; #ifndef ntohs tcp_routines.aa_ntohs = ntohs; #endif tcp_routines.aa_listen = listen; tcp_routines.aa_recv = (int (*)())gtm_recv; tcp_routines.aa_select = select; tcp_routines.aa_send = (int (*)())gtm_send; tcp_routines.aa_setsockopt = setsockopt; tcp_routines.aa_socket = socket; return 0; }