1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
|
/*
** Copyright 2001 Double Precision, Inc.
** See COPYING for distribution information.
*/
#include "sconnect.h"
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "soxwrap.h"
static const char rcsid[]="$Id: sconnect.c,v 1.5 2006/03/04 14:48:32 mrsam Exp $";
int s_connect(int sockfd, const struct sockaddr *addr, size_t addr_s,
time_t connect_timeout)
{
fd_set fdr;
struct timeval tv;
int rc;
#ifdef SOL_KEEPALIVE
setsockopt(sockfd, SOL_SOCKET, SOL_KEEPALIVE,
(const char *)&dummy, sizeof(dummy));
#endif
#ifdef SOL_LINGER
{
struct linger l;
l.l_onoff=0;
l.l_linger=0;
setsockopt(sockfd, SOL_SOCKET, SOL_LINGER,
(const char *)&l, sizeof(l));
}
#endif
/*
** If configuration says to use the kernel's timeout settings,
** just call connect, and be done with it.
*/
if (connect_timeout == 0)
return ( sox_connect(sockfd, addr, addr_s));
/* Asynchronous connect with timeout. */
if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) return (-1);
if ( sox_connect(sockfd, addr, addr_s) == 0)
{
/* That was easy, we're done. */
if (fcntl(sockfd, F_SETFL, 0) < 0) return (-1);
return (0);
}
else
if (errno != EINPROGRESS) return (-1);
/* Wait for the connection to go through, until the timeout expires */
FD_ZERO(&fdr);
FD_SET(sockfd, &fdr);
tv.tv_sec=connect_timeout;
tv.tv_usec=0;
rc=sox_select(sockfd+1, 0, &fdr, 0, &tv);
if (rc < 0) return (-1);
if (!FD_ISSET(sockfd, &fdr))
{
errno=ETIMEDOUT;
return (-1);
}
{
int gserr;
socklen_t gslen = sizeof(gserr);
if (sox_getsockopt(sockfd, SOL_SOCKET,
SO_ERROR,
(char *)&gserr, &gslen)==0)
{
if (gserr == 0)
return 0;
errno=gserr;
}
}
return (-1);
}
|