25#include <blackboard/blackboard.h>
26#include <blackboard/exceptions.h>
27#include <blackboard/net/handler.h>
28#include <blackboard/net/ilist_content.h>
29#include <blackboard/net/interface_listener.h>
30#include <blackboard/net/interface_observer.h>
31#include <blackboard/net/messages.h>
32#include <interface/interface.h>
33#include <interface/interface_info.h>
34#include <logging/liblogger.h>
35#include <netcomm/fawkes/component_ids.h>
36#include <netcomm/fawkes/hub.h>
56:
Thread(
"BlackBoardNetworkHandler",
Thread::OPMODE_WAITFORWAKEUP),
71 inbound_queue_.
clear();
73 for (lit_ = listeners_.begin(); lit_ != listeners_.end(); ++lit_) {
76 for (iit_ = interfaces_.begin(); iit_ != interfaces_.end(); ++iit_) {
77 bb_->
close(iit_->second);
85 while (!inbound_queue_.empty()) {
89 unsigned int clid = msg->
clid();
91 switch (msg->
msgid()) {
92 case MSG_BB_LIST_ALL: {
96 for (InterfaceInfoList::iterator i = infl->begin(); i != infl->end(); ++i) {
101 nhub_->
send(clid, FAWKES_CID_BLACKBOARD, MSG_BB_INTERFACE_LIST, ilist);
104 "Failed to send interface "
105 "list to %u, exception follows",
117 char type_pattern[INTERFACE_TYPE_SIZE_ + 1];
118 char id_pattern[INTERFACE_ID_SIZE_ + 1];
119 type_pattern[INTERFACE_TYPE_SIZE_] = 0;
120 id_pattern[INTERFACE_ID_SIZE_] = 0;
121 strncpy(type_pattern, lrm->
type_pattern, INTERFACE_TYPE_SIZE_);
122 strncpy(id_pattern, lrm->
id_pattern, INTERFACE_ID_SIZE_);
125 for (InterfaceInfoList::iterator i = infl->begin(); i != infl->end(); ++i) {
130 nhub_->
send(clid, FAWKES_CID_BLACKBOARD, MSG_BB_INTERFACE_LIST, ilist);
134 "interface list to %u, exception follows",
141 case MSG_BB_OPEN_FOR_READING:
142 case MSG_BB_OPEN_FOR_WRITING: {
145 char type[INTERFACE_TYPE_SIZE_ + 1];
146 char id[INTERFACE_ID_SIZE_ + 1];
147 type[INTERFACE_TYPE_SIZE_] = 0;
148 id[INTERFACE_ID_SIZE_] = 0;
149 strncpy(type, om->
type, INTERFACE_TYPE_SIZE_);
150 strncpy(
id, om->
id, INTERFACE_ID_SIZE_);
156 if (msg->
msgid() == MSG_BB_OPEN_FOR_READING) {
161 if (memcmp(iface->
hash(), om->
hash, INTERFACE_HASH_SIZE_) != 0) {
163 "Opening interface %s::%s failed, "
169 interfaces_[iface->
serial()] = iface;
170 client_interfaces_[clid].push_back(iface);
171 serial_to_clid_[iface->
serial()] = clid;
172 listeners_[iface->
serial()] =
174 send_opensuccess(clid, iface);
178 "Opening interface %s::%s failed, "
179 "interface class not found",
185 "Opening interface %s::%s failed, "
186 "writer already exists",
192 "Opening interface %s::%s failed",
208 if (interfaces_.find(sm_serial) != interfaces_.end()) {
210 client_interfaces_.lock();
211 if (client_interfaces_.find(clid) != client_interfaces_.end()) {
213 for (ciit_ = client_interfaces_[clid].begin(); ciit_ != client_interfaces_[clid].end();
215 if ((*ciit_)->serial() == sm_serial) {
217 serial_to_clid_.erase(sm_serial);
218 client_interfaces_[clid].erase(ciit_);
219 if (client_interfaces_[clid].empty()) {
220 client_interfaces_.erase(clid);
226 client_interfaces_.unlock();
231 "Remote %u closing interface %s",
233 interfaces_[sm_serial]->uid());
234 delete listeners_[sm_serial];
235 listeners_.erase(sm_serial);
236 bb_->
close(interfaces_[sm_serial]);
237 interfaces_.erase(sm_serial);
238 interfaces_.unlock();
241 "Client %u tried to close "
242 "interface with serial %s, but opened by other client",
244 sm_serial.get_string().c_str());
248 "Client %u tried to close "
249 "interface with serial %s which has not been opened",
251 sm_serial.get_string().c_str());
259 case MSG_BB_DATA_CHANGED:
260 case MSG_BB_DATA_REFRESHED: {
261 bool data_changed = msg->
msgid() == MSG_BB_DATA_CHANGED;
262 void * payload = msg->
payload();
265 if (interfaces_.find(dm_serial) != interfaces_.end()) {
266 if (ntohl(dm->
data_size) != interfaces_[dm_serial]->datasize()) {
268 "%s: Data size mismatch, expected %zu, but got %zu, ignoring.",
269 data_changed ?
"DATA_CHANGED" :
"DATA_REFRESHED",
270 interfaces_[dm_serial]->datasize(),
273 interfaces_[dm_serial]->set_from_chunk((
char *)payload +
sizeof(
bb_idata_msg_t));
275 interfaces_[dm_serial]->mark_data_changed();
276 interfaces_[dm_serial]->write();
280 "%s: Interface with "
281 "serial %s not found, ignoring.",
282 data_changed ?
"DATA_CHANGED" :
"DATA_REFRESHED",
287 case MSG_BB_INTERFACE_MESSAGE: {
288 void * payload = msg->
payload();
292 if (interfaces_.find(mm_serial) != interfaces_.end()) {
293 if (!interfaces_[mm_serial]->is_writer()) {
301 "MESSAGE: Data size mismatch, "
302 "expected %zu, but got %zu, ignoring.",
309 "Processing message from sender %s, source %s, mm source %s",
314 interfaces_[mm_serial]->msgq_enqueue(ifm,
true);
318 "MESSAGE: Could not create "
319 "interface message, ignoring.");
324 "MESSAGE: Received message "
325 "notification, but for a writing instance, ignoring.");
329 "DATA_CHANGED: Interface with "
330 "serial %s not found, ignoring.",
337 "Unknown message of type %u "
349BlackBoardNetworkHandler::send_opensuccess(
unsigned int clid,
Interface *interface)
366 memcpy((
char *)payload +
sizeof(bb_iopensucc_msg_t),
370 FawkesNetworkMessage *omsg =
371 new FawkesNetworkMessage(clid,
372 FAWKES_CID_BLACKBOARD,
375 sizeof(bb_iopensucc_msg_t) + interface->
datasize());
378 }
catch (Exception &e) {
380 "Failed to send interface "
381 "open success to %u, exception follows",
388BlackBoardNetworkHandler::send_openfailure(
unsigned int clid,
unsigned int error_code)
390 bb_iopenfail_msg_t *ofm = (bb_iopenfail_msg_t *)malloc(
sizeof(bb_iopenfail_msg_t));
391 ofm->error_code = htonl(error_code);
393 FawkesNetworkMessage *omsg =
new FawkesNetworkMessage(
394 clid, FAWKES_CID_BLACKBOARD, MSG_BB_OPEN_FAILURE, ofm,
sizeof(bb_iopenfail_msg_t));
397 }
catch (Exception &e) {
399 "Failed to send interface "
400 "open failure to %u, exception follows",
434 client_interfaces_.lock();
435 if (client_interfaces_.find(clid) != client_interfaces_.end()) {
437 for (ciit_ = client_interfaces_[clid].begin(); ciit_ != client_interfaces_[clid].end();
440 "Closing interface %s::%s of remote "
441 "%u (client disconnected)",
446 Uuid serial = (*ciit_)->serial();
447 serial_to_clid_.erase(serial);
448 interfaces_.erase_locked(serial);
449 delete listeners_[serial];
450 listeners_.erase(serial);
453 client_interfaces_.erase(clid);
455 client_interfaces_.unlock();
BlackBoard interface list content.
void append_interface(const char *type, const char *id, const unsigned char *hash, unsigned int serial, bool has_writer, unsigned int num_readers, const fawkes::Time &time)
Append interface info.
Thrown if no definition of interface or interface generator found.
Interface listener for network handler.
Interface observer for blackboard network handler.
virtual void client_connected(unsigned int clid)
Client connected.
virtual void client_disconnected(unsigned int clid)
Client disconnected.
~BlackBoardNetworkHandler()
Destructor.
virtual void handle_network_message(FawkesNetworkMessage *msg)
Handle network message.
virtual void loop()
Process all network messages that have been received.
BlackBoardNetworkHandler(BlackBoard *blackboard, FawkesNetworkHub *hub)
Constructor.
Thrown if a writer is already active on an interface that writing has been requested for.
The BlackBoard abstract class.
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
virtual InterfaceInfoList * list_all()=0
Get list of all currently existing interfaces.
virtual InterfaceInfoList * list(const char *type_pattern, const char *id_pattern)=0
Get list of interfaces matching type and ID patterns.
virtual Interface * open_for_writing(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for writing.
virtual void close(Interface *interface)=0
Close interface.
Base class for exceptions in Fawkes.
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.
Interface information list.
Base class for all Fawkes BlackBoard interfaces.
const void * datachunk() const
Get data chunk.
bool is_writer() const
Check if this is a writing instance.
const unsigned char * hash() const
Get interface hash.
Uuid serial() const
Get instance serial of interface.
unsigned int num_readers() const
Get the number of readers.
void read()
Read from BlackBoard into local copy.
unsigned int datasize() const
Get data size.
bool has_writer() const
Check if there is a writer for the interface.
static void log_warn(const char *component, const char *format,...)
Log warning message.
static void log_error(const char *component, const char *format,...)
Log error message.
static void log_debug(const char *component, const char *format,...)
Log debug message.
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.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
unsigned int datasize() const
Get size of data.
Uuid source_id() const
Get ID of the original source of the message.
void set_source_id(const Uuid &id)
Set source ID.
void set_from_chunk(const void *chunk)
Set from raw data chunk.
void set_id(unsigned int message_id)
Set message ID.
Uuid sender_id() const
Get ID of the immediate sender, not necessarily the creator of the message.
void set_hops(unsigned int hops)
Set number of hops.
void unref()
Decrement reference count and conditionally delete this instance.
void ref()
Increment reference count.
Thread class encapsulation of pthreads.
void wakeup()
Wake up thread.
A convenience class for universally unique identifiers (UUIDs).
std::string get_string() const
Get the string representation of the Uuid.
Fawkes library namespace.
@ BB_ERR_UNKNOWN_ERR
Unknown error occured.
@ BB_ERR_WRITER_EXISTS
You tried to open an interface for writing but there is already a writing instance for this interface...
@ BB_ERR_HASH_MISMATCH
The hashes of the interfaces do not match.
@ BB_ERR_UNKNOWN_TYPE
Requested interface type is unknown.
uint32_t data_size
size in bytes of the following data.
Uuid serial
instance serial to unique identify this instance
Message to request constrained interface list.
char type_pattern[INTERFACE_TYPE_SIZE_]
type pattern
char id_pattern[INTERFACE_ID_SIZE_]
ID pattern.
Uuid serial
interface instance serial
Uuid source
serial of the original message source
uint32_t data_size
data for message
char msg_type[INTERFACE_MESSAGE_TYPE_SIZE_]
message type
uint32_t hops
number of hops this message already passed
Message to identify an interface on open.
char id[INTERFACE_ID_SIZE_]
interface instance ID
unsigned char hash[INTERFACE_HASH_SIZE_]
interface version hash
char type[INTERFACE_TYPE_SIZE_]
interface type name
Interface open success The serial denotes a unique instance of an interface within the (remote) Black...
Uuid serial
instance serial to unique identify this instance
uint32_t data_size
size in bytes of the following data.
uint32_t writer_readers
combined writer reader information.
Message to identify an interface instance.
Uuid serial
instance serial to unique identify this instance