-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathServerPrivateMemberFuncs.cpp
139 lines (121 loc) · 4.47 KB
/
ServerPrivateMemberFuncs.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ServerPrivateMemberFuncs.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: ychen2 <ychen2@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/07 16:05:27 by ychen2 #+# #+# */
/* Updated: 2024/09/08 21:20:08 by ychen2 ### ########.fr */
/* */
/* ************************************************************************** */
#include "Server.hpp"
#include "Server_helper.hpp"
#include "constants.hpp"
#include "handle_error.hpp"
#include <csignal>
bool Server::_constructed = false;
void Server::run_a_server(std::vector<Settings>::iterator &it) {
int new_socket_fd;
#ifdef __linux__
// new_socket_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
new_socket_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
// For Linux, set the socket to non-blocking at the time of creation
if (new_socket_fd < 0) {
throw std::runtime_error(strerror(errno));
}
#elif __APPLE__
// For macOS, set the socket to non-blocking using fcntl
new_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (new_socket_fd < 0)
throw std::runtime_error(strerror(errno));
int flags = fcntl(new_socket_fd, F_GETFL, 0);
if (flags == -1) {
close_fds(_socks_fd);
throw std::runtime_error(strerror(errno));
}
if (fcntl(new_socket_fd, F_SETFL, flags | O_NONBLOCK) == -1) {
close_fds(_socks_fd);
throw std::runtime_error(strerror(errno));
}
#endif
it->_socket_fd = new_socket_fd;
_socks_fd.push_back(new_socket_fd);
// To allow address receive multiple connections at the same time
{
int on = 1;
if (setsockopt(new_socket_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
sizeof(on)) < 0) {
close_fds(_socks_fd);
throw std::runtime_error(strerror(errno));
}
}
if (bind(new_socket_fd, (struct sockaddr *)&(it->_addr), sizeof(it->_addr)) <
0) {
close_fds(_socks_fd);
throw std::runtime_error(strerror(errno));
}
if (listen(new_socket_fd, BACK_LOG) < 0) {
close_fds(_socks_fd);
throw std::runtime_error(strerror(errno));
}
// Set up sockets for poll
add_to_poll_in(new_socket_fd);
}
void Server::new_conns(int sock_fd) {
int new_sd;
// Accept new connections
struct sockaddr_in addr_client;
socklen_t client_addr_len = sizeof(addr_client);
if ((new_sd = accept(sock_fd, (sockaddr *)&addr_client, &client_addr_len)) < 0)
throw std::runtime_error("Poll doesn't work.");
add_to_poll_in(new_sd);
_states.push_back(
State(new_sd, ntohl(addr_client.sin_addr.s_addr), sock_fd));
}
bool Server::is_socket(int fd) {
return !(std::find(_socks_fd.begin(), _socks_fd.end(), fd) ==
_socks_fd.end());
}
std::list<State>::iterator Server::getState(int fd) {
for (std::list<State>::iterator it = _states.begin(); it != _states.end();
it++) {
if (it->conn_fd == fd || it->file_fd == fd || it->cgi_pipe_w[1] == fd ||
it->cgi_pipe_r[0] == fd)
return it;
}
return _states.end();
}
void Server::checkTimeoutConn() {
bool isDelete = true;
while(isDelete) {
isDelete = false;
for (std::list<State>::iterator it = _states.begin(); it != _states.end(); it++) {
if (std::time(NULL) - it->timeEvent > EVENT_TIMEOUT) {
std::cerr << "Close conn by checkTimeout" << std::endl;
close_conn(it);
isDelete = true;
break;
}
}
}
_cur_poll_fds = _next_poll_fds;
}
void Server::checkTimeoutCGI() {
for (std::vector<struct pollfd>::iterator it = _cur_poll_fds.begin();
it != _cur_poll_fds.end(); it++) {
std::list<State>::iterator cur_state = getState(it->fd);
if (cur_state == _states.end())
continue;
if (!cur_state->isCGIrunning)
continue;
if (std::time(NULL) - cur_state->timeCGI > CGI_TIMEOUT) {
if (cur_state->cgiPID > 0)
kill(cur_state->cgiPID, SIGKILL);
cur_state->isCGIrunning = false;
handle_error(*cur_state, UNDEFINED, TIMEOUT_ERROR, *this);
}
}
_cur_poll_fds = _next_poll_fds;
}
Server::~Server() { close_fds(_socks_fd); }