-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathexample-echo-server.cc
129 lines (108 loc) · 4.59 KB
/
example-echo-server.cc
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
#include <cerrno>
#include <iostream>
#include <ranges>
#include <span>
#include <string.h>
#include <system_error>
#include "ces/async/async-connect.h"
#include "ces/async/async-read.h"
#include "ces/async/async-server.h"
#include "ces/async/async-write.h"
#include "ces/conditions/condition-emitter.h"
#include "ces/coroutines/scheduler.h"
#include "ces/coroutines/terminating.h"
#include "ces/epoll/epoll-emitter.h"
#include "ces/epoll/socket.h"
#include "ces/timeouts/timeout-emitter.h"
using namespace std::chrono_literals;
std::span<std::byte> to_read_buff(auto &data) {
return std::as_writable_bytes(std::span(data));
}
std::span<const std::byte> to_write_buff(auto &data) {
return std::as_bytes(std::span(data));
}
ces::terminating_task echo_server_handle(ces::Socket s) {
uint32_t rd_size[1] = {0};
auto rd_buff = to_read_buff(rd_size);
if (auto status = co_await async_read(s.without_timeout(), rd_buff);
status.err != 0)
throw std::system_error(status.err, std::system_category(),
status.err_message);
std::cout << "Server | read length of request " << rd_size[0] << "\n";
std::string rd_text(rd_size[0], ' ');
rd_buff = to_read_buff(rd_text);
if (auto status = co_await async_read(s.without_timeout(), rd_buff);
status.err != 0)
throw std::system_error(status.err, std::system_category(),
status.err_message);
std::cout << "Server | read content of request \"" << rd_text << "\"\n";
auto wr_buff = to_write_buff(rd_size);
if (auto status = co_await async_write(s.without_timeout(), wr_buff);
status.err != 0)
throw std::system_error(status.err, std::system_category(),
status.err_message);
std::cout << "Server | wrote response length\n";
wr_buff = to_write_buff(rd_text);
if (auto status = co_await async_write(s.without_timeout(), wr_buff);
status.err != 0)
throw std::system_error(status.err, std::system_category(),
status.err_message);
std::cout << "Server | wrote response content\n";
co_return;
}
ces::terminating_task echo_client(ces::SocketView server_socket) {
if (auto status = co_await ces::main_scheduler().condition(
[server_socket]() { return server_socket->operational_; });
!status)
throw std::system_error(status.err, std::system_category(),
status.err_message);
ces::Socket s = server_socket->make_client();
if (auto status = co_await ces::async_connect(s.without_timeout());
status.err != 0) {
throw std::system_error(status.err, std::system_category(),
status.err_message);
}
std::string wr_text = "Hello World!";
uint32_t wr_size[1] = {static_cast<uint32_t>(wr_text.length())};
auto wr_buff = to_write_buff(wr_size);
if (auto status = co_await async_write(s.without_timeout(), wr_buff);
status.err != 0)
throw std::system_error(status.err, std::system_category(),
status.err_message);
std::cout << "Echo Client | wrote request length\n";
wr_buff = to_write_buff(wr_text);
if (auto status = co_await async_write(s.without_timeout(), wr_buff);
status.err != 0)
throw std::system_error(status.err, std::system_category(),
status.err_message);
std::cout << "Echo Client | wrote request content\n";
uint32_t rd_size[1] = {0};
auto rd_buff = to_read_buff(rd_size);
if (auto status = co_await async_read(s.without_timeout(), rd_buff);
status.err != 0)
throw std::system_error(status.err, std::system_category(),
status.err_message);
std::cout << "Echo Client | got reponse length " << rd_size[0] << "\n";
std::string rd_text(rd_size[0], ' ');
rd_buff = to_read_buff(rd_text);
if (auto status = co_await async_read(s.without_timeout(), rd_buff);
status.err != 0)
throw std::system_error(status.err, std::system_category(),
status.err_message);
std::cout << "Echo Client | got data \"" << rd_text << "\"\n";
co_return;
}
int main() {
auto &sched = ces::main_scheduler();
sched.register_emitter(std::make_unique<ces::TimeoutEmitter>());
sched.register_emitter(std::make_unique<ces::ConditionEmitter>());
sched.register_emitter(std::make_unique<ces::EpollEmitter>());
ces::Socket s =
ces::Socket::ServerSocket(ces::SockAddr(ces::IPv4{}, "127.0.0.1", 9090));
auto server = async_server(s.without_timeout(), echo_server_handle);
auto client = echo_client(s.without_timeout());
sched.schedule(server);
sched.schedule(client);
sched.run();
std::cout << "Main done.\n";
}