diff --git a/daemon/log.c b/daemon/log.c index 396fd65f9..0dec25c47 100644 --- a/daemon/log.c +++ b/daemon/log.c @@ -5,6 +5,7 @@ #include #include "str.h" #include "call.h" +#include "poller.h" @@ -60,6 +61,13 @@ const char const* prio_str[] = { gboolean _log_stderr = 0; int _log_facility = LOG_DAEMON; + +static GHashTable *__log_limiter; +static mutex_t __log_limiter_lock; +static GStringChunk *__log_limiter_strings; +static unsigned int __log_limiter_count; + + void log_to_stderr(int facility_priority, char *format, ...) { char *msg; int ret; @@ -122,6 +130,31 @@ void ilog(int prio, const char *fmt, ...) { return; } + if ((prio & LOG_FLAG_LIMIT)) { + time_t when; + + mutex_lock(&__log_limiter_lock); + + if (__log_limiter_count > 10000) { + g_hash_table_remove_all(__log_limiter); + g_string_chunk_clear(__log_limiter_strings); + __log_limiter_count = 0; + } + + when = (time_t) g_hash_table_lookup(__log_limiter, msg); + if (!when || (poller_now - when) >= 15) { + g_hash_table_insert(__log_limiter, g_string_chunk_insert(__log_limiter_strings, + msg), (void *) poller_now); + __log_limiter_count++; + when = 0; + } + + mutex_unlock(&__log_limiter_lock); + + if (when) + goto out; + } + piece = msg; while (ret > MAX_LOG_LINE_LENGTH) { @@ -133,7 +166,13 @@ void ilog(int prio, const char *fmt, ...) { write_log(xprio, "%s%s%s", prefix, infix, piece); +out: free(msg); } +void log_init() { + mutex_init(&__log_limiter_lock); + __log_limiter = g_hash_table_new(g_str_hash, g_str_equal); + __log_limiter_strings = g_string_chunk_new(1024); +} diff --git a/daemon/log.h b/daemon/log.h index 79c142e29..23170f4dc 100644 --- a/daemon/log.h +++ b/daemon/log.h @@ -42,6 +42,7 @@ extern volatile gint log_level; +void log_init(void); void ilog(int prio, const char *fmt, ...)__attribute__ ((format (printf, 2, 3))); @@ -92,6 +93,7 @@ INLINE void log_info_stream_fd(struct stream_fd *sfd) { #define LOG_LEVEL_MASK(v) ((v) & 0x0f) #define LOG_FLAG_RESTORE 0x10 +#define LOG_FLAG_LIMIT 0x20 diff --git a/daemon/main.c b/daemon/main.c index 7afdc7036..d746cb7db 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -432,6 +432,7 @@ static void wpidfile(void) { static void init_everything() { struct timespec ts; + log_init(); clock_gettime(CLOCK_REALTIME, &ts); srandom(ts.tv_sec ^ ts.tv_nsec); SSL_library_init(); diff --git a/daemon/rtcp.c b/daemon/rtcp.c index 8054846d5..aa9bc3e06 100644 --- a/daemon/rtcp.c +++ b/daemon/rtcp.c @@ -358,7 +358,7 @@ INLINE int check_session_keys(struct crypto_context *c) { return 0; error: - ilog(LOG_ERROR, "%s", err); + ilog(LOG_ERROR | LOG_FLAG_LIMIT, "%s", err); return -1; } @@ -386,7 +386,7 @@ static int rtcp_payload(struct rtcp_packet **out, str *p, const str *s) { return 0; error: - ilog(LOG_WARNING, "Error parsing RTCP header: %s", err); + ilog(LOG_WARNING | LOG_FLAG_LIMIT, "Error parsing RTCP header: %s", err); return -1; } @@ -461,7 +461,7 @@ int rtcp_savp2avp(str *s, struct crypto_context *c) { return 0; error: - ilog(LOG_WARNING, "Discarded invalid SRTCP packet: %s", err); + ilog(LOG_WARNING | LOG_FLAG_LIMIT, "Discarded invalid SRTCP packet: %s", err); return -1; } diff --git a/daemon/rtp.c b/daemon/rtp.c index 2edaa2e48..79ef2b52c 100644 --- a/daemon/rtp.c +++ b/daemon/rtp.c @@ -47,7 +47,7 @@ INLINE int check_session_keys(struct crypto_context *c) { return 0; error: - ilog(LOG_ERROR, "%s", err); + ilog(LOG_ERROR | LOG_FLAG_LIMIT, "%s", err); return -1; } @@ -89,7 +89,7 @@ static int rtp_payload(struct rtp_header **out, str *p, const str *s) { return 0; error: - ilog(LOG_WARNING, "Error parsing RTP header: %s", err); + ilog(LOG_WARNING | LOG_FLAG_LIMIT, "Error parsing RTP header: %s", err); return -1; } @@ -199,7 +199,7 @@ int rtp_savp2avp(str *s, struct crypto_context *c) { return 0; error: - ilog(LOG_WARNING, "Discarded invalid SRTP packet: authentication failed"); + ilog(LOG_WARNING | LOG_FLAG_LIMIT, "Discarded invalid SRTP packet: authentication failed"); return -1; } @@ -239,6 +239,6 @@ int srtp_payloads(str *to_auth, str *to_decrypt, str *auth_tag, str *mki, return 0; error: - ilog(LOG_WARNING, "Invalid SRTP/SRTCP packet received (short packet)"); + ilog(LOG_WARNING | LOG_FLAG_LIMIT, "Invalid SRTP/SRTCP packet received (short packet)"); return -1; }