cluck 1.0.1
The cluster lock service.
computer.cpp
Go to the documentation of this file.
1// Copyright (c) 2016-2025 Made to Order Software Corp. All Rights Reserved
2//
3// https://snapwebsites.org/project/cluck
4// contact@m2osw.com
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19// self
20//
21#include "computer.h"
22
23
24// cluck
25//
26#include <cluck/exception.h>
27
28
29// cppthread
30//
31#include <cppthread/thread.h>
32
33
34// snaplogger
35//
36#include <snaplogger/message.h>
37
38
39// libaddr
40//
41#include <libaddr/addr_parser.h>
42#include <libaddr/exception.h>
43
44
45// advgetopt
46//
47#include <advgetopt/validator_integer.h>
48
49
50// snapdev
51//
52#include <snapdev/tokenize_string.h>
53
54
55// C++
56//
57#include <iomanip>
58
59
60// openssl
61//
62#include <openssl/rand.h>
63
64
65// last include
66//
67#include <snapdev/poison.h>
68
69
70
71namespace cluck_daemon
72{
73
74
75
77{
78 // used for a remote computer, we'll eventually get a set_id() which
79 // defines the necessary computer parameters
80}
81
82
83computer::computer(std::string const & name, priority_t priority, addr::addr ip_address)
84 : f_self(true)
85 , f_priority(priority)
86 , f_ip_address(ip_address)
87 , f_pid(getpid())
88 , f_name(name)
89{
90 // verify the name becaue it can cause issues in the serializer if it
91 // includes invalid characters are is empty
92 //
93 if(f_name.empty())
94 {
95 throw cluck::invalid_parameter("the computer name cannot be an empty string.");
96 }
97 std::string invalid_name_characters("|");
98 invalid_name_characters += '\0';
99 if(f_name.find_first_of(invalid_name_characters) != std::string::npos)
100 {
101 throw cluck::invalid_parameter("a computer name cannot include the '|' or null characters.");
102 }
103
106 {
107 throw cluck::invalid_parameter(
108 "priority is limited to a number between "
109 + std::to_string(static_cast<int>(PRIORITY_USER_MIN))
110 + " and "
111 + std::to_string(static_cast<int>(PRIORITY_MAX))
112 + " inclusive.");
113 }
114
115 RAND_bytes(reinterpret_cast<unsigned char *>(&f_random_id), sizeof(f_random_id));
116}
117
118
120{
121 return f_self;
122}
123
124
125void computer::set_connected(bool connected)
126{
127 f_connected = connected;
128}
129
130
132{
133 return f_connected;
134}
135
136
153bool computer::set_id(std::string const & id)
154{
156 {
157 throw cluck::logic_error("computer::set_id() cannot be called more than once.");
158 }
159
160 std::vector<std::string> parts;
161 snapdev::tokenize_string(parts, id, "|");
162 if(parts.size() != 5)
163 {
164 // do not throw in case something changes we do not want snaplock to
165 // "crash" over and over again
166 //
167 SNAP_LOG_ERROR
168 << "received a computer id which does not have exactly 5 parts: \""
169 << id
170 << "\"."
171 << SNAP_LOG_SEND;
172 return false;
173 }
174
175 // base is VERY IMPORTANT for this one as we save priorities below ten
176 // as 0n (01 to 09) so the sort works as expected
177 //
178 std::int64_t value(0);
179 bool valid(advgetopt::validator_integer::convert_string(parts[0], value));
180 if(!valid
181 || value < PRIORITY_USER_MIN
182 || value > PRIORITY_MAX)
183 {
184 SNAP_LOG_ERROR
185 << "priority is limited to a number between "
186 << static_cast<int>(PRIORITY_USER_MIN)
187 << " and "
188 << static_cast<int>(PRIORITY_MAX)
189 << " inclusive."
190 << SNAP_LOG_SEND;
191 return false;
192 }
193 f_priority = value;
194
195 if(!advgetopt::validator_integer::convert_string(parts[1], value))
196 {
197 SNAP_LOG_ERROR
198 << "random value is expected to be a valid integer, not "
199 << parts[1]
200 << "."
201 << SNAP_LOG_SEND;
202 return false;
203 }
204 f_random_id = value;
205
206 if(parts[2].empty())
207 {
208 SNAP_LOG_ERROR
209 << "the process IP cannot be an empty string."
210 << SNAP_LOG_SEND;
211 return false;
212 }
213 try
214 {
215 f_ip_address = addr::string_to_addr(parts[2]);
216 if(f_ip_address.is_default())
217 {
218 SNAP_LOG_ERROR
219 << "the IP address cannot be the default IP (0.0.0.0)."
220 << SNAP_LOG_SEND;
221 return false;
222 }
223 }
224 catch(addr::addr_invalid_argument const & e)
225 {
226 // we want to avoid "crashing" because any hacker could send us an
227 // invalid message and get the service to stop on this one
228 //
229 SNAP_LOG_ERROR
230 << "the process IP, \""
231 << parts[2]
232 << "\", is not valid: "
233 << e.what()
234 << SNAP_LOG_SEND;
235 return false;
236 }
237
238 valid = advgetopt::validator_integer::convert_string(parts[3], value);
239 if(!valid
240 || value < 1
241 || value > cppthread::get_pid_max())
242 {
243 SNAP_LOG_ERROR
244 << "process identifier "
245 << parts[3]
246 << " is invalid ("
247 << std::boolalpha << valid
248 << ") or out of bounds: [1.."
249 << cppthread::get_pid_max()
250 << "]."
251 << SNAP_LOG_SEND;
252 return false;
253 }
254 f_pid = value;
255
256 if(parts[4].empty())
257 {
258 SNAP_LOG_ERROR
259 << "the server name in the lock identifier cannot be empty."
260 << SNAP_LOG_SEND;
261 return false;
262 }
263 f_name = parts[4];
264
265 f_id = id;
266
267 return true;
268}
269
270
275
276
277void computer::set_start_time(snapdev::timespec_ex const & start_time)
278{
279 f_start_time = start_time;
280}
281
282
283snapdev::timespec_ex const & computer::get_start_time() const
284{
285 return f_start_time;
286}
287
288
289std::string const & computer::get_name() const
290{
291 return f_name;
292}
293
294
295std::string const & computer::get_id() const
296{
297 if(f_id.empty())
298 {
300 {
301 throw cluck::invalid_parameter("computer::get_id() can't be called when the priority is not defined.");
302 }
303 if(f_ip_address.is_default())
304 {
305 throw cluck::invalid_parameter("computer::get_id() can't be called when the address is the default address.");
306 }
307 if(f_pid == 0)
308 {
309 throw cluck::invalid_parameter("computer::get_id() can't be called when the pid is not defined.");
310 }
311
312 std::stringstream ss;
313 ss
314 << std::setfill('0') << std::setw(2) << static_cast<int>(f_priority)
315 << '|'
316 << f_random_id
317 << '|'
318 << f_ip_address.to_ipv4or6_string(addr::STRING_IP_ADDRESS | addr::STRING_IP_BRACKET_ADDRESS)
319 << '|'
320 << f_pid
321 << '|'
322 << f_name;
323 f_id = ss.str();
324 }
325
326 return f_id;
327}
328
329
330addr::addr const & computer::get_ip_address() const
331{
332 return f_ip_address;
333}
334
335
336} // namespace cluck_daemon
337// vim: ts=4 sw=4 et
void set_start_time(snapdev::timespec_ex const &start_time)
Definition computer.cpp:277
void set_connected(bool connected)
Definition computer.cpp:125
std::string const & get_name() const
Definition computer.cpp:289
bool get_connected() const
Definition computer.cpp:131
snapdev::timespec_ex const & get_start_time() const
Definition computer.cpp:283
static priority_t const PRIORITY_UNDEFINED
Definition computer.h:53
addr::addr const & get_ip_address() const
Definition computer.cpp:330
static priority_t const PRIORITY_USER_MIN
Definition computer.h:56
std::string f_name
Definition computer.h:90
addr::addr f_ip_address
Definition computer.h:88
static priority_t const PRIORITY_MAX
Definition computer.h:59
priority_t f_priority
Definition computer.h:86
snapdev::timespec_ex f_start_time
Definition computer.h:92
std::int8_t priority_t
Definition computer.h:47
bool set_id(std::string const &id)
Initialize this computer object from id.
Definition computer.cpp:153
priority_t get_priority() const
Definition computer.cpp:271
std::string const & get_id() const
Definition computer.cpp:295

This document is part of the Snap! Websites Project.

Copyright by Made to Order Software Corp.