-
Notifications
You must be signed in to change notification settings - Fork 0
/
connect.cpp
executable file
·116 lines (101 loc) · 3.21 KB
/
connect.cpp
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
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include "connect.h"
TCPStream* TCPConnector::connect(const char* server, int port)
{
struct sockaddr_in address;
memset (&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port);
if (resolveHostName(server, &(address.sin_addr)) != 0 ) {
inet_pton(PF_INET, server, &(address.sin_addr));
}
// Create and connect the socket
int sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0) {
perror("socket() failed");
return NULL;
}
if (::connect(sd, (struct sockaddr*)&address, sizeof(address)) != 0) {
perror("connect() failed");
close(sd);
return NULL;
}
return new TCPStream(sd, &address);
}
TCPStream* TCPConnector::connect(const char* server, int port, int timeout)
{
if (timeout == 0) return connect(server, port);
struct sockaddr_in address;
memset (&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port);
if (resolveHostName(server, &(address.sin_addr)) != 0 ) {
inet_pton(PF_INET, server, &(address.sin_addr));
}
long arg;
fd_set sdset;
struct timeval tv;
socklen_t len;
int result = -1;
int valopt;
int sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0) {
perror("socket() failed");
return NULL;
}
// Set socket to non-blocking
arg = fcntl(sd, F_GETFL, NULL);
arg |= O_NONBLOCK;
fcntl(sd, F_SETFL, arg);
// Connect with time limit
string message;
if ((result = ::connect(sd, (struct sockaddr *)&address, sizeof(address))) < 0)
{
if (errno == EINPROGRESS)
{
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO(&sdset);
FD_SET(sd, &sdset);
int s = -1;
do {
s = select(sd + 1, NULL, &sdset, NULL, &tv);
} while (s == -1 && errno == EINTR);
if (s > 0)
{
len = sizeof(int);
getsockopt(sd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &len);
if (valopt) {
fprintf(stderr, "connect() error %d - %s\n", valopt, strerror(valopt));
}
// connection established
else result = 0;
}
else fprintf(stderr, "connect() timed out\n");
}
else fprintf(stderr, "connect() error %d - %s\n", errno, strerror(errno));
}
// Return socket to blocking mode
arg = fcntl(sd, F_GETFL, NULL);
arg &= (~O_NONBLOCK);
fcntl(sd, F_SETFL, arg);
// Create stream object if connected
if (result == -1) return NULL;
return new TCPStream(sd, &address);
}
int TCPConnector::resolveHostName(const char* hostname, struct in_addr* addr)
{
struct addrinfo *res;
//set room in memory and get addr of your host
int result = getaddrinfo (hostname, NULL, NULL, &res);
if (result == 0) {
memcpy(addr, &((struct sockaddr_in *) res->ai_addr)->sin_addr, sizeof(struct in_addr));
freeaddrinfo(res);
}
return result;
}