-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbootstrap.cpp
More file actions
126 lines (107 loc) · 3.26 KB
/
Copy pathbootstrap.cpp
File metadata and controls
126 lines (107 loc) · 3.26 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
/* Any copyright is dedicated to the Public Domain.
* https://creativecommons.org/publicdomain/zero/1.0/ */
#include "bootstrap.hpp"
#include "event_worker_group.hpp"
#include "logger.hpp"
#include "serv_types.hpp"
#include "server_channel.hpp"
#include "socket_utils.hpp"
#include <smart_ptr/shared_ptr.hpp>
#include <exception>
#include <string>
ft::serv::bootstrap::bootstrap(const ft::shared_ptr<event_worker_group>& boss_group, const ft::shared_ptr<event_worker_group>& child_group, make_server_t make_server, make_client_t make_client)
: boss_group(boss_group),
child_group(child_group),
make_server(make_server),
make_client(make_client),
success(),
ended()
{
boss_group->wait_all();
child_group->wait_all();
}
ft::serv::bootstrap::~bootstrap()
{
this->finalize();
}
static const char* _to_c_str_nullable(const std::string& str)
{
return str.empty() ? null : str.c_str();
}
bool ft::serv::bootstrap::start_server(const std::string& host_str, const std::string& serv_str, void* arg)
{
assert(this->make_server);
const ident_t boss_ident = socket_utils::bind_socket(_to_c_str_nullable(host_str), _to_c_str_nullable(serv_str));
if (boss_ident < 0)
{
return false;
}
try
{
socket_utils::set_nonblocking(boss_ident, true);
socket_utils::listen_socket(boss_ident);
}
catch (const std::exception& e)
{
socket_utils::close_socket(boss_ident);
throw;
}
std::string host;
int serv;
socket_utils::name_socket(boss_ident, host, serv);
const ft::shared_ptr<event_channel_base> boss = (*this->make_server)(boss_ident, host, serv, this->child_group, arg);
logger::trace("Boot Server (%d, %s, %d)", boss_ident, host.c_str(), serv);
boss->set_loop(this->boss_group->next());
boss->loop_register();
return true;
}
bool ft::serv::bootstrap::start_client(const std::string& host_str, const std::string& serv_str, void* arg)
{
assert(this->make_client);
const ident_t child_ident = ft::serv::socket_utils::connect_socket(_to_c_str_nullable(host_str), _to_c_str_nullable(serv_str));
if (child_ident < 0)
{
return false;
}
try
{
socket_utils::set_nonblocking(child_ident, true);
}
catch (const std::exception& e)
{
socket_utils::close_socket(child_ident);
throw;
}
std::string host;
int serv;
socket_utils::name_socket(child_ident, host, serv);
const ft::shared_ptr<event_channel_base> child = (*this->make_client)(child_ident, host, serv, arg);
logger::trace("Boot Client (%d, %s, %d)", child_ident, host.c_str(), serv);
child->set_loop(this->child_group->next());
child->loop_register();
return true;
}
void ft::serv::bootstrap::set_success()
{
this->success = true;
}
void ft::serv::bootstrap::finalize()
{
if (!this->ended)
{
this->ended = true;
if (!this->success)
{
this->boss_group->shutdown_all();
if (this->boss_group != this->child_group)
{
this->child_group->shutdown_all();
}
}
this->boss_group->join_all();
if (this->boss_group != this->child_group)
{
this->child_group->join_all();
}
}
}