This repository was archived by the owner on Nov 11, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsws_q7.cpp
More file actions
148 lines (126 loc) · 3.9 KB
/
sws_q7.cpp
File metadata and controls
148 lines (126 loc) · 3.9 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
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/timerfd.h>
#include <sys/epoll.h>
#include <signal.h>
#include <map>
#include <ctime>
#include "utility.h"
#include "inet_socket.h"
#define BUF_SIZE 300
#define LISTEN_PORT "8080"
#define BACKLOG 5
#define EPOLL_SIZE 10
#define MAX_EVENTS 10
using std::map;
int main(int argc, char *argv[])
{
if (argc < 2) {
errExit("invalid number of arguments");
return EXIT_FAILURE;
}
int listen_fd = inetListen(LISTEN_PORT, BACKLOG, NULL);
if (listen_fd == -1)
errExit("inetListen");
signal(SIGPIPE, SIG_IGN);
// Turn on non-blocking mode on the passive socket
int flags = fcntl(listen_fd, F_GETFL);
if (fcntl(listen_fd, F_SETFL, flags | O_NONBLOCK) == -1)
errExit("listen fd non block");
// Initialize the epoll instance
int epfd;
epfd = epoll_create(EPOLL_SIZE);
if (epfd == -1)
errExit("epoll_create");
struct epoll_event ev;
ev.events = EPOLLIN; // event : data can be read
// add listen_fd to the interest list
ev.data = {};
ev.data.fd = listen_fd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev) == -1)
errExit("epoll_ctl");
// the event list used with epoll_wait()
struct epoll_event evlist[MAX_EVENTS];
map<int, int> connections;
for (;; ) {
int nb_fd_ready = epoll_wait(epfd, evlist, MAX_EVENTS, 0);
if (nb_fd_ready == -1) {
if (errno == EINTR) // restart if interrupted by signal
continue;
else
errExit("epoll");
}
for (int i = 0; i < nb_fd_ready; ++i) {
int fd_ready = evlist[i].data.fd;
if (fd_ready == listen_fd) {
int client_fd = accept(listen_fd, NULL, NULL);
printf("Accept a new connection... \n");
int timerfd = timerfd_create(CLOCK_REALTIME, 0);
if (epoll_ctl(epfd, EPOLL_CTL_ADD, timerfd, &ev) == -1)
errExit("epoll_ctl");
connections[timerfd] = client_fd;
struct itimerspec timerspec = {};
timerspec.it_value.tv_sec = 5;
timerfd_settime(timerfd, 0, &timerspec, NULL);
flags = fcntl(client_fd, F_GETFL);
if (fcntl(client_fd, F_SETFL, flags | O_NONBLOCK) == -1) {
close(client_fd);
printf("Closed connection...\n");
} else {
ev.data.fd = client_fd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &ev) == -1) {
close(client_fd);
printf("Closed connection...\n");
}
}
} else if (connections.count(fd_ready) == 1) {
close(connections[fd_ready]);
printf("Closed connection because of timeout...\n");
if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd_ready, &ev) == -1)
errExit("epoll_ctl");
} else {
char buf[BUF_SIZE];
int numRead = read(fd_ready, buf, BUF_SIZE);
if (numRead == 0) {
close(fd_ready);
printf("Closed connection...\n");
}
if (write(STDOUT_FILENO, buf, numRead) != numRead)
errExit("partial/failed write");
char *request = strtok(buf, " ");
request = strtok(NULL, " ");
char path[BUF_SIZE];
snprintf(path, BUF_SIZE, "%s%s", argv[1], request);
struct stat sb;
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
char path2[BUF_SIZE];
strcpy(path2, path);
snprintf(path, BUF_SIZE, "%sindex.html", path2);
printf("PATH = %s\n", path);
}
int fd = open(path, O_RDONLY);
if (fd < 0) {
char headers[BUF_SIZE];
ssize_t nbBytes = snprintf(headers, BUF_SIZE, "HTTP/1.x 404 NOT FOUND\r\nConnection: keep-alive\r\n\r\n");
write(fd_ready, headers, nbBytes);
} else {
struct stat stat_buf;
fstat(fd, &stat_buf);
char headers[BUF_SIZE];
ssize_t nbBytes = snprintf(headers, BUF_SIZE, "HTTP/1.x 200 OK\r\nContent-Type: text/html;\r\nContent-Length: %i\r\ncharset=UTF-8\r\nConnection: keep-alive\r\n\r\n", stat_buf.st_size);
write(fd_ready, headers, nbBytes);
sendfile(fd_ready, fd, 0, stat_buf.st_size);
close(fd);
}
}
}
}
close(listen_fd);
return EXIT_SUCCESS;
}