You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.7 KiB
117 lines
3.7 KiB
|
|
#include "webserv.hpp"
|
|
|
|
Socket::Socket(string def) {
|
|
size_t split = def.rfind(':');
|
|
|
|
string tmp = def.substr(0, split - 1);
|
|
_ip = isInt(tmp) ? "localhost" : tmp;
|
|
tmp = def.substr(split + 1, def.length() - split - 1).c_str();
|
|
_port = !isInt(tmp) ? 80 : std::atoi(tmp.c_str());
|
|
|
|
_max_clients = 30;
|
|
|
|
int opt = 1;
|
|
_master_socket = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (_master_socket == 0) {
|
|
cout << "Socket creation: " << strerror(errno) << "\n";
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
int opt_ret = setsockopt(_master_socket, SOL_SOCKET, SO_REUSEADDR,
|
|
(char *)&opt, sizeof(opt));
|
|
if (opt_ret < 0) {
|
|
cout << "Sockopt: " << strerror(errno) << "\n";
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
_address.sin_family = AF_INET;
|
|
_address.sin_addr.s_addr = INADDR_ANY;
|
|
_address.sin_port = htons(_port);
|
|
|
|
if (bind(_master_socket, (struct sockaddr *)&_address, sizeof(_address)) <
|
|
0) {
|
|
cout << "Bind: " << strerror(errno) << "\n";
|
|
cout << "Socket destroyed!\n";
|
|
return;
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
cout << "Listener on port " << _port << "\n";
|
|
|
|
if (listen(_master_socket, 3) < 0) {
|
|
cout << "Listen: " << strerror(errno) << "\n";
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
for (int i = 0; i < _max_clients; i++)
|
|
_client_socket[i] = 0;
|
|
}
|
|
void Socket::check() {
|
|
int new_socket, activity, i, valread, sd;
|
|
char buffer[1024];
|
|
char r404[72] =
|
|
"HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 4\n\n404!";
|
|
|
|
fd_set readfds;
|
|
int max_sd = _master_socket;
|
|
|
|
int addrlen = sizeof(_address);
|
|
FD_ZERO(&readfds);
|
|
FD_SET(_master_socket, &readfds);
|
|
|
|
for (i = 0; i < _max_clients; i++) {
|
|
sd = _client_socket[i];
|
|
if (sd > 0)
|
|
FD_SET(sd, &readfds);
|
|
if (sd > max_sd)
|
|
max_sd = sd;
|
|
}
|
|
|
|
activity = select(max_sd + 1, &readfds, NULL, NULL, NULL);
|
|
|
|
if ((activity < 0) && (errno != EINTR))
|
|
cout << "Select: " << strerror(errno) << "\n";
|
|
|
|
if (FD_ISSET(_master_socket, &readfds)) {
|
|
new_socket = accept(_master_socket, (struct sockaddr *)&_address,
|
|
(socklen_t *)&addrlen);
|
|
if (new_socket < 0) {
|
|
cout << "Accept: " << strerror(errno) << "\n";
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
#ifdef __APPLE__
|
|
fcntl(new_socket, F_GETNOSIGPIPE);
|
|
#endif
|
|
cout << "New connection, socket fd is " << new_socket
|
|
<< ", ip is : " << inet_ntoa(_address.sin_addr)
|
|
<< ", port : " << ntohs(_address.sin_port) << "\n";
|
|
for (i = 0; i < _max_clients; i++) {
|
|
if (_client_socket[i] == 0) {
|
|
_client_socket[i] = new_socket;
|
|
cout << "Adding to list of sockets as " << i << "\n";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
cout << "Socket: " << _ip << ":" << _port << "\n";
|
|
for (i = 0; i < _max_clients; i++) {
|
|
sd = _client_socket[i];
|
|
if (FD_ISSET(sd, &readfds)) {
|
|
cout << "Client " << i << ": set\n";
|
|
valread = read(sd, buffer, 1024);
|
|
if (valread == 0) {
|
|
getpeername(sd, (struct sockaddr *)&_address,
|
|
(socklen_t *)&addrlen);
|
|
cout << "Host disconnected, ip " << inet_ntoa(_address.sin_addr)
|
|
<< ", port " << ntohs(_address.sin_port) << "\n";
|
|
close(sd);
|
|
_client_socket[i] = 0;
|
|
} else {
|
|
cout << buffer << "\n";
|
|
#ifdef __linux__
|
|
send(sd, r404, strlen(r404), MSG_NOSIGNAL);
|
|
#elif __APPLE__
|
|
send(sd, r404, strlen(r404), 0);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|