File: tcp.c

package info (click to toggle)
httping 0.0.96-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 136 kB
  • ctags: 37
  • sloc: ansic: 807; makefile: 72
file content (123 lines) | stat: -rw-r--r-- 3,331 bytes parent folder | download
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/* The GPL applies to this program.
  In addition, as a special exception, the copyright holders give
  permission to link the code of portions of this program with the
  OpenSSL library under certain conditions as described in each
  individual source file, and distribute linked combinations
  including the two.
  You must obey the GNU General Public License in all respects
  for all of the code used other than OpenSSL.  If you modify
  file(s) with this exception, you may extend this exception to your
  version of the file(s), but you are not obligated to do so.  If you
  do not wish to do so, delete this exception statement from your
  version.  If you delete this exception statement from all source
  files in the program, then also delete it here.
*/

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "io.h"
#include "tcp.h"

int connect_to(char *host, int portnr, int timeout)
{
        int     fd;
        int     loop;
        struct sockaddr_in      addr;
        struct hostent  *hostdnsentries;

        /* create socket */
        fd = socket(AF_INET, SOCK_STREAM, 0);
        if (fd == -1)
        {
                perror("problem creating socket ");
                return -1;
        }

        hostdnsentries = gethostbyname(host);
        if (hostdnsentries == NULL)
        {
                fprintf(stderr, "could not resolve %s:%d: %s\n", host, portnr, strerror(errno));
                close(fd);
                return -1;
        }

        /* initialize address structure */
        memset((void *)&addr, 0, sizeof(addr));
        addr.sin_port   = htons(portnr);
        addr.sin_family = hostdnsentries -> h_addrtype;

	/* make fd nonblocking */
	if (set_fd_nonblocking(fd) == -1)
		return -1;

        /* try to connect for each of the entries: */
        for(loop=0; ; loop++)
        {
		int rc;
		struct timeval to;
		fd_set wfds;

		/* end of list with hosts? */
                if ((hostdnsentries -> h_addr_list[loop]) == NULL)
                        break;

		/* create address structure */
                addr.sin_addr = incopy(hostdnsentries -> h_addr_list[loop]);

		/* wait for connection */
		FD_ZERO(&wfds);
		FD_SET(fd, &wfds);

		to.tv_sec  = timeout / 1000;
		to.tv_usec = (timeout - (to.tv_sec * 1000)) * 1000;

                /* connect to peer */
                if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0)
                {
                        /* connection made, return */
                        return fd;
                }

		/* wait for connection */
		rc = select(fd + 1, NULL, &wfds, NULL, &to);
		if (rc == 0)
			return -2;	/* timeout */
		else if (rc == -1)
		{
			if (errno == EINTR)
				return -3;	/* ^C pressed */
			else
				return -1;	/* error */
		}
		else
		{
			int optval=0;
			int optvallen=sizeof(optval);

			/* see if the connect succeeded or failed */
			if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optvallen) == -1)
				return -1;

			/* no error? */
			if (optval == 0)
				return fd;

			/* don't ask */
			errno = optval;
		}
        }

        close(fd);

	fprintf(stderr, "could not connect to %s:%d: %s\n", host, portnr, strerror(errno));

        return -1;
}