-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver_func.cpp
More file actions
70 lines (62 loc) · 2.4 KB
/
Copy pathserver_func.cpp
File metadata and controls
70 lines (62 loc) · 2.4 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
#include "server_func.h"
#include "databaseutils.h"
void make_non_blocking(int fd){
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) {
throw std::runtime_error("Failed to get socket flags");
}
flags |= O_NONBLOCK; // Add the O_NONBLOCK flag
if (fcntl(fd, F_SETFL, flags) == -1) {
throw std::runtime_error("Failed to set socket as non blocking");
}
}
void handle_new_connection(int epoll_fd, int server_fd, std::vector<struct epoll_event> &poll_fds, std::unordered_map<int, std::unique_ptr<Connection>> &connections){
struct epoll_event ev;
int client_fd;
socklen_t socklen;
struct sockaddr_storage client_addr;
for(;;){
client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &socklen);
if (client_fd < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// No more connections to accept
break;
}
throw std::runtime_error("Error accepting new connections");
}
// Make client socket non-blocking
make_non_blocking(client_fd);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = client_fd;
poll_fds.push_back(ev);
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev) < 0){
close(client_fd);
continue;
}
}
return;
}
void disconnect_client(int epoll_fd,int client_fd){
if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL) < 0){
throw std::system_error(errno, std::generic_category(), "Failed to open an epoll file descriptor.");
}
}
void process_poll_events(int server_fd, int epoll_fd, std::vector<struct epoll_event> &poll_fds, std::unordered_map<int, std::unique_ptr<Connection>> &connections){
for(int i = poll_fds.size() - 1; i ; i = i - 1) {
// Check if someone's ready to read
struct epoll_event event = poll_fds[i];
if (event.data.fd == server_fd) {
// New connection(s) available
handle_new_connection(epoll_fd, server_fd, poll_fds, connections);
}else{
// Client event
if (event.events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR)) {
// Client disconnected or error
disconnect_client(epoll_fd, event.data.fd);
} else if (event.events & EPOLLIN) {
// Data available to read
HandleClientRequest(fd);
}
}
}
}