24 #include <blackboard/remote.h>
25 #include <blackboard/exceptions.h>
26 #include <blackboard/net/messages.h>
27 #include <blackboard/net/ilist_content.h>
28 #include <blackboard/net/interface_proxy.h>
29 #include <blackboard/internal/notifier.h>
30 #include <blackboard/internal/instance_factory.h>
32 #include <interface/interface_info.h>
34 #include <core/threading/thread.h>
35 #include <core/threading/mutex.h>
36 #include <core/threading/mutex_locker.h>
37 #include <core/threading/wait_condition.h>
38 #include <netcomm/fawkes/client.h>
43 #include <arpa/inet.h>
64 throw Exception(
"Cannot instantiate RemoteBlackBoard on unconnected client");
69 __mutex =
new Mutex();
72 __wait_mutex =
new Mutex();
75 __inbound_thread = NULL;
99 throw Exception(
"Cannot instantiate RemoteBlackBoard on unconnected client");
104 __mutex =
new Mutex();
107 __wait_mutex =
new Mutex();
110 __inbound_thread = NULL;
120 delete __instance_factory;
122 for ( __pit = __proxies.begin(); __pit != __proxies.end(); ++__pit) {
123 delete __pit->second;
144 RemoteBlackBoard::reopen_interfaces()
147 __ipit = __invalid_proxies.begin();
148 while ( __ipit != __invalid_proxies.end() ) {
150 Interface *iface = (*__ipit)->interface();
153 __ipit = __invalid_proxies.erase(__ipit);
154 }
catch (Exception &e) {
180 RemoteBlackBoard::open_interface(
const char *type,
const char *identifier,
184 throw Exception(
"Cannot instantiate remote interface, connection is dead");
188 if (__inbound_thread != NULL &&
192 throw Exception(
"Cannot call open_interface() from inbound handler");
196 bb_iopen_msg_t *om = (bb_iopen_msg_t *)calloc(1,
sizeof(bb_iopen_msg_t));
197 strncpy(om->type, type, __INTERFACE_TYPE_SIZE);
198 strncpy(om->id, identifier, __INTERFACE_ID_SIZE);
199 memcpy(om->hash, iface->
hash(), __INTERFACE_HASH_SIZE);
201 FawkesNetworkMessage *omsg =
new FawkesNetworkMessage(FAWKES_CID_BLACKBOARD,
202 writer ? MSG_BB_OPEN_FOR_WRITING : MSG_BB_OPEN_FOR_READING,
203 om,
sizeof(bb_iopen_msg_t));
205 __wait_mutex->
lock();
209 ((__m->
msgid() != MSG_BB_OPEN_SUCCESS) &&
210 (__m->
msgid() != MSG_BB_OPEN_FAILURE))))
221 throw Exception(
"Connection died while trying to open %s::%s",
225 if ( __m->
msgid() == MSG_BB_OPEN_SUCCESS ) {
227 BlackBoardInterfaceProxy *proxy =
new BlackBoardInterfaceProxy(__fnc, __m,
__notifier,
229 __proxies[proxy->serial()] = proxy;
230 }
else if ( __m->
msgid() == MSG_BB_OPEN_FAILURE ) {
231 bb_iopenfail_msg_t *fm = __m->
msg<bb_iopenfail_msg_t>();
232 unsigned int error = ntohl(fm->errno);
236 throw BlackBoardWriterActiveException(identifier, type);
238 throw Exception(
"Hash mismatch for interface %s:%s", type, identifier);
240 throw Exception(
"Type %s unknown (%s::%s)", type, type, identifier);
242 throw BlackBoardWriterActiveException(identifier, type);
244 throw Exception(
"Could not open interface");
253 RemoteBlackBoard::open_interface(
const char *type,
const char *identifier,
bool writer)
256 throw Exception(
"Cannot instantiate remote interface, connection is dead");
261 open_interface(type, identifier, writer, iface);
262 }
catch (Exception &e) {
274 return open_interface(type, identifier,
false);
281 return open_interface(type, identifier,
true);
285 std::list<Interface *>
287 const char *id_pattern)
289 std::list<Interface *> rv;
292 for (InterfaceInfoList::iterator i = infl->begin(); i != infl->end(); ++i) {
294 char type[__INTERFACE_TYPE_SIZE + 1];
295 char id[__INTERFACE_ID_SIZE + 1];
296 type[__INTERFACE_TYPE_SIZE] = 0;
297 id[__INTERFACE_TYPE_SIZE] = 0;
298 strncpy(type, i->type(), __INTERFACE_TYPE_SIZE);
299 strncpy(
id, i->id(), __INTERFACE_ID_SIZE);
301 if ((fnmatch(type_pattern, type, 0) == FNM_NOMATCH) ||
302 (fnmatch(id_pattern,
id, 0) == FNM_NOMATCH) ) {
311 for (std::list<Interface *>::iterator j = rv.begin(); j != rv.end(); ++j) {
328 if ( interface == NULL )
return;
330 unsigned int serial = interface->
serial();
332 if ( __proxies.find(serial) != __proxies.end() ) {
333 delete __proxies[serial];
334 __proxies.erase(serial);
356 if (__inbound_thread != NULL &&
359 throw Exception(
"Cannot call list_all() from inbound handler");
367 __wait_mutex->
lock();
370 (__m->
msgid() != MSG_BB_INTERFACE_LIST)) {
398 if (__inbound_thread != NULL &&
401 throw Exception(
"Cannot call list() from inbound handler");
409 strncpy(om->
type_pattern, type_pattern, __INTERFACE_TYPE_SIZE);
410 strncpy(om->
id_pattern, id_pattern, __INTERFACE_ID_SIZE);
417 __wait_mutex->
lock();
420 (__m->
msgid() != MSG_BB_INTERFACE_LIST)) {
457 unsigned int id)
throw()
463 if ( m->cid() == FAWKES_CID_BLACKBOARD ) {
464 unsigned int msgid = m->msgid();
466 if ( msgid == MSG_BB_DATA_CHANGED ) {
467 unsigned int serial = ntohl(((
unsigned int *)m->payload())[0]);
468 if ( __proxies.find(serial) != __proxies.end() ) {
469 __proxies[serial]->process_data_changed(m);
471 }
else if (msgid == MSG_BB_INTERFACE_MESSAGE) {
472 unsigned int serial = ntohl(((
unsigned int *)m->payload())[0]);
473 if ( __proxies.find(serial) != __proxies.end() ) {
474 __proxies[serial]->process_interface_message(m);
476 }
else if (msgid == MSG_BB_READER_ADDED) {
478 if ( __proxies.find(ntohl(esm->
serial)) != __proxies.end() ) {
481 }
else if (msgid == MSG_BB_READER_REMOVED) {
483 if ( __proxies.find(ntohl(esm->
serial)) != __proxies.end() ) {
486 }
else if (msgid == MSG_BB_WRITER_ADDED) {
488 if ( __proxies.find(ntohl(esm->
serial)) != __proxies.end() ) {
491 }
else if (msgid == MSG_BB_WRITER_REMOVED) {
493 if ( __proxies.find(ntohl(esm->
serial)) != __proxies.end() ) {
496 }
else if (msgid == MSG_BB_INTERFACE_CREATED) {
498 __notifier->notify_of_interface_created(em->
type, em->
id);
499 }
else if (msgid == MSG_BB_INTERFACE_DESTROYED) {
501 __notifier->notify_of_interface_destroyed(em->
type, em->
id);
503 __wait_mutex->lock();
506 __wait_cond->wake_all();
507 __wait_mutex->unlock();
515 __inbound_thread = NULL;
525 for (__pit = __proxies.begin(); __pit != __proxies.end(); ++__pit) {
526 __pit->second->interface()->set_validity(
false);
527 __invalid_proxies.push_back(__pit->second);
531 __wait_cond->wake_all();
uint32_t serial
instance serial to unique identify this instance
Interface * new_interface_instance(const char *type, const char *identifier)
Creates a new interface instance.
bool has_next()
Check if more list elements are available.
BlackBoard instance factory.
Wait until a given condition holds.
unsigned short serial() const
Get instance serial of interface.
Requested interface type is unknown.
Simple Fawkes network client.
void unref()
Decrement reference count and conditionally delete this instance.
char type[__INTERFACE_TYPE_SIZE]
interface type name
uint32_t num_readers
number of currently existing readers
Message to identify an two interface instances.
Fawkes library namespace.
void unlock()
Unlock the mutex.
virtual bool is_alive() const
Check if the BlackBoard is still alive.
void disconnect()
Disconnect socket.
uint32_t has_writer
1 if the interface currently has a writer, 0 otherwise
void register_handler(FawkesNetworkClientHandler *handler, unsigned int component_id)
Register handler.
void enqueue(FawkesNetworkMessage *message)
Enqueue message to send.
const unsigned char * hash() const
Get interface hash.
Representation of a message that is sent over the network.
void connect()
Connect to remote.
bb_iinfo_msg_t * next(size_t *size)
Get next plugin from list.
unsigned short int msgid() const
Get message type ID.
virtual void deregistered(unsigned int id)
We are no longer registered in Fawkes network client.
virtual void connection_established(unsigned int id)
Client has established a connection.
Base class for all Fawkes BlackBoard interfaces.
Message for interface info.
You tried to open an interface for writing but there is already a writing instance for this interface...
uint32_t event_serial
instance serial to unique identify instance that caused the event.
virtual InterfaceInfoList * list(const char *type_pattern, const char *id_pattern)
Get list of interfaces matching type and ID patterns.
const char * id() const
Get identifier of interface.
Interface information list.
char id[__INTERFACE_ID_SIZE]
interface instance ID
virtual void close(Interface *interface)
Close interface.
char id_pattern[__INTERFACE_ID_SIZE]
ID pattern.
Base class for exceptions in Fawkes.
virtual ~RemoteBlackBoard()
Destructor.
uint32_t serial
instance serial to unique identify own instance
void delete_interface_instance(Interface *interface)
Destroy an interface instance.
char type[__INTERFACE_TYPE_SIZE]
interface type name
virtual bool try_aliveness_restore()
Try to restore the aliveness of the BlackBoard instance.
virtual void inbound_received(FawkesNetworkMessage *msg, unsigned int id)
Called for incoming messages.
unsigned char hash[__INTERFACE_HASH_SIZE]
interface version hash
The hashes of the interfaces do not match.
static Thread * current_thread()
Get the Thread instance of the currently running thread.
bool connected() const
Check if connection is alive.
BlackBoardNotifier * __notifier
Notifier for BB events.
virtual void connection_died(unsigned int id)
Client connection died.
void wait()
Wait for the condition forever.
const char * name() const
Get name of thread.
MT * msgc() const
Get correctly parsed output.
virtual Interface * open_for_reading(const char *interface_type, const char *identifier)
Open interface for reading.
MT * msg() const
Get correctly casted payload.
uint32_t serial
instance serial to unique identify this instance
RemoteBlackBoard(FawkesNetworkClient *client)
Constructor.
char type_pattern[__INTERFACE_TYPE_SIZE]
type pattern
virtual InterfaceInfoList * list_all()
Get list of all currently existing interfaces.
void append(const char *type, const char *id, const unsigned char *hash, unsigned int serial, bool has_writer, unsigned int num_readers)
Append an interface info.
void deregister_handler(unsigned int component_id)
Deregister handler.
Message for interface events.
void set_validity(bool valid)
Mark this interface invalid.
Message to request constrained interface list.
BlackBoard interface list content.
Message to identify an interface instance.
void lock()
Lock this mutex.
bool is_writer() const
Check if this is a writing instance.
Mutex mutual exclusion lock.
std::list< Interface * > open_multiple_for_reading(const char *interface_type, const char *id_pattern="*")
Open multiple interfaces for reading.
char id[__INTERFACE_ID_SIZE]
interface instance ID
const char * type() const
Get type of interface.
virtual Interface * open_for_writing(const char *interface_type, const char *identifier)
Open interface for writing.