[xiph-cvs] cvs commit: icecast/src source.c source.h util.c util.h yp.c yp.h
Ed
oddsock at xiph.org
Wed Feb 26 15:52:23 PST 2003
oddsock 03/02/26 18:52:23
Modified: src source.c source.h util.c util.h yp.c yp.h
Log:
added parsing of new icy-audio-info header which will be used to
communicate things like samplerate/quality/number of channels to
icecast2. This info will be then forwarded to the yp servers for
better stream info.
also factored out some logic in source_main into common functions
added a few new routines into util.c (taken from Brendan's
updates to libshout)
Revision Changes Path
1.37 +168 -45 icecast/src/source.c
Index: source.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/source.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- source.c 25 Feb 2003 09:40:34 -0000 1.36
+++ source.c 26 Feb 2003 23:52:23 -0000 1.37
@@ -34,12 +34,28 @@
#undef CATMODULE
#define CATMODULE "source"
+#define YP_SERVER_NAME 1
+#define YP_SERVER_DESC 2
+#define YP_SERVER_GENRE 3
+#define YP_SERVER_URL 4
+#define YP_BITRATE 5
+#define YP_AUDIO_INFO 6
+#define YP_SERVER_TYPE 7
+#define YP_CURRENT_SONG 8
+#define YP_URL_TIMEOUT 9
+#define YP_TOUCH_INTERVAL 10
+#define YP_LAST_TOUCH 11
+
/* avl tree helper */
static int _compare_clients(void *compare_arg, void *a, void *b);
static int _remove_client(void *key);
static int _free_client(void *key);
+static int _parse_audio_info(source_t *source, char *s);
+static void _add_yp_info(source_t *source, char *stat_name,
+ void *info, int type);
-source_t *source_create(client_t *client, connection_t *con, http_parser_t *parser, const char *mount, format_type_t type)
+source_t *source_create(client_t *client, connection_t *con,
+ http_parser_t *parser, const char *mount, format_type_t type)
{
int i = 0;
source_t *src;
@@ -57,6 +73,7 @@
src->num_yp_directories = 0;
src->listeners = 0;
src->send_return = 0;
+ src->audio_info = util_dict_new();
for (i=0;i<config_get_config()->num_yp_directories;i++) {
if (config_get_config()->yp_url[i]) {
src->ypdata[src->num_yp_directories] = yp_create_ypdata();
@@ -124,6 +141,7 @@
for (i=0; i<source->num_yp_directories; i++) {
yp_destroy_ypdata(source->ypdata[i]);
}
+ util_dict_free(source->audio_info);
free(source);
return 1;
@@ -149,9 +167,11 @@
refbuf_t *refbuf, *abuf;
int data_done;
- int listeners = 0;
- int i=0;
- int suppress_yp = 0;
+ int listeners = 0;
+ int i=0;
+ int suppress_yp = 0;
+ util_dict *audio_info;
+ char *ai;
long queue_limit = config_get_config()->queue_size_limit;
@@ -191,59 +211,32 @@
stats_event(source->mount, "listeners", "0");
source->listeners = 0;
if ((s = httpp_getvar(source->parser, "ice-name"))) {
- for (i=0;i<source->num_yp_directories;i++) {
- if (source->ypdata[i]->server_name) {
- free(source->ypdata[i]->server_name);
- }
- source->ypdata[i]->server_name = malloc(strlen(s) +1);
- strcpy(source->ypdata[i]->server_name, s);
- }
- stats_event(source->mount, "name", s);
+ _add_yp_info(source, "server name", s, YP_SERVER_NAME);
}
if ((s = httpp_getvar(source->parser, "ice-url"))) {
- for (i=0;i<source->num_yp_directories;i++) {
- if (source->ypdata[i]->server_url) {
- free(source->ypdata[i]->server_url);
- }
- source->ypdata[i]->server_url = malloc(strlen(s) +1);
- strcpy(source->ypdata[i]->server_url, s);
- }
- stats_event(source->mount, "url", s);
+ _add_yp_info(source, "server url", s, YP_SERVER_URL);
}
if ((s = httpp_getvar(source->parser, "ice-genre"))) {
- for (i=0;i<source->num_yp_directories;i++) {
- if (source->ypdata[i]->server_genre) {
- free(source->ypdata[i]->server_genre);
- }
- source->ypdata[i]->server_genre = malloc(strlen(s) +1);
- strcpy(source->ypdata[i]->server_genre, s);
- }
- stats_event(source->mount, "genre", s);
+ _add_yp_info(source, "genre", s, YP_SERVER_GENRE);
}
if ((s = httpp_getvar(source->parser, "ice-bitrate"))) {
- for (i=0;i<source->num_yp_directories;i++) {
- if (source->ypdata[i]->bitrate) {
- free(source->ypdata[i]->bitrate);
- }
- source->ypdata[i]->bitrate = malloc(strlen(s) +1);
- strcpy(source->ypdata[i]->bitrate, s);
- }
- stats_event(source->mount, "bitrate", s);
+ _add_yp_info(source, "bitrate", s, YP_BITRATE);
}
if ((s = httpp_getvar(source->parser, "ice-description"))) {
- for (i=0;i<source->num_yp_directories;i++) {
- if (source->ypdata[i]->server_desc) {
- free(source->ypdata[i]->server_desc);
- }
- source->ypdata[i]->server_desc = malloc(strlen(s) +1);
- strcpy(source->ypdata[i]->server_desc, s);
- }
- stats_event(source->mount, "description", s);
+ _add_yp_info(source, "server description", s, YP_SERVER_DESC);
}
if ((s = httpp_getvar(source->parser, "ice-private"))) {
stats_event(source->mount, "public", s);
suppress_yp = atoi(s);
}
+ if ((s = httpp_getvar(source->parser, "ice-audio-info"))) {
+ if (_parse_audio_info(source, s)) {
+ ai = util_dict_urlencode(source->audio_info, '&');
+ _add_yp_info(source, "audio info",
+ ai,
+ YP_AUDIO_INFO);
+ }
+ }
for (i=0;i<source->num_yp_directories;i++) {
if (source->ypdata[i]->server_type) {
free(source->ypdata[i]->server_type);
@@ -275,8 +268,14 @@
current_time = time(NULL);
+ _add_yp_info(source, "last_touch", (void *)current_time,
+ YP_LAST_TOUCH);
+
for (i=0;i<source->num_yp_directories;i++) {
- source->ypdata[i]->yp_last_touch = current_time;
+ /* Give the source 5 seconds to update the metadata
+ before we do our first touch */
+ source->ypdata[i]->yp_last_touch = current_time -
+ source->ypdata[i]->yp_touch_interval + 5;
/* Don't permit touch intervals of less than 30 seconds */
if (source->ypdata[i]->yp_touch_interval <= 30) {
source->ypdata[i]->yp_touch_interval = 30;
@@ -622,3 +621,127 @@
return 1;
}
+static int _parse_audio_info(source_t *source, char *s)
+{
+ char *token;
+ char *pvar;
+ char *variable;
+ char *value;
+
+ while ((token = strtok(s,";")) != NULL) {
+ pvar = strchr(token, '=');
+ if (pvar) {
+ variable = (char *)malloc(pvar-token+1);
+ memset(variable, '\000', pvar-token+1);
+ strncpy(variable, token, pvar-token);
+ pvar++;
+ if (strlen(pvar)) {
+ value = (char *)malloc(strlen(pvar)+1);
+ memset(value, '\000', strlen(pvar)+1);
+ strncpy(value, pvar, strlen(pvar));
+ util_dict_set(source->audio_info, variable, value);
+ stats_event(source->mount, variable, value);
+ }
+ if (variable) {
+ free(variable);
+ }
+ if (value) {
+ free(value);
+ }
+ }
+ s = NULL;
+ }
+ return 1;
+}
+
+static void _add_yp_info(source_t *source, char *stat_name,
+ void *info, int type)
+{
+ int i;
+ if (!info) {
+ return;
+ }
+ for (i=0;i<source->num_yp_directories;i++) {
+ switch (type) {
+ case YP_SERVER_NAME:
+ if (source->ypdata[i]->server_name) {
+ free(source->ypdata[i]->server_name);
+ }
+ source->ypdata[i]->server_name =
+ malloc(strlen((char *)info) +1);
+ strcpy(source->ypdata[i]->server_name, (char *)info);
+ stats_event(source->mount, stat_name, (char *)info);
+ break;
+ case YP_SERVER_DESC:
+ if (source->ypdata[i]->server_desc) {
+ free(source->ypdata[i]->server_desc);
+ }
+ source->ypdata[i]->server_desc =
+ malloc(strlen((char *)info) +1);
+ strcpy(source->ypdata[i]->server_desc, (char *)info);
+ stats_event(source->mount, stat_name, (char *)info);
+ break;
+ case YP_SERVER_GENRE:
+ if (source->ypdata[i]->server_genre) {
+ free(source->ypdata[i]->server_genre);
+ }
+ source->ypdata[i]->server_genre =
+ malloc(strlen((char *)info) +1);
+ strcpy(source->ypdata[i]->server_genre, (char *)info);
+ stats_event(source->mount, stat_name, (char *)info);
+ break;
+ case YP_SERVER_URL:
+ if (source->ypdata[i]->server_url) {
+ free(source->ypdata[i]->server_url);
+ }
+ source->ypdata[i]->server_url =
+ malloc(strlen((char *)info) +1);
+ strcpy(source->ypdata[i]->server_url, (char *)info);
+ stats_event(source->mount, stat_name, (char *)info);
+ break;
+ case YP_BITRATE:
+ if (source->ypdata[i]->bitrate) {
+ free(source->ypdata[i]->bitrate);
+ }
+ source->ypdata[i]->bitrate =
+ malloc(strlen((char *)info) +1);
+ strcpy(source->ypdata[i]->bitrate, (char *)info);
+ stats_event(source->mount, stat_name, (char *)info);
+ break;
+ case YP_AUDIO_INFO:
+ if (source->ypdata[i]->audio_info) {
+ free(source->ypdata[i]->audio_info);
+ }
+ source->ypdata[i]->audio_info =
+ malloc(strlen((char *)info) +1);
+ strcpy(source->ypdata[i]->audio_info, (char *)info);
+ break;
+ case YP_SERVER_TYPE:
+ if (source->ypdata[i]->server_type) {
+ free(source->ypdata[i]->server_type);
+ }
+ source->ypdata[i]->server_type =
+ malloc(strlen((char *)info) +1);
+ strcpy(source->ypdata[i]->server_type, (char *)info);
+ break;
+ case YP_CURRENT_SONG:
+ if (source->ypdata[i]->current_song) {
+ free(source->ypdata[i]->current_song);
+ }
+ source->ypdata[i]->current_song =
+ malloc(strlen((char *)info) +1);
+ strcpy(source->ypdata[i]->current_song, (char *)info);
+ stats_event(source->mount, stat_name, (char *)info);
+ break;
+ case YP_URL_TIMEOUT:
+ source->ypdata[i]->yp_url_timeout = (int)info;
+ break;
+ case YP_LAST_TOUCH:
+ source->ypdata[i]->yp_last_touch = (int)info;
+ break;
+ case YP_TOUCH_INTERVAL:
+ source->ypdata[i]->yp_touch_interval = (int)info;
+ break;
+ }
+ }
+}
<p><p>1.9 +2 -0 icecast/src/source.h
Index: source.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/source.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- source.h 17 Feb 2003 13:01:37 -0000 1.8
+++ source.h 26 Feb 2003 23:52:23 -0000 1.9
@@ -3,6 +3,7 @@
#include "config.h"
#include "yp.h"
+#include "util.h"
#include "format.h"
typedef struct source_tag
@@ -27,6 +28,7 @@
rwlock_t *shutdown_rwlock;
ypdata_t *ypdata[MAX_YP_DIRECTORIES];
+ util_dict *audio_info;
int num_yp_directories;
long listeners;
long max_listeners;
<p><p>1.17 +136 -0 icecast/src/util.c
Index: util.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/util.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- util.c 25 Feb 2003 09:40:34 -0000 1.16
+++ util.c 26 Feb 2003 23:52:23 -0000 1.17
@@ -385,3 +385,139 @@
return result;
}
+util_dict *util_dict_new(void)
+{
+ return (util_dict *)calloc(1, sizeof(util_dict));
+}
+
+void util_dict_free(util_dict *dict)
+{
+ util_dict *next;
+
+ while (dict) {
+ next = dict->next;
+
+ if (dict->key)
+ free (dict->key);
+ if (dict->val)
+ free (dict->val);
+ free (dict);
+
+ dict = next;
+ }
+}
+
+const char *util_dict_get(util_dict *dict, const char *key)
+{
+ while (dict) {
+ if (!strcmp(key, dict->key))
+ return dict->val;
+ dict = dict->next;
+ }
+}
+
+int util_dict_set(util_dict *dict, const char *key, const char *val)
+{
+ util_dict *prev;
+
+ if (!dict || !key) {
+ ERROR0("NULL values passed to util_dict_set()");
+ return 0;
+ }
+
+ prev = NULL;
+ while (dict) {
+ if (!dict->key || !strcmp(dict->key, key))
+ break;
+ prev = dict;
+ dict = dict->next;
+ }
+
+ if (!dict) {
+ dict = util_dict_new();
+ if (!dict) {
+ ERROR0("unable to allocate new dictionary");
+ return 0;
+ }
+ if (prev)
+ prev->next = dict;
+ }
+
+ if (dict->key)
+ free (dict->val);
+ else if (!(dict->key = strdup(key))) {
+ if (prev)
+ prev->next = NULL;
+ util_dict_free (dict);
+
+ ERROR0("unable to allocate new dictionary key");
+ return 0;
+ }
+
+ dict->val = strdup(val);
+ if (!dict->val) {
+ ERROR0("unable to allocate new dictionary value");
+ return 0;
+ }
+
+ return 1;
+}
+
+/* given a dictionary, URL-encode each key and val and
+ stringify them in order as key=val&key=val... if val
+ is set, or just key&key if val is NULL.
+ TODO: Memory management needs overhaul. */
+char *util_dict_urlencode(util_dict *dict, char delim)
+{
+ char *res, *tmp;
+ char *enc;
+ int start = 1;
+
+ for (res = NULL; dict; dict = dict->next) {
+ /* encode key */
+ if (!dict->key)
+ continue;
+ if (!(enc = util_url_escape(dict->key))) {
+ if (res)
+ free(res);
+ return NULL;
+ }
+ if (start) {
+ if (!(res = malloc(strlen(enc) + 1))) {
+ free(enc);
+ return NULL;
+ }
+ sprintf(res, "%s", enc);
+ free(enc);
+ start = 0;
+ } else {
+ if (!(tmp = realloc(res, strlen(res) + strlen(enc) + 2))) {
+ free(enc);
+ free(res);
+ return NULL;
+ } else
+ res = tmp;
+ sprintf(res + strlen(res), "%c%s", delim, enc);
+ free(enc);
+ }
+
+ /* encode value */
+ if (!dict->val)
+ continue;
+ if (!(enc = util_url_escape(dict->val))) {
+ free(res);
+ return NULL;
+ }
+
+ if (!(tmp = realloc(res, strlen(res) + strlen(enc) + 2))) {
+ free(enc);
+ free(res);
+ return NULL;
+ } else
+ res = tmp;
+ sprintf(res + strlen(res), "=%s", enc);
+ free(enc);
+ }
+
+ return res;
+}
<p><p>1.10 +14 -0 icecast/src/util.h
Index: util.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/util.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- util.h 31 Dec 2002 06:28:38 -0000 1.9
+++ util.h 26 Feb 2003 23:52:23 -0000 1.10
@@ -16,4 +16,18 @@
char *util_url_escape(char *src);
+/* String dictionary type, without support for NULL keys, or multiple
+ * instances of the same key */
+typedef struct _util_dict {
+ char *key;
+ char *val;
+ struct _util_dict *next;
+} util_dict;
+
+util_dict *util_dict_new(void);
+void util_dict_free(util_dict *dict);
+/* dict, key must not be NULL. */
+int util_dict_set(util_dict *dict, const char *key, const char *val);
+const char *util_dict_get(util_dict *dict, const char *key);
+char *util_dict_urlencode(util_dict *dict, char delim);
#endif /* __UTIL_H__ */
<p><p>1.5 +18 -5 icecast/src/yp.c
Index: yp.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/yp.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- yp.c 6 Feb 2003 13:10:48 -0000 1.4
+++ yp.c 26 Feb 2003 23:52:23 -0000 1.5
@@ -196,8 +196,9 @@
if (ok) {
if (source->ypdata[i]) {
- url_size = strlen("action=add&sn=&genre=&cpswd=&desc=&url="
- "&listenurl=&type=&b=") + 1;
+ url_size = strlen("action=add&sn=&genre=&cpswd="
+ "&desc=&url=&listenurl=&type=&b=&")
+ + 1;
if (source->ypdata[i]->server_name) {
url_size += strlen(source->ypdata[i]->server_name);
}
@@ -261,10 +262,18 @@
source->ypdata[i]->current_song = (char *)malloc(1);
source->ypdata[i]->current_song[0] = 0;
}
+ if (source->ypdata[i]->audio_info) {
+ url_size += strlen(source->ypdata[i]->audio_info);
+ }
+ else {
+ source->ypdata[i]->audio_info = (char *)malloc(1);
+ source->ypdata[i]->audio_info[0] = 0;
+ }
+
url_size += 1024;
url = malloc(url_size);
- sprintf(url, "action=add&sn=%s&genre=%s&cpswd=%s&desc=%s&url=%s"
- "&listenurl=%s&type=%s&b=%s",
+ sprintf(url, "action=add&sn=%s&genre=%s&cpswd=%s&desc="
+ "%s&url=%s&listenurl=%s&type=%s&b=%s&%s",
source->ypdata[i]->server_name,
source->ypdata[i]->server_genre,
source->ypdata[i]->cluster_password,
@@ -272,7 +281,8 @@
source->ypdata[i]->server_url,
source->ypdata[i]->listen_url,
source->ypdata[i]->server_type,
- source->ypdata[i]->bitrate);
+ source->ypdata[i]->bitrate,
+ source->ypdata[i]->audio_info);
curl_con = curl_get_connection();
if (curl_con < 0) {
@@ -349,6 +359,9 @@
}
if (ypdata->server_type) {
free(ypdata->server_type);
+ }
+ if (ypdata->audio_info) {
+ free(ypdata->audio_info);
}
free(ypdata);
}
<p><p>1.4 +1 -0 icecast/src/yp.h
Index: yp.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/yp.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- yp.h 6 Feb 2003 13:10:48 -0000 1.3
+++ yp.h 26 Feb 2003 23:52:23 -0000 1.4
@@ -16,6 +16,7 @@
char *server_url;
char *listen_url;
char *bitrate;
+ char *audio_info;
char *server_type;
char *current_song;
char *yp_url;
<p><p>--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list