-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathServer.cpp
More file actions
149 lines (129 loc) · 4.83 KB
/
Copy pathServer.cpp
File metadata and controls
149 lines (129 loc) · 4.83 KB
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
140
141
142
143
144
145
146
147
148
149
#include "Server.hpp"
#include <sys/poll.h>
Server::Server(std::string port, std::string password) {
memset(_fds, 0, sizeof(_fds));
this->_port = atoi(port.c_str());
if (this->_port <= 0)
throw std::runtime_error("Invalid port");
this->_password = password;
if (this->_password.empty())
throw std::runtime_error("Invalid password");
}
void Server::sendToAll(std::string msg){
for (std::map<int, Client>::iterator it = this->list.begin(); it != this->list.end(); it++){
if (it->second.isRegistered() == true)
this->sendMessage(it->first, msg);
}
}
Server::~Server() {
std::map<int, Client>::iterator it = this->list.begin();
for (; it != this->list.end(); it++){
close(it->first);
}
close(this->_socketfd);
}
void Server::setSocket() {
int tmp = 1;
this->_socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (this->_socketfd < 0)
throw std::runtime_error("Failed to create socket");
if (setsockopt(this->_socketfd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(int)) < 0)
throw std::runtime_error("Failed to set socket reuse option");
if (fcntl(this->_socketfd, F_SETFL, O_NONBLOCK) < 0)
throw std::runtime_error("Failed to set socket to non-blocking mode");
}
std::string Server::getHostName()
{
std::system("hostname > ip.txt");
std::ifstream ip("ip.txt");
std::string hostname;
std::getline(ip, hostname);
std::remove("ip.txt");
return (hostname);
}
void Server::setAddrInfo() {
memset(&this->_addr, 0, sizeof(this->_addr));
this->_addr.sin_family = AF_INET;
this->_addr.sin_port = htons(this->_port);
this->_hostname = this->getHostName();
struct pollfd _pollfd;
_pollfd.fd = this->_socketfd;
_pollfd.events = POLLIN;
_pollfd.revents = 0;
this->_fds[0] = _pollfd;
}
void Server::bindPort() {
if (bind(this->_socketfd, (struct sockaddr*)&this->_addr, sizeof(this->_addr)) < 0)
throw std::runtime_error("Failed to bind socket");
}
std::string Server::addClient(struct pollfd _poll, std::string line)
{
std::stringstream iss(line);
std::string pass;
iss >> pass;
if (pass != "PASS")
return "464 :Password incorrect\r\n";
iss >> pass;
if (!pass.empty() && pass[0] == ':')
pass = pass.substr(1);
if (pass != this->_password)
return "464 :Password incorrect\r\n";
this->list[_poll.fd].setRegistered(true);
return "";
}
void Server::launch() {
this->setSocket();
this->setAddrInfo();
this->bindPort();
if (listen(this->_socketfd, 10) < 0)
throw std::runtime_error("Failed to listen for connections");
int fdnbr = 1;
while (true) {
if (poll(this->_fds, SIZE, -1) < 0)
throw std::runtime_error("poll failed");
for (int i = 1; i < fdnbr; i++){ /*through list of clients*/
if (this->_fds[i].revents & POLLIN) {
char buffer[1024];
int bytesRead = read(_fds[i].fd, buffer, 1024);
if (bytesRead < 0)
throw std::runtime_error("Failed to receive data");
if (bytesRead == 0)
this->quit(this->_fds[i].fd);
std::string line;
line.assign(buffer, bytesRead);
if (line[line.length() - 1] != '\n'){
this->list[this->_fds[i].fd].joinBuffer(line);
continue;
}
else{
line = this->list[this->_fds[i].fd].joinBuffer(line);
this->list[this->_fds[i].fd].clearBuffer();
}
std::stringstream iss(line);
while (std::getline(iss, line, '\n')){
if (this->list[this->_fds[i].fd].isRegistered() == false){
std::string message = this->addClient(this->_fds[i], line);
if (!message.empty())
this->sendMessage(this->_fds[i].fd, message);
}
else
this->parse(this->_fds[i].fd, line);
}
}
}
if (this->_fds[0].fd != 0 && this->_fds[0].revents == POLLIN) { // if the event is on the socket fd; we add the new_fd to the list.
struct sockaddr_in addr;
struct pollfd _clientpoll;
socklen_t len = sizeof(addr);
Client newClient;
_clientpoll.fd = accept(this->_socketfd, (struct sockaddr *)&addr, &len);
if (_clientpoll.fd < 0)
throw std::runtime_error("Failed to accept connection");
_clientpoll.events = POLLIN;
_clientpoll.revents = 0;
newClient.initClient(_clientpoll, addr);
this->_fds[fdnbr++] = _clientpoll;
this->list[_clientpoll.fd] = newClient;
}
}
}