introduced new logging subsystem using bus:
passive listeners can register on the bus active listeners wait for signals actively multiplexing allows multiple listeners to receive debug signals a lot more...
This commit is contained in:
+267
-7
@@ -22,6 +22,102 @@
|
||||
|
||||
#include "bus.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
ENUM(signal_names, SIG_ANY, SIG_MAX,
|
||||
/** should not get printed */
|
||||
"SIG_ANY",
|
||||
/** debugging message types */
|
||||
"DMN",
|
||||
"MGR",
|
||||
"IKE",
|
||||
"CHD",
|
||||
"JOB",
|
||||
"CFG",
|
||||
"KNL",
|
||||
"NET",
|
||||
"ENC",
|
||||
"LIB",
|
||||
/** should not get printed */
|
||||
"SIG_DBG_MAX",
|
||||
/** all level0 signals are AUDIT signals */
|
||||
"AUD",
|
||||
"AUD",
|
||||
"AUD",
|
||||
"AUD",
|
||||
"AUD",
|
||||
"AUD",
|
||||
"AUD",
|
||||
"AUD",
|
||||
"AUD",
|
||||
"AUD",
|
||||
"AUD",
|
||||
"AUD",
|
||||
/** should not get printed */
|
||||
"SIG_MAX",
|
||||
);
|
||||
|
||||
typedef struct active_listener_t active_listener_t;
|
||||
|
||||
/**
|
||||
* information for a active listener
|
||||
*/
|
||||
struct active_listener_t {
|
||||
|
||||
/**
|
||||
* associated thread
|
||||
*/
|
||||
pthread_t id;
|
||||
|
||||
/**
|
||||
* condvar to wait for a signal
|
||||
*/
|
||||
pthread_cond_t cond;
|
||||
|
||||
/**
|
||||
* state of the thread
|
||||
*/
|
||||
enum {
|
||||
/** not registered, do not wait for thread */
|
||||
UNREGISTERED,
|
||||
/** registered, if a signal occurs, wait until it is LISTENING */
|
||||
REGISTERED,
|
||||
/** listening, deliver signal */
|
||||
LISTENING,
|
||||
} state;
|
||||
|
||||
/**
|
||||
* currently processed signals type
|
||||
*/
|
||||
signal_t signal;
|
||||
|
||||
/**
|
||||
* verbosity level of the signal
|
||||
*/
|
||||
level_t level;
|
||||
|
||||
/**
|
||||
* current processed signals thread number
|
||||
*/
|
||||
int thread;
|
||||
|
||||
/**
|
||||
* currently processed signals ike_sa
|
||||
*/
|
||||
ike_sa_t *ike_sa;
|
||||
|
||||
/**
|
||||
* currently processed signals format string
|
||||
*/
|
||||
char *format;
|
||||
|
||||
/**
|
||||
* currently processed signals format varargs
|
||||
*/
|
||||
va_list args;
|
||||
|
||||
};
|
||||
|
||||
typedef struct private_bus_t private_bus_t;
|
||||
|
||||
/**
|
||||
@@ -38,6 +134,16 @@ struct private_bus_t {
|
||||
*/
|
||||
linked_list_t *listeners;
|
||||
|
||||
/**
|
||||
* List of active listeners with listener_state TRUE
|
||||
*/
|
||||
linked_list_t *active_listeners;
|
||||
|
||||
/**
|
||||
* mutex to synchronize active listeners
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
/**
|
||||
* Thread local storage for a unique, simple thread ID
|
||||
*/
|
||||
@@ -76,9 +182,95 @@ static int get_thread_number(private_bus_t *this)
|
||||
*/
|
||||
static void add_listener(private_bus_t *this, bus_listener_t *listener)
|
||||
{
|
||||
pthread_mutex_lock(&this->mutex);
|
||||
this->listeners->insert_last(this->listeners, (void*)listener);
|
||||
pthread_mutex_unlock(&this->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the listener object for the calling thread
|
||||
*/
|
||||
static active_listener_t *get_active_listener(private_bus_t *this)
|
||||
{
|
||||
active_listener_t *current, *found = NULL;
|
||||
iterator_t *iterator;
|
||||
|
||||
/* if the thread was here once before, we have a active_listener record */
|
||||
iterator = this->active_listeners->create_iterator(this->active_listeners, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)¤t))
|
||||
{
|
||||
if (current->id == pthread_self())
|
||||
{
|
||||
found = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
|
||||
if (found == NULL)
|
||||
{
|
||||
/* create a new object for a never-seen thread */
|
||||
found = malloc_thing(active_listener_t);
|
||||
found->id = pthread_self();
|
||||
pthread_cond_init(&found->cond, NULL);
|
||||
this->active_listeners->insert_last(this->active_listeners, found);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of bus_t.listen.
|
||||
*/
|
||||
static signal_t listen_(private_bus_t *this, level_t *level, int *thread,
|
||||
ike_sa_t **ike_sa, char** format, va_list* args)
|
||||
{
|
||||
active_listener_t *listener;
|
||||
|
||||
pthread_mutex_lock(&this->mutex);
|
||||
listener = get_active_listener(this);
|
||||
/* go "listening", say hello to a thread which have a signal for us */
|
||||
listener->state = LISTENING;
|
||||
pthread_cond_broadcast(&listener->cond);
|
||||
/* wait until it has us delivered a signal, and go back to "registered" */
|
||||
pthread_cond_wait(&listener->cond, &this->mutex);
|
||||
pthread_mutex_unlock(&this->mutex);
|
||||
|
||||
/* return signal values */
|
||||
*level = listener->level;
|
||||
*thread = listener->thread;
|
||||
*ike_sa = listener->ike_sa;
|
||||
*format = listener->format;
|
||||
*args = listener->args;
|
||||
|
||||
return listener->signal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of bus_t.set_listen_state.
|
||||
*/
|
||||
static void set_listen_state(private_bus_t *this, bool active)
|
||||
{
|
||||
active_listener_t *listener;
|
||||
|
||||
pthread_mutex_lock(&this->mutex);
|
||||
|
||||
listener = get_active_listener(this);
|
||||
if (active)
|
||||
{
|
||||
listener->state = REGISTERED;
|
||||
}
|
||||
else
|
||||
{
|
||||
listener->state = UNREGISTERED;
|
||||
/* say hello to signal omitter; we are finished processing the signal */
|
||||
pthread_cond_signal(&listener->cond);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&this->mutex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of bus_t.set_sa.
|
||||
*/
|
||||
@@ -88,28 +280,83 @@ static void set_sa(private_bus_t *this, ike_sa_t *ike_sa)
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of bus_t.signal.
|
||||
* Implementation of bus_t.vsignal.
|
||||
*/
|
||||
static void signal_(private_bus_t *this, signal_t signal, level_t condition,
|
||||
char* format, ...)
|
||||
static void vsignal(private_bus_t *this, signal_t signal, level_t level,
|
||||
char* format, va_list args)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
bus_listener_t *listener;
|
||||
va_list args;
|
||||
active_listener_t *active_listener;
|
||||
ike_sa_t *ike_sa;
|
||||
int thread;
|
||||
|
||||
ike_sa = pthread_getspecific(this->thread_sa);
|
||||
thread = get_thread_number(this);
|
||||
va_start(args, format);
|
||||
|
||||
pthread_mutex_lock(&this->mutex);
|
||||
|
||||
/* do the job for all passive bus_listeners */
|
||||
iterator = this->listeners->create_iterator(this->listeners, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)&listener))
|
||||
{
|
||||
listener->signal(listener, thread, ike_sa,
|
||||
signal, condition, format, args);
|
||||
va_list args_copy;
|
||||
|
||||
va_copy(args_copy, args);
|
||||
listener->signal(listener, signal, level, thread, ike_sa, format, args_copy);
|
||||
va_end(args_copy);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
|
||||
/* wake up all active listeners */
|
||||
iterator = this->active_listeners->create_iterator(this->active_listeners, TRUE);
|
||||
while (iterator->iterate(iterator, (void**)&active_listener))
|
||||
{
|
||||
/* wait until it is back */
|
||||
while (active_listener->state == REGISTERED)
|
||||
{
|
||||
pthread_cond_wait(&active_listener->cond, &this->mutex);
|
||||
}
|
||||
/* if thread is listening now, give it the signal to process */
|
||||
if (active_listener->state == LISTENING)
|
||||
{
|
||||
active_listener->level = level;
|
||||
active_listener->thread = thread;
|
||||
active_listener->ike_sa = ike_sa;
|
||||
active_listener->signal = signal;
|
||||
active_listener->format = format;
|
||||
va_copy(active_listener->args, args);
|
||||
active_listener->state = REGISTERED;
|
||||
pthread_cond_signal(&active_listener->cond);
|
||||
}
|
||||
}
|
||||
|
||||
/* we must wait now until all are not in state REGISTERED,
|
||||
* as they may still use our arguments */
|
||||
iterator->reset(iterator);
|
||||
while (iterator->iterate(iterator, (void**)&active_listener))
|
||||
{
|
||||
while (active_listener->state == REGISTERED)
|
||||
{
|
||||
pthread_cond_wait(&active_listener->cond, &this->mutex);
|
||||
}
|
||||
va_end(active_listener->args);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
|
||||
pthread_mutex_unlock(&this->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of bus_t.signal.
|
||||
*/
|
||||
static void signal_(private_bus_t *this, signal_t signal, level_t level,
|
||||
char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
vsignal(this, signal, level, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@@ -118,6 +365,14 @@ static void signal_(private_bus_t *this, signal_t signal, level_t condition,
|
||||
*/
|
||||
static void destroy(private_bus_t *this)
|
||||
{
|
||||
active_listener_t *listener;
|
||||
while (this->active_listeners->remove_last(this->active_listeners,
|
||||
(void**)&listener) == SUCCESS)
|
||||
{
|
||||
free(listener);
|
||||
}
|
||||
|
||||
this->active_listeners->destroy(this->active_listeners);
|
||||
this->listeners->destroy(this->listeners);
|
||||
free(this);
|
||||
}
|
||||
@@ -130,11 +385,16 @@ bus_t *bus_create()
|
||||
private_bus_t *this = malloc_thing(private_bus_t);
|
||||
|
||||
this->public.add_listener = (void(*)(bus_t*,bus_listener_t*))add_listener;
|
||||
this->public.listen = (signal_t(*)(bus_t*,level_t*,int*,ike_sa_t**,char**,va_list*))listen_;
|
||||
this->public.set_listen_state = (void(*)(bus_t*,bool))set_listen_state;
|
||||
this->public.set_sa = (void(*)(bus_t*,ike_sa_t*))set_sa;
|
||||
this->public.signal = (void(*)(bus_t*,signal_t,level_t,char*,...))signal_;
|
||||
this->public.vsignal = (void(*)(bus_t*,signal_t,level_t,char*,va_list))vsignal;
|
||||
this->public.destroy = (void(*)(bus_t*)) destroy;
|
||||
|
||||
this->listeners = linked_list_create();
|
||||
this->active_listeners = linked_list_create();
|
||||
pthread_mutex_init(&this->mutex, NULL);
|
||||
pthread_key_create(&this->thread_id, NULL);
|
||||
pthread_key_create(&this->thread_sa, NULL);
|
||||
|
||||
|
||||
+224
-78
@@ -29,60 +29,81 @@
|
||||
#include <sa/child_sa.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Raise a signal for an occured event.
|
||||
*
|
||||
* @param sig signal_t signal description
|
||||
* @param level level for the signal
|
||||
* @param format printf() style format string
|
||||
* @param ... printf() style agument list
|
||||
*/
|
||||
#define SIG(sig, level, format, ...) charon->bus->signal(charon->bus, sig, level, format, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Set the IKE_SA the calling thread is using.
|
||||
*
|
||||
* @param ike_sa ike_sa to register, or NULL to unregister
|
||||
*/
|
||||
#define SIG_SA(ike_sa) charon->bus->set_sa(charon->bus, ike_sa)
|
||||
|
||||
/**
|
||||
* @brief Log a debug message via the signal bus.
|
||||
*
|
||||
* @param signal signal_t signal description
|
||||
* @param format printf() style format string
|
||||
* @param ... printf() style agument list
|
||||
*/
|
||||
#define DBG1(sig, format, ...) charon->bus->signal(charon->bus, sig, LEV_DBG1, format, ##__VA_ARGS__)
|
||||
#define DBG2(sig, format, ...) charon->bus->signal(charon->bus, sig, LEV_DBG2, format, ##__VA_ARGS__)
|
||||
#define DBG3(sig, format, ...) charon->bus->signal(charon->bus, sig, LEV_DBG3, format, ##__VA_ARGS__)
|
||||
#define DBG4(sig, format, ...) charon->bus->signal(charon->bus, sig, LEV_DBG4, format, ##__VA_ARGS__)
|
||||
|
||||
|
||||
typedef enum signal_t signal_t;
|
||||
|
||||
/**
|
||||
* @brief signals ommited by the daemon.
|
||||
*
|
||||
* Signaling is for different purporses. First, it allows debugging via
|
||||
* "debugging signal messages", sencondly, it allows to follow certain
|
||||
* mechanisms currently going on in the daemon. As we are multithreaded,
|
||||
* and a multiple messages are involved, it's not possible to follow
|
||||
* one connection setup without further infrastructure. These infrastructure
|
||||
* is provided by the bus and the signals the whole daemon ommits to the bus.
|
||||
*
|
||||
* @par Schema 1: Signals involved in IKE_SA/CHILD_SA initiation
|
||||
*
|
||||
* In the initiation of a IKE- or CHILD_SA is triggered by three possible
|
||||
* sources: User request, a request from the other peer, or a request
|
||||
* triggered by the kernel.
|
||||
* Once the user requests initiation, the SIG_INITIATE signal is ommited.
|
||||
* This signal contains the IKE_SA that got created. Any further signals
|
||||
* have the same IKE_SA and are therefore easy to trace.
|
||||
* If the kernel initiates, a SIG_ACQUIRE is sent over the bus.
|
||||
* If a new IKE_SA is needed, it is set up. If it succeeds, a
|
||||
* SIG_IKE_ESTABLISHED is ommitted. If the peer didn't accept our DH
|
||||
* group, the initiation fails. A SIG_DH_INVALID is sent over the bus. It still
|
||||
* contains the the old IKE_SA. Shortly afterwards, a SIG_DH_RETRY is ommited.
|
||||
* It contains the NEW IKE_SA. This mechanism allows us to trace the setup even
|
||||
* beyond a INVALID_KE_PAYLOUD error.
|
||||
* If the setup fails, SIG_IKE_ESTABLISH_FAILED is sent.
|
||||
* After a successful establishment of the IKE_SA, or if an already established
|
||||
* IKE_SA is reused, the child establishment begins. If it is set up with
|
||||
* the ike_auth transaction, the SIG_CHILD_ESTABLISHED signal is ommited
|
||||
* directly after the SIG_IKE_ESTABLISHED signal, as both are set up
|
||||
* simultaneously. The child setup may fail (in a ike_auth, or in a
|
||||
* create_child_sa exchange), if so, the SIG_CHID_ESTABLISH_FAILED signal
|
||||
* is raised.
|
||||
*
|
||||
* @verbatim
|
||||
|
||||
"ipsec up" "peer msg" "kernel acquire"
|
||||
| | |
|
||||
V | V
|
||||
SIG_INITIATE | SIG_ACQUIRE
|
||||
\ | /
|
||||
\ |/______________________________________________
|
||||
\/________________________________ \
|
||||
/\ \ \ |
|
||||
| | | | |
|
||||
V V | V |
|
||||
SIG_IKE_ESTABLISHED SIG_IKE_ESTABLISH_FALIED | SIG_DH_INVALID |
|
||||
\ | | | |
|
||||
\ X | V |
|
||||
\___________________________/ SIG_DH_RETRY |
|
||||
/\ \______________/
|
||||
| |
|
||||
V V
|
||||
SIG_CHILD_ESTABLISHED SIG_CHILD_ESTABLISH_FAILED
|
||||
|
|
||||
X
|
||||
@endverbatim
|
||||
* Other scenarios are much simpler. Termination is just indicated with
|
||||
* a simple SIG_CHILD_TERMINATED and/or SIG_IKE_TERMINATED signal. There
|
||||
* are other signals as SIG_CHILD_ROUTED or SIG_CHILD_UNROUTED. Rekeying is
|
||||
* also trivial (SIG_IKE_REKEYED/SIG_CHILD_REKEYED), but may contain
|
||||
* SIG_DH_INVALID...
|
||||
*
|
||||
* @ingroup bus
|
||||
*/
|
||||
enum signal_t {
|
||||
/** an IKE_SA has been established */
|
||||
SIG_IKE_UP,
|
||||
/** an IKE_SA has been closed */
|
||||
SIG_IKE_DOWN,
|
||||
/** an IKE_SA has been rekeyed */
|
||||
SIG_IKE_REKEY,
|
||||
/** a CHILD_SA has been installed */
|
||||
SIG_CHILD_UP,
|
||||
/** a CHILD_SA has been closed */
|
||||
SIG_CHILD_DOWN,
|
||||
/** a CHILD_SA has been rekeyed */
|
||||
SIG_CHILD_REKEY,
|
||||
/** a CHILD_SA has been routed */
|
||||
SIG_CHILD_ROUTE,
|
||||
/** a CHILD_SA has been unrouted */
|
||||
SIG_CHILD_UNROUTE,
|
||||
/** a remote peer has been authenticated using RSA digital signature */
|
||||
SIG_AUTH_RSA,
|
||||
/** a remote peer has been authenticated using preshared keys */
|
||||
SIG_AUTH_PSK,
|
||||
/** pseudo signal, representing any other signal */
|
||||
SIG_ANY,
|
||||
|
||||
/** debugging messages printed from daemon main loop */
|
||||
SIG_DBG_DMN,
|
||||
/** debugging message printed from IKE_SA_MANAGER */
|
||||
SIG_DBG_MGR,
|
||||
/** debugging message printed from an IKE_SA */
|
||||
SIG_DBG_IKE,
|
||||
/** debugging message printed from a CHILD_SA */
|
||||
@@ -97,27 +118,103 @@ enum signal_t {
|
||||
SIG_DBG_NET,
|
||||
/** debugging message printed from message encoding/decoding */
|
||||
SIG_DBG_ENC,
|
||||
/** debugging message printed from libstrongswan via logging hook */
|
||||
SIG_DBG_LIB,
|
||||
|
||||
SIG_MAX,
|
||||
/** number of debug signals */
|
||||
SIG_DBG_MAX,
|
||||
|
||||
/** initiation started on user request */
|
||||
SIG_INITIATE,
|
||||
/** acquiring on kernel request */
|
||||
SIG_ACQUIRE,
|
||||
|
||||
/** an IKE_SA has been established */
|
||||
SIG_IKE_UP,
|
||||
/** an IKE_SA has been closed as requested */
|
||||
SIG_IKE_DOWN,
|
||||
/** an IKE_SA got deleted due an error */
|
||||
SIG_IKE_FAILED,
|
||||
/** an IKE_SA has been rekeyed */
|
||||
SIG_IKE_REKEY,
|
||||
|
||||
/** a CHILD_SA has been established */
|
||||
SIG_CHILD_UP,
|
||||
/** a CHILD_SA has been closed as requested */
|
||||
SIG_CHILD_DOWN,
|
||||
/** a CHILD_SA got deleted due an error */
|
||||
SIG_CHILD_FAILED,
|
||||
/** a CHILD_SA has been rekeyed */
|
||||
SIG_CHILD_REKEY,
|
||||
/** a CHILD_SA has been routed */
|
||||
SIG_CHILD_ROUTE,
|
||||
/** a CHILD_SA has been unrouted */
|
||||
SIG_CHILD_UNROUTE,
|
||||
|
||||
SIG_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* short names of signals using 3 chars
|
||||
*/
|
||||
extern enum_name_t *signal_names;
|
||||
|
||||
typedef enum level_t level_t;
|
||||
|
||||
/**
|
||||
* Signal levels used to control output verbosity.
|
||||
*/
|
||||
enum level_t {
|
||||
/** Signal indicates something has failed */
|
||||
LEV_FAILED,
|
||||
/** Signal indicates something was successful */
|
||||
LEV_SUCCESS,
|
||||
/** Debug level 1, control flow messages */
|
||||
LEV_DBG1,
|
||||
/** Debug level 2, more detail informational messages */
|
||||
LEV_DBG2,
|
||||
/** Debug level 3, RAW data output */
|
||||
LEV_DBG3,
|
||||
/** Debug level 4, RAW data with sensitive (private) data */
|
||||
LEV_DBG4,
|
||||
/** numerical levels from 0 to 4 */
|
||||
LEVEL_0 = 0,
|
||||
LEVEL_1 = 1,
|
||||
LEVEL_2 = 2,
|
||||
LEVEL_3 = 3,
|
||||
LEVEL_4 = 4,
|
||||
/** absolutely silent, no signal is ommited with this level */
|
||||
LEVEL_SILENT = -1,
|
||||
/** alias for numberical levels */
|
||||
LEVEL_AUDIT = LEVEL_0,
|
||||
LEVEL_CTRL = LEVEL_1,
|
||||
LEVEL_CTRLMORE = LEVEL_2,
|
||||
LEVEL_RAW = LEVEL_3,
|
||||
LEVEL_PRIVATE = LEVEL_4,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Raise a signal for an occured event.
|
||||
*
|
||||
* @param sig signal_t signal description
|
||||
* @param format printf() style format string
|
||||
* @param ... printf() style agument list
|
||||
*/
|
||||
#define SIG(sig, format, ...) charon->bus->signal(charon->bus, sig, LEVEL_0, format, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log a debug message via the signal bus.
|
||||
*
|
||||
* @param signal signal_t signal description
|
||||
* @param format printf() style format string
|
||||
* @param ... printf() style agument list
|
||||
*/
|
||||
#define DBG1(sig, format, ...) charon->bus->signal(charon->bus, sig, LEVEL_1, format, ##__VA_ARGS__)
|
||||
#define DBG2(sig, format, ...) charon->bus->signal(charon->bus, sig, LEVEL_2, format, ##__VA_ARGS__)
|
||||
#define DBG3(sig, format, ...) charon->bus->signal(charon->bus, sig, LEVEL_3, format, ##__VA_ARGS__)
|
||||
#define DBG4(sig, format, ...) charon->bus->signal(charon->bus, sig, LEVEL_4, format, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Get the type of a signal.
|
||||
*
|
||||
* A signal may be a debugging signal with a specific context. They have
|
||||
* a level specific for their context > 0. All audit signals use the
|
||||
* type 0. This allows filtering of singals by their type.
|
||||
*
|
||||
* @param signal signal to get the type from
|
||||
* @return type of the signal, between 0..(SIG_DBG_MAX-1)
|
||||
*/
|
||||
#define SIG_TYPE(sig) (sig > SIG_DBG_MAX ? SIG_ANY : sig)
|
||||
|
||||
|
||||
typedef struct bus_listener_t bus_listener_t;
|
||||
|
||||
/**
|
||||
@@ -135,21 +232,21 @@ struct bus_listener_t {
|
||||
*
|
||||
* A numerical identification for the thread is included, as the
|
||||
* associated IKE_SA, if any. Signal specifies the type of
|
||||
* the event occured, with a verbosity level. The format string specifies
|
||||
* the event occured. The format string specifies
|
||||
* an additional informational or error message with a printf() like
|
||||
* variable argument list. This is in the va_list form, as forwarding
|
||||
* a "..." parameters to functions is not (cleanly) possible.
|
||||
*
|
||||
* @param this listener
|
||||
* @param singal kind of the signal (up, down, rekeyed, ...)
|
||||
* @param level verbosity level of the signal
|
||||
* @param thread ID of the thread raised this signal
|
||||
* @param ike_sa IKE_SA associated to the event
|
||||
* @param singal kind of the signal (up, down, rekeyed, ...)
|
||||
* @param level level for signal
|
||||
* @param format printf() style format string
|
||||
* @param args vprintf() style va_list argument list
|
||||
*/
|
||||
void (*signal) (bus_listener_t *this, int thread, ike_sa_t *ike_sa,
|
||||
signal_t signal, level_t level, char* format, va_list args);
|
||||
void (*signal) (bus_listener_t *this, signal_t signal, level_t level,
|
||||
int thread, ike_sa_t *ike_sa, char* format, va_list args);
|
||||
};
|
||||
|
||||
|
||||
@@ -161,7 +258,8 @@ typedef struct bus_t bus_t;
|
||||
* The signal bus is not much more than a multiplexer. A listener interested
|
||||
* in receiving event signals registers at the bus. Any signals sent to
|
||||
* are delivered to all registered listeners.
|
||||
*
|
||||
* To deliver signals to threads, the blocking listen() call may be used
|
||||
* to wait for a signal.
|
||||
*
|
||||
* @ingroup bus
|
||||
*/
|
||||
@@ -171,12 +269,51 @@ struct bus_t {
|
||||
* @brief Register a listener to the bus.
|
||||
*
|
||||
* A registered listener receives all signals which are sent to the bus.
|
||||
* The listener is passive; the thread which ommited the signal
|
||||
* processes the listener routine.
|
||||
*
|
||||
* @param this bus
|
||||
* @param listener listener to register.
|
||||
*/
|
||||
void (*add_listener) (bus_t *this, bus_listener_t *listener);
|
||||
|
||||
/**
|
||||
* @brief Listen actively on the bus.
|
||||
*
|
||||
* As we are fully multithreaded, we must provide a mechanism
|
||||
* for active threads to listen to the bus. With the listen() method,
|
||||
* a thread waits until a signal occurs, and then processes it.
|
||||
* To prevent the listen() calling thread to miss signals ommited while
|
||||
* it processes a signal, registration is required. This is done through
|
||||
* the set_listen_state() method, see below.
|
||||
*
|
||||
* @param this bus
|
||||
* @param level verbosity level of the signal
|
||||
* @param thread receives thread number ommited the signal
|
||||
* @param ike_sa receives the IKE_SA involved in the signal, or NULL
|
||||
* @param format receives the format string supplied with the signal
|
||||
* @param va_list receives the variable argument list for format
|
||||
* @return the ommited signal type
|
||||
*/
|
||||
signal_t (*listen) (bus_t *this, level_t* level, int *thread,
|
||||
ike_sa_t **ike_sa, char** format, va_list* args);
|
||||
|
||||
/**
|
||||
* @brief Set the listening state of the calling thread.
|
||||
*
|
||||
* To prevent message loss for active listeners using listen(), threads
|
||||
* must register themself to the bus before starting to listen(). When
|
||||
* a signal occurs, the ommiter waits until all threads with listen_state
|
||||
* TRUE are waiting in the listen() method to process the signal.
|
||||
* It is important that a thread with liste_state TRUE calls listen()
|
||||
* periodically, or sets it's listening state to FALSE; otherwise
|
||||
* all signal omitting threads get blocked on the bus.
|
||||
*
|
||||
* @param this bus
|
||||
* @param active TRUE to set to listening
|
||||
*/
|
||||
void (*set_listen_state) (bus_t *this, bool active);
|
||||
|
||||
/**
|
||||
* @brief Set the IKE_SA the calling thread is using.
|
||||
*
|
||||
@@ -185,8 +322,6 @@ struct bus_t {
|
||||
* time it checked it out. Before checking it in, the thread unregisters
|
||||
* the IKE_SA (by passing NULL). This IKE_SA is stored per-thread, so each
|
||||
* thread has one IKE_SA registered (or not).
|
||||
* There is a macro to simplify the call.
|
||||
* @see SIG_SA()
|
||||
*
|
||||
* @param this bus
|
||||
* @param ike_sa ike_sa to register, or NULL to unregister
|
||||
@@ -196,22 +331,33 @@ struct bus_t {
|
||||
/**
|
||||
* @brief Send a signal to the bus.
|
||||
*
|
||||
* A signal may belong to an IKE_SA and a CHILD_SA. If so, these
|
||||
* are supplied to the signal function. The signal specifies the type of
|
||||
* the event occured. The format string specifies an additional
|
||||
* informational or error message with a printf() like variable argument
|
||||
* list.
|
||||
* Some useful macros may be available to shorten this call.
|
||||
* The signal specifies the type of the event occured. The format string
|
||||
* specifies an additional informational or error message with a
|
||||
* printf() like variable argument list.
|
||||
* Some useful macros are available to shorten this call.
|
||||
* @see SIG(), DBG1()
|
||||
*
|
||||
* @param this bus
|
||||
* @param singal kind of the signal (up, down, rekeyed, ...)
|
||||
* @param level status level of the signal to send
|
||||
* @param level verbosity level of the signal
|
||||
* @param format printf() style format string
|
||||
* @param ... printf() style argument list
|
||||
*/
|
||||
void (*signal) (bus_t *this, signal_t signal, level_t level, char* format, ...);
|
||||
|
||||
/**
|
||||
* @brief Send a signal to the bus using va_list arguments.
|
||||
*
|
||||
* Same as bus_t.signal(), but uses va_list argument list.
|
||||
*
|
||||
* @param this bus
|
||||
* @param singal kind of the signal (up, down, rekeyed, ...)
|
||||
* @param level verbosity level of the signal
|
||||
* @param format printf() style format string
|
||||
* @param args va_list arguments
|
||||
*/
|
||||
void (*vsignal) (bus_t *this, signal_t signal, level_t level, char* format, va_list args);
|
||||
|
||||
/**
|
||||
* @brief Destroy the signal bus.
|
||||
*
|
||||
|
||||
@@ -20,15 +20,11 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/* for fmemopen() */
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "file_logger.h"
|
||||
|
||||
#include <bus/listeners/stream_logger.h>
|
||||
|
||||
|
||||
typedef struct private_file_logger_t private_file_logger_t;
|
||||
|
||||
@@ -48,99 +44,58 @@ struct private_file_logger_t {
|
||||
FILE *out;
|
||||
|
||||
/**
|
||||
* Internal used stream logger that does the dirty work
|
||||
* Maximum level to log
|
||||
*/
|
||||
stream_logger_t *logger;
|
||||
|
||||
/**
|
||||
* Memory stream used for stream_logger
|
||||
*/
|
||||
FILE *stream;
|
||||
|
||||
/**
|
||||
* Underlying buffer for stream
|
||||
*/
|
||||
char buffer[4096];
|
||||
level_t levels[SIG_DBG_MAX];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of bus_listener_t.signal.
|
||||
*/
|
||||
static void signal_(private_file_logger_t *this, int thread, ike_sa_t* ike_sa,
|
||||
signal_t signal, level_t level,
|
||||
char *format, va_list args)
|
||||
static void signal_(private_file_logger_t *this, signal_t signal, level_t level,
|
||||
int thread, ike_sa_t* ike_sa, char *format, va_list args)
|
||||
{
|
||||
char line[512];
|
||||
char *prefix;
|
||||
FILE *reader;
|
||||
|
||||
switch (signal)
|
||||
if (level <= this->levels[SIG_TYPE(signal)])
|
||||
{
|
||||
case SIG_IKE_UP:
|
||||
case SIG_IKE_DOWN:
|
||||
case SIG_IKE_REKEY:
|
||||
case SIG_DBG_IKE:
|
||||
prefix = "IKE";
|
||||
break;
|
||||
case SIG_DBG_CHD:
|
||||
prefix = "CHD";
|
||||
break;
|
||||
case SIG_DBG_JOB:
|
||||
prefix = "JOG";
|
||||
break;
|
||||
case SIG_DBG_CFG:
|
||||
prefix = "CFG";
|
||||
break;
|
||||
case SIG_DBG_KNL:
|
||||
prefix = "KNL";
|
||||
break;
|
||||
case SIG_DBG_NET:
|
||||
prefix = "NET";
|
||||
break;
|
||||
case SIG_DBG_ENC:
|
||||
prefix = "ENC";
|
||||
break;
|
||||
default:
|
||||
prefix = "???";
|
||||
break;
|
||||
}
|
||||
|
||||
flockfile(this->stream);
|
||||
/* reset memory stream */
|
||||
rewind(this->stream);
|
||||
memset(this->buffer, '\0', sizeof(this->buffer));
|
||||
/* log to memstream */
|
||||
this->logger->listener.signal(&this->logger->listener, thread, ike_sa,
|
||||
signal, level, format, args);
|
||||
/* flush is needed to append a '\0' */
|
||||
fflush(this->stream);
|
||||
|
||||
/* create a reader stream that reads out line by line */
|
||||
reader = fmemopen(this->buffer, sizeof(this->buffer), "r");
|
||||
|
||||
while (fgets(line, sizeof(line), reader))
|
||||
{
|
||||
if (line[0] == '\0')
|
||||
char buffer[8192];
|
||||
char *current = buffer, *next;
|
||||
|
||||
/* write in memory buffer first */
|
||||
vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
|
||||
/* prepend a prefix in front of every line */
|
||||
while (current)
|
||||
{
|
||||
/* abort on EOF */
|
||||
break;
|
||||
}
|
||||
else if (line[0] != '\n')
|
||||
{
|
||||
fprintf(this->out, "%.2d[%s] %s", thread, prefix, line);
|
||||
next = strchr(current, '\n');
|
||||
if (next)
|
||||
{
|
||||
*(next++) = '\0';
|
||||
}
|
||||
fprintf(this->out, "%.2d[%N] %s\n", thread, signal_names, signal, current);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
fclose(reader);
|
||||
funlockfile(this->stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of file_logger_t.set_level.
|
||||
*/
|
||||
static void set_level(private_file_logger_t *this, signal_t signal, level_t max)
|
||||
static void set_level(private_file_logger_t *this, signal_t signal, level_t level)
|
||||
{
|
||||
this->logger->set_level(this->logger, signal, max);
|
||||
if (signal == SIG_ANY)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < SIG_DBG_MAX; i++)
|
||||
{
|
||||
this->levels[i] = level;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
this->levels[SIG_TYPE(signal)] = level;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,8 +103,6 @@ static void set_level(private_file_logger_t *this, signal_t signal, level_t max)
|
||||
*/
|
||||
static void destroy(private_file_logger_t *this)
|
||||
{
|
||||
fclose(this->stream);
|
||||
this->logger->destroy(this->logger);
|
||||
free(this);
|
||||
}
|
||||
|
||||
@@ -161,19 +114,13 @@ file_logger_t *file_logger_create(FILE *out)
|
||||
private_file_logger_t *this = malloc_thing(private_file_logger_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.listener.signal = (void(*)(bus_listener_t*,int,ike_sa_t*,signal_t,level_t,char*,va_list))signal_;
|
||||
this->public.listener.signal = (void(*)(bus_listener_t*,signal_t,level_t,int,ike_sa_t*,char*,va_list))signal_;
|
||||
this->public.set_level = (void(*)(file_logger_t*,signal_t,level_t))set_level;
|
||||
this->public.destroy = (void(*)(file_logger_t*))destroy;
|
||||
|
||||
/* private variables */
|
||||
this->out = out;
|
||||
this->stream = fmemopen(this->buffer, sizeof(this->buffer), "w");
|
||||
if (this->stream == NULL)
|
||||
{
|
||||
/* fallback to stderr */
|
||||
this->stream = stderr;
|
||||
}
|
||||
this->logger = stream_logger_create(this->stream);
|
||||
set_level(this, SIG_ANY, LEVEL_SILENT);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ struct file_logger_t {
|
||||
*
|
||||
* @param this stream_logger_t object
|
||||
* @param singal type of signal
|
||||
* @param level max level to log
|
||||
* @param level max level to log (0..4)
|
||||
*/
|
||||
void (*set_level) (file_logger_t *this, signal_t signal, level_t level);
|
||||
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
/**
|
||||
* @file stream_logger.c
|
||||
*
|
||||
* @brief Implementation of stream_logger_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "stream_logger.h"
|
||||
|
||||
|
||||
typedef struct private_stream_logger_t private_stream_logger_t;
|
||||
|
||||
/**
|
||||
* @brief Private data of a stream_logger_t object.
|
||||
*/
|
||||
struct private_stream_logger_t {
|
||||
|
||||
/**
|
||||
* Public data
|
||||
*/
|
||||
stream_logger_t public;
|
||||
|
||||
/**
|
||||
* Maximum level to log
|
||||
*/
|
||||
level_t max;
|
||||
|
||||
/**
|
||||
* stream to write log output to
|
||||
*/
|
||||
FILE *out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of bus_listener_t.signal.
|
||||
*/
|
||||
static void signal_(private_stream_logger_t *this, int thread,
|
||||
ike_sa_t* ike_sa, signal_t signal, level_t level,
|
||||
char *format, va_list args)
|
||||
{
|
||||
FILE *o = this->out;
|
||||
|
||||
flockfile(o);
|
||||
|
||||
if (level <= this->max)
|
||||
{
|
||||
/* then print the info */
|
||||
switch (signal)
|
||||
{
|
||||
case SIG_IKE_UP:
|
||||
{
|
||||
if (level == LEV_SUCCESS)
|
||||
{
|
||||
fprintf(o, "established: %H[%D]...%H[%D]\n",
|
||||
ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa),
|
||||
ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(o, "establishing failed: %H[%D]...%H[%D]:\n",
|
||||
ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa),
|
||||
ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa));
|
||||
fprintf(o, " ");
|
||||
vfprintf(o, format, args);
|
||||
fprintf(o, "\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SIG_DBG_IKE:
|
||||
case SIG_DBG_CHD:
|
||||
case SIG_DBG_JOB:
|
||||
case SIG_DBG_CFG:
|
||||
case SIG_DBG_KNL:
|
||||
case SIG_DBG_NET:
|
||||
case SIG_DBG_ENC:
|
||||
{
|
||||
vfprintf(o, format, args);
|
||||
fprintf(o, "\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
funlockfile(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of stream_logger_t.set_level.
|
||||
*/
|
||||
static void set_level(private_stream_logger_t *this, signal_t signal, level_t max)
|
||||
{
|
||||
this->max = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of stream_logger_t.destroy.
|
||||
*/
|
||||
static void destroy(private_stream_logger_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
stream_logger_t *stream_logger_create(FILE *out)
|
||||
{
|
||||
private_stream_logger_t *this = malloc_thing(private_stream_logger_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.listener.signal = (void(*)(bus_listener_t*,int,ike_sa_t*,signal_t,level_t,char*,va_list))signal_;
|
||||
this->public.set_level = (void(*)(stream_logger_t*,signal_t,level_t))set_level;
|
||||
this->public.destroy = (void(*)(stream_logger_t*))destroy;
|
||||
|
||||
/* private variables */
|
||||
this->max = LEV_DBG4;
|
||||
this->out = out;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
* @file stream_logger.h
|
||||
*
|
||||
* @brief Interface of stream_logger_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef STREAM_LOGGER_H_
|
||||
#define STREAM_LOGGER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <types.h>
|
||||
#include <bus/bus.h>
|
||||
|
||||
typedef struct stream_logger_t stream_logger_t;
|
||||
|
||||
/**
|
||||
* @brief Logger for a file stream which implements bus_listener_t.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - stream_logger_create()
|
||||
*
|
||||
* @ingroup listeners
|
||||
*/
|
||||
struct stream_logger_t {
|
||||
|
||||
/**
|
||||
* Implements the bus_listener_t interface.
|
||||
*/
|
||||
bus_listener_t listener;
|
||||
|
||||
/**
|
||||
* @brief Set the loglevel for a signal type.
|
||||
*
|
||||
* @param this stream_logger_t object
|
||||
* @param singal type of signal
|
||||
* @param level max level to log
|
||||
*/
|
||||
void (*set_level) (stream_logger_t *this, signal_t signal, level_t level);
|
||||
|
||||
/**
|
||||
* @brief Destroys a stream_logger_t object.
|
||||
*
|
||||
* @param this stream_logger_t object
|
||||
*/
|
||||
void (*destroy) (stream_logger_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor to create a stream_logger_t object.
|
||||
*
|
||||
* @param out output stream to log to
|
||||
* @return stream_logger_t object
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
stream_logger_t *stream_logger_create(FILE *out);
|
||||
|
||||
#endif /* STREAM_LOGGER_H_ */
|
||||
@@ -20,16 +20,12 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/* for open_memstream() */
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "sys_logger.h"
|
||||
|
||||
#include <bus/listeners/stream_logger.h>
|
||||
|
||||
|
||||
typedef struct private_sys_logger_t private_sys_logger_t;
|
||||
|
||||
@@ -49,99 +45,59 @@ struct private_sys_logger_t {
|
||||
int facility;
|
||||
|
||||
/**
|
||||
* Internal used stream logger that does the dirty work
|
||||
* Maximum level to log
|
||||
*/
|
||||
stream_logger_t *logger;
|
||||
|
||||
/**
|
||||
* Memory stream used for stream_logger
|
||||
*/
|
||||
FILE *stream;
|
||||
|
||||
/**
|
||||
* Underlying buffer for stream
|
||||
*/
|
||||
char buffer[4096];
|
||||
level_t levels[SIG_DBG_MAX];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of bus_listener_t.signal.
|
||||
*/
|
||||
static void signal_(private_sys_logger_t *this, int thread, ike_sa_t* ike_sa,
|
||||
signal_t signal, level_t level,
|
||||
char *format, va_list args)
|
||||
static void signal_(private_sys_logger_t *this, signal_t signal, level_t level,
|
||||
int thread, ike_sa_t* ike_sa, char *format, va_list args)
|
||||
{
|
||||
char line[512];
|
||||
char *prefix;
|
||||
FILE *reader;
|
||||
|
||||
switch (signal)
|
||||
if (level <= this->levels[SIG_TYPE(signal)])
|
||||
{
|
||||
case SIG_IKE_UP:
|
||||
case SIG_IKE_DOWN:
|
||||
case SIG_IKE_REKEY:
|
||||
case SIG_DBG_IKE:
|
||||
prefix = "IKE";
|
||||
break;
|
||||
case SIG_DBG_CHD:
|
||||
prefix = "CHD";
|
||||
break;
|
||||
case SIG_DBG_JOB:
|
||||
prefix = "JOG";
|
||||
break;
|
||||
case SIG_DBG_CFG:
|
||||
prefix = "CFG";
|
||||
break;
|
||||
case SIG_DBG_KNL:
|
||||
prefix = "KNL";
|
||||
break;
|
||||
case SIG_DBG_NET:
|
||||
prefix = "NET";
|
||||
break;
|
||||
case SIG_DBG_ENC:
|
||||
prefix = "ENC";
|
||||
break;
|
||||
default:
|
||||
prefix = "???";
|
||||
break;
|
||||
}
|
||||
|
||||
flockfile(this->stream);
|
||||
/* reset memory stream */
|
||||
rewind(this->stream);
|
||||
memset(this->buffer, '\0', sizeof(this->buffer));
|
||||
/* log to memstream */
|
||||
this->logger->listener.signal(&this->logger->listener, thread, ike_sa,
|
||||
signal, level, format, args);
|
||||
/* flush is needed to append a '\0' */
|
||||
fflush(this->stream);
|
||||
|
||||
/* create a reader stream that reads out line by line */
|
||||
reader = fmemopen(this->buffer, sizeof(this->buffer), "r");
|
||||
|
||||
while (fgets(line, sizeof(line), reader))
|
||||
{
|
||||
if (line[0] == '\0')
|
||||
char buffer[8192];
|
||||
char *current = buffer, *next;
|
||||
|
||||
/* write in memory buffer first */
|
||||
vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
|
||||
/* do a syslog with every line */
|
||||
while (current)
|
||||
{
|
||||
/* abort on EOF */
|
||||
break;
|
||||
}
|
||||
else if (line[0] != '\n')
|
||||
{
|
||||
syslog(this->facility|LOG_INFO, "%.2d[%s] %s", thread, prefix, line);
|
||||
next = strchr(current, '\n');
|
||||
if (next)
|
||||
{
|
||||
*(next++) = '\0';
|
||||
}
|
||||
syslog(this->facility|LOG_INFO, "%.2d[%N] %s\n",
|
||||
thread, signal_names, signal, current);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
fclose(reader);
|
||||
funlockfile(this->stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of sys_logger_t.set_level.
|
||||
*/
|
||||
static void set_level(private_sys_logger_t *this, signal_t signal, level_t max)
|
||||
static void set_level(private_sys_logger_t *this, signal_t signal, level_t level)
|
||||
{
|
||||
this->logger->set_level(this->logger, signal, max);
|
||||
if (signal == SIG_ANY)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < SIG_DBG_MAX; i++)
|
||||
{
|
||||
this->levels[i] = level;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
this->levels[SIG_TYPE(signal)] = level;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,8 +106,6 @@ static void set_level(private_sys_logger_t *this, signal_t signal, level_t max)
|
||||
static void destroy(private_sys_logger_t *this)
|
||||
{
|
||||
closelog();
|
||||
fclose(this->stream);
|
||||
this->logger->destroy(this->logger);
|
||||
free(this);
|
||||
}
|
||||
|
||||
@@ -163,19 +117,13 @@ sys_logger_t *sys_logger_create(int facility)
|
||||
private_sys_logger_t *this = malloc_thing(private_sys_logger_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.listener.signal = (void(*)(bus_listener_t*,int,ike_sa_t*,signal_t,level_t,char*,va_list))signal_;
|
||||
this->public.listener.signal = (void(*)(bus_listener_t*,signal_t,level_t,int,ike_sa_t*,char*,va_list))signal_;
|
||||
this->public.set_level = (void(*)(sys_logger_t*,signal_t,level_t))set_level;
|
||||
this->public.destroy = (void(*)(sys_logger_t*))destroy;
|
||||
|
||||
/* private variables */
|
||||
this->facility = facility;
|
||||
this->stream = fmemopen(this->buffer, sizeof(this->buffer), "w");
|
||||
if (this->stream == NULL)
|
||||
{
|
||||
/* fallback to stderr */
|
||||
this->stream = stderr;
|
||||
}
|
||||
this->logger = stream_logger_create(this->stream);
|
||||
set_level(this, SIG_ANY, LEVEL_SILENT);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user