-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.cc
More file actions
202 lines (159 loc) · 5.38 KB
/
main.cc
File metadata and controls
202 lines (159 loc) · 5.38 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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
* for HTTP protocol communication server
* Created by Yi BeomSeok
*/
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <iostream>
#include <string>
#include <unordered_map>
#include <utility>
#include <map>
#include <chrono>
#include <mutex>
#include "server/socket.h"
#include "server/protocol/http_protocol.h"
#include "json/json.h"
using namespace std;
extern struct stat_socket sock;
void send_msg(const std::string& msg, int client);
void *handle_client(void *arg);
void signal_handler(int sig) {
std::cout << "Signal " << sig << '\n';
std::cout << "Closing socket\n";
close(sock.server_sock);
exit(0);
}
std::map<unsigned long long, std::pair<std::string, std::string>> message_history;
std::mutex history_m;
int main(int argc, char *argv[]) {
int port_number = 8085;
int webserver_port = 3000;
const char* ip_address = "3.37.112.35";
if (argc > 1) port_number = atoi(argv[1]);
if (argc > 2) webserver_port = atoi(argv[2]);
if (argc > 3) ip_address = argv[3];
sock_init(port_number);
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
message_history.emplace(10, std::make_pair("James", "Hi"));
message_history.emplace(20, std::make_pair("Nana", "Hi to you too"));
while (true) {
sock_accept(ip_address, webserver_port);
pthread_create(&sock.t_id, NULL, handle_client, (void*)&sock.client_sock);
pthread_detach(sock.t_id);
printf("Connected client IP: %s \n", inet_ntoa(sock.client_addr.sin_addr));
}
close(sock.server_sock);
return 0;
}
void *handle_client(void *arg) {
std::cout << __func__ << '\n';
int client_sock = *((int*)arg);
int str_len = 0, i;
std::string buf(100'000, '\0');
// buf = "POST /user HTTP/1.1\r\n"
// "\r\n"
// "{\"name\": \"이민호\", \"chat\": \"안녕하세요\"}";
// buf = "GET / HTTP/1.1\r\n"
// "From-Time: 3\r\n"
// "\r\n";
if(read(client_sock, buf.data(), buf.size()) < 0) {
// if (false) {
perror("state code 500\n");
} else {
do {
printf("HTTP Request:\n%s\n", buf.data()); // TEST
network::HTTPProtocol parser;
const auto b = parser.parse(buf);
if (!b) {
std::cerr << "Failed to parse HTTP request!\n";
break;
}
std::cout << "Request type: " << parser.http_method() << '\n';
if (const auto& method = parser.http_method(); method == "POST") {
std::cout << "Content: " << parser.content() << '\n';
Json::Value root;
Json::Reader reader;
const auto success = reader.parse(parser.content(), root);
if (!success) {
std::cerr << "Failed to parse!\n";
break;
}
const auto now = std::chrono::system_clock::now();
const auto t = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
const auto name = root["name"].asString();
const auto chat = root["chat"].asString();
std::cout << "name: " << name << '\n';
std::cout << "chat: " << chat << '\n';
{
std::lock_guard lck(history_m);
message_history.emplace(t, std::make_pair(name, chat));
}
string response =
"HTTP/1.1 200 OK\r\n"
"\r\n";
send_msg(response, client_sock);
} else if (method == "GET") {
const auto& header = parser.header();
const auto it = header.find("from_time");
if (it == header.end()) {
std::cerr << "Header " << "from_time" << " Not found!\n";
std::string res =
"HTTP/1.1 200 OK\r\n"
"Server: Apache\r\n"
"Date: Sun, 6 Nov 2022 20:54:51 GMT\r\n"
"\r\n";
// "["
// "{\"name\":\"이범석\", \"chatKey\":\"안녕못해요\"},"
// "{\"name\":\"이민호\", \"chatKey\":\"나도안녕못해\"},"
// "{\"name\":\"이용규\", \"chatKey\":\"나도마찬가지\"}"
// "]";
send_msg(res, client_sock);
} else {
std::cout << "from_time: " << it->second << '\n';
const auto t = std::stoll(it->second);
std::unique_lock lck(history_m);
auto lb = message_history.lower_bound(t);
std::string res =
"HTTP/1.1 200 OK\r\n"
"Server: Apache\r\n"
"Date: Sun, 6 Nov 2022 20:54:51 GMT\r\n"
"\r\n"
"[";
if (lb != message_history.end()) {
res += "{\"name\":\"" + lb->second.first + "\",\"chatKey\":\"" + lb->second.second + "\"}";
}
++lb;
while (lb != message_history.end()) {
res += ",{\"name\":\"" + lb->second.first + "\",\"chatKey\":\"" + lb->second.second + "\"}";
++lb;
}
lck.unlock();
res += "]";
send_msg(res, client_sock);
}
}
} while (false);
}
pthread_mutex_lock(&sock.mutx);
for(i = 0; i < sock.client_cnt; i++) {
if (client_sock == sock.client_socks[i]) {
while(i++ < sock.client_cnt - 1)
sock.client_socks[i] = sock.client_socks[i+1];
break;
}
}
sock.client_cnt--;
pthread_mutex_unlock(&sock.mutx);
close(client_sock);
return NULL;
}
void send_msg(const std::string& msg, int client_sock) {
std::cout << "Sending Response to " << client_sock << ": \n";
std::cout << msg << "\n\n";
pthread_mutex_lock(&sock.mutx);
write(client_sock, msg.c_str(), msg.size());
pthread_mutex_unlock(&sock.mutx);
}