-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathserver.cpp
More file actions
137 lines (123 loc) · 3.57 KB
/
server.cpp
File metadata and controls
137 lines (123 loc) · 3.57 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
#include <cerrno>
#include <cstddef>
#include <exception>
#include <iostream>
#include <poll.h>
#include <stdexcept>
#include <string_view>
#include <variant>
#include "server.hpp"
#include "udp_session.hpp"
#include "udp_socket.hpp"
#include "command.hpp"
namespace auth
{
namespace server
{
namespace
{
std::string_view bytes_to_string(const UdpSession::Bytes& bytes)
{
std::string_view str{reinterpret_cast<const char*>(bytes.data()),
bytes.size()};
str = str.substr(0, str.find_last_not_of(" \t\n\r\f\v") + 1);
return str;
}
UdpSession::Bytes string_to_bytes(std::string_view str)
{
UdpSession::Bytes bytes{};
bytes.reserve(str.size());
for (const auto c : str)
{
const auto byte{static_cast<std::byte>(static_cast<unsigned char>(c))};
bytes.emplace_back(byte);
}
return bytes;
}
std::string process_command(std::string_view income)
{
std::string answer{"not implemented\n"};
try
{
Command command{income};
const auto vargs = command.GetArgs();
if (std::holds_alternative<args::Login>(vargs))
{
// TODO: обработайте команду login
[[maybe_unused]] const auto args = std::get<args::Login>(vargs);
}
else if (std::holds_alternative<args::Logout>(vargs))
{
// TODO: обработайте команду logout
[[maybe_unused]] const auto args = std::get<args::Logout>(vargs);
}
else if (std::holds_alternative<args::Adduser>(vargs))
{
// TODO: обработайте команду adduser
[[maybe_unused]] const auto args = std::get<args::Adduser>(vargs);
}
else if (std::holds_alternative<args::Deluser>(vargs))
{
// TODO: обработайте команда deluser
[[maybe_unused]] const auto args = std::get<args::Deluser>(vargs);
}
}
catch (const std::exception& err)
{
answer = std::string("error: ") + err.what() + '\n';
}
return answer;
}
} // namespace
Server::Server(std::string_view adminUsername,
[[maybe_unused]] std::string_view adminPassword, const int port,
const std::atomic<bool>& running)
: running_(running), socket_(port), session_(socket_)
{
// TODO: добавьте администратора с именем и паролем
// из параметров конструктора
std::cout << "Add administrator user '" << adminUsername << "/***'\n";
std::cout << "Listening on port " << port << '\n';
}
void Server::Run()
{
pollfd handlers[1] = {{socket_.Handler(), POLLIN, 0}};
while (running_.load())
{
const int timeoutMs = 100;
const int pollResult = poll(handlers, 1, timeoutMs);
if (pollResult < 0)
{
if (errno == EINTR)
{
continue;
}
throw std::runtime_error("failed to poll");
}
else if (pollResult == 0)
{
continue;
}
else if (handlers[0].revents & POLLIN)
{
ProcessIncome();
}
}
}
void Server::ProcessIncome()
{
try
{
const auto incomeRaw{session_.Receive()};
const auto income{bytes_to_string(incomeRaw)};
const auto outcome{process_command(income)};
auto outcomeRaw{string_to_bytes(outcome)};
session_.Reply(outcomeRaw);
}
catch (const std::exception& err)
{
std::cerr << "Error while processing income: " << err.what() << '\n';
}
}
} // namespace server
} // namespace auth