Fawkes API  Fawkes Development Version
network.cpp
1 
2 /***************************************************************************
3  * network.cpp - Fawkes network logger
4  *
5  * Created: Sat Dec 15 00:48:52 2007 (after I5 xmas party)
6  * Copyright 2006-2007 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 <logging/network.h>
25 
26 #include <core/threading/mutex.h>
27 #include <netcomm/fawkes/component_ids.h>
28 #include <netcomm/fawkes/hub.h>
29 #include <netcomm/utils/ntoh64.h>
30 
31 #include <sys/time.h>
32 #include <time.h>
33 #include <netinet/in.h>
34 #include <cstring>
35 #include <cstdlib>
36 #include <cstdio>
37 
38 namespace fawkes {
39 
40 void
42 {
43 }
44 
45 
46 /** @class NetworkLogger <logging/network.h>
47  * Interface for logging to network clients.
48  * The NetwokLogger will pipe all output to clients that subscribed for log
49  * messages.
50  * @author Tim Niemueller
51  */
52 
53 /** Constructor.
54  * @param hub FawkesNetworkHub to use to send and receive messages
55  * @param log_level minimum level to log
56  */
58  : Logger(log_level),
59  FawkesNetworkHandler(FAWKES_CID_NETWORKLOGGER)
60 {
61  this->hub = hub;
62 
63  hub->add_handler(this);
64 }
65 
66 
67 /** Destructor. */
69 {
70  hub->remove_handler(this);
71 }
72 
73 
74 void
75 NetworkLogger::send_message(Logger::LogLevel level, struct timeval *t,
76  const char *component, bool is_exception,
77  const char *format, va_list va)
78 {
79  struct timeval now;
80  if ( t == NULL ) {
81  gettimeofday(&now, NULL);
82  t = &now;
83  }
84 
86  component,
87  is_exception,
88  format, va);
89 
90  for ( __ssit = __subscribers.begin(); __ssit != __subscribers.end(); ++__ssit) {
91  NetworkLoggerMessageContent *content_copy = new NetworkLoggerMessageContent(content);
92  try {
93  hub->send(*__ssit, FAWKES_CID_NETWORKLOGGER, MSGTYPE_LOGMESSAGE, content_copy);
94  } catch (Exception &e) {
95  // Boom, can't do anything about it, logging could cause infinite loop...
96  }
97  }
98 
99  delete content;
100 }
101 
102 
103 void
104 NetworkLogger::send_message(Logger::LogLevel level, struct timeval *t,
105  const char *component, bool is_exception,
106  const char *message)
107 {
108  struct timeval now;
109  if ( t == NULL ) {
110  gettimeofday(&now, NULL);
111  t = &now;
112  }
113 
115  component,
116  is_exception,
117  message);
118 
119  for ( __ssit = __subscribers.begin(); __ssit != __subscribers.end(); ++__ssit) {
120  NetworkLoggerMessageContent *content_copy = new NetworkLoggerMessageContent(content);
121  try {
122  hub->send(*__ssit, FAWKES_CID_NETWORKLOGGER, MSGTYPE_LOGMESSAGE, content_copy);
123  } catch (Exception &e) {
124  // Boom, can't do anything about it, logging could cause infinite loop...
125  }
126  }
127 
128  delete content;
129 }
130 
131 
132 void
133 NetworkLogger::vlog_debug(const char *component, const char *format, va_list va)
134 {
135  if ((log_level <= LL_DEBUG) && (! __subscribers.empty()) ) {
136  __subscribers.lock();
137  send_message(LL_DEBUG, NULL, component, /* exception? */ false, format, va);
138  __subscribers.unlock();
139  }
140 }
141 
142 
143 void
144 NetworkLogger::vlog_info(const char *component, const char *format, va_list va)
145 {
146  if ((log_level <= LL_INFO) && (! __subscribers.empty()) ) {
147  __subscribers.lock();
148  send_message(LL_INFO, NULL, component, /* exception? */ false, format, va);
149  __subscribers.unlock();
150  }
151 }
152 
153 
154 void
155 NetworkLogger::vlog_warn(const char *component, const char *format, va_list va)
156 {
157  if ((log_level <= LL_WARN) && (! __subscribers.empty()) ) {
158  __subscribers.lock();
159  send_message(LL_WARN, NULL, component, /* exception? */ false, format, va);
160  __subscribers.unlock();
161  }
162 }
163 
164 
165 void
166 NetworkLogger::vlog_error(const char *component, const char *format, va_list va)
167 {
168  if ((log_level <= LL_ERROR) && (! __subscribers.empty()) ) {
169  __subscribers.lock();
170  send_message(LL_ERROR, NULL, component, /* exception? */ false, format, va);
171  __subscribers.unlock();
172  }
173 }
174 
175 
176 void
177 NetworkLogger::log_debug(const char *component, const char *format, ...)
178 {
179  va_list arg;
180  va_start(arg, format);
181  vlog_debug(component, format, arg);
182  va_end(arg);
183 }
184 
185 
186 void
187 NetworkLogger::log_info(const char *component, const char *format, ...)
188 {
189  va_list arg;
190  va_start(arg, format);
191  vlog_info(component, format, arg);
192  va_end(arg);
193 }
194 
195 
196 void
197 NetworkLogger::log_warn(const char *component, const char *format, ...)
198 {
199  va_list arg;
200  va_start(arg, format);
201  vlog_warn(component, format, arg);
202  va_end(arg);
203 }
204 
205 
206 void
207 NetworkLogger::log_error(const char *component, const char *format, ...)
208 {
209  va_list arg;
210  va_start(arg, format);
211  vlog_error(component, format, arg);
212  va_end(arg);
213 }
214 
215 
216 void
217 NetworkLogger::log_debug(const char *component, Exception &e)
218 {
219  if ((log_level <= LL_DEBUG) && (! __subscribers.empty()) ) {
220  __subscribers.lock();
221  for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
222  send_message(LL_DEBUG, NULL, component, /* exception? */ true, *i);
223  }
224  __subscribers.unlock();
225  }
226 }
227 
228 void
229 NetworkLogger::log_info(const char *component, Exception &e)
230 {
231  if ((log_level <= LL_INFO) && (! __subscribers.empty()) ) {
232  __subscribers.lock();
233  for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
234  send_message(LL_INFO, NULL, component, /* exception? */ true, *i);
235  }
236  __subscribers.unlock();
237  }
238 }
239 
240 
241 void
242 NetworkLogger::log_warn(const char *component, Exception &e)
243 {
244  if ((log_level <= LL_WARN) && (! __subscribers.empty()) ) {
245  __subscribers.lock();
246  for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
247  send_message(LL_WARN, NULL, component, /* exception? */ true, *i);
248  }
249  __subscribers.unlock();
250  }
251 }
252 
253 
254 void
255 NetworkLogger::log_error(const char *component, Exception &e)
256 {
257  if ((log_level <= LL_ERROR) && (! __subscribers.empty()) ) {
258  __subscribers.lock();
259  for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
260  send_message(LL_ERROR, NULL, component, /* exception? */ true, *i);
261  }
262  __subscribers.unlock();
263  }
264 }
265 
266 
267 
268 
269 void
270 NetworkLogger::vtlog_debug(struct timeval *t, const char *component,
271  const char *format, va_list va)
272 {
273  if ((log_level <= LL_DEBUG) && (! __subscribers.empty()) ) {
274  __subscribers.lock();
275  send_message(LL_DEBUG, t, component, /* exception? */ false, format, va);
276  __subscribers.unlock();
277  }
278 }
279 
280 
281 void
282 NetworkLogger::vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
283 {
284  if ((log_level <= LL_INFO) && (! __subscribers.empty()) ) {
285  __subscribers.lock();
286  send_message(LL_INFO, t, component, /* exception? */ false, format, va);
287  __subscribers.unlock();
288  }
289 }
290 
291 
292 void
293 NetworkLogger::vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
294 {
295  if ((log_level <= LL_WARN) && (! __subscribers.empty()) ) {
296  __subscribers.lock();
297  send_message(LL_WARN, t, component, /* exception? */ false, format, va);
298  __subscribers.unlock();
299  }
300 }
301 
302 
303 void
304 NetworkLogger::vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
305 {
306  if ((log_level <= LL_ERROR) && (! __subscribers.empty()) ) {
307  __subscribers.lock();
308  send_message(LL_ERROR, t, component, /* exception? */ false, format, va);
309  __subscribers.unlock();
310  }
311 }
312 
313 
314 void
315 NetworkLogger::tlog_debug(struct timeval *t, const char *component, const char *format, ...)
316 {
317  va_list arg;
318  va_start(arg, format);
319  vtlog_debug(t, component, format, arg);
320  va_end(arg);
321 }
322 
323 
324 void
325 NetworkLogger::tlog_info(struct timeval *t, const char *component, const char *format, ...)
326 {
327  va_list arg;
328  va_start(arg, format);
329  vtlog_info(t, component, format, arg);
330  va_end(arg);
331 }
332 
333 
334 void
335 NetworkLogger::tlog_warn(struct timeval *t, const char *component, const char *format, ...)
336 {
337  va_list arg;
338  va_start(arg, format);
339  vtlog_warn(t, component, format, arg);
340  va_end(arg);
341 }
342 
343 
344 void
345 NetworkLogger::tlog_error(struct timeval *t, const char *component, const char *format, ...)
346 {
347  va_list arg;
348  va_start(arg, format);
349  vtlog_error(t, component, format, arg);
350  va_end(arg);
351 }
352 
353 
354 void
355 NetworkLogger::tlog_debug(struct timeval *t, const char *component, Exception &e)
356 {
357  if ((log_level <= LL_DEBUG) && (! __subscribers.empty()) ) {
358  __subscribers.lock();
359  for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
360  send_message(LL_DEBUG, t, component, /* exception? */ true, *i);
361  }
362  __subscribers.unlock();
363  }
364 }
365 
366 void
367 NetworkLogger::tlog_info(struct timeval *t, const char *component, Exception &e)
368 {
369  if ((log_level <= LL_INFO) && (! __subscribers.empty()) ) {
370  __subscribers.lock();
371  for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
372  send_message(LL_INFO, t, component, /* exception? */ true, *i);
373  }
374  __subscribers.unlock();
375  }
376 }
377 
378 
379 void
380 NetworkLogger::tlog_warn(struct timeval *t, const char *component, Exception &e)
381 {
382  if ((log_level <= LL_WARN) && (! __subscribers.empty()) ) {
383  __subscribers.lock();
384  for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
385  send_message(LL_WARN, t, component, /* exception? */ true, *i);
386  }
387  __subscribers.unlock();
388  }
389 }
390 
391 
392 void
393 NetworkLogger::tlog_error(struct timeval *t, const char *component, Exception &e)
394 {
395  if ((log_level <= LL_ERROR) && (! __subscribers.empty()) ) {
396  __subscribers.lock();
397  for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
398  send_message(LL_ERROR, t, component, /* exception? */ true, *i);
399  }
400  __subscribers.unlock();
401  }
402 }
403 
404 
405 void
407 {
408  if ( (msg->cid() == FAWKES_CID_NETWORKLOGGER) &&
409  (msg->msgid() == MSGTYPE_SUBSCRIBE) ) {
410  __subscribers.lock();
411  __subscribers.push_back(msg->clid());
412  __subscribers.sort();
413  __subscribers.unique();
414  __subscribers.unlock();
415  }
416 }
417 
418 void
420 {
421 }
422 
423 
424 void
426 {
427  __subscribers.remove_locked(clid);
428 }
429 
430 
431 /** @class NetworkLoggerMessageContent <logging/network.h>
432  * Message sent over the network with a log message.
433  * Contains a buffer with a small header and two null-terminated strings, the first
434  * being the component and the second being the real message.
435  * @author Tim Niemueller
436  */
437 
438 
439 /** Constructor.
440  * @param log_level Log level
441  * @param t time
442  * @param component component string
443  * @param is_exception true if this message originates from an exception, false otherwise
444  * @param format message string format
445  * @param va va_list containing the arguments for the given format
446  */
448  struct timeval *t,
449  const char *component,
450  bool is_exception,
451  const char *format, va_list va)
452 {
453  char *tmp = NULL;
454  int tmplen;
455  if ( (tmplen = vasprintf(&tmp, format, va)) != -1 ) {
456  _payload_size = sizeof(NetworkLogger::network_logger_header_t) + strlen(component) + tmplen + 2;
457  _payload = calloc(1, _payload_size);
458  __own_payload = true;
459  header = (NetworkLogger::network_logger_header_t *)_payload;
460  header->log_level = log_level;
461  header->exception = is_exception ? 1 : 0;
462  header->time_sec = hton64(t->tv_sec);
463  header->time_usec = htonl(t->tv_usec);
464  copy_payload(sizeof(NetworkLogger::network_logger_header_t), component, strlen(component));
465  copy_payload(sizeof(NetworkLogger::network_logger_header_t) + strlen(component) + 1, tmp, tmplen);
466  __component = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t);
467  __message = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t) + strlen(component) + 1;
468  free(tmp);
469  }
470 }
471 
472 
473 /** Constructor.
474  * @param log_level Log level
475  * @param t time
476  * @param component component string
477  * @param is_exception true if this message originates from an exception, false otherwise
478  * @param message message string.
479  */
481  struct timeval *t,
482  const char *component,
483  bool is_exception,
484  const char *message)
485 {
486  _payload_size = sizeof(NetworkLogger::network_logger_header_t) + strlen(component) + strlen(message) + 2;
487  _payload = calloc(1, _payload_size);
488  __own_payload = true;
489  header = (NetworkLogger::network_logger_header_t *)_payload;
490  header->log_level = log_level;
491  header->exception = is_exception ? 1 : 0;
492  header->time_sec = hton64(t->tv_sec);
493  header->time_usec = htonl(t->tv_usec);
494  copy_payload(sizeof(NetworkLogger::network_logger_header_t), component, strlen(component));
495  copy_payload(sizeof(NetworkLogger::network_logger_header_t) + strlen(component) + 1, message, strlen(message));
496  __component = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t);
497  __message = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t) + strlen(component) + 1;
498 }
499 
500 
501 /** Copy constructor.
502  * @param content content to copy
503  */
505 {
506  _payload_size = content->_payload_size;
507  _payload = malloc(_payload_size);
508  __own_payload = true;
509  memcpy(_payload, content->_payload, _payload_size);
510  header = (NetworkLogger::network_logger_header_t *)_payload;
511  __component = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t);
512  __message = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t) + strlen(__component) + 1;
513 }
514 
515 
516 /** Message parsing constructor.
517  * To be used with FawkesNetworkMessage::msgc().
518  * @param component_id component ID
519  * @param msg_id message ID
520  * @param payload payload
521  * @param payload_size payload size
522  */
524  unsigned int msg_id,
525  void *payload, size_t payload_size)
526 {
527  if ( component_id != FAWKES_CID_NETWORKLOGGER ) {
528  throw TypeMismatchException("Wrong CID, expected FAWKES_CID_NETWORKLOGGER");
529  }
530 
531  _payload = payload;
532  _payload_size = payload_size;
533  __own_payload = false;
534  header = (NetworkLogger::network_logger_header_t *)_payload;
535  __component = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t);
536  __message = (char *)_payload + sizeof(NetworkLogger::network_logger_header_t) + strlen(__component) + 1;
537 }
538 
539 /** Destructor. */
541 {
542  if (__own_payload) free(_payload);
543 }
544 
545 /** Get time.
546  * @return time of the log message
547  */
548 struct timeval
550 {
551  struct timeval rv;
552  rv.tv_sec = (time_t)ntoh64(header->time_sec);
553  rv.tv_usec = ntohl(header->time_usec);
554  return rv;
555 }
556 
557 
558 /** Get component.
559  * @return component string
560  */
561 const char *
563 {
564  return __component;
565 }
566 
567 
568 /** Get message.
569  * @return message string
570  */
571 const char *
573 {
574  return __message;
575 }
576 
577 
578 /** Log level.
579  * @return log level.
580  */
583 {
584  return (Logger::LogLevel)header->log_level;
585 }
586 
587 
588 /** Check if message was generated by exception.
589  * @return true if message was generated by exception, false otherwise
590  */
591 bool
593 {
594  return (header->exception == 1);
595 }
596 
597 } // end namespace fawkes
void * _payload
Pointer to payload.
LogLevel
Log level.
Definition: logger.h:45
const char * get_component() const
Get component.
Definition: network.cpp:562
virtual void vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
Log informational message for specific time.
Definition: network.cpp:282
const char * get_message() const
Get message.
Definition: network.cpp:572
LogLevel log_level
Minimum log level.
Definition: logger.h:128
Message sent over the network with a log message.
Definition: network.h:120
informational output about normal procedures
Definition: logger.h:47
virtual ~NetworkLogger()
Destructor.
Definition: network.cpp:68
virtual void tlog_error(struct timeval *t, const char *component, const char *format,...)
Log error message for specific time.
Definition: network.cpp:345
virtual void lock() const
Lock list.
Definition: lock_list.h:128
unsigned short int cid() const
Get component ID.
Definition: message.cpp:291
virtual void log_error(const char *component, const char *format,...)
Log error message.
Definition: network.cpp:207
virtual void tlog_debug(struct timeval *t, const char *component, const char *format,...)
Log debug message for specific time.
Definition: network.cpp:315
NetworkLogger(FawkesNetworkHub *hub, LogLevel log_level=LL_DEBUG)
Constructor.
Definition: network.cpp:57
Fawkes library namespace.
unsigned int clid() const
Get client ID.
Definition: message.cpp:281
virtual void serialize()
Serialize message content.
Definition: network.cpp:41
virtual void add_handler(FawkesNetworkHandler *handler)=0
Add a message handler.
Representation of a message that is sent over the network.
Definition: message.h:75
warning, should be investigated but software still functions, an example is that something was reques...
Definition: logger.h:48
virtual void tlog_warn(struct timeval *t, const char *component, const char *format,...)
Log warning message for specific time.
Definition: network.cpp:335
Logger::LogLevel get_loglevel() const
Log level.
Definition: network.cpp:582
Message iterator for exceptions.
Definition: exception.h:72
void remove_locked(const Type &x)
Remove element from list with lock protection.
Definition: lock_list.h:172
virtual void tlog_info(struct timeval *t, const char *component, const char *format,...)
Log informational message for specific time.
Definition: network.cpp:325
Network logging message header.
Definition: network.h:95
virtual void vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
Log warning message for specific time.
Definition: network.cpp:293
error, may be recoverable (software still running) or not (software has to terminate).
Definition: logger.h:51
Fawkes Network Hub.
Definition: hub.h:33
iterator end()
Get end iterator for messages.
Definition: exception.cpp:717
virtual void handle_network_message(FawkesNetworkMessage *msg)
Called for incoming messages that are addressed to the correct component ID.
Definition: network.cpp:406
virtual void vlog_info(const char *component, const char *format, va_list va)
Log informational message.
Definition: network.cpp:144
Base class for exceptions in Fawkes.
Definition: exception.h:36
virtual void send(FawkesNetworkMessage *msg)=0
Method to send a message to a specific client.
virtual void client_connected(unsigned int clid)
Called when a new client connected.
Definition: network.cpp:419
virtual void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: network.cpp:197
virtual void vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
Log error message for specific time.
Definition: network.cpp:304
virtual void vlog_warn(const char *component, const char *format, va_list va)
Log warning message.
Definition: network.cpp:155
virtual void unlock() const
Unlock list.
Definition: lock_list.h:144
bool is_exception() const
Check if message was generated by exception.
Definition: network.cpp:592
iterator begin()
Get iterator for messages.
Definition: exception.cpp:700
virtual void log_info(const char *component, const char *format,...)
Log informational message.
Definition: network.cpp:187
Network handler abstract base class.
Definition: handler.h:31
debug output, relevant only when tracking down problems
Definition: logger.h:46
virtual void vtlog_debug(struct timeval *t, const char *component, const char *format, va_list va)
Log debug message for specific time.
Definition: network.cpp:270
unsigned short int msgid() const
Get message type ID.
Definition: message.cpp:301
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
Definition: network.cpp:177
virtual void remove_handler(FawkesNetworkHandler *handler)=0
Remove a message handler.
virtual void vlog_debug(const char *component, const char *format, va_list va)
Log debug message.
Definition: network.cpp:133
virtual void vlog_error(const char *component, const char *format, va_list va)
Log error message.
Definition: network.cpp:166
NetworkLoggerMessageContent(Logger::LogLevel log_level, struct timeval *t, const char *component, bool is_exception, const char *message)
Constructor.
Definition: network.cpp:480
virtual void client_disconnected(unsigned int clid)
Called when a client disconnected.
Definition: network.cpp:425
virtual ~NetworkLoggerMessageContent()
Destructor.
Definition: network.cpp:540
Subscribe for logging messages.
Definition: network.h:88
Interface for logging.
Definition: logger.h:34