Fawkes API Fawkes Development Version
netconf.cpp
1
2/***************************************************************************
3 * netconf.cpp - Fawkes remote configuration access via Fawkes net
4 *
5 * Created: Sun Jan 07 15:04:41 2007
6 * Copyright 2006-2009 Tim Niemueller [www.niemueller.de]
7 *
8 ****************************************************************************/
9
10/* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version. A runtime exception applies to
14 * this software (see LICENSE.GPL_WRE file mentioned below for details).
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22 */
23
24#include <config/memory.h>
25#include <config/net_list_content.h>
26#include <config/net_messages.h>
27#include <config/netconf.h>
28#include <core/threading/interruptible_barrier.h>
29#include <core/threading/mutex.h>
30#include <logging/liblogger.h>
31#include <netcomm/fawkes/client.h>
32#include <netcomm/fawkes/message.h>
33#include <netcomm/utils/exceptions.h>
34#include <utils/misc/string_conversions.h>
35
36#ifndef _GNU_SOURCE
37# define _GNU_SOURCE
38#endif
39#include <cstdlib>
40#include <cstring>
41
42namespace fawkes {
43
44/** @class CannotEnableMirroringException <config/netconf.h>
45 * Thrown if enabling mirror mode failed.
46 */
47
48/** Constructor.
49 * @param msg message describing the problem
50 */
52: Exception("Could not enable mirroring: %s", msg)
53{
54}
55
56/** @class NetworkConfiguration <config/netconf.h>
57 * Remote configuration via Fawkes net.
58 * This implementation of the Configuration interface allows for remote access
59 * to a Fawkes process implemented using the ConfigurationManager.
60 *
61 * The network configuration can operator in two modes. In mirror and in non-mirror
62 * mode. The non-mirror mode is recommended if only a few operations have to be
63 * carried out like getting only a very few values or setting a single value.
64 * The mirror mode is for longer usage periods and on-the-fly updates. In mirror
65 * mode the complete configuration is copied once from the Fawkes process and then
66 * all updates are incorporated into the local database. You can register change
67 * handlers to be notified as soon as someone modifies a value.
68 *
69 */
70
71/** Constructor.
72 * @param c Fawkes network client (thread).
73 * @param mirror_timeout_sec timeout in seconds for initiating mirroring
74 */
76{
77 mirror_timeout_sec_ = mirror_timeout_sec;
78 mutex = new Mutex();
79 msg = NULL;
80 mirror_mode_ = false;
81 mirror_mode_before_connection_dead_ = false;
82 mirror_init_waiting_ = false;
83 mirror_init_barrier_ = new InterruptibleBarrier(2);
84
85 connected_ = c->connected();
86 this->c = c;
87 try {
88 c->register_handler(this, FAWKES_CID_CONFIGMANAGER);
89 } catch (Exception &e) {
90 e.append("Failed to register for config manager component on network client");
91 throw;
92 }
93}
94
95/** Destructor. */
97{
98 set_mirror_mode(false);
99 c->deregister_handler(FAWKES_CID_CONFIGMANAGER);
100 if (msg != NULL) {
101 msg->unref();
102 }
103 delete mirror_init_barrier_;
104 delete mutex;
105}
106
107void
108NetworkConfiguration::load(const char *file_path)
109{
110}
111
112/** Copy all values from the given configuration.
113 * All values from the given configuration are copied. Old values are not erased
114 * so that the copied values will overwrite existing values, new values are
115 * created, but values existent in current config but not in the copie config
116 * will remain unchanged.
117 * @param copyconf configuration to copy
118 */
119void
121{
122 copyconf->lock();
123 Configuration::ValueIterator *i = copyconf->iterator();
124 while (i->next()) {
125 if (i->is_float()) {
126 set_float(i->path(), i->get_float());
127 } else if (i->is_int()) {
128 set_int(i->path(), i->get_int());
129 } else if (i->is_uint()) {
130 set_uint(i->path(), i->get_uint());
131 } else if (i->is_bool()) {
132 set_bool(i->path(), i->get_bool());
133 } else if (i->is_string()) {
134 std::string s = i->get_string();
135 set_string(i->path(), s);
136 }
137 }
138 delete i;
139 copyconf->unlock();
140}
141
142bool
144{
145 ValueIterator *i = get_value(path);
146 bool rv = i->valid();
147 delete i;
148 return rv;
149}
150
151bool
153{
154 ValueIterator *i = get_value(path);
155 bool rv = i->is_default();
156 delete i;
157 return rv;
158}
159
160/** Get type of field.
161 * @param path path
162 * @return string of type
163 */
164std::string
166{
167 std::string s = "";
168 mutex->lock();
169 if (mirror_mode_) {
170 s = mirror_config->get_type(path);
171 mutex->unlock();
172 } else {
173 mutex->unlock();
175 s = i->type();
176 delete i;
177 }
178 return s;
179}
180
181bool
183{
184 return (get_type(path) == "float");
185}
186
187bool
189{
190 return (get_type(path) == "unsigned int");
191}
192
193bool
195{
196 return (get_type(path) == "int");
197}
198
199bool
201{
202 return (get_type(path) == "bool");
203}
204
205bool
207{
208 return (get_type(path) == "string");
209}
210
211bool
213{
214 return false;
215}
216
217void
218NetworkConfiguration::send_get(const char *path, unsigned int msgid, unsigned int expected_reply)
219{
220 if (!connected_) {
221 throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
222 "client connection is not alive");
223 }
224 config_getval_msg_t *g = (config_getval_msg_t *)calloc(1, sizeof(config_getval_msg_t));
225 strncpy(g->cp.path, path, CONFIG_MSG_PATH_LENGTH - 1);
226 FawkesNetworkMessage *omsg =
227 new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER, msgid, g, sizeof(config_getval_msg_t));
228 c->enqueue_and_wait(omsg);
229
230 if (!msg) {
231 mutex->unlock();
232 throw NullPointerException("NetworkConfiguration::send_get: msg == NULL");
233 }
234
235 if (msg->msgid() != expected_reply) {
236 unsigned int msg_msgid = msg->msgid();
237 msg->unref();
238 msg = NULL;
239 mutex->unlock();
240 throw Exception("NetworkConfiguration::send_get: expected %u, but got %u",
241 expected_reply,
242 msg_msgid);
243 }
244}
245
246float
248{
249 if (strlen(path) > CONFIG_MSG_PATH_LENGTH) {
250 throw OutOfBoundsException("NetworkConfiguration::get_float: "
251 "Maximum length for path exceeded");
252 }
253 if (!connected_) {
254 throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
255 "client connection is not alive");
256 }
257
258 float f;
259 mutex->lock();
260
261 if (mirror_mode_) {
262 try {
263 f = mirror_config->get_float(path);
264 } catch (Exception &e) {
265 e.append("NetworkConfiguration[mirroring]::get_float: exception in mirror database");
266 mutex->unlock();
267 throw;
268 }
269 } else {
270 try {
271 send_get(path, MSG_CONFIG_GET_FLOAT, MSG_CONFIG_FLOAT_VALUE);
272
274 if (d->num_values > 0) {
275 msg->unref();
276 msg = NULL;
277 throw Exception("NetworkConfiguration: received list of and not a single value");
278 }
279 f = *(float *)((char *)msg->payload() + sizeof(config_descriptor_t));
280
281 msg->unref();
282 msg = NULL;
283
284 } catch (Exception &e) {
285 e.append("NetworkConfiguration::get_float: Fetching float failed");
286 if (msg != NULL) {
287 msg->unref();
288 msg = NULL;
289 }
290 mutex->unlock();
291 throw;
292 }
293 }
294
295 mutex->unlock();
296
297 return f;
298}
299
300unsigned int
302{
303 if (strlen(path) >= CONFIG_MSG_PATH_LENGTH) {
304 throw OutOfBoundsException("NetworkConfiguration::get_uint: "
305 "Maximum length for path exceeded");
306 }
307 if (!connected_) {
308 throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
309 "client connection is not alive");
310 }
311
312 unsigned int u;
313 mutex->lock();
314
315 if (mirror_mode_) {
316 try {
317 u = mirror_config->get_uint(path);
318 } catch (Exception &e) {
319 e.append("NetworkConfiguration[mirroring]::get_uint: exception in mirror database");
320 mutex->unlock();
321 throw;
322 }
323 } else {
324 try {
325 send_get(path, MSG_CONFIG_GET_UINT, MSG_CONFIG_UINT_VALUE);
326
328 if (d->num_values > 0) {
329 msg->unref();
330 msg = NULL;
331 throw Exception("NetworkConfiguration: received list of and not a single value");
332 }
333 u = *(uint32_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
334
335 msg->unref();
336 msg = NULL;
337
338 } catch (Exception &e) {
339 e.append("NetworkConfiguration::get_uint: Fetching unsigned int failed");
340 if (msg != NULL) {
341 msg->unref();
342 msg = NULL;
343 }
344 mutex->unlock();
345 throw;
346 }
347 }
348
349 mutex->unlock();
350
351 return u;
352}
353
354int
356{
357 if (strlen(path) >= CONFIG_MSG_PATH_LENGTH) {
358 throw OutOfBoundsException("NetworkConfiguration::get_int: "
359 "Maximum length for path exceeded");
360 }
361 if (!connected_) {
362 throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
363 "client connection is not alive");
364 }
365
366 int i;
367 mutex->lock();
368
369 if (mirror_mode_) {
370 try {
371 i = mirror_config->get_int(path);
372 } catch (Exception &e) {
373 e.append("NetworkConfiguration[mirroring]::get_int: exception in mirror database");
374 mutex->unlock();
375 throw;
376 }
377 } else {
378 try {
379 send_get(path, MSG_CONFIG_GET_INT, MSG_CONFIG_INT_VALUE);
380
382 if (d->num_values > 0) {
383 msg->unref();
384 msg = NULL;
385 throw Exception("NetworkConfiguration: received list of and not a single value");
386 }
387 i = *(int32_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
388
389 msg->unref();
390 msg = NULL;
391
392 } catch (Exception &e) {
393 e.append("NetworkConfiguration::get_int: Fetching int failed");
394 if (msg != NULL) {
395 msg->unref();
396 msg = NULL;
397 }
398 mutex->unlock();
399 throw;
400 }
401 }
402
403 mutex->unlock();
404
405 return i;
406}
407
408bool
410{
411 if (strlen(path) >= CONFIG_MSG_PATH_LENGTH) {
412 throw OutOfBoundsException("NetworkConfiguration::get_bool: "
413 "Maximum length for path exceeded");
414 }
415 if (!connected_) {
416 throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
417 "client connection is not alive");
418 }
419
420 bool b;
421 mutex->lock();
422
423 if (mirror_mode_) {
424 try {
425 b = mirror_config->get_bool(path);
426 } catch (Exception &e) {
427 e.append("NetworkConfiguration[mirroring]::get_bool: exception in mirror database");
428 mutex->unlock();
429 throw;
430 }
431 } else {
432 try {
433 send_get(path, MSG_CONFIG_GET_BOOL, MSG_CONFIG_BOOL_VALUE);
434
436 if (d->num_values > 0) {
437 msg->unref();
438 msg = NULL;
439 throw Exception("NetworkConfiguration: received list of and not a single value");
440 }
441 b = (*(int32_t *)((char *)msg->payload() + sizeof(config_descriptor_t)) != 0);
442
443 msg->unref();
444 msg = NULL;
445
446 } catch (Exception &e) {
447 e.append("NetworkConfiguration::get_bool: Fetching bool failed");
448 if (msg != NULL) {
449 msg->unref();
450 msg = NULL;
451 }
452 mutex->unlock();
453 throw;
454 }
455 }
456
457 mutex->unlock();
458
459 return b;
460}
461
462std::string
464{
465 if (strlen(path) >= CONFIG_MSG_PATH_LENGTH) {
466 throw OutOfBoundsException("NetworkConfiguration::get_string: "
467 "Maximum length for path exceeded");
468 }
469 if (!connected_) {
470 throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
471 "client connection is not alive");
472 }
473
474 std::string s;
475 mutex->lock();
476
477 if (mirror_mode_) {
478 try {
479 s = mirror_config->get_string(path);
480 } catch (Exception &e) {
481 e.append("NetworkConfiguration[mirroring]::get_string: exception in mirror database");
482 mutex->unlock();
483 throw;
484 }
485 } else {
486 try {
487 send_get(path, MSG_CONFIG_GET_STRING, MSG_CONFIG_STRING_VALUE);
488
490 if (d->num_values > 0) {
491 msg->unref();
492 msg = NULL;
493 throw Exception("NetworkConfiguration: received list of and not a single value");
494 }
496 (config_string_value_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
497 s = std::string((char *)sv + sizeof(config_string_value_t), sv->s_length);
498
499 msg->unref();
500 msg = NULL;
501
502 } catch (Exception &e) {
503 e.append("NetworkConfiguration::get_string: Fetching string failed");
504 if (msg != NULL) {
505 msg->unref();
506 msg = NULL;
507 }
508 mutex->unlock();
509 throw;
510 }
511 }
512
513 mutex->unlock();
514
515 return s;
516}
517
518std::vector<float>
520{
521 throw NotImplementedException("NetworkConf: list values are not supported");
522}
523
524std::vector<unsigned int>
526{
527 throw NotImplementedException("NetworkConf: list values are not supported");
528}
529
530std::vector<int>
532{
533 throw NotImplementedException("NetworkConf: list values are not supported");
534}
535
536std::vector<bool>
538{
539 throw NotImplementedException("NetworkConf: list values are not supported");
540}
541
542std::vector<std::string>
544{
545 throw NotImplementedException("NetworkConf: list values are not supported");
546}
547
548std::string
550{
551 if (strlen(path) >= CONFIG_MSG_PATH_LENGTH) {
552 throw OutOfBoundsException("NetworkConfiguration::get_comment: "
553 "Maximum length for path exceeded");
554 }
555 if (!connected_) {
556 throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
557 "client connection is not alive");
558 }
559
560 std::string s;
561 mutex->lock();
562
563 if (mirror_mode_) {
564 try {
565 s = mirror_config->get_comment(path);
566 } catch (Exception &e) {
567 e.append("NetworkConfiguration[mirroring]::get_comment: exception in mirror database");
568 mutex->unlock();
569 throw;
570 }
571 } else {
572 try {
573 send_get(path, MSG_CONFIG_GET_COMMENT, MSG_CONFIG_COMMENT_VALUE);
574
576 s = sm->s;
577
578 msg->unref();
579 msg = NULL;
580
581 } catch (Exception &e) {
582 e.append("NetworkConfiguration::get_comment: Fetching int failed");
583 if (msg != NULL) {
584 msg->unref();
585 msg = NULL;
586 }
587 mutex->unlock();
588 throw;
589 }
590 }
591
592 mutex->unlock();
593
594 return s;
595}
596
597std::string
599{
600 if (strlen(path) >= CONFIG_MSG_PATH_LENGTH) {
601 throw OutOfBoundsException("NetworkConfiguration::get_default_comment: "
602 "Maximum length for path exceeded");
603 }
604 if (!connected_) {
605 throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
606 "client connection is not alive");
607 }
608
609 std::string s;
610 mutex->lock();
611
612 if (mirror_mode_) {
613 try {
614 s = mirror_config->get_default_comment(path);
615 } catch (Exception &e) {
616 e.append("NetworkConfiguration[mirroring]::get_default_comment: "
617 "exception in mirror database");
618 mutex->unlock();
619 throw;
620 }
621 } else {
622 try {
623 send_get(path, MSG_CONFIG_GET_DEFAULT_COMMENT, MSG_CONFIG_COMMENT_VALUE);
624
626 s = sm->s;
627
628 msg->unref();
629 msg = NULL;
630
631 } catch (Exception &e) {
632 e.append("NetworkConfiguration::get_comment: Fetching int failed");
633 if (msg != NULL) {
634 msg->unref();
635 msg = NULL;
636 }
637 mutex->unlock();
638 throw;
639 }
640 }
641
642 mutex->unlock();
643
644 return s;
645}
646
649{
650 if (strlen(path) >= CONFIG_MSG_PATH_LENGTH) {
651 throw OutOfBoundsException("NetworkConfiguration::get_value: "
652 "Maximum length for path exceeded");
653 }
654 if (!connected_) {
655 throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
656 "client connection is not alive");
657 }
658
660 mutex->lock();
661
662 if (mirror_mode_) {
663 try {
664 i = mirror_config->get_value(path);
665 } catch (Exception &e) {
666 e.append("NetworkConfiguration[mirroring]::get_float: exception in mirror database");
667 mutex->unlock();
668 throw;
669 }
670 } else {
672 strncpy(g->cp.path, path, CONFIG_MSG_PATH_LENGTH - 1);
673 FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
674 MSG_CONFIG_GET_VALUE,
675 g,
676 sizeof(config_getval_msg_t));
677 c->enqueue_and_wait(omsg);
678
679 if (msg == NULL) {
680 mutex->unlock();
681 throw NullPointerException("NetworkConfiguration::get_value: msg == NULL");
682 }
683
684 i = new NetConfValueIterator(msg);
685
686 msg->unref();
687 msg = NULL;
688 }
689
690 mutex->unlock();
691
692 return i;
693}
694
695void
696NetworkConfiguration::set_value_internal(unsigned int msg_type,
697 const char * path,
698 uint16_t num_values,
699 size_t data_size,
700 void * data)
701{
702 if (strlen(path) >= CONFIG_MSG_PATH_LENGTH) {
703 throw OutOfBoundsException("NetworkConfiguration::set_float: "
704 "Maximum length for path exceeded");
705 }
706 if (!connected_) {
707 throw ConnectionDiedException("NetworkConfiguration: Cannot set value, "
708 "client connection is not alive");
709 }
710
711 mutex->lock();
712 size_t msg_size = sizeof(config_descriptor_t) + data_size;
713 FawkesNetworkMessage *omsg =
714 new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER, msg_type, msg_size);
715 config_descriptor_t *cd = omsg->msgge<config_descriptor_t>();
716 strncpy(cd->path, path, CONFIG_MSG_PATH_LENGTH - 1);
717 cd->num_values = num_values;
718
719 void *mdata = ((char *)omsg->payload() + sizeof(config_descriptor_t));
720 memcpy(mdata, data, data_size);
721
722 c->enqueue_and_wait(omsg);
723 if (!mirror_mode_ && (msg != NULL)) {
724 msg->unref();
725 msg = NULL;
726 }
727 mutex->unlock();
728}
729
730void
731NetworkConfiguration::set_float(const char *path, float f)
732{
733 set_value_internal(MSG_CONFIG_SET_FLOAT, path, 0, sizeof(float), &f);
734}
735
736void
738{
739 set_value_internal(MSG_CONFIG_SET_DEFAULT_FLOAT, path, 0, sizeof(float), &f);
740}
741
742void
743NetworkConfiguration::set_uint(const char *path, unsigned int uint)
744{
745 set_value_internal(MSG_CONFIG_SET_UINT, path, 0, sizeof(uint32_t), &uint);
746}
747
748void
749NetworkConfiguration::set_default_uint(const char *path, unsigned int uint)
750{
751 set_value_internal(MSG_CONFIG_SET_DEFAULT_UINT, path, 0, sizeof(uint32_t), &uint);
752}
753
754void
755NetworkConfiguration::set_int(const char *path, int i)
756{
757 set_value_internal(MSG_CONFIG_SET_INT, path, 0, sizeof(int32_t), &i);
758}
759
760void
762{
763 set_value_internal(MSG_CONFIG_SET_DEFAULT_INT, path, 0, sizeof(int32_t), &i);
764}
765
766void
767NetworkConfiguration::set_bool(const char *path, bool b)
768{
769 int32_t bs[1] = {b ? 1 : 0};
770 set_value_internal(MSG_CONFIG_SET_BOOL, path, 0, sizeof(int32_t), bs);
771}
772
773void
775{
776 int32_t bs[1] = {b ? 1 : 0};
777 set_value_internal(MSG_CONFIG_SET_DEFAULT_BOOL, path, 0, sizeof(int32_t), bs);
778}
779
780void
781NetworkConfiguration::set_string(const char *path, const char *s)
782{
783 size_t s_length = strlen(s);
784 size_t data_size = sizeof(config_string_value_t) + s_length;
785 void * data = malloc(data_size);
786 memset(data, 0, data_size);
788 sv->s_length = s_length;
789 strcpy((char *)data + sizeof(config_string_value_t), s);
790
791 set_value_internal(MSG_CONFIG_SET_STRING, path, 0, data_size, data);
792 free(data);
793}
794
795void
796NetworkConfiguration::set_default_string(const char *path, const char *s)
797{
798 size_t s_length = strlen(s);
799 size_t data_size = sizeof(config_string_value_t) + s_length;
800 void * data = malloc(data_size);
801 memset(data, 0, data_size);
803 sv->s_length = s_length;
804 strcpy((char *)data + sizeof(config_string_value_t), s);
805 set_value_internal(MSG_CONFIG_SET_DEFAULT_STRING, path, 0, data_size, data);
806 free(data);
807}
808
809void
810NetworkConfiguration::set_string(const char *path, std::string &s)
811{
812 set_string(path, s.c_str());
813}
814
815void
816NetworkConfiguration::set_default_string(const char *path, std::string &s)
817{
818 set_default_string(path, s.c_str());
819}
820
821void
822NetworkConfiguration::set_floats(const char *path, std::vector<float> &f)
823{
824 throw NotImplementedException("NetworkConf: list values are not supported");
825}
826
827void
828NetworkConfiguration::set_uints(const char *path, std::vector<unsigned int> &u)
829{
830 throw NotImplementedException("NetworkConf: list values are not supported");
831}
832
833void
834NetworkConfiguration::set_ints(const char *path, std::vector<int> &i)
835{
836 throw NotImplementedException("NetworkConf: list values are not supported");
837}
838
839void
840NetworkConfiguration::set_bools(const char *path, std::vector<bool> &b)
841{
842 throw NotImplementedException("NetworkConf: list values are not supported");
843}
844
845void
846NetworkConfiguration::set_strings(const char *path, std::vector<std::string> &s)
847{
848 throw NotImplementedException("NetworkConf: list values are not supported");
849}
850
851void
852NetworkConfiguration::set_strings(const char *path, std::vector<const char *> &s)
853{
854 throw NotImplementedException("NetworkConf: list values are not supported");
855}
856
857void
858NetworkConfiguration::set_comment(const char *path, const char *comment)
859{
860}
861
862void
863NetworkConfiguration::set_default_comment(const char *path, const char *comment)
864{
865}
866
867void
868NetworkConfiguration::set_comment(const char *path, std::string &comment)
869{
870}
871
872void
873NetworkConfiguration::set_default_comment(const char *path, std::string &comment)
874{
875}
876
877void
878NetworkConfiguration::erase_internal(const char *path, bool is_default)
879{
880 if (strlen(path) >= CONFIG_MSG_PATH_LENGTH) {
881 throw OutOfBoundsException("NetworkConfiguration::erase: "
882 "Maximum length for path exceeded");
883 }
884 if (!connected_) {
885 throw ConnectionDiedException("NetworkConfiguration: Cannot set value, "
886 "client connection is not alive");
887 }
888
889 mutex->lock();
890 FawkesNetworkMessage * omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
891 MSG_CONFIG_ERASE_VALUE,
892 sizeof(config_erase_value_msg_t));
893 config_erase_value_msg_t *m = omsg->msg<config_erase_value_msg_t>();
894 m->cp.is_default = is_default ? 1 : 0;
895 strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH - 1);
896 c->enqueue_and_wait(omsg);
897 if (!mirror_mode_ && (msg != NULL)) {
898 msg->unref();
899 msg = NULL;
900 }
901 mutex->unlock();
902}
903
904void
906{
907 erase_internal(path, /*default */ false);
908}
909
910void
912{
913 erase_internal(path, /*default */ true);
914}
915
916/** We are no longer registered in Fawkes network client.
917 * Ignored.
918 * @param id the id of the calling client
919 */
920void
921NetworkConfiguration::deregistered(unsigned int id) noexcept
922{
923}
924
925void
927{
928 if (m->cid() == FAWKES_CID_CONFIGMANAGER) {
929 if (mirror_mode_) {
930 switch (m->msgid()) {
931 case MSG_CONFIG_LIST:
932 // put all values into mirror database
933 {
934 //mirror_config->transaction_begin();
935 ConfigListContent *clc = m->msgc<ConfigListContent>();
936 while (clc->has_next()) {
937 size_t cle_size = 0;
938 config_list_entity_header_t *cle = clc->next(&cle_size);
939 switch (cle->type) {
940 case MSG_CONFIG_FLOAT_VALUE: {
941 float *msg_values = (float *)((char *)cle + sizeof(config_list_entity_header_t));
942 if (cle->cp.num_values > 0) {
943 std::vector<float> values(cle->cp.num_values, 0);
944 for (volatile unsigned int j = 0; j < cle->cp.num_values; ++j) {
945 values[j] = msg_values[j];
946 }
947 mirror_config->set_floats(cle->cp.path, values);
948 } else {
949 if (cle->cp.is_default) {
950 mirror_config->set_default_float(cle->cp.path, *msg_values);
951 } else {
952 mirror_config->set_float(cle->cp.path, *msg_values);
953 }
954 }
955 } break;
956
957 case MSG_CONFIG_INT_VALUE: {
958 int32_t *msg_values = (int32_t *)((char *)cle + sizeof(config_list_entity_header_t));
959 if (cle->cp.num_values > 0) {
960 std::vector<int32_t> values(cle->cp.num_values, 0);
961 for (volatile unsigned int j = 0; j < cle->cp.num_values; ++j) {
962 values[j] = msg_values[j];
963 }
964 mirror_config->set_ints(cle->cp.path, values);
965 } else {
966 if (cle->cp.is_default) {
967 mirror_config->set_default_int(cle->cp.path, *msg_values);
968 } else {
969 mirror_config->set_int(cle->cp.path, *msg_values);
970 }
971 }
972 } break;
973
974 case MSG_CONFIG_UINT_VALUE: {
975 uint32_t *msg_values =
976 (uint32_t *)((char *)cle + sizeof(config_list_entity_header_t));
977 if (cle->cp.num_values > 0) {
978 std::vector<uint32_t> values(cle->cp.num_values, 0);
979 for (volatile unsigned int j = 0; j < cle->cp.num_values; ++j) {
980 values[j] = msg_values[j];
981 }
982 mirror_config->set_uints(cle->cp.path, values);
983 } else {
984 if (cle->cp.is_default) {
985 mirror_config->set_default_uint(cle->cp.path, *msg_values);
986 } else {
987 mirror_config->set_uint(cle->cp.path, *msg_values);
988 }
989 }
990 } break;
991
992 case MSG_CONFIG_BOOL_VALUE: {
993 int32_t *msg_values = (int32_t *)((char *)cle + sizeof(config_list_entity_header_t));
994 if (cle->cp.num_values > 0) {
995 std::vector<bool> values(cle->cp.num_values, 0);
996 for (volatile unsigned int j = 0; j < cle->cp.num_values; ++j) {
997 values[j] = (msg_values[j] != 0);
998 }
999 mirror_config->set_bools(cle->cp.path, values);
1000 } else {
1001 if (cle->cp.is_default) {
1002 mirror_config->set_default_bool(cle->cp.path, (*msg_values != 0));
1003 } else {
1004 mirror_config->set_bool(cle->cp.path, (*msg_values != 0));
1005 }
1006 }
1007 } break;
1008
1009 case MSG_CONFIG_STRING_VALUE: {
1010 char *tmpdata = (char *)cle + sizeof(config_list_entity_header_t);
1011 if (cle->cp.num_values > 0) {
1012 std::vector<std::string> values(cle->cp.num_values, "");
1013 for (volatile unsigned int j = 0; j < cle->cp.num_values; ++j) {
1015 char * msg_string = tmpdata + sizeof(config_string_value_t);
1016 values[j] = std::string(msg_string, csv->s_length);
1017 tmpdata += sizeof(config_string_value_t) + csv->s_length + 1;
1018 }
1019 mirror_config->set_strings(cle->cp.path, values);
1020 } else {
1022 char * msg_string = tmpdata + sizeof(config_string_value_t);
1023 if (cle->cp.is_default) {
1024 mirror_config->set_default_string(cle->cp.path,
1025 std::string(msg_string, csv->s_length).c_str());
1026 } else {
1027 mirror_config->set_string(cle->cp.path,
1028 std::string(msg_string, csv->s_length).c_str());
1029 }
1030 }
1031 } break;
1032
1033 case MSG_CONFIG_COMMENT_VALUE:
1034 // ignored
1035 break;
1036 }
1037 }
1038 //mirror_config->transaction_commit();
1039 delete clc;
1040 }
1041
1042 // add all change handlers
1043 for (ChangeHandlerMultimap::const_iterator j = _change_handlers.begin();
1044 j != _change_handlers.end();
1045 ++j) {
1046 _ch_range = _change_handlers.equal_range((*j).first);
1047 for (ChangeHandlerMultimap::const_iterator i = _ch_range.first; i != _ch_range.second;
1048 ++i) {
1049 mirror_config->add_change_handler((*i).second);
1050 }
1051 }
1052 // initial answer received -> wake up set_mirror_mode()
1053 if (mirror_init_waiting_) {
1054 mirror_init_barrier_->wait();
1055 }
1056 break;
1057
1058 case MSG_CONFIG_VALUE_ERASED:
1059 try {
1061 if (em->cp.is_default == 1) {
1062 mirror_config->erase_default(em->cp.path);
1063 } else {
1064 mirror_config->erase(em->cp.path);
1065 }
1066 } catch (Exception &e) {
1067 // Just ignore silently
1068 LibLogger::log_warn("NetworkConfiguration",
1069 "[mirroring]::inboundReceived: erasing failed");
1070 }
1071 break;
1072
1073 case MSG_CONFIG_FLOAT_VALUE:
1074 try {
1075 config_descriptor_t *cd = m->msgge<config_descriptor_t>();
1076 if (cd->num_values > 0) {
1077 float * fs = (float *)((char *)msg->payload() + sizeof(config_descriptor_t));
1078 std::vector<float> floats(cd->num_values, 0.0);
1079 for (unsigned int i = 0; i < cd->num_values; ++i) {
1080 floats[i] = fs[i];
1081 }
1082 mirror_config->set_floats(cd->path, floats);
1083 } else {
1084 float f = *(float *)((char *)msg->payload() + sizeof(config_descriptor_t));
1085 if (cd->is_default == 1) {
1086 mirror_config->set_default_float(cd->path, f);
1087 } else {
1088 mirror_config->set_float(cd->path, f);
1089 }
1090 }
1091 } catch (TypeMismatchException &e) {
1092 // Just ignore silently
1093 LibLogger::log_warn("NetworkConfiguration",
1094 "[mirroring]::inboundReceived: invalid float received");
1095 }
1096 break;
1097
1098 case MSG_CONFIG_UINT_VALUE:
1099 try {
1100 config_descriptor_t *cd = m->msgge<config_descriptor_t>();
1101 if (cd->num_values > 0) {
1102 uint32_t *vs = (uint32_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
1103 std::vector<unsigned int> values(cd->num_values, 0);
1104 for (unsigned int i = 0; i < cd->num_values; ++i) {
1105 values[i] = vs[i];
1106 }
1107 mirror_config->set_uints(cd->path, values);
1108 } else {
1109 unsigned int u = *(uint32_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
1110
1111 if (cd->is_default == 1) {
1112 mirror_config->set_default_uint(cd->path, u);
1113 } else {
1114 mirror_config->set_uint(cd->path, u);
1115 }
1116 }
1117 } catch (TypeMismatchException &e) {
1118 // Just ignore silently
1119 LibLogger::log_warn("NetworkConfiguration",
1120 "[mirroring]::inboundReceived: invalid uint received");
1121 }
1122 break;
1123
1124 case MSG_CONFIG_INT_VALUE:
1125 try {
1126 config_descriptor_t *cd = m->msgge<config_descriptor_t>();
1127 if (cd->num_values > 0) {
1128 int32_t * vs = (int32_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
1129 std::vector<int> values(cd->num_values, 0);
1130 for (unsigned int i = 0; i < cd->num_values; ++i) {
1131 values[i] = vs[i];
1132 }
1133 mirror_config->set_ints(cd->path, values);
1134 } else {
1135 unsigned int i = *(int32_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
1136
1137 if (cd->is_default == 1) {
1138 mirror_config->set_default_int(cd->path, i);
1139 } else {
1140 mirror_config->set_int(cd->path, i);
1141 }
1142 }
1143 } catch (TypeMismatchException &e) {
1144 // Just ignore silently
1145 LibLogger::log_warn("NetworkConfiguration",
1146 "[mirroring]::inboundReceived: invalid int received");
1147 }
1148 break;
1149
1150 case MSG_CONFIG_BOOL_VALUE:
1151 try {
1152 config_descriptor_t *cd = m->msgge<config_descriptor_t>();
1153 if (cd->num_values > 0) {
1154 int32_t *vs = (int32_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
1155 std::vector<bool> values(cd->num_values, 0);
1156 for (unsigned int i = 0; i < cd->num_values; ++i) {
1157 values[i] = (vs[i] != 0);
1158 }
1159 mirror_config->set_bools(cd->path, values);
1160 } else {
1161 unsigned int i = *(int32_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
1162
1163 if (cd->is_default == 1) {
1164 mirror_config->set_default_bool(cd->path, (i != 0));
1165 } else {
1166 mirror_config->set_bool(cd->path, (i != 0));
1167 }
1168 }
1169 } catch (TypeMismatchException &e) {
1170 // Just ignore silently
1171 LibLogger::log_warn("NetworkConfiguration",
1172 "[mirroring]::inboundReceived: invalid bool received");
1173 }
1174 break;
1175
1176 case MSG_CONFIG_STRING_VALUE:
1177 try {
1178 config_descriptor_t *cd = m->msgge<config_descriptor_t>();
1179 if (cd->num_values > 0) {
1180 std::vector<std::string> values(cd->num_values, "");
1181 size_t pos = sizeof(config_descriptor_t);
1182 for (unsigned int i = 0; i < cd->num_values; ++i) {
1183 config_string_value_t *vs = (config_string_value_t *)((char *)msg->payload() + pos);
1184 char *msg_string = ((char *)msg->payload() + pos) + sizeof(config_string_value_t);
1185 values[i] = std::string(msg_string, vs->s_length);
1186 pos += sizeof(config_string_value_t) + vs->s_length + 1;
1187 }
1188 mirror_config->set_strings(cd->path, values);
1189 } else {
1191 (config_string_value_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
1192 char *msg_string = (char *)msg->payload() + sizeof(config_string_value_t);
1193
1194 std::string value = std::string(msg_string, sv->s_length);
1195 if (cd->is_default == 1) {
1196 mirror_config->set_default_string(cd->path, value);
1197 } else {
1198 mirror_config->set_string(cd->path, value);
1199 }
1200 }
1201 } catch (TypeMismatchException &e) {
1202 // Just ignore silently
1203 LibLogger::log_warn("NetworkConfiguration",
1204 "[mirroring]::inboundReceived: invalid string received");
1205 }
1206 break;
1207
1208 case MSG_CONFIG_COMMENT_VALUE:
1209 try {
1211 if (cm->cp.is_default == 1) {
1212 mirror_config->set_default_comment(cm->cp.path, cm->s);
1213 } else {
1214 mirror_config->set_comment(cm->cp.path, cm->s);
1215 }
1216 } catch (TypeMismatchException &e) {
1217 // Just ignore silently
1218 LibLogger::log_warn("NetworkConfiguration",
1219 "[mirroring]::inboundReceived: invalid string received");
1220 }
1221 break;
1222 }
1223 } else {
1224 msg = m;
1225 msg->ref();
1226 }
1227 }
1228}
1229
1230void
1232{
1233 connected_ = false;
1234 mirror_mode_before_connection_dead_ = mirror_mode_;
1235 set_mirror_mode(false);
1236 mutex->unlock(); //Just in case...
1237}
1238
1239void
1241{
1242 connected_ = true;
1243 set_mirror_mode(mirror_mode_before_connection_dead_);
1244}
1245
1246void
1248{
1250
1251 if (mirror_mode_) {
1252 mirror_config->add_change_handler(h);
1253 }
1254}
1255
1256void
1258{
1260 if (mirror_mode_) {
1261 mirror_config->rem_change_handler(h);
1262 }
1263}
1264
1265/** Enable or disable mirror mode.
1266 * @param mirror true to enable mirror mode, false to disable
1267 */
1268void
1270{
1271 if (mirror) {
1272 if (!mirror_mode_) {
1273 if (!connected_) {
1274 throw CannotEnableMirroringException("Client connection is dead");
1275 }
1276
1277 mirror_config = new MemoryConfiguration();
1278
1279 mirror_init_waiting_ = true;
1280 mutex->lock();
1281
1282 mirror_mode_ = true;
1283
1284 // subscribe
1285 FawkesNetworkMessage *omsg =
1286 new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER, MSG_CONFIG_SUBSCRIBE);
1287 c->enqueue(omsg);
1288
1289 // wait until all data has been received (or timeout)
1290 if (!mirror_init_barrier_->wait(mirror_timeout_sec_, 0)) {
1291 // timeout
1292 mirror_init_waiting_ = false;
1293 delete mirror_config;
1294 mutex->unlock();
1295 throw CannotEnableMirroringException("Didn't receive data in time");
1296 }
1297 mirror_init_waiting_ = false;
1298 mutex->unlock();
1299 }
1300 } else {
1301 if (mirror_mode_) {
1302 mirror_mode_ = false;
1303 // unsubscribe
1304 if (connected_) {
1305 FawkesNetworkMessage *omsg =
1306 new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER, MSG_CONFIG_UNSUBSCRIBE);
1307 c->enqueue(omsg);
1308 }
1309
1310 // delete local temporary mirror database
1311 delete mirror_config;
1312 }
1313 }
1314}
1315
1316void
1318{
1319 mutex->lock();
1320}
1321
1322bool
1324{
1325 return mutex->try_lock();
1326}
1327
1328void
1330{
1331 mutex->unlock();
1332}
1333
1334void
1336{
1337}
1338
1341{
1342 if (mirror_mode_) {
1343 return mirror_config->iterator();
1344 } else {
1345 throw Exception("NetworkConfiguration: Iterating only supported in mirror mode");
1346 }
1347}
1348
1349/** Iterator for all default values.
1350 * Returns an iterator that can be used to iterate over all default values in
1351 * the current default configuration. Note that this might return less paths than
1352 * available, because the values for which no default entry exists are not
1353 * returned.
1354 * @return iterator over all default values
1355 */
1358{
1359 if (mirror_mode_) {
1360 return mirror_config->iterator_default();
1361 } else {
1362 throw Exception("NetworkConfiguration: Iterating only supported in mirror mode");
1363 }
1364}
1365
1366/** Iterator for all host-specific values.
1367 * Returns an iterator that can be used to iterate over all host-specific values
1368 * in the current configuration. Note that this might return less paths than
1369 * available, because the default values for which no host-specific entry exists
1370 * are not returned.
1371 * @return iterator over all host-specific values
1372 */
1375{
1376 if (mirror_mode_) {
1377 return mirror_config->iterator_hostspecific();
1378 } else {
1379 throw Exception("NetworkConfiguration: Iterating only supported in mirror mode");
1380 }
1381}
1382
1385{
1386 if (mirror_mode_) {
1387 return mirror_config->search(path);
1388 } else {
1389 throw Exception("NetworkConfiguration: Searching only supported in mirror mode");
1390 }
1391}
1392
1393/** @class NetworkConfiguration::NetConfValueIterator <config/netconf.h>
1394 * Network configuration value iterator.
1395 * @author Tim Niemueller
1396 */
1397
1398/** Constructor.
1399 * @param i internal other iterator, for instance form local mirrored database.
1400 */
1402{
1403 // not interesting in this case, but anyway...
1404 iterated_once = false;
1405 this->i = i;
1406 msg = NULL;
1407 _path = NULL;
1408}
1409
1410/** Constructor.
1411 * Returns invalid iterator.
1412 */
1414{
1415 // not interesting in this case, but anyway...
1416 iterated_once = false;
1417 i = NULL;
1418 msg = NULL;
1419 _path = NULL;
1420}
1421
1422/** Constructor.
1423 * Internally holds a message. Only this one value is accessible.
1424 * @param m message
1425 */
1427{
1428 i = NULL;
1429 msg = NULL;
1430 iterated_once = false;
1431 _path = NULL;
1432
1433 if ((m->cid() == FAWKES_CID_CONFIGMANAGER) && (m->msgid() >= MSG_CONFIG_VALUE_BEGIN)
1434 && (m->msgid() <= MSG_CONFIG_VALUE_END)
1435 && (m->payload_size() > sizeof(config_descriptor_t))) {
1436 msg = m;
1437 msg->ref();
1438 // extract path
1439 // all messages start with config_descriptor!
1440 _path = (char *)malloc(CONFIG_MSG_PATH_LENGTH + 1);
1441 _path[CONFIG_MSG_PATH_LENGTH] = 0;
1443 strncpy(_path, cd->path, CONFIG_MSG_PATH_LENGTH);
1444 } else {
1445 // invalid value, maybe path does not exist!
1446 }
1447}
1448
1449/** Destructor. */
1451{
1452 delete i;
1453 if (msg != NULL)
1454 msg->unref();
1455 if (_path != NULL)
1456 free(_path);
1457}
1458
1459bool
1461{
1462 if (i == NULL) {
1463 if ((msg == NULL) || iterated_once) {
1464 return false;
1465 } else {
1466 iterated_once = true;
1467 return true;
1468 }
1469 } else {
1470 return i->next();
1471 }
1472}
1473
1474bool
1476{
1477 return ((i != NULL) || (msg != NULL));
1478}
1479
1480const char *
1482{
1483 if (i == NULL) {
1484 if (msg == NULL) {
1485 throw NullPointerException("You may not access path on invalid iterator");
1486 } else {
1487 return _path;
1488 }
1489 } else {
1490 return i->path();
1491 }
1492}
1493
1494const char *
1496{
1497 if (i == NULL) {
1498 if (msg == NULL) {
1499 throw NullPointerException("You may not access path on invalid iterator");
1500 }
1501
1502 switch (msg->msgid()) {
1503 case MSG_CONFIG_FLOAT_VALUE: return "float";
1504 case MSG_CONFIG_UINT_VALUE: return "unsigned int";
1505 case MSG_CONFIG_INT_VALUE: return "int";
1506 case MSG_CONFIG_BOOL_VALUE: return "bool";
1507 case MSG_CONFIG_STRING_VALUE: return "string";
1508 default: throw NullPointerException("Unknown type in NetConfValueIterator");
1509 }
1510 } else {
1511 return i->type();
1512 }
1513}
1514
1515bool
1517{
1518 if (i == NULL) {
1519 if (msg == NULL) {
1520 throw NullPointerException("You may not access value methods on invalid iterator");
1521 }
1522 return (msg->msgid() == MSG_CONFIG_FLOAT_VALUE);
1523 } else {
1524 return i->is_float();
1525 }
1526}
1527
1528bool
1530{
1531 if (i == NULL) {
1532 if (msg == NULL) {
1533 throw NullPointerException("You may not access value methods on invalid iterator");
1534 }
1535 return (msg->msgid() == MSG_CONFIG_UINT_VALUE);
1536 } else {
1537 return i->is_float();
1538 }
1539}
1540
1541bool
1543{
1544 if (i == NULL) {
1545 if (msg == NULL) {
1546 throw NullPointerException("You may not access value methods on invalid iterator");
1547 }
1548 return (msg->msgid() == MSG_CONFIG_INT_VALUE);
1549 } else {
1550 return i->is_int();
1551 }
1552}
1553
1554bool
1556{
1557 if (i == NULL) {
1558 if (msg == NULL) {
1559 throw NullPointerException("You may not access value methods on invalid iterator");
1560 }
1561 return (msg->msgid() == MSG_CONFIG_BOOL_VALUE);
1562 } else {
1563 return i->is_bool();
1564 }
1565}
1566
1567bool
1569{
1570 if (i == NULL) {
1571 if (msg == NULL) {
1572 throw NullPointerException("You may not access value methods on invalid iterator");
1573 }
1574 return (msg->msgid() == MSG_CONFIG_STRING_VALUE);
1575 } else {
1576 return i->is_string();
1577 }
1578}
1579
1580bool
1582{
1583 if (i == NULL) {
1584 if (msg == NULL) {
1585 throw NullPointerException("You may not access value methods on invalid iterator");
1586 }
1588 return cd->num_values > 0;
1589 } else {
1590 return i->is_list();
1591 }
1592}
1593
1594size_t
1596{
1597 if (i == NULL) {
1598 if (msg == NULL) {
1599 throw NullPointerException("You may not access value methods on invalid iterator");
1600 }
1602 return cd->num_values;
1603 } else {
1604 return i->get_list_size();
1605 }
1606}
1607
1608bool
1610{
1611 if (i == NULL) {
1612 if (msg == NULL) {
1613 throw NullPointerException("You may not access value methods on invalid iterator");
1614 } else {
1615 unsigned int msgid = msg->msgid();
1616 switch (msgid) {
1617 case MSG_CONFIG_FLOAT_VALUE:
1618 case MSG_CONFIG_UINT_VALUE:
1619 case MSG_CONFIG_INT_VALUE:
1620 case MSG_CONFIG_BOOL_VALUE:
1621 case MSG_CONFIG_STRING_VALUE: {
1623 return cd->is_default;
1624 }
1625 }
1626
1627 throw TypeMismatchException("NetworkConfiguration: Neither in mirror mode nor "
1628 "iterator to value message");
1629 }
1630 } else {
1631 return i->is_default();
1632 }
1633}
1634
1635float
1637{
1638 if (i == NULL) {
1639 if (msg == NULL) {
1640 throw NullPointerException("You may not access value methods on invalid iterator");
1641 }
1642 if (msg->msgid() == MSG_CONFIG_FLOAT_VALUE) {
1644 if (cd->num_values > 0) {
1645 throw TypeMismatchException("NetConfValueIterator::get_float: list received");
1646 }
1647 return *(float *)((char *)msg->payload() + sizeof(config_descriptor_t));
1648 } else {
1649 throw TypeMismatchException("NetConfValueIterator::get_float: type mismatch");
1650 }
1651 } else {
1652 return i->get_float();
1653 }
1654}
1655
1656unsigned int
1658{
1659 if (i == NULL) {
1660 if (msg == NULL) {
1661 throw NullPointerException("You may not access value methods on invalid iterator");
1662 }
1663 if (msg->msgid() == MSG_CONFIG_UINT_VALUE) {
1665 if (cd->num_values > 0) {
1666 throw TypeMismatchException("NetConfValueIterator::get_uint: list received");
1667 }
1668 return *(uint32_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
1669 } else {
1670 throw TypeMismatchException("NetConfValueIterator::get_uint: type mismatch");
1671 }
1672 } else {
1673 return i->get_int();
1674 }
1675}
1676
1677int
1679{
1680 if (i == NULL) {
1681 if (msg == NULL) {
1682 throw NullPointerException("You may not access value methods on invalid iterator");
1683 }
1684 if (msg->msgid() == MSG_CONFIG_INT_VALUE) {
1686 if (cd->num_values > 0) {
1687 throw TypeMismatchException("NetConfValueIterator::get_int: list received");
1688 }
1689 return *(int32_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
1690 } else {
1691 throw TypeMismatchException("NetConfValueIterator::get_int: type mismatch");
1692 }
1693 } else {
1694 return i->get_int();
1695 }
1696}
1697
1698bool
1700{
1701 if (i == NULL) {
1702 if (msg == NULL) {
1703 throw NullPointerException("You may not access value methods on invalid iterator");
1704 }
1705 if (msg->msgid() == MSG_CONFIG_BOOL_VALUE) {
1707 if (cd->num_values > 0) {
1708 throw TypeMismatchException("NetConfValueIterator::get_int: list received");
1709 }
1710 return (*(int32_t *)((char *)msg->payload() + sizeof(config_descriptor_t)) != 0);
1711 } else {
1712 throw TypeMismatchException("NetConfValueIterator::get_bool: type mismatch");
1713 }
1714 } else {
1715 return i->get_bool();
1716 }
1717}
1718
1719std::string
1721{
1722 if (i == NULL) {
1723 if (msg == NULL) {
1724 throw NullPointerException("You may not access value methods on invalid iterator");
1725 }
1726 if (msg->msgid() == MSG_CONFIG_STRING_VALUE) {
1728 if (cd->num_values > 0) {
1729 throw TypeMismatchException("NetConfValueIterator::get_int: list received");
1730 }
1732 (config_string_value_t *)((char *)msg->payload() + sizeof(config_descriptor_t));
1733 char *msg_string =
1734 (char *)msg->payload() + sizeof(config_descriptor_t) + sizeof(config_string_value_t);
1735 return std::string(msg_string, sv->s_length);
1736 } else {
1738 "NetConfValueIterator::get_string: type mismatch, expected %u, got %u",
1739 MSG_CONFIG_STRING_VALUE,
1740 msg->msgid());
1741 }
1742 } else {
1743 return i->get_string();
1744 }
1745}
1746
1747std::vector<float>
1749{
1750 if (i == NULL) {
1751 if (msg == NULL) {
1752 throw NullPointerException("You may not access value methods on invalid iterator");
1753 }
1754 if (msg->msgid() == MSG_CONFIG_FLOAT_VALUE) {
1756 if (cd->num_values <= 1) {
1757 throw TypeMismatchException("NetConfValueIterator::get_floats: not a list");
1758 }
1759 float * data = (float *)((char *)cd + sizeof(config_descriptor_t));
1760 std::vector<float> rv(cd->num_values, 0);
1761
1762 for (unsigned int j = 0; j < cd->num_values; ++j) {
1763 rv[j] = data[j];
1764 }
1765 return rv;
1766 } else {
1768 "NetConfValueIterator::get_string: type mismatch, expected %u, got %u",
1769 MSG_CONFIG_STRING_VALUE,
1770 msg->msgid());
1771 }
1772 } else {
1773 return i->get_floats();
1774 }
1775}
1776
1777std::vector<unsigned int>
1779{
1780 if (i == NULL) {
1781 if (msg == NULL) {
1782 throw NullPointerException("You may not access value methods on invalid iterator");
1783 }
1784 if (msg->msgid() == MSG_CONFIG_UINT_VALUE) {
1786 if (cd->num_values <= 1) {
1787 throw TypeMismatchException("NetConfValueIterator::get_uints: not a list");
1788 }
1789 uint32_t * data = (uint32_t *)((char *)cd + sizeof(config_descriptor_t));
1790 std::vector<unsigned int> rv(cd->num_values, 0);
1791
1792 for (unsigned int j = 0; j < cd->num_values; ++j) {
1793 rv[j] = data[j];
1794 }
1795 return rv;
1796 } else {
1798 "NetConfValueIterator::get_string: type mismatch, expected %u, got %u",
1799 MSG_CONFIG_STRING_VALUE,
1800 msg->msgid());
1801 }
1802 } else {
1803 return i->get_uints();
1804 }
1805}
1806
1807std::vector<int>
1809{
1810 if (i == NULL) {
1811 if (msg == NULL) {
1812 throw NullPointerException("You may not access value methods on invalid iterator");
1813 }
1814 if (msg->msgid() == MSG_CONFIG_INT_VALUE) {
1816 if (cd->num_values <= 1) {
1817 throw TypeMismatchException("NetConfValueIterator::get_ints: not a list");
1818 }
1819 int32_t * data = (int32_t *)((char *)cd + sizeof(config_descriptor_t));
1820 std::vector<int> rv(cd->num_values, 0);
1821
1822 for (unsigned int j = 0; j < cd->num_values; ++j) {
1823 rv[j] = data[j];
1824 }
1825 return rv;
1826 } else {
1828 "NetConfValueIterator::get_string: type mismatch, expected %u, got %u",
1829 MSG_CONFIG_STRING_VALUE,
1830 msg->msgid());
1831 }
1832 } else {
1833 return i->get_ints();
1834 }
1835}
1836
1837std::vector<bool>
1839{
1840 if (i == NULL) {
1841 if (msg == NULL) {
1842 throw NullPointerException("You may not access value methods on invalid iterator");
1843 }
1844 if (msg->msgid() == MSG_CONFIG_INT_VALUE) {
1846 if (cd->num_values <= 1) {
1847 throw TypeMismatchException("NetConfValueIterator::get_ints: not a list");
1848 }
1849 int32_t * data = (int32_t *)((char *)cd + sizeof(config_descriptor_t));
1850 std::vector<bool> rv(cd->num_values, 0);
1851
1852 for (unsigned int j = 0; j < cd->num_values; ++j) {
1853 rv[j] = (data[j] != 0);
1854 }
1855 return rv;
1856 } else {
1858 "NetConfValueIterator::get_string: type mismatch, expected %u, got %u",
1859 MSG_CONFIG_STRING_VALUE,
1860 msg->msgid());
1861 }
1862 } else {
1863 return i->get_bools();
1864 }
1865}
1866
1867std::vector<std::string>
1869{
1870 if (i == NULL) {
1871 if (msg == NULL) {
1872 throw NullPointerException("You may not access value methods on invalid iterator");
1873 }
1874 if (msg->msgid() == MSG_CONFIG_STRING_VALUE) {
1876 if (cd->num_values <= 1) {
1877 throw TypeMismatchException("NetConfValueIterator::get_strings: not a list");
1878 }
1879 std::vector<std::string> rv(cd->num_values, "");
1880 char * tmpdata = (char *)cd + sizeof(config_descriptor_t);
1881
1882 for (unsigned int j = 0; j < cd->num_values; ++j) {
1884 char * msg_string = tmpdata + sizeof(config_string_value_t);
1885 rv[j] = std::string(msg_string, sv->s_length);
1886 tmpdata += sizeof(config_string_value_t) + sv->s_length + 1;
1887 }
1888 return rv;
1889 } else {
1891 "NetConfValueIterator::get_string: type mismatch, expected %u, got %u",
1892 MSG_CONFIG_STRING_VALUE,
1893 msg->msgid());
1894 }
1895 } else {
1896 return i->get_strings();
1897 }
1898}
1899
1900std::string
1902{
1903 if (i == NULL) {
1904 if (msg == NULL) {
1905 throw NullPointerException("You may not access value methods on "
1906 "invalid iterator");
1907 }
1908 if (msg->msgid() == MSG_CONFIG_STRING_VALUE) {
1909 return get_string();
1910 } else if (msg->msgid() == MSG_CONFIG_BOOL_VALUE) {
1911 return get_bool() ? "true" : "false";
1912 } else if (msg->msgid() == MSG_CONFIG_INT_VALUE) {
1914 } else if (msg->msgid() == MSG_CONFIG_UINT_VALUE) {
1916 } else if (msg->msgid() == MSG_CONFIG_FLOAT_VALUE) {
1918 } else {
1919 throw Exception("NetConfValueIterator::get_as_string: unknown type");
1920 }
1921 } else {
1922 return i->get_as_string();
1923 }
1924}
1925
1926std::string
1928{
1929 if (i == NULL) {
1930 if (msg == NULL) {
1931 throw NullPointerException("You may not access value methods on invalid iterator");
1932 }
1933 if (msg->msgid() == MSG_CONFIG_COMMENT_VALUE) {
1935 return cm->s;
1936 } else {
1937 throw TypeMismatchException("NetConfValueIterator::get_comment: type mismatch");
1938 }
1939 } else {
1940 return i->get_comment();
1941 }
1942}
1943
1944} // end namespace fawkes
Thrown if enabling mirror mode failed.
Definition: netconf.h:44
CannotEnableMirroringException(const char *msg)
Constructor.
Definition: netconf.cpp:51
Config list content.
bool has_next()
Check if more list elements are available.
config_list_entity_header_t * next(size_t *size)
Get next plugin from list.
Interface for configuration change handling.
Iterator interface to iterate over config values.
Definition: config.h:75
virtual bool is_uint() const =0
Check if current value is a unsigned int.
virtual const char * path() const =0
Path of value.
virtual bool get_bool() const =0
Get bool value.
virtual unsigned int get_uint() const =0
Get unsigned int value.
virtual bool next()=0
Check if there is another element and advance to this if possible.
virtual float get_float() const =0
Get float value.
virtual bool is_float() const =0
Check if current value is a float.
virtual bool is_int() const =0
Check if current value is a int.
virtual bool is_default() const =0
Check if current value was read from the default config.
virtual bool is_string() const =0
Check if current value is a string.
virtual bool is_bool() const =0
Check if current value is a bool.
virtual int get_int() const =0
Get int value.
virtual bool valid() const =0
Check if the current element is valid.
virtual const char * type() const =0
Type of value.
virtual std::string get_string() const =0
Get string value.
Interface for configuration handling.
Definition: config.h:68
virtual ValueIterator * iterator()=0
Iterator for all values.
virtual void rem_change_handler(ConfigurationChangeHandler *h)
Remove a configuration change handler.
Definition: config.cpp:619
virtual void lock()=0
Lock the config.
virtual void unlock()=0
Unlock the config.
virtual void add_change_handler(ConfigurationChangeHandler *h)
Add a configuration change handler.
Definition: config.cpp:603
Thrown if the connection died during an operation.
Definition: exceptions.h:32
Base class for exceptions in Fawkes.
Definition: exception.h:36
void append(const char *format,...) noexcept
Append messages to the message list.
Definition: exception.cpp:333
Simple Fawkes network client.
Definition: client.h:52
void register_handler(FawkesNetworkClientHandler *handler, unsigned int component_id)
Register handler.
Definition: client.cpp:658
void enqueue_and_wait(FawkesNetworkMessage *message, unsigned int timeout_sec=15)
Enqueue message to send and wait for answer.
Definition: client.cpp:614
void deregister_handler(unsigned int component_id)
Deregister handler.
Definition: client.cpp:676
bool connected() const noexcept
Check if connection is alive.
Definition: client.cpp:828
void enqueue(FawkesNetworkMessage *message)
Enqueue message to send.
Definition: client.cpp:596
Representation of a message that is sent over the network.
Definition: message.h:77
unsigned short int msgid() const
Get message type ID.
Definition: message.cpp:294
unsigned short int cid() const
Get component ID.
Definition: message.cpp:285
MT * msgge() const
Get correctly casted payload.
Definition: message.h:139
void * payload() const
Get payload buffer.
Definition: message.cpp:312
size_t payload_size() const
Get payload size.
Definition: message.cpp:303
A barrier is a synchronization tool which blocks until a given number of threads have reached the bar...
bool wait(unsigned int timeout_sec, unsigned int timeout_nanosec)
Wait for other threads.
static void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: liblogger.cpp:156
In-memory configuration store.
Definition: memory.h:39
ValueIterator * search(const char *path)
Iterator with search results.
Definition: memory.cpp:525
virtual bool get_bool(const char *path)
Get value from configuration which is of type bool.
Definition: memory.cpp:147
ValueIterator * iterator_hostspecific()
Get iterator over host-specific values.
Definition: memory.cpp:506
virtual std::string get_default_comment(const char *path)
Get comment of value at given path.
Definition: memory.cpp:245
ValueIterator * iterator()
Iterator for all values.
Definition: memory.cpp:473
ValueIterator * iterator_default()
Get iterator over default values.
Definition: memory.cpp:484
virtual std::string get_string(const char *path)
Get value from configuration which is of type string.
Definition: memory.cpp:153
virtual unsigned int get_uint(const char *path)
Get value from configuration which is of type unsigned int.
Definition: memory.cpp:135
virtual std::string get_type(const char *path)
Get type of value at given path.
Definition: memory.cpp:76
virtual float get_float(const char *path)
Get value from configuration which is of type float.
Definition: memory.cpp:129
virtual std::string get_comment(const char *path)
Get comment of value at given path.
Definition: memory.cpp:87
virtual ValueIterator * get_value(const char *path)
Get value from configuration.
Definition: memory.cpp:267
virtual int get_int(const char *path)
Get value from configuration which is of type int.
Definition: memory.cpp:141
Mutex mutual exclusion lock.
Definition: mutex.h:33
bool try_lock()
Tries to lock the mutex.
Definition: mutex.cpp:117
void lock()
Lock this mutex.
Definition: mutex.cpp:87
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
Network configuration value iterator.
Definition: netconf.h:123
virtual bool is_bool() const
Check if current value is a bool.
Definition: netconf.cpp:1555
virtual std::vector< float > get_floats() const
Get list of values from configuration which is of type float.
Definition: netconf.cpp:1748
virtual std::string get_as_string() const
Get value as string.
Definition: netconf.cpp:1901
virtual size_t get_list_size() const
Get number of elements in list value.
Definition: netconf.cpp:1595
virtual std::vector< unsigned int > get_uints() const
Get list of values from configuration which is of type unsigned int.
Definition: netconf.cpp:1778
virtual bool is_string() const
Check if current value is a string.
Definition: netconf.cpp:1568
virtual std::vector< bool > get_bools() const
Get list of values from configuration which is of type bool.
Definition: netconf.cpp:1838
virtual bool is_int() const
Check if current value is a int.
Definition: netconf.cpp:1542
virtual bool valid() const
Check if the current element is valid.
Definition: netconf.cpp:1475
virtual bool get_bool() const
Get bool value.
Definition: netconf.cpp:1699
virtual std::string get_string() const
Get string value.
Definition: netconf.cpp:1720
virtual float get_float() const
Get float value.
Definition: netconf.cpp:1636
virtual bool is_list() const
Check if a value is a list.
Definition: netconf.cpp:1581
virtual std::vector< std::string > get_strings() const
Get list of values from configuration which is of type string.
Definition: netconf.cpp:1868
virtual bool is_float() const
Check if current value is a float.
Definition: netconf.cpp:1516
virtual const char * type() const
Type of value.
Definition: netconf.cpp:1495
virtual std::string get_comment() const
Get comment of value.
Definition: netconf.cpp:1927
virtual bool is_uint() const
Check if current value is a unsigned int.
Definition: netconf.cpp:1529
virtual bool next()
Check if there is another element and advance to this if possible.
Definition: netconf.cpp:1460
virtual const char * path() const
Path of value.
Definition: netconf.cpp:1481
virtual unsigned int get_uint() const
Get unsigned int value.
Definition: netconf.cpp:1657
virtual std::vector< int > get_ints() const
Get list of values from configuration which is of type int.
Definition: netconf.cpp:1808
virtual int get_int() const
Get int value.
Definition: netconf.cpp:1678
virtual bool is_default() const
Check if current value was read from the default config.
Definition: netconf.cpp:1609
virtual bool is_float(const char *path)
Check if a value is of type float.
Definition: netconf.cpp:182
virtual void add_change_handler(ConfigurationChangeHandler *h)
Add a configuration change handler.
Definition: netconf.cpp:1247
ValueIterator * iterator_default()
Iterator for all default values.
Definition: netconf.cpp:1357
virtual void erase_default(const char *path)
Erase the given default value from the configuration.
Definition: netconf.cpp:911
bool try_lock()
Try to lock the config.
Definition: netconf.cpp:1323
virtual std::vector< unsigned int > get_uints(const char *path)
Get list of values from configuration which is of type unsigned int.
Definition: netconf.cpp:525
virtual std::string get_comment(const char *path)
Get comment of value at given path.
Definition: netconf.cpp:549
virtual std::string get_string(const char *path)
Get value from configuration which is of type string.
Definition: netconf.cpp:463
NetworkConfiguration(FawkesNetworkClient *c, unsigned int mirror_timeout_sec=15)
Constructor.
Definition: netconf.cpp:75
virtual int get_int(const char *path)
Get value from configuration which is of type int.
Definition: netconf.cpp:355
virtual void set_default_int(const char *path, int i)
Set new default value in configuration of type int.
Definition: netconf.cpp:761
virtual std::string get_default_comment(const char *path)
Get comment of value at given path.
Definition: netconf.cpp:598
virtual std::string get_type(const char *path)
Get type of field.
Definition: netconf.cpp:165
virtual bool exists(const char *path)
Check if a given value exists.
Definition: netconf.cpp:143
ValueIterator * iterator()
Iterator for all values.
Definition: netconf.cpp:1340
void lock()
Lock the config.
Definition: netconf.cpp:1317
virtual void erase(const char *path)
Erase the given value from the configuration.
Definition: netconf.cpp:905
void unlock()
Unlock the config.
Definition: netconf.cpp:1329
virtual void set_int(const char *path, int i)
Set new value in configuration of type int.
Definition: netconf.cpp:755
virtual void connection_established(unsigned int id) noexcept
Client has established a connection.
Definition: netconf.cpp:1240
virtual void load(const char *file_path)
Load configuration.
Definition: netconf.cpp:108
virtual bool is_list(const char *path)
Check if a value is a list.
Definition: netconf.cpp:212
ValueIterator * iterator_hostspecific()
Iterator for all host-specific values.
Definition: netconf.cpp:1374
ValueIterator * search(const char *path)
Iterator with search results.
Definition: netconf.cpp:1384
virtual unsigned int get_uint(const char *path)
Get value from configuration which is of type unsigned int.
Definition: netconf.cpp:301
virtual void set_bool(const char *path, bool b)
Set new value in configuration of type bool.
Definition: netconf.cpp:767
virtual void set_default_float(const char *path, float f)
Set new default value in configuration of type float.
Definition: netconf.cpp:737
virtual bool is_uint(const char *path)
Check if a value is of type unsigned int.
Definition: netconf.cpp:188
virtual void set_mirror_mode(bool mirror)
Enable or disable mirror mode.
Definition: netconf.cpp:1269
virtual void inbound_received(FawkesNetworkMessage *msg, unsigned int id) noexcept
Called for incoming messages.
Definition: netconf.cpp:926
virtual void set_default_string(const char *path, std::string &s)
Set new default value in configuration of type string.
Definition: netconf.cpp:816
virtual void set_default_bool(const char *path, bool b)
Set new default value in configuration of type bool.
Definition: netconf.cpp:774
virtual void set_default_uint(const char *path, unsigned int uint)
Set new default value in configuration of type unsigned int.
Definition: netconf.cpp:749
virtual void deregistered(unsigned int id) noexcept
We are no longer registered in Fawkes network client.
Definition: netconf.cpp:921
virtual bool is_bool(const char *path)
Check if a value is of type bool.
Definition: netconf.cpp:200
virtual std::vector< bool > get_bools(const char *path)
Get list of values from configuration which is of type bool.
Definition: netconf.cpp:537
virtual void set_float(const char *path, float f)
Set new value in configuration of type float.
Definition: netconf.cpp:731
virtual std::vector< std::string > get_strings(const char *path)
Get list of values from configuration which is of type string.
Definition: netconf.cpp:543
virtual void set_strings(const char *path, std::vector< std::string > &s)
Set new value in configuration of type string.
Definition: netconf.cpp:846
virtual ~NetworkConfiguration()
Destructor.
Definition: netconf.cpp:96
virtual std::vector< int > get_ints(const char *path)
Get list of values from configuration which is of type int.
Definition: netconf.cpp:531
virtual bool is_string(const char *path)
Check if a value is of type string.
Definition: netconf.cpp:206
virtual void set_comment(const char *path, std::string &comment)
Set new comment for existing value.
Definition: netconf.cpp:868
virtual bool is_default(const char *path)
Check if a value was read from the default config.
Definition: netconf.cpp:152
virtual void set_bools(const char *path, std::vector< bool > &b)
Set new value in configuration of type bool.
Definition: netconf.cpp:840
virtual void set_uints(const char *path, std::vector< unsigned int > &uint)
Set new value in configuration of type unsigned int.
Definition: netconf.cpp:828
virtual void rem_change_handler(ConfigurationChangeHandler *h)
Remove a configuration change handler.
Definition: netconf.cpp:1257
virtual void set_ints(const char *path, std::vector< int > &i)
Set new value in configuration of type int.
Definition: netconf.cpp:834
virtual void set_default_comment(const char *path, std::string &comment)
Set new default comment for existing default configuration value.
Definition: netconf.cpp:873
virtual void try_dump()
Try to dump configuration.
Definition: netconf.cpp:1335
virtual bool get_bool(const char *path)
Get value from configuration which is of type bool.
Definition: netconf.cpp:409
virtual bool is_int(const char *path)
Check if a value is of type int.
Definition: netconf.cpp:194
virtual void set_uint(const char *path, unsigned int uint)
Set new value in configuration of type unsigned int.
Definition: netconf.cpp:743
virtual float get_float(const char *path)
Get value from configuration which is of type float.
Definition: netconf.cpp:247
virtual void connection_died(unsigned int id) noexcept
Client connection died.
Definition: netconf.cpp:1231
virtual void copy(Configuration *copyconf)
Copy all values from the given configuration.
Definition: netconf.cpp:120
virtual ValueIterator * get_value(const char *path)
Get value from configuration.
Definition: netconf.cpp:648
virtual std::vector< float > get_floats(const char *path)
Get list of values from configuration which is of type float.
Definition: netconf.cpp:519
virtual void set_string(const char *path, std::string &s)
Set new value in configuration of type string.
Definition: netconf.cpp:810
virtual void set_floats(const char *path, std::vector< float > &f)
Set new value in configuration of type float.
Definition: netconf.cpp:822
Called method has not been implemented.
Definition: software.h:105
A NULL pointer was supplied where not allowed.
Definition: software.h:32
Index out of bounds.
Definition: software.h:86
void unref()
Decrement reference count and conditionally delete this instance.
Definition: refcount.cpp:95
void ref()
Increment reference count.
Definition: refcount.cpp:67
static std::string to_string(unsigned int i)
Convert unsigned int value to a string.
Fawkes library namespace.
char s[2]
comment, 0-terminated
Definition: net_messages.h:137
config_descriptor_t cp
value descriptor
Definition: net_messages.h:135
Basic config descriptor.
Definition: net_messages.h:93
uint16_t num_values
Number of valus in list.
Definition: net_messages.h:98
uint16_t is_default
1 if value is a default value, 0 otherwise, only for get response
Definition: net_messages.h:95
char path[CONFIG_MSG_PATH_LENGTH]
path to config value.
Definition: net_messages.h:94
Get value message.
Definition: net_messages.h:103
config_descriptor_t cp
value descriptor
Definition: net_messages.h:104
Config list entity header.
Definition: net_messages.h:155
uint32_t type
type of entity, uses MSG_CONFIG_*_VALUE message IDs
Definition: net_messages.h:157
config_descriptor_t cp
Config descriptor.
Definition: net_messages.h:156
String value header indicating the string length.
Definition: net_messages.h:127
uint16_t s_length
Length of following string.
Definition: net_messages.h:128
config_descriptor_t cp
value descriptor
Definition: net_messages.h:122