[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