Back to index

courier  0.68.2
sconnect.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2001 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "sconnect.h"
00007 
00008 #if HAVE_UNISTD_H
00009 #include      <unistd.h>
00010 #endif
00011 #if HAVE_FCNTL_H
00012 #include      <fcntl.h>
00013 #endif
00014 #include      <stdio.h>
00015 #include      <errno.h>
00016 #include      <string.h>
00017 
00018 #include      "soxwrap.h"
00019 
00020 
00021 int s_connect(int sockfd, const struct sockaddr *addr, size_t addr_s,
00022              time_t connect_timeout)
00023 {
00024        fd_set fdr;
00025        struct timeval tv;
00026        int    rc;
00027 
00028 #ifdef SOL_KEEPALIVE
00029        setsockopt(sockfd, SOL_SOCKET, SOL_KEEPALIVE,
00030                  (const char *)&dummy, sizeof(dummy));
00031 #endif
00032 
00033 #ifdef  SOL_LINGER
00034         {
00035               struct linger l;
00036 
00037                 l.l_onoff=0;
00038                 l.l_linger=0;
00039 
00040                 setsockopt(sockfd, SOL_SOCKET, SOL_LINGER,
00041                         (const char *)&l, sizeof(l));
00042         }
00043 #endif
00044 
00045         /*
00046         ** If configuration says to use the kernel's timeout settings,
00047         ** just call connect, and be done with it.
00048         */
00049 
00050         if (connect_timeout == 0)
00051                 return ( sox_connect(sockfd, addr, addr_s));
00052 
00053         /* Asynchronous connect with timeout. */
00054 
00055         if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0)     return (-1);
00056 
00057         if ( sox_connect(sockfd, addr, addr_s) == 0)
00058         {
00059                 /* That was easy, we're done. */
00060 
00061                 if (fcntl(sockfd, F_SETFL, 0) < 0)      return (-1);
00062                 return (0);
00063         }
00064         else
00065                 if (errno != EINPROGRESS) return (-1);
00066 
00067        /* Wait for the connection to go through, until the timeout expires */
00068 
00069         FD_ZERO(&fdr);
00070         FD_SET(sockfd, &fdr);
00071         tv.tv_sec=connect_timeout;
00072         tv.tv_usec=0;
00073 
00074         rc=sox_select(sockfd+1, 0, &fdr, 0, &tv);
00075         if (rc < 0)     return (-1);
00076 
00077         if (!FD_ISSET(sockfd, &fdr))
00078         {
00079                 errno=ETIMEDOUT;
00080                 return (-1);
00081         }
00082 
00083        {
00084               int     gserr;
00085               socklen_t gslen = sizeof(gserr);
00086 
00087               if (sox_getsockopt(sockfd, SOL_SOCKET,
00088                                SO_ERROR,
00089                                (char *)&gserr, &gslen)==0)
00090               {
00091                      if (gserr == 0)
00092                             return 0;
00093 
00094                      errno=gserr;
00095               }
00096        }
00097        return (-1);
00098 }