[xiph-commits] r8186 - icecast/branches/kh/icecast/src

karl at motherfish-iii.xiph.org karl at motherfish-iii.xiph.org
Wed Nov 10 06:35:19 PST 2004


Author: karl
Date: 2004-11-10 06:35:18 -0800 (Wed, 10 Nov 2004)
New Revision: 8186

Modified:
   icecast/branches/kh/icecast/src/client.c
   icecast/branches/kh/icecast/src/client.h
   icecast/branches/kh/icecast/src/format.c
   icecast/branches/kh/icecast/src/format.h
   icecast/branches/kh/icecast/src/format_mp3.c
   icecast/branches/kh/icecast/src/format_ogg.c
   icecast/branches/kh/icecast/src/format_vorbis.c
   icecast/branches/kh/icecast/src/slave.c
   icecast/branches/kh/icecast/src/slave.h
   icecast/branches/kh/icecast/src/source.c
Log:
drop separate predata handler for http headers, now use a per-client refbuf
instead with a specific write handler. drop ICY reply and cleanup some API
bits as well


Modified: icecast/branches/kh/icecast/src/client.c
===================================================================
--- icecast/branches/kh/icecast/src/client.c	2004-11-09 08:06:21 UTC (rev 8185)
+++ icecast/branches/kh/icecast/src/client.c	2004-11-10 14:35:18 UTC (rev 8186)
@@ -29,6 +29,7 @@
 
 #include "connection.h"
 #include "refbuf.h"
+#include "format.h"
 
 #include "client.h"
 #include "logging.h"
@@ -48,6 +49,7 @@
     client->parser = parser;
     client->refbuf = NULL;
     client->pos = 0;
+    client->write_to_client = format_generic_write_to_client;
 
     return client;
 }

Modified: icecast/branches/kh/icecast/src/client.h
===================================================================
--- icecast/branches/kh/icecast/src/client.h	2004-11-09 08:06:21 UTC (rev 8185)
+++ icecast/branches/kh/icecast/src/client.h	2004-11-10 14:35:18 UTC (rev 8186)
@@ -25,6 +25,8 @@
 #include "connection.h"
 #include "refbuf.h"
 
+struct source_tag;
+
 typedef struct _client_tag
 {
     /* the client's connection */
@@ -64,12 +66,8 @@
 
     /* function to call to release format specific resources */
     void (*free_client_data)(struct _client_tag *client);
+    int (*write_to_client)(struct source_tag *source, struct _client_tag *client);
 
-    char *predata;
-    unsigned predata_size;
-    unsigned predata_len;
-    unsigned predata_offset;
-
     struct _client_tag *next;
 } client_t;
 

Modified: icecast/branches/kh/icecast/src/format.c
===================================================================
--- icecast/branches/kh/icecast/src/format.c	2004-11-09 08:06:21 UTC (rev 8185)
+++ icecast/branches/kh/icecast/src/format.c	2004-11-10 14:35:18 UTC (rev 8186)
@@ -48,6 +48,9 @@
 #define snprintf _snprintf
 #endif
 
+static int format_prepare_headers (source_t *source, client_t *client);
+
+
 format_type_t format_get_type(char *contenttype)
 {
     if(strcmp(contenttype, "application/x-ogg") == 0)
@@ -95,41 +98,84 @@
     return ret;
 }
 
+int format_http_write_to_client (source_t *source, client_t *client)
+{
+    refbuf_t *refbuf = client->refbuf;
+    const char *buf;
+    unsigned int len;
+    int ret;
 
-int format_generic_write_buf_to_client(format_plugin_t *format, 
-        client_t *client, unsigned char *buf, int len)
+    if (refbuf == NULL)
+    {
+        client->write_to_client = source->format->write_buf_to_client;
+        return 0;
+    }
+    if (client->respcode == 0)
+    {
+        DEBUG0("processing pending client headers");
+
+        client->respcode = 200;
+        if (format_prepare_headers (source, client) < 0)
+        {
+            ERROR0 ("internal problem, dropping client");
+            client->con->error = 1;
+            return 0;
+        }
+    }
+
+    buf = refbuf->data + client->pos;
+    len = refbuf->len - client->pos;
+
+    ret = client_send_bytes (client, buf, len);
+
+    if (ret > 0)
+        client->pos += ret;
+    if (client->pos == refbuf->len)
+        client_set_queue (client, NULL);
+
+    return ret;
+}
+
+
+int format_generic_write_to_client (source_t *source, client_t *client)
 {
     int ret;
+    const char *buf;
+    unsigned int len;
+    refbuf_t * refbuf = client->refbuf;
 
+    if (refbuf == NULL)
+        return 0;
+    buf = refbuf->data + client->pos;
+    len = refbuf->len - client->pos;
+
     ret = client_send_bytes (client, buf, len);
-    if (ret < 0 && client->con->error == 0)
-        ret = 0;
 
+    if (ret == len)
+    {
+        client_set_queue (client, refbuf->next);
+        if (client->refbuf == NULL)
+            client->write_to_client = source->format->write_buf_to_client;
+    }
+
     return ret;
 }
 
 
-void format_prepare_headers (source_t *source, client_t *client)
+static int format_prepare_headers (source_t *source, client_t *client)
 {
     unsigned remaining;
     char *ptr;
     int bytes;
     int bitrate_filtered = 0;
     avl_node *node;
-    char *agent;
 
-    remaining = client->predata_size;
-    ptr = client->predata;
+    remaining = client->refbuf->len;
+    ptr = client->refbuf->data;
     client->respcode = 200;
 
-    /* ugly hack, but send ICY OK header when client is realplayer */
-    agent = httpp_getvar (client->parser, "user-agent");
-    if (agent && strstr (agent, "RealMedia") != NULL)
-        bytes = snprintf (ptr, remaining, "ICY 200 OK\r\nContent-Type: %s\r\n",
-                format_get_mimetype (source->format->type));
-    else
-        bytes = snprintf (ptr, remaining, "HTTP/1.0 200 OK\r\nContent-Type: %s\r\n",
-                format_get_mimetype (source->format->type));
+    bytes = snprintf (ptr, remaining, "HTTP/1.0 200 OK\r\n"
+            "Content-Type: %s\r\n", format_get_mimetype (source->format->type));
 
     remaining -= bytes;
     ptr += bytes;
@@ -200,7 +246,11 @@
     remaining -= bytes;
     ptr += bytes;
 
-    client->predata_len = client->predata_size - remaining;
+    client->refbuf->len -= remaining;
+    if (source->format->create_client_data)
+        if (source->format->create_client_data (source, client) < 0)
+            return -1;
+    return 0;
 }
 
 

Modified: icecast/branches/kh/icecast/src/format.h
===================================================================
--- icecast/branches/kh/icecast/src/format.h	2004-11-09 08:06:21 UTC (rev 8185)
+++ icecast/branches/kh/icecast/src/format.h	2004-11-10 14:35:18 UTC (rev 8186)
@@ -43,7 +43,7 @@
     char *format_description;
 
     refbuf_t *(*get_buffer)(struct source_tag *);
-    int (*write_buf_to_client)(struct _format_plugin_tag *format, client_t *client);
+    int (*write_buf_to_client)(struct source_tag *format, client_t *client);
     void  (*write_buf_to_file)(struct source_tag *source, refbuf_t *refbuf);
     int (*create_client_data)(struct source_tag *source, client_t *client);
     void (*set_tag)(struct _format_plugin_tag *plugin, char *tag, char *value);
@@ -59,11 +59,10 @@
 char *format_get_mimetype(format_type_t type);
 int format_get_plugin(format_type_t type, struct source_tag *source);
 
-int format_generic_write_buf_to_client(format_plugin_t *format, 
-        client_t *client, unsigned char *buf, int len);
+int format_generic_write_to_client (struct source_tag *source, client_t *client);
 void format_send_general_headers(format_plugin_t *format, 
         struct source_tag *source, client_t *client);
-void format_prepare_headers (struct source_tag *source, client_t *client);
+int format_http_write_to_client (struct source_tag *source, client_t *client);
 void format_initialise();
 
 #endif  /* __FORMAT_H__ */

Modified: icecast/branches/kh/icecast/src/format_mp3.c
===================================================================
--- icecast/branches/kh/icecast/src/format_mp3.c	2004-11-09 08:06:21 UTC (rev 8185)
+++ icecast/branches/kh/icecast/src/format_mp3.c	2004-11-10 14:35:18 UTC (rev 8186)
@@ -59,7 +59,7 @@
 
 static int  format_mp3_create_client_data (source_t *source, client_t *client);
 static void free_mp3_client_data (client_t *client);
-static int format_mp3_write_buf_to_client(format_plugin_t *self, client_t *client);
+static int format_mp3_write_buf_to_client(source_t *self, client_t *client);
 static void write_mp3_to_file (struct source_tag *source, refbuf_t *refbuf);
 static void mp3_set_tag (format_plugin_t *plugin, char *tag, char *value);
 static void format_mp3_apply_settings(struct source_tag *source, struct _mount_proxy *mount);
@@ -263,15 +263,15 @@
     /* If there is a change in metadata then send it else
      * send a single zero value byte in its place
      */
-    if (associated == client_mp3->associated)
+    if (associated && associated != client_mp3->associated)
     {
-        metadata = "\0";
-        meta_len = 1;
+        metadata = associated->data + client_mp3->metadata_offset;
+        meta_len = associated->len - client_mp3->metadata_offset;
     }
     else
     {
-        metadata = associated->data + client_mp3->metadata_offset;
-        meta_len = associated->len - client_mp3->metadata_offset;
+        metadata = "\0";
+        meta_len = 1;
     }
     ret = client_send_bytes (client, metadata, meta_len);
 
@@ -296,7 +296,7 @@
 /* Handler for writing mp3 data to a client, taking into account whether
  * client has requested shoutcast style metadata updates
  */
-static int format_mp3_write_buf_to_client (format_plugin_t *self, client_t *client) 
+static int format_mp3_write_buf_to_client (source_t *self, client_t *client) 
 {
     int ret, written = 0;
     mp3_client_data *client_mp3 = client->format_data;
@@ -576,8 +576,9 @@
     mp3_client_data *client_mp3 = calloc(1,sizeof(mp3_client_data));
     mp3_state *source_mp3 = source->format->_state;
     const char *metadata;
-    unsigned remaining = client->predata_size - client->predata_len + 2;
-    char *ptr = client->predata + client->predata_len - 2;
+    /* the +-2 is for overwriting the last set of \r\n */
+    unsigned remaining = 4096 - client->refbuf->len + 2;
+    char *ptr = client->refbuf->data + client->refbuf->len - 2;
     int bytes;
 
     if (client_mp3 == NULL)
@@ -604,12 +605,20 @@
             client_mp3->interval = ICY_METADATA_INTERVAL;
         else
             client_mp3->interval = source_mp3->interval;
-        bytes = snprintf (ptr, remaining, "icy-metaint:%u\r\n\r\n",
+        bytes = snprintf (ptr, remaining, "icy-metaint:%u\r\n",
                 client_mp3->interval);
         if (bytes > 0)
-            client->predata_len += bytes - 2;
+        {
+            remaining -= bytes;
+            ptr += bytes;
+        }
     }
+    bytes = snprintf (ptr, remaining, "\r\n");
+    remaining -= bytes;
+    ptr += bytes;
 
+    client->refbuf->len = 4096 - remaining;
+
     return 0;
 }
 

Modified: icecast/branches/kh/icecast/src/format_ogg.c
===================================================================
--- icecast/branches/kh/icecast/src/format_ogg.c	2004-11-09 08:06:21 UTC (rev 8185)
+++ icecast/branches/kh/icecast/src/format_ogg.c	2004-11-10 14:35:18 UTC (rev 8186)
@@ -509,7 +509,7 @@
 
 static void write_ogg_to_file (struct source_tag *source, refbuf_t *refbuf);
 static refbuf_t *ogg_get_buffer (source_t *source);
-static int write_buf_to_client (format_plugin_t *self, client_t *client);
+static int write_buf_to_client (source_t *self, client_t *client);
 
 
 static void free_ogg_codecs (ogg_state_t *ogg_info)
@@ -802,7 +802,7 @@
 }
 
 
-static int write_buf_to_client (format_plugin_t *self, client_t *client)
+static int write_buf_to_client (source_t *self, client_t *client)
 {
     refbuf_t *refbuf = client->refbuf;
     char *buf;

Modified: icecast/branches/kh/icecast/src/format_vorbis.c
===================================================================
--- icecast/branches/kh/icecast/src/format_vorbis.c	2004-11-09 08:06:21 UTC (rev 8185)
+++ icecast/branches/kh/icecast/src/format_vorbis.c	2004-11-10 14:35:18 UTC (rev 8186)
@@ -98,7 +98,7 @@
 
 static void write_vorbis_to_file (struct source_tag *source, refbuf_t *refbuf);
 static refbuf_t *vorbis_get_buffer (source_t *source);
-static int vorbis_write_buf_to_client (format_plugin_t *self, client_t *client);
+static int vorbis_write_buf_to_client (source_t *self, client_t *client);
 static void vorbis_set_tag (format_plugin_t *plugin, char *tag, char *value);
 
 
@@ -751,7 +751,7 @@
 }
 
 
-static int vorbis_write_buf_to_client (format_plugin_t *self, client_t *client)
+static int vorbis_write_buf_to_client (source_t *self, client_t *client)
 {
     refbuf_t *refbuf = client->refbuf;
     char *buf;

Modified: icecast/branches/kh/icecast/src/slave.c
===================================================================
--- icecast/branches/kh/icecast/src/slave.c	2004-11-09 08:06:21 UTC (rev 8185)
+++ icecast/branches/kh/icecast/src/slave.c	2004-11-10 14:35:18 UTC (rev 8186)
@@ -147,7 +147,7 @@
 }
 
 
-int slave_redirect (char *mountpoint, client_t *client)
+int slave_redirect (const char *mountpoint, client_t *client)
 {
     slave_host *slave = NULL;
 

Modified: icecast/branches/kh/icecast/src/slave.h
===================================================================
--- icecast/branches/kh/icecast/src/slave.h	2004-11-09 08:06:21 UTC (rev 8185)
+++ icecast/branches/kh/icecast/src/slave.h	2004-11-10 14:35:18 UTC (rev 8186)
@@ -13,9 +13,10 @@
 #ifndef __SLAVE_H__
 #define __SLAVE_H__
 
-#include <client.h>
 #include <thread/thread.h>
 
+struct _client_tag;
+
 typedef struct _relay_server {
     char *server;
     int port;
@@ -44,9 +45,9 @@
 void slave_shutdown(void);
 void slave_recheck (void);
 void slave_rescan (void);
-int slave_redirect (char *mountpoint, client_t *client);
-void slave_host_add (client_t *client, const char *header);
-void slave_host_remove (client_t *client);
+int slave_redirect (const char *mountpoint, struct _client_tag *client);
+void slave_host_add (struct _client_tag *client, const char *header);
+void slave_host_remove (struct _client_tag *client);
 relay_server *relay_free (relay_server *relay);
 
 #endif  /* __SLAVE_H__ */

Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c	2004-11-09 08:06:21 UTC (rev 8185)
+++ icecast/branches/kh/icecast/src/source.c	2004-11-10 14:35:18 UTC (rev 8186)
@@ -366,10 +366,19 @@
         /* we need to move the client and pending trees */
         while (source->active_clients)
         {
-            /* switch client to different queue */
             client_t *client = source->active_clients;
             source->active_clients = client->next;
-            client_set_queue (client, dest->stream_data_tail);
+
+            /* when switching a client to a different queue, be wary of the 
+             * refbuf it's referring to, if it's http headers then we need
+             * to write them so don't release it.
+             */
+            if (client->write_to_client != format_http_write_to_client)
+            {
+                client_set_queue (client, NULL);
+                client->write_to_client = NULL;
+            }
+
             *dest->pending_clients_tail = client;
             dest->pending_clients_tail = &client->next;
             count++;
@@ -381,6 +390,8 @@
         {
             client_t *client = source->pending_clients;
             source->pending_clients = client->next;
+            /* clients on pending have a unique refbuf containing headers
+             * so no need to change them here */
             *dest->pending_clients_tail = client;
             dest->pending_clients_tail = &client->next;
             count++;
@@ -447,21 +458,6 @@
     int total_written = 0;
     int ret = 1;
 
-    if (client->predata)
-    {
-        char *ptr = client->predata + client->predata_offset;
-        unsigned len  = client->predata_len - client->predata_offset;
-        bytes = client_send_bytes (client, ptr, len);
-        if (bytes > 0 && (unsigned)bytes < len)
-        {
-            client->predata_offset += bytes;
-            return 0;
-        }
-        free (client->predata);
-        client->predata_size = client->predata_len = client->predata_offset = 0;
-        client->predata = NULL;
-    }
-
     /* new users need somewhere to start from */
     if (client->refbuf == NULL)
     {
@@ -483,7 +479,7 @@
 
         loop--;
 
-        bytes = source->format->write_buf_to_client (source->format, client);
+        bytes = client->write_to_client (source, client);
         if (bytes <= 0)
         {
             ret = 0;
@@ -520,9 +516,9 @@
     client_p = &source->active_clients;
     while (client && client != sentinel)
     {
-        int move_it = send_to_listener (source, client, deletion_expected);
+        int fast_client = send_to_listener (source, client, deletion_expected);
 
-        if (move_it)
+        if (fast_client)
         {
             client_t *to_go = client;
 
@@ -802,8 +798,9 @@
     client->next = source->pending_clients;
     source->pending_clients = client;
 
-    client->predata_size = 4096;
-    client->predata = calloc (1, client->predata_size);
+    client->write_to_client = format_http_write_to_client;
+    client->refbuf = refbuf_new (4096);
+
     sock_set_blocking (client->con->sock, SOCK_NONBLOCK);
     sock_set_nodelay (client->con->sock);
     if (source->running == 0 && source->on_demand)
@@ -933,33 +930,20 @@
     while (client)
     {
         client_t *to_go = client;
-        int drop_client = 0;
 
         client = client->next;
-        to_go->next = NULL;
-        /* do we need to handle http style headers */
-        if (to_go->respcode == 0)
+        if (to_go->write_to_client == NULL)
         {
-            DEBUG0("processing pending client headers");
-
-            format_prepare_headers (source, to_go);
-            if (source->format->create_client_data &&
-                    source->format->create_client_data (source, to_go) < 0)
-                drop_client = 1;
+            /* The client may of been moved here when we were an 
+             * inactive on-demand relay */
+            to_go->write_to_client = source->format->write_buf_to_client;
+            client_set_queue (to_go, source->stream_data_tail);
         }
-        if (drop_client)
-        {
-            /* shouldn't happen, but don't stall */
-            ERROR0 ("dropping pending client");
-            to_go->respcode = 200;
-            source_free_client (source, to_go);
-        }
-        else
-        {
-            to_go->next = source->active_clients;
-            source->active_clients = to_go;
-            count++;
-        }
+
+        to_go->next = source->active_clients;
+        source->active_clients = to_go;
+
+        count++;
         source->new_listeners--;
     }
     source->pending_clients = NULL;



More information about the commits mailing list