24#include <config/config.h>
25#include <config/net_handler.h>
26#include <config/net_list_content.h>
27#include <config/net_messages.h>
28#include <logging/liblogger.h>
29#include <netcomm/fawkes/component_ids.h>
30#include <netcomm/fawkes/hub.h>
52:
Thread(
"ConfigNetworkHandler",
Thread::OPMODE_WAITFORWAKEUP),
72 inbound_queue_.
clear();
80ConfigNetworkHandler::send_inv_value(
unsigned int clid,
const char *path)
91ConfigNetworkHandler::send_value(
unsigned int clid,
const Configuration::ValueIterator *i)
96 uint16_t num_values = i->is_list() ? i->get_list_size() : 0;
98 void * m = prepare_value_msg<uint32_t>(
99 i->path(), i->is_default(), i->is_list(), num_values, data_size, (
void **)&values);
101 std::vector<unsigned int> c_values = i->get_uints();
102 for (uint16_t j = 0; j < num_values; ++j)
103 values[j] = c_values[j];
105 values[0] = i->get_uint();
107 hub_->
send(clid, FAWKES_CID_CONFIGMANAGER, MSG_CONFIG_UINT_VALUE, m, data_size);
108 }
catch (Exception &e) {
110 "send_value: Value %s could not be sent",
114 }
else if (i->is_int()) {
117 int16_t num_values = i->is_list() ? i->get_list_size() : 0;
118 size_t data_size = 0;
119 void * m = prepare_value_msg<int32_t>(
120 i->path(), i->is_default(), i->is_list(), num_values, data_size, (
void **)&values);
122 std::vector<int> c_values = i->get_ints();
123 for (uint16_t j = 0; j < num_values; ++j)
124 values[j] = c_values[j];
126 values[0] = i->get_int();
128 hub_->
send(clid, FAWKES_CID_CONFIGMANAGER, MSG_CONFIG_INT_VALUE, m, data_size);
129 }
catch (Exception &e) {
131 "send_value: Value %s could not be sent",
135 }
else if (i->is_bool()) {
138 int16_t num_values = i->is_list() ? i->get_list_size() : 0;
139 size_t data_size = 0;
140 void * m = prepare_value_msg<int32_t>(
141 i->path(), i->is_default(), i->is_list(), num_values, data_size, (
void **)&values);
143 std::vector<bool> c_values = i->get_bools();
144 for (uint16_t j = 0; j < num_values; ++j)
145 values[j] = (c_values[j] ? 1 : 0);
147 values[0] = i->get_bool() ? 1 : 0;
149 hub_->
send(clid, FAWKES_CID_CONFIGMANAGER, MSG_CONFIG_BOOL_VALUE, m, data_size);
150 }
catch (Exception &e) {
152 "send_value: Value %s could not be sent",
156 }
else if (i->is_float()) {
159 uint16_t num_values = i->is_list() ? i->get_list_size() : 0;
160 size_t data_size = 0;
161 void * m = prepare_value_msg<float>(
162 i->path(), i->is_default(), i->is_list(), num_values, data_size, (
void **)&values);
164 std::vector<float> c_values = i->get_floats();
165 for (uint16_t j = 0; j < num_values; ++j)
166 values[j] = c_values[j];
168 values[0] = i->get_float();
170 hub_->
send(clid, FAWKES_CID_CONFIGMANAGER, MSG_CONFIG_FLOAT_VALUE, m, data_size);
171 }
catch (Exception &e) {
173 "send_value: Value %s could not be sent",
177 }
else if (i->is_string()) {
180 std::vector<std::string> s = i->get_strings();
181 size_t data_size =
sizeof(config_descriptor_t);
183 for (
unsigned int j = 0; j < s.size(); ++j) {
184 data_size +=
sizeof(config_string_value_t) + s[j].length() + 1;
186 void *m = calloc(1, data_size);
188 config_descriptor_t *cd = (config_descriptor_t *)m;
189 strncpy(cd->path, i->path(), CONFIG_MSG_PATH_LENGTH - 1);
190 cd->is_default = i->is_default();
191 cd->num_values = s.size();
193 char *tmp = ((
char *)m +
sizeof(config_descriptor_t));
194 for (
unsigned int j = 0; j < s.size(); ++j) {
195 config_string_value_t *sv = (config_string_value_t *)tmp;
196 char * msg_string = tmp +
sizeof(config_string_value_t);
197 sv->s_length = s[j].length();
198 strcpy(msg_string, s[j].c_str());
199 tmp +=
sizeof(config_string_value_t) + sv->s_length + 1;
202 hub_->
send(clid, FAWKES_CID_CONFIGMANAGER, MSG_CONFIG_STRING_VALUE, m, data_size);
204 std::string s = i->get_string();
206 sizeof(config_descriptor_t) +
sizeof(config_string_value_t) + s.length() + 1;
207 void * m = calloc(1, data_size);
208 config_descriptor_t *cd = (config_descriptor_t *)m;
209 strncpy(cd->path, i->path(), CONFIG_MSG_PATH_LENGTH - 1);
210 cd->is_default = i->is_default();
213 config_string_value_t *sv =
214 (config_string_value_t *)((
char *)m +
sizeof(config_descriptor_t));
215 char *msg_string = (
char *)sv +
sizeof(config_string_value_t);
217 sv->s_length = s.length();
218 strcpy(msg_string, s.c_str());
220 hub_->
send(clid, FAWKES_CID_CONFIGMANAGER, MSG_CONFIG_STRING_VALUE, m, data_size);
222 }
catch (Exception &e) {
224 "send_value: Value %s could not be sent",
229 LibLogger::log_warn(
"ConfigNetworkHandler",
"send_value: unknown type of value %s", i->path());
237 while (!inbound_queue_.empty()) {
242 if (msg->
msgid() == MSG_CONFIG_SUBSCRIBE) {
245 subscribers_.unique();
263 hub_->
send(msg->
clid(), FAWKES_CID_CONFIGMANAGER, MSG_CONFIG_LIST, content);
266 }
else if (msg->
msgid() == MSG_CONFIG_ERASE_VALUE) {
269 char path[CONFIG_MSG_PATH_LENGTH];
270 path[CONFIG_MSG_PATH_LENGTH - 1] = 0;
271 memcpy(path, m->
cp.
path, CONFIG_MSG_PATH_LENGTH);
276 config_->
erase(path);
280 prepare_msg<config_value_erased_msg_t>(path, (m->
cp.
is_default == 1));
282 FAWKES_CID_CONFIGMANAGER,
283 MSG_CONFIG_VALUE_ERASED,
288 send_inv_value(msg->
clid(),
"?");
289 e.
append(
"Failed to erase value");
294 }
else if ((msg->
msgid() >= MSG_CONFIG_GET_BEGIN) && (msg->
msgid() <= MSG_CONFIG_GET_END)) {
297 "CONFIG_GET_FLOAT: invalid payload size "
298 "(received %zu instead of %zu bytes",
303 char path[CONFIG_MSG_PATH_LENGTH + 1];
304 path[CONFIG_MSG_PATH_LENGTH] = 0;
305 strncpy(path, m->
cp.
path, CONFIG_MSG_PATH_LENGTH);
307 switch (msg->
msgid()) {
308 case MSG_CONFIG_GET_FLOAT:
309 case MSG_CONFIG_GET_UINT:
310 case MSG_CONFIG_GET_INT:
311 case MSG_CONFIG_GET_BOOL:
312 case MSG_CONFIG_GET_STRING:
313 case MSG_CONFIG_GET_VALUE:
317 send_value(msg->
clid(), i);
319 send_inv_value(msg->
clid(), path);
324 "get value: Value %s could not be found",
331 }
else if ((msg->
msgid() >= MSG_CONFIG_SET_BEGIN) && (msg->
msgid() <= MSG_CONFIG_SET_END)) {
332 bool success =
false;
334 char path[CONFIG_MSG_PATH_LENGTH + 1];
337 "inbound set: payload is too small"
338 "(%zu is less than %zu bytes",
341 send_inv_value(msg->
clid(),
"?");
344 path[CONFIG_MSG_PATH_LENGTH] = 0;
345 strncpy(path, cd->
path, CONFIG_MSG_PATH_LENGTH);
347 switch (msg->
msgid()) {
348 case MSG_CONFIG_SET_FLOAT:
349 case MSG_CONFIG_SET_DEFAULT_FLOAT:
354 for (
unsigned int i = 0; i < cd->
num_values; ++i) {
359 if (msg->
msgid() == MSG_CONFIG_SET_FLOAT) {
367 send_inv_value(msg->
clid(), path);
369 "set float: Value %s could not be set",
375 case MSG_CONFIG_SET_UINT:
376 case MSG_CONFIG_SET_DEFAULT_UINT:
380 std::vector<unsigned int> values(cd->
num_values);
381 for (
unsigned int i = 0; i < cd->
num_values; ++i) {
386 if (msg->
msgid() == MSG_CONFIG_SET_UINT) {
394 send_inv_value(msg->
clid(), path);
396 "set uint: Value %s could not be set",
402 case MSG_CONFIG_SET_INT:
403 case MSG_CONFIG_SET_DEFAULT_INT:
408 for (
unsigned int i = 0; i < cd->
num_values; ++i) {
413 if (msg->
msgid() == MSG_CONFIG_SET_INT) {
421 send_inv_value(msg->
clid(), path);
427 case MSG_CONFIG_SET_BOOL:
428 case MSG_CONFIG_SET_DEFAULT_BOOL:
433 for (
unsigned int i = 0; i < cd->
num_values; ++i) {
434 values[i] = (vs[i] != 0);
438 if (msg->
msgid() == MSG_CONFIG_SET_INT) {
439 config_->
set_bool(path, (*vs != 0));
446 send_inv_value(msg->
clid(), path);
448 "set bool: Value %s could not be set",
454 case MSG_CONFIG_SET_STRING:
455 case MSG_CONFIG_SET_DEFAULT_STRING:
460 std::vector<std::string> values(cd->
num_values);
461 for (
unsigned int i = 0; i < cd->
num_values; ++i) {
465 values[i] = std::string(msg_string, sv->
s_length);
471 std::string value = std::string(msg_string, sv->
s_length);
472 if (msg->
msgid() == MSG_CONFIG_SET_INT) {
480 send_inv_value(msg->
clid(), path);
482 "set string: Value %s could not be set",
494 send_value(msg->
clid(), i);
496 send_inv_value(msg->
clid(), path);
501 "get value: Value %s could not be found",
542 if (find(subscribers_.begin(), subscribers_.end(), clid) != subscribers_.end()) {
544 "ConfigNetworkHandler",
545 "Client %u disconnected without closing the config, removing from list of subscribers",
547 subscribers_.remove(clid);
564 const char *path = v->
path();
567 for (sit_ = subscribers_.begin(); sit_ != subscribers_.end(); ++sit_) {
569 send_value(*sit_, v);
572 "config_value_changed: Value for %s could not be sent "
591 for (sit_ = subscribers_.begin(); sit_ != subscribers_.end(); ++sit_) {
595 FAWKES_CID_CONFIGMANAGER,
596 MSG_CONFIG_VALUE_ERASED,
601 "configValueErased: Value for %s could not be sent "
void append(Configuration::ValueIterator *i)
Append from iterator.
ConfigNetworkHandler(Configuration *config, FawkesNetworkHub *hub)
Constructor.
virtual void loop()
Process all network messages that have been received.
virtual void config_value_erased(const char *path)
Called whenever a value has been erased from the config.
~ConfigNetworkHandler()
Destructor.
virtual void client_disconnected(unsigned int clid)
Client disconnected.
virtual void client_connected(unsigned int clid)
Client connected.
virtual void config_value_changed(const Configuration::ValueIterator *v)
Called whenever a watched value has changed.
virtual void config_tag_changed(const char *new_location)
Tag changed.
virtual void config_comment_changed(const Configuration::ValueIterator *v)
Called whenever a comment of a watched value has changed.
virtual void handle_network_message(FawkesNetworkMessage *msg)
Handle network message.
Interface for configuration change handling.
Generic configuration exception.
Iterator interface to iterate over config values.
virtual const char * path() const =0
Path of value.
virtual bool next()=0
Check if there is another element and advance to this if possible.
virtual bool is_default() const =0
Check if current value was read from the default config.
Interface for configuration handling.
virtual void set_bools(const char *path, std::vector< bool > &b)=0
Set new value in configuration of type bool.
virtual void set_uint(const char *path, unsigned int uint)=0
Set new value in configuration of type unsigned int.
virtual void set_ints(const char *path, std::vector< int > &i)=0
Set new value in configuration of type int.
virtual void set_bool(const char *path, bool b)=0
Set new value in configuration of type bool.
virtual ValueIterator * iterator()=0
Iterator for all values.
virtual void rem_change_handler(ConfigurationChangeHandler *h)
Remove a configuration change handler.
virtual void set_default_float(const char *path, float f)=0
Set new default value in configuration of type float.
virtual void set_float(const char *path, float f)=0
Set new value in configuration of type float.
virtual void set_default_string(const char *path, std::string &s)=0
Set new default value in configuration of type string.
virtual ValueIterator * get_value(const char *path)=0
Get value from configuration.
virtual void set_string(const char *path, std::string &s)=0
Set new value in configuration of type string.
virtual void set_uints(const char *path, std::vector< unsigned int > &uint)=0
Set new value in configuration of type unsigned int.
virtual void erase_default(const char *path)=0
Erase the given default value from the configuration.
virtual void set_floats(const char *path, std::vector< float > &f)=0
Set new value in configuration of type float.
virtual void lock()=0
Lock the config.
virtual void unlock()=0
Unlock the config.
virtual void set_default_bool(const char *path, bool b)=0
Set new default value in configuration of type bool.
virtual void set_int(const char *path, int i)=0
Set new value in configuration of type int.
virtual void set_default_uint(const char *path, unsigned int uint)=0
Set new default value in configuration of type unsigned int.
virtual void set_default_int(const char *path, int i)=0
Set new default value in configuration of type int.
virtual void set_strings(const char *path, std::vector< std::string > &s)=0
Set new value in configuration of type string.
virtual void add_change_handler(ConfigurationChangeHandler *h)
Add a configuration change handler.
virtual void erase(const char *path)=0
Erase the given value from the configuration.
Base class for exceptions in Fawkes.
void append(const char *format,...) noexcept
Append messages to the message list.
Network handler abstract base class.
virtual void send(FawkesNetworkMessage *msg)=0
Method to send a message to a specific client.
virtual void remove_handler(FawkesNetworkHandler *handler)=0
Remove a message handler.
virtual void add_handler(FawkesNetworkHandler *handler)=0
Add a message handler.
Representation of a message that is sent over the network.
unsigned short int msgid() const
Get message type ID.
MT * msg() const
Get correctly casted payload.
unsigned int clid() const
Get client ID.
void * payload() const
Get payload buffer.
size_t payload_size() const
Get payload size.
static void log_warn(const char *component, const char *format,...)
Log warning message.
virtual void unlock() const
Unlock list.
void push_back_locked(const Type &x)
Push element to list at back with lock protection.
virtual void lock() const
Lock list.
void clear()
Clear the queue.
void pop_locked()
Pop element from queue with lock protection.
void push_locked(const Type &x)
Push element to queue with lock protection.
void unref()
Decrement reference count and conditionally delete this instance.
void ref()
Increment reference count.
Thread class encapsulation of pthreads.
void start(bool wait=true)
Call this method to start the thread.
void join()
Join the thread.
void wakeup()
Wake up thread.
void cancel()
Cancel a thread.
Fawkes library namespace.
uint16_t num_values
Number of valus in list.
uint16_t is_default
1 if value is a default value, 0 otherwise, only for get response
char path[CONFIG_MSG_PATH_LENGTH]
path to config value.
config_descriptor_t cp
value descriptor
config_descriptor_t cp
value descriptor
Invalid value request message.
String value header indicating the string length.
uint16_t s_length
Length of following string.