2004-01-28 20:02:12 -05:00
|
|
|
/* Icecast
|
|
|
|
*
|
|
|
|
* This program is distributed under the GNU General Public License, version 2.
|
|
|
|
* A copy of this license is included with this source.
|
|
|
|
*
|
2015-01-10 13:53:44 -05:00
|
|
|
* Copyright 2000-2004, Jack Moffitt <jack@xiph.org,
|
2004-01-28 20:02:12 -05:00
|
|
|
* Michael Smith <msmith@xiph.org>,
|
|
|
|
* oddsock <oddsock@xiph.org>,
|
|
|
|
* Karl Heyes <karl@xiph.org>
|
|
|
|
* and others (see AUTHORS for details).
|
2018-11-26 02:42:05 -05:00
|
|
|
* Copyright 2011-2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
|
2004-01-28 20:02:12 -05:00
|
|
|
*/
|
|
|
|
|
2003-07-20 21:58:54 -04:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2001-09-09 22:21:46 -04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <time.h>
|
2003-07-11 19:54:50 -04:00
|
|
|
#include <string.h>
|
2001-09-09 22:21:46 -04:00
|
|
|
|
2014-12-02 16:50:57 -05:00
|
|
|
#include "common/thread/thread.h"
|
|
|
|
#include "common/httpp/httpp.h"
|
2001-09-09 22:21:46 -04:00
|
|
|
|
2018-06-17 08:28:38 -04:00
|
|
|
#include "logging.h"
|
2001-09-09 22:21:46 -04:00
|
|
|
#include "connection.h"
|
|
|
|
#include "refbuf.h"
|
|
|
|
#include "client.h"
|
|
|
|
|
2005-12-17 07:41:34 -05:00
|
|
|
#include "compat.h"
|
2003-07-20 21:58:54 -04:00
|
|
|
#include "cfgfile.h"
|
2004-01-26 21:16:25 -05:00
|
|
|
#include "util.h"
|
2001-09-09 22:21:46 -04:00
|
|
|
|
2001-10-20 02:43:04 -04:00
|
|
|
#ifdef _WIN32
|
|
|
|
#define snprintf _snprintf
|
2007-11-22 21:48:37 -05:00
|
|
|
#define vsnprintf _vsnprintf
|
2001-10-20 02:43:04 -04:00
|
|
|
#endif
|
|
|
|
|
2001-09-09 22:21:46 -04:00
|
|
|
/* the global log descriptors */
|
2002-07-23 11:15:11 -04:00
|
|
|
int errorlog = 0;
|
|
|
|
int accesslog = 0;
|
2004-11-15 23:04:02 -05:00
|
|
|
int playlistlog = 0;
|
2004-10-25 11:51:50 -04:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
/* Since strftime's %z option on win32 is different, we need
|
2014-11-30 15:32:30 -05:00
|
|
|
to go through a few loops to get the same info as %z */
|
2004-10-25 11:51:50 -04:00
|
|
|
int get_clf_time (char *buffer, unsigned len, struct tm *t)
|
|
|
|
{
|
2014-11-30 15:32:30 -05:00
|
|
|
char sign;
|
2015-04-08 05:36:59 -04:00
|
|
|
char timezone_string[7];
|
2004-10-25 11:51:50 -04:00
|
|
|
struct tm gmt;
|
|
|
|
time_t time1 = time(NULL);
|
|
|
|
int time_days, time_hours, time_tz;
|
|
|
|
int tempnum1, tempnum2;
|
|
|
|
struct tm *thetime;
|
|
|
|
time_t now;
|
|
|
|
|
2012-10-10 18:41:30 -04:00
|
|
|
#if !defined(_WIN32)
|
|
|
|
thetime = gmtime_r(&time1, &gmt)
|
|
|
|
#else
|
|
|
|
/* gmtime() on W32 breaks POSIX and IS thread-safe (uses TLS) */
|
|
|
|
thetime = gmtime (&time1);
|
|
|
|
if (thetime)
|
|
|
|
memcpy (&gmt, thetime, sizeof (gmt));
|
|
|
|
#endif
|
|
|
|
/* FIXME: bail out if gmtime* returns NULL */
|
2004-10-25 11:51:50 -04:00
|
|
|
|
2015-04-08 05:36:59 -04:00
|
|
|
if (!thetime) {
|
|
|
|
snprintf(buffer, len, "<<BAD TIMESTAMP>>");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-10-25 11:51:50 -04:00
|
|
|
time_days = t->tm_yday - gmt.tm_yday;
|
|
|
|
|
|
|
|
if (time_days < -1) {
|
|
|
|
tempnum1 = 24;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tempnum1 = 1;
|
|
|
|
}
|
|
|
|
if (tempnum1 < time_days) {
|
|
|
|
tempnum2 = -24;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tempnum2 = time_days*24;
|
|
|
|
}
|
|
|
|
|
|
|
|
time_hours = (tempnum2 + t->tm_hour - gmt.tm_hour);
|
|
|
|
time_tz = time_hours * 60 + t->tm_min - gmt.tm_min;
|
|
|
|
|
|
|
|
if (time_tz < 0) {
|
|
|
|
sign = '-';
|
|
|
|
time_tz = -time_tz;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sign = '+';
|
|
|
|
}
|
2005-05-24 21:43:33 -04:00
|
|
|
|
2015-04-08 05:36:59 -04:00
|
|
|
snprintf(timezone_string, sizeof(timezone_string), " %c%.2d%.2d", sign, time_tz / 60, time_tz % 60);
|
2004-10-25 11:51:50 -04:00
|
|
|
|
|
|
|
now = time(NULL);
|
|
|
|
|
|
|
|
thetime = localtime(&now);
|
2015-04-08 05:36:59 -04:00
|
|
|
strftime(buffer, len - sizeof(timezone_string), "%d/%b/%Y:%H:%M:%S", thetime);
|
2004-10-25 11:51:50 -04:00
|
|
|
strcat(buffer, timezone_string);
|
|
|
|
return 1;
|
|
|
|
}
|
2004-10-25 10:43:07 -04:00
|
|
|
#endif
|
2015-01-10 13:53:44 -05:00
|
|
|
/*
|
2014-11-30 15:32:30 -05:00
|
|
|
** ADDR IDENT USER DATE REQUEST CODE BYTES REFERER AGENT [TIME]
|
|
|
|
**
|
|
|
|
** ADDR = client->con->ip
|
|
|
|
** IDENT = always - , we don't support it because it's useless
|
|
|
|
** USER = client->username
|
|
|
|
** DATE = _make_date(client->con->con_time)
|
|
|
|
** REQUEST = build from client->parser
|
|
|
|
** CODE = client->respcode
|
|
|
|
** BYTES = client->con->sent_bytes
|
|
|
|
** REFERER = get from client->parser
|
|
|
|
** AGENT = get from client->parser
|
|
|
|
** TIME = timing_get_time() - client->con->con_time
|
|
|
|
*/
|
2001-09-09 22:21:46 -04:00
|
|
|
void logging_access(client_t *client)
|
|
|
|
{
|
2003-03-14 21:10:19 -05:00
|
|
|
char datebuf[128];
|
2004-01-26 21:16:25 -05:00
|
|
|
struct tm thetime;
|
2003-03-14 21:10:19 -05:00
|
|
|
time_t now;
|
|
|
|
time_t stayed;
|
2007-08-16 18:49:13 -04:00
|
|
|
const char *referrer, *user_agent, *username;
|
2003-03-14 21:10:19 -05:00
|
|
|
|
|
|
|
now = time(NULL);
|
|
|
|
|
2005-05-24 21:43:33 -04:00
|
|
|
localtime_r (&now, &thetime);
|
2003-03-14 21:10:19 -05:00
|
|
|
/* build the data */
|
2004-10-25 11:51:50 -04:00
|
|
|
#ifdef _WIN32
|
2005-05-24 21:43:33 -04:00
|
|
|
memset(datebuf, '\000', sizeof(datebuf));
|
|
|
|
get_clf_time(datebuf, sizeof(datebuf)-1, &thetime);
|
2004-10-25 11:51:50 -04:00
|
|
|
#else
|
2004-01-26 21:16:25 -05:00
|
|
|
strftime (datebuf, sizeof(datebuf), LOGGING_FORMAT_CLF, &thetime);
|
2004-10-25 10:43:07 -04:00
|
|
|
#endif
|
2003-03-14 21:10:19 -05:00
|
|
|
|
|
|
|
stayed = now - client->con->con_time;
|
|
|
|
|
2005-09-12 12:47:04 -04:00
|
|
|
if (client->username == NULL)
|
2015-01-10 13:53:44 -05:00
|
|
|
username = "-";
|
2005-09-12 12:47:04 -04:00
|
|
|
else
|
|
|
|
username = client->username;
|
|
|
|
|
2004-01-26 21:16:25 -05:00
|
|
|
referrer = httpp_getvar (client->parser, "referer");
|
|
|
|
if (referrer == NULL)
|
|
|
|
referrer = "-";
|
|
|
|
|
|
|
|
user_agent = httpp_getvar (client->parser, "user-agent");
|
|
|
|
if (user_agent == NULL)
|
|
|
|
user_agent = "-";
|
|
|
|
|
2005-05-24 21:43:33 -04:00
|
|
|
log_write_direct (accesslog,
|
2014-11-08 08:34:45 -05:00
|
|
|
"%s - %H [%s] \"%H %H %H/%H\" %d %llu \"% H\" \"% H\" %llu",
|
2005-05-24 21:43:33 -04:00
|
|
|
client->con->ip,
|
2005-09-12 12:47:04 -04:00
|
|
|
username,
|
2005-05-24 21:43:33 -04:00
|
|
|
datebuf,
|
2013-04-02 08:19:33 -04:00
|
|
|
httpp_getvar (client->parser, HTTPP_VAR_REQ_TYPE),
|
|
|
|
httpp_getvar (client->parser, HTTPP_VAR_URI),
|
|
|
|
httpp_getvar (client->parser, HTTPP_VAR_PROTOCOL),
|
|
|
|
httpp_getvar (client->parser, HTTPP_VAR_VERSION),
|
2005-05-24 21:43:33 -04:00
|
|
|
client->respcode,
|
2014-11-08 08:34:45 -05:00
|
|
|
(long long unsigned int)client->con->sent_bytes,
|
2005-05-24 21:43:33 -04:00
|
|
|
referrer,
|
|
|
|
user_agent,
|
2014-11-08 08:34:45 -05:00
|
|
|
(long long unsigned int)stayed);
|
2001-09-09 22:21:46 -04:00
|
|
|
}
|
2004-11-15 23:04:02 -05:00
|
|
|
/* This function will provide a log of metadata for each
|
|
|
|
mountpoint. The metadata *must* be in UTF-8, and thus
|
|
|
|
you can assume that the log itself is UTF-8 encoded */
|
2005-05-24 21:43:33 -04:00
|
|
|
void logging_playlist(const char *mount, const char *metadata, long listeners)
|
2004-11-15 23:04:02 -05:00
|
|
|
{
|
|
|
|
char datebuf[128];
|
|
|
|
struct tm thetime;
|
|
|
|
time_t now;
|
|
|
|
|
|
|
|
if (playlistlog == -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
now = time(NULL);
|
|
|
|
|
|
|
|
localtime_r (&now, &thetime);
|
|
|
|
/* build the data */
|
|
|
|
#ifdef _WIN32
|
|
|
|
memset(datebuf, '\000', sizeof(datebuf));
|
|
|
|
get_clf_time(datebuf, sizeof(datebuf)-1, &thetime);
|
|
|
|
#else
|
|
|
|
strftime (datebuf, sizeof(datebuf), LOGGING_FORMAT_CLF, &thetime);
|
|
|
|
#endif
|
|
|
|
/* This format MAY CHANGE OVER TIME. We are looking into finding a good
|
|
|
|
standard format for this, if you have any ideas, please let us know */
|
2007-11-22 21:48:37 -05:00
|
|
|
log_write_direct (playlistlog, "%s|%s|%ld|%s",
|
2004-11-15 23:04:02 -05:00
|
|
|
datebuf,
|
|
|
|
mount,
|
|
|
|
listeners,
|
|
|
|
metadata);
|
|
|
|
}
|
2001-09-09 22:21:46 -04:00
|
|
|
|
|
|
|
|
2005-08-16 12:56:24 -04:00
|
|
|
void log_parse_failure (void *ctx, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
char line [200];
|
|
|
|
va_list ap;
|
|
|
|
char *eol;
|
|
|
|
|
|
|
|
va_start (ap, fmt);
|
|
|
|
vsnprintf (line, sizeof (line), fmt, ap);
|
|
|
|
eol = strrchr (line, '\n');
|
|
|
|
if (eol) *eol='\0';
|
|
|
|
va_end (ap);
|
|
|
|
log_write (errorlog, 2, (char*)ctx, "", "%s", line);
|
|
|
|
}
|
|
|
|
|
2001-09-09 22:21:46 -04:00
|
|
|
|
2004-08-20 17:40:44 -04:00
|
|
|
void restart_logging (ice_config_t *config)
|
2003-07-11 19:54:50 -04:00
|
|
|
{
|
|
|
|
if (strcmp (config->error_log, "-"))
|
|
|
|
{
|
|
|
|
char fn_error[FILENAME_MAX];
|
|
|
|
snprintf (fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->error_log);
|
|
|
|
log_set_filename (errorlog, fn_error);
|
|
|
|
log_set_level (errorlog, config->loglevel);
|
2005-10-24 10:51:54 -04:00
|
|
|
log_set_trigger (errorlog, config->logsize);
|
|
|
|
log_set_archive_timestamp(errorlog, config->logarchive);
|
2003-07-11 19:54:50 -04:00
|
|
|
log_reopen (errorlog);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp (config->access_log, "-"))
|
|
|
|
{
|
|
|
|
char fn_error[FILENAME_MAX];
|
|
|
|
snprintf (fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->access_log);
|
|
|
|
log_set_filename (accesslog, fn_error);
|
2007-11-22 21:48:37 -05:00
|
|
|
log_set_trigger (accesslog, config->logsize);
|
|
|
|
log_set_archive_timestamp (accesslog, config->logarchive);
|
2003-07-11 19:54:50 -04:00
|
|
|
log_reopen (accesslog);
|
|
|
|
}
|
2004-11-15 23:04:02 -05:00
|
|
|
|
|
|
|
if (config->playlist_log)
|
|
|
|
{
|
|
|
|
char fn_error[FILENAME_MAX];
|
|
|
|
snprintf (fn_error, FILENAME_MAX, "%s%s%s", config->log_dir, PATH_SEPARATOR, config->playlist_log);
|
|
|
|
log_set_filename (playlistlog, fn_error);
|
2007-11-22 21:48:37 -05:00
|
|
|
log_set_trigger (playlistlog, config->logsize);
|
|
|
|
log_set_archive_timestamp (playlistlog, config->logarchive);
|
2004-11-15 23:04:02 -05:00
|
|
|
log_reopen (playlistlog);
|
|
|
|
}
|
2020-10-02 07:02:07 -04:00
|
|
|
|
|
|
|
log_set_lines_kept(errorlog, config->error_log_lines_kept);
|
|
|
|
log_set_lines_kept(accesslog, config->access_log_lines_kept);
|
|
|
|
log_set_lines_kept(playlistlog, config->playlist_log_lines_kept);
|
2003-07-11 19:54:50 -04:00
|
|
|
}
|