-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconnection.cc
100 lines (81 loc) · 1.88 KB
/
connection.cc
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
/** @file
* Connection implementation.
*
* Copyright 2020, Verizon Media
* SPDX-License-Identifier: Apache-2.0
*
*/
#include "connection.h"
#include "globals.h"
#include <cassert>
#include <cerrno>
#include <cstring>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
struct addrinfo *Connection::_addr = nullptr;
std::mutex Connection::_getaddrinfo_mutex;
void
Connection::close()
{
_state = NOT_CONNECTED;
::close(_fd);
_counter = 0;
_time = 0;
}
int
Connection::bind(const addrinfo *addr)
{
return ::bind(_fd, addr->ai_addr, addr->ai_addrlen);
}
int
Connection::socket(const char *host, const char *port)
{
// setup the hints
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
// look up the address
if (unlikely(_addr == nullptr)) {
const std::lock_guard<std::mutex> lock(_getaddrinfo_mutex);
if (_addr == nullptr) {
getaddrinfo(host, port, &hints, &_addr);
}
}
// create a socket
_fd = ::socket(_addr->ai_family, _addr->ai_socktype, _addr->ai_protocol);
if (_fd < 0) {
perror("error calling socket");
}
constexpr int const ONE = 1;
if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &ONE, sizeof(ONE)) < 0) {
perror("setsockopt(SO_REUSEADDR) failed");
}
// set to non blocking
assert(fcntl(_fd, F_SETFL, O_NONBLOCK) == 0);
return _fd;
}
int
Connection::connect()
{
_time = time(nullptr);
// make the connection
int rval = ::connect(_fd, _addr->ai_addr, _addr->ai_addrlen);
++cf::attemptedConnections;
if (rval == 0) {
_state = CONNECTED;
} else {
if (errno == EINPROGRESS) {
_state = CONNECTING;
} else {
std::cout << errno << std::endl;
perror("connecting: ");
abort();
}
}
return rval;
}