4 #include <linux/if_link.h>
7 #include <sys/socket.h>
10 #include <netinet/ip.h>
23 void Server::start(in_port_t port,
char *bindaddress,
bool useSSL,
int backlog)
25 start(port,
string(bindaddress),useSSL,backlog);
28 void Server::start(in_port_t port,
string bindaddress,
bool useSSL,
int backlog)
32 memset(&addr_,0,
sizeof(addr_));
33 if ((bindaddress ==
"") || (bindaddress ==
"0.0.0.0") || (bindaddress ==
"::")) {
34 if (domain() == AF_INET) {
35 reinterpret_cast<struct sockaddr_in*>(&addr_)->sin_addr.s_addr = INADDR_ANY;
37 if (domain() == AF_INET6) {
38 reinterpret_cast<struct sockaddr_in6*>(&addr_)->sin6_addr = IN6ADDR_ANY_INIT;
41 if (!findifaddr(bindaddress,reinterpret_cast<struct sockaddr*>(&addr_))) {
42 error(
"Interface " +
string(bindaddress) +
" not found");
45 if (domain() == AF_INET) {
46 addr_.ss_family = AF_INET;
47 reinterpret_cast<struct sockaddr_in*>(&addr_)->sin_port = htons(port);
49 if (domain() == AF_INET6) {
50 addr_.ss_family = AF_INET6;
51 reinterpret_cast<struct sockaddr_in6*>(&addr_)->sin6_port = htons(port);
55 if (setsockopt(socket(), SOL_SOCKET, SO_REUSEADDR, &enable,
sizeof(enable)) < 0)
56 error(
"setsockopt",
"Server could not set socket option SO_REUSEADDR");
58 if (bindToAddress((
struct sockaddr*)&addr_,(domain() == AF_INET ?
sizeof(
struct sockaddr_in) :
sizeof(
struct sockaddr_in6)))) {
59 startListening(backlog);
67 log(
"Sending disconnect to all sessions");
69 std::map<int,Session*>::iterator it;
70 for (it = sessions.begin();it != sessions.end();++it) {
71 it->second->disconnect();
79 if (listening() && (events & EPOLLIN)) {
85 struct ifaddrs *list, *item;
87 char host[NI_MAXHOST];
89 if (getifaddrs(&list) == 0) {
91 while (item !=
nullptr) {
92 int f = item->ifa_addr->sa_family;
93 if ((f == AF_INET) || (f == AF_INET6)) {
95 case AF_INET: family.assign(
"AF_INET");
break;
96 case AF_INET6: family.assign(
"AF_INET6");
break;
97 default: family.assign(
"");
99 int res = getnameinfo(item->ifa_addr,(f == AF_INET) ?
sizeof(
struct sockaddr_in) :
sizeof(
struct sockaddr_in6),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
101 error(
"printifaddrs",gai_strerror(res));
104 cout << family <<
" " << item->ifa_name <<
" address: " << host << endl;
106 item = item->ifa_next;
109 error(
"printifaddrs",strerror(errno));
117 struct ifaddrs *list, *item;
120 char host[NI_MAXHOST];
123 if (getifaddrs(&list) == 0) {
125 while (item !=
nullptr) {
126 f = item->ifa_addr->sa_family;
127 if (getnameinfo(item->ifa_addr,(f == AF_INET) ?
sizeof(
struct sockaddr_in) :
sizeof(
struct sockaddr_in6),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) != 0) {
130 if (f == domain() && ((ifname.compare(item->ifa_name) == 0) || (ifname.compare(host) == 0))) {
132 *(sockaddr_in*)addr = *(sockaddr_in*)item->ifa_addr;
137 *(sockaddr_in6*)addr = *(sockaddr_in6*)item->ifa_addr;
142 item = item->ifa_next;
145 error(
"findifaddrs",strerror(errno));
152 bool Server::bindToAddress(sockaddr *addr, socklen_t len) {
153 if (::bind(socket(),addr,len) == -1) {
154 error(
"bind",strerror(errno));
157 char ip[INET6_ADDRSTRLEN];
158 memset(&ip,0,INET6_ADDRSTRLEN);
159 if (addr->sa_family == AF_INET) {
160 struct sockaddr_in * a = reinterpret_cast<struct sockaddr_in*>(addr);
162 if (a->sin_addr.s_addr == INADDR_ANY) {
163 msg =
"Server bound to any IP4";
165 inet_ntop(AF_INET,&a->sin_addr,ip,INET_ADDRSTRLEN);
166 msg =
"Server bound to " + string(ip);
168 msg +=
" on port " + to_string(ntohs(a->sin_port));
171 struct sockaddr_in6 * a = reinterpret_cast<struct sockaddr_in6*>(addr);
172 inet_ntop(AF_INET6,&a->sin6_addr,ip,INET6_ADDRSTRLEN);
174 if (strcmp(ip,
"::") == 0) {
175 msg =
"Server bound to any IP6";
177 msg =
"Server bound to " + string(ip);
179 msg +=
" on port " + to_string(ntohs(a->sin6_port));
186 bool Server::startListening(
int backlog) {
187 if (listen(socket(),backlog) == -1) {
188 error(
"listen",strerror(errno));
191 state_ = SocketState::LISTENING;
192 log(
"Server started listening");
197 bool Server::acceptConnection() {
198 struct sockaddr_in peer_addr;
199 socklen_t peer_addr_len =
sizeof(
struct sockaddr_in);
201 int conn_sock = ::accept(socket(),(
struct sockaddr *) &peer_addr, &peer_addr_len);
202 if (conn_sock == -1) {
203 error(
"accept",strerror(errno));
208 Session* session = sessions[conn_sock];
209 sessions.erase(conn_sock);
210 if (session !=
nullptr) {
211 warning(
"A session with socket handle " + to_string(conn_sock) +
" already exists. Deleting it.");
215 session = createSession(conn_sock,peer_addr);
216 sessions[conn_sock] = session;
219 return session->connected();
227 server_.sessions.erase(socket());
231 void Session::connectionMessage(
string action)
233 char ip[INET6_ADDRSTRLEN];
234 memset(&ip,0,INET6_ADDRSTRLEN);
235 inet_ntop(domain(),&addr_,ip,domain() == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN);
236 string msg(
"Connection from ");
237 if (domain() == AF_INET) {
240 msg +=
"[" + string(ip) +
"]";
242 msg +=
":" + to_string(port_) +
" " + action;
250 connectionMessage(
"accepted");
251 if (server().useSSL_) {
252 ssl_ = createSSL(server().ctx());
253 ssl_->setfd(socket());
255 state_ = SocketState::CONNECTED;
259 state_ = SocketState::CONNECTED;
287 state_ = SocketState::DISCONNECTED;
288 connectionMessage(
"disconnected");