Webserv
Loading...
Searching...
No Matches
Master.cpp
Go to the documentation of this file.
1
8#include "webserv.hpp"
9/* Master destructor */
10
12 close(_fd);
13 cout << "Destroyed master socket\n";
14}
15/* |==========|
16 * Master constructor
17 * Try to create a socket listening to ip and port defined by input.
18 * If the creation success, the socket is then ready to select for new clients.
19 *
20 * Input: A ip_port_t structure which contain the ip and the port the master
21 * care about.
22 * Output: A Master object.
23 */
24
25Master::Master(ip_port_t list) : _listen(list) {
26 int x = 1, port = _listen.port;
27 string ip = _listen.ip;
28
29 _fd = socket(AF_INET, SOCK_STREAM, 0);
30 if (_fd == 0)
31 throw std::runtime_error("socket() error" + string(strerror(errno)));
32 if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&x, sizeof(x)) < 0 && close(_fd) <= 0)
33 throw std::runtime_error("setsockopt() error: " + string(strerror(errno)));
34
35 _address.sin_family = AF_INET;
36 _address.sin_addr.s_addr = inet_addr(ip.c_str());
37 _address.sin_port = htons(port);
38
39 if (bind(_fd, (struct sockaddr *)&_address, sizeof(_address)) && close(_fd) <= 0)
40 throw std::runtime_error("bind() error: " + string(strerror(errno)));
41 if (listen(_fd, 3) < 0 && close(_fd) <= 0)
42 throw std::runtime_error("listen() error: " + string(strerror(errno)));
43 cout << "New master socket with fd " << _fd << " which listen " << ip << ":" << port << "\n";
44 if (_fd < _min_fd)
45 _min_fd = _fd;
46 _amount++;
47}
48/* Set into static Master::readfds the active fds which will be select.*/
49
51 FD_SET(_fd, &_readfds);
52 for (std::vector<Client *>::iterator child = _childs.begin(); child < _childs.end(); child++) {
53 FD_SET((*child)->_fd, &_readfds);
54 if ((*child)->_fd > _max_fd)
55 _max_fd = (*child)->_fd;
56 }
57}
58/* |==========|
59 * Refresh master socket datas after select()
60 * - look first for new clients
61 * - look then if known clients sent requests or disconnected
62 * - if client sent request, handle it to generate answer adapted
63 */
64
66 int valread;
67 int addrlen = sizeof(_address);
68 char buffer[128];
69
70 if (FD_ISSET(_fd, &_readfds)) {
71 int new_socket = accept(_fd, (struct sockaddr *)&_address, (socklen_t *)&addrlen);
72 if (new_socket < 0)
73 throw std::runtime_error("accept() error:" + string(strerror(errno)));
74#ifdef __APPLE__
75 fcntl(new_socket, F_SETFL, O_NONBLOCK);
76#endif
77 ip_port_t cli_listen = get_ip_port_t(inet_ntoa(_address.sin_addr), ntohs(_address.sin_port));
78 _childs.push_back(new Client(new_socket, cli_listen, this));
79 _amount++;
80 }
81 int child_fd;
82 for (std::vector<Client *>::iterator it = _childs.begin(); it < _childs.end(); it++) {
83 child_fd = (*it)->_fd;
84 if (FD_ISSET(child_fd, &_readfds)) {
85 valread = read(child_fd, buffer, 128);
86 buffer[valread] = '\0';
87 if (valread == 0) {
88 getpeername(child_fd, (struct sockaddr *)&_address, (socklen_t *)&addrlen);
89 delete (*it);
90 _childs.erase(it);
91 _amount--;
92 } else if ((*it)->getRequest(env, buffer))
93 (*it)->handleRequest();
94 }
95 }
96}
97/* |==========|
98 * Choose the server which must handle a request
99 * Each server can listen multiple range_ip:port and each range_ip:port can be
100 * listen by multiple servers. So for each request, we must look at the socket
101 * which given us the client to know how the client came. If multiple servers
102 * listen the range from where the client came, ones with exact correspondance
103 * are prefered.
104 *
105 * If there are multiples servers listening exactly the ip the client try to
106 * reach or whic listen a range which contain it, the first one which have the
107 * same server_name as the host the client used to reach server is used, else
108 * it's the first one of exact correspondance or first one which have the ip
109 * requested in his listen range.
110 *
111 */
112
113Server *Master::choose_server(Env *env, string host) {
114 std::vector<Server *> exact, inrange;
115 vec_string ip_listen, ip_required;
116
117 ip_required = split(_listen.ip, ".");
118 for (std::vector<Server *>::iterator server = env->_servers.begin(); server < env->_servers.end(); server++) {
119 std::vector<ip_port_t> serv_listens = (*server)->_listens;
120 for (std::vector<ip_port_t>::iterator it = serv_listens.begin(); it < serv_listens.end(); it++) {
121 if (_listen.port != (*it).port)
122 continue;
123 if (_listen.ip == (*it).ip) {
124 exact.push_back(*server);
125 continue;
126 }
127 bool is_inrange = true;
128 ip_listen = split((*it).ip, ".");
129 vec_string::iterator r = ip_required.begin();
130 for (vec_string::iterator l = ip_listen.end(); l >= ip_listen.begin(); --l) {
131 if (*l != *r && *l != "0")
132 is_inrange = false;
133 }
134 if (is_inrange)
135 inrange.push_back(*server);
136 }
137 }
138 if (DEBUG)
139 std::cout << "req: " << _listen.ip << ":" << _listen.port << "\n";
140 if (exact.size() == 0) {
141 std::cout << "in range server check\n";
142 for (std::vector<Server *>::iterator server = inrange.begin(); server < inrange.end(); server++) {
143 if (host == (*server)->getName())
144 return *server;
145 }
146 return inrange.front();
147 } else {
148 std::cout << "exact server check\n";
149 for (std::vector<Server *>::iterator server = exact.begin(); server < exact.end(); server++) {
150 if (host == (*server)->getName())
151 return *server;
152 }
153 return exact.front();
154 }
155}
Definition: Client.hpp:4
Definition: Env.hpp:4
std::vector< Server * > _servers
Definition: Env.hpp:6
static fd_set _readfds
Definition: Master.hpp:19
static int _amount
< The higher one
Definition: Master.hpp:20
struct sockaddr_in _address
Definition: Master.hpp:7
void post_select(Env *env)
Definition: Master.cpp:65
static int _max_fd
< The lower socket fd
Definition: Master.hpp:20
Server * choose_server(Env *env, string host)
Definition: Master.cpp:113
static int _min_fd
< The sockets fd which will be select
Definition: Master.hpp:20
void pre_select(void)
Definition: Master.cpp:50
Master(ip_port_t listen)
Definition: Master.cpp:25
~Master(void)
Definition: Master.cpp:11
int _fd
Definition: Master.hpp:5
std::vector< Client * > _childs
Definition: Master.hpp:6
ip_port_t _listen
Definition: Master.hpp:18
Definition: Server.hpp:4
int port
Definition: webserv.hpp:38
string ip
Definition: webserv.hpp:37
vec_string split(string str, string delim)
Definition: tools.cpp:20
ip_port_t get_ip_port_t(string listen)
Definition: tools.cpp:35
std::vector< string > vec_string
Definition: webserv.hpp:50
#define DEBUG
Definition: webserv.hpp:2