[xiph-commits] r9565 - in icecast/branches/kh/icecast: doc src

karl at svn.xiph.org karl at svn.xiph.org
Thu Jul 14 03:29:40 PDT 2005


Author: karl
Date: 2005-07-14 03:29:34 -0700 (Thu, 14 Jul 2005)
New Revision: 9565

Modified:
   icecast/branches/kh/icecast/doc/icecast2_listenerauth.html
   icecast/branches/kh/icecast/src/auth.c
   icecast/branches/kh/icecast/src/auth.h
   icecast/branches/kh/icecast/src/auth_cmd.c
   icecast/branches/kh/icecast/src/auth_htpasswd.c
   icecast/branches/kh/icecast/src/auth_url.c
   icecast/branches/kh/icecast/src/connection.h
   icecast/branches/kh/icecast/src/source.c
Log:
auth update. handle missing options better. Add port= to each request POST. Add timelimit
mechanism for automatic listener termination (url auth gets actual time from auth server)


Modified: icecast/branches/kh/icecast/doc/icecast2_listenerauth.html
===================================================================
--- icecast/branches/kh/icecast/doc/icecast2_listenerauth.html	2005-07-13 06:13:34 UTC (rev 9564)
+++ icecast/branches/kh/icecast/doc/icecast2_listenerauth.html	2005-07-14 10:29:34 UTC (rev 9565)
@@ -82,7 +82,8 @@
             <option name="remove" value="http://myauthserver.com/listener_left.php"/>
             <option name="username" value="user"/>
             <option name="password" value="pass"/>
-            <option name="header" value="listener-validated: 1"/>
+            <option name="header" value="icecast-auth-user: 1"/>
+            <option name="timelimit-header" value="icecast-auth-timelimit:"/>
         </authentication>
     </mount>
 </pre>
@@ -94,7 +95,7 @@
 </p>
 <p>POST details are</p>
 <pre>
-    action=start&amp;mount=/live&amp;server=myserver.com
+    action=start&amp;mount=/live&amp;server=myserver.com&amp;port=8000
 </pre>
 <p>Here the details indicate the server name (&lt;hostname&gt;) and mountpoint starting up</p>
 <h3>end</h3>
@@ -102,18 +103,18 @@
 listener details are passed.</p>
 <p>POST details are</p>
 <pre>
-    action=end&amp;mount=/live&amp;server=myserver.com
+    action=end&amp;mount=/live&amp;server=myserver.com&amp;port=8000
 </pre>
 <p>like the start option, server name and mountpoint are provided</p>
 </p>
 <h3>add</h3>
 <p>This is most likely to be used if anything. When a listener connects, before anything is
 sent back to them, this request is processed.  The default action is to reject a listener
-unless the auth server sends back a response header which is stated in the 'header' option
+unless the auth server sends back a response header which can be stated in the 'header' option
 </p>
 <p>POST details are</p>
 <pre>
-    action=auth&amp;server=myserver.com&amp;client=1&amp;mount=/live&amp;user=&amp;pass=&amp;ip=127.0.0.1&amp;agent="My player"
+    action=auth&amp;server=myserver.com&amp;port=8000&amp;client=1&amp;mount=/live&amp;user=&amp;pass=&amp;ip=127.0.0.1&amp;agent="My%20player"
 </pre>
 <p>There are more details with this, client is the unique ID for the client within icecast,
 user and pass may be blank but come from the HTTP basic auth that the listener states, ip
@@ -126,7 +127,7 @@
 <p>This URL is for when a listener connection closes.</p>
 <p>POST details are</p>
 <pre>
-    action=remove&amp;client=1&amp;mount=/live&amp;user=&amp;pass=&amp;duration=3600
+    action=remove&amp;server=myserver.com&amp;port=8000&amp;client=1&amp;mount=/live&amp;user=&amp;pass=&amp;duration=3600
 </pre>
 <p>Again this is similar to the add option, the difference being that a duration is passed
 reflecting the number of seconds the listener was connected for </p>
@@ -134,8 +135,12 @@
 <p>The response header returned from these requests that allows the authencation to take
 place can be stated here. The default is 
 <pre>icecast-auth-user: 1</pre>
-but it could can anything you wish for instance
+but it could can anything you like, for instance
 <pre>HTTP 200 OK</pre>
+<h3>timelimit-header</h3>
+<p>Listeners could have a time limit imposed on them, and if this header is sent back with a
+figure (which represents seconds) then that is how long the client will remain connected for.
+</p>
 <br />
 <br />
 <h2>A note about players and authentication</h2>

Modified: icecast/branches/kh/icecast/src/auth.c
===================================================================
--- icecast/branches/kh/icecast/src/auth.c	2005-07-13 06:13:34 UTC (rev 9564)
+++ icecast/branches/kh/icecast/src/auth.c	2005-07-14 10:29:34 UTC (rev 9565)
@@ -137,10 +137,42 @@
 }
 
 
+/* wrapper function for auth thread to authenticate new listener
+ * connection details
+ */
+static void auth_new_listener (auth_client *auth_user)
+{
+    client_t *client = auth_user->client;
+
+    if (client->auth->authenticate)
+    {
+        if (client->auth->authenticate (auth_user) != AUTH_OK)
+            return;
+    }
+    if (auth_postprocess_client (auth_user) < 0)
+        INFO1 ("client %lu failed", client->con->id);
+}
+
+
+/* wrapper function are auth thread to authenticate new listener
+ * connections
+ */
+static void auth_remove_listener (auth_client *auth_user)
+{
+    client_t *client = auth_user->client;
+
+    if (client->auth->release_client)
+        client->auth->release_client (auth_user);
+    auth_release (client->auth);
+    client->auth = NULL;
+    return;
+}
+
+
 /* The auth thread main loop. */
 static void *auth_run_thread (void *arg)
 {
-    INFO0 ("Authenication thread started");
+    INFO0 ("Authentication thread started");
     while (1)
     {
         if (clients_to_auth)
@@ -153,14 +185,11 @@
             thread_mutex_unlock (&auth_lock);
             auth_user->next = NULL;
 
-            if (auth_user->process == NULL)
+            if (auth_user->process)
+                auth_user->process (auth_user);
+            else
                 ERROR0 ("client auth process not set");
 
-            if (auth_user->process (auth_user) != AUTH_OK)
-            {
-                INFO0 ("client failed");
-            }
-
             auth_client_free (auth_user);
 
             continue;
@@ -351,7 +380,7 @@
             return;
         }
         auth_user->mount = strdup (mount);
-        auth_user->process = client->auth->authenticate;
+        auth_user->process = auth_new_listener;
         auth_user->client = client;
 
         INFO0 ("adding client for authentication");
@@ -379,7 +408,7 @@
             return 0;
 
         auth_user->mount = strdup (httpp_getvar (client->parser, HTTPP_VAR_URI));
-        auth_user->process = client->auth->release_client;
+        auth_user->process = auth_remove_listener;
         auth_user->client = client;
 
         queue_auth_client (auth_user);

Modified: icecast/branches/kh/icecast/src/auth.h
===================================================================
--- icecast/branches/kh/icecast/src/auth.h	2005-07-13 06:13:34 UTC (rev 9564)
+++ icecast/branches/kh/icecast/src/auth.h	2005-07-14 10:29:34 UTC (rev 9565)
@@ -41,7 +41,7 @@
 {
     char        *mount;
     client_t    *client;
-    auth_result (*process)(struct auth_client_tag *auth_user);
+    void        (*process)(struct auth_client_tag *auth_user);
     struct auth_client_tag *next;
 } auth_client;
 
@@ -57,8 +57,8 @@
     /* callbacks to specific auth for notifying auth server on source
      * startup or shutdown
      */
-    auth_result (*stream_start)(auth_client *auth_user);
-    auth_result (*stream_end)(auth_client *auth_user);
+    void (*stream_start)(auth_client *auth_user);
+    void (*stream_end)(auth_client *auth_user);
 
     void (*free)(struct auth_tag *self);
     auth_result (*adduser)(struct auth_tag *auth, const char *username, const char *password);

Modified: icecast/branches/kh/icecast/src/auth_cmd.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_cmd.c	2005-07-13 06:13:34 UTC (rev 9564)
+++ icecast/branches/kh/icecast/src/auth_cmd.c	2005-07-14 10:29:34 UTC (rev 9565)
@@ -95,8 +95,7 @@
                 {
                     DEBUG1("command exited normally with %d", WEXITSTATUS (status));
                     if (WEXITSTATUS(status) == 0)
-                        if (auth_postprocess_client (auth_user) < 0)
-                            return AUTH_FAILED;
+                        return AUTH_OK;
                 }
                 break;
         }

Modified: icecast/branches/kh/icecast/src/auth_htpasswd.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_htpasswd.c	2005-07-13 06:13:34 UTC (rev 9564)
+++ icecast/branches/kh/icecast/src/auth_htpasswd.c	2005-07-14 10:29:34 UTC (rev 9565)
@@ -123,8 +123,6 @@
                 fclose(passwdfile);
                 free(hashed_password);
                 thread_rwlock_unlock(&state->file_rwlock);
-                if (auth_postprocess_client (auth_user) < 0)
-                    return AUTH_FAILED;
                 return AUTH_OK;
             }
             free(hashed_password);

Modified: icecast/branches/kh/icecast/src/auth_url.c
===================================================================
--- icecast/branches/kh/icecast/src/auth_url.c	2005-07-13 06:13:34 UTC (rev 9564)
+++ icecast/branches/kh/icecast/src/auth_url.c	2005-07-14 10:29:34 UTC (rev 9565)
@@ -17,28 +17,35 @@
  * be handled. The request will have POST information about the request in
  * the form of
  *
- * action=auth&client=1&mount=/live&user=fred&pass=mypass&ip=127.0.0.1&agent=""
+ * action=auth&client=1&server=host&port=8000&mount=/live&user=fred&pass=mypass&ip=127.0.0.1&agent=""
  *
  * For a user to be accecpted the following HTTP header needs
- * to be returned
+ * to be returned (the actual string can be specified in the xml file)
  *
  * icecast-auth-user: 1
  *
- * On client disconnection another request is sent to that same URL with the
- * POST information of
+ * A listening client may also be configured as only to stay connected for a
+ * certain length of time. eg The auth server may only allow a 15 minute
+ * playback by sending back.
  *
- * action=remove&client=1&mount=/live&user=fred&pass=mypass&duration=3600
+ * icecast-auth-timelimit: 900
  *
- * client refers to the icecast client identification number, mount refers
- * to the mountpoint (beginning with /) and duration is the amount of time in
- * seconds
+ * On client disconnection another request can be sent to a URL with the POST
+ * information of
  *
+ * action=remove&server=host&port=8000&client=1&mount=/live&user=fred&pass=mypass&duration=3600
+ *
+ * client refers to the icecast client identification number. mount refers
+ * to the mountpoint (beginning with / and may contain query parameters eg ?&
+ * encoded) and duration is the amount of time in seconds. user and pass
+ * setting can be blank
+ *
  * On stream start and end, another url can be issued to help clear any user
  * info stored at the auth server. Useful for abnormal outage/termination
  * cases.
  *
- * action=start&mount=/live&server=myserver.com
- * action=end&mount=/live&server=myserver.com
+ * action=start&mount=/live&server=myserver.com&port=8000
+ * action=end&mount=/live&server=myserver.com&port=8000
  */
 
 #ifdef HAVE_CONFIG_H
@@ -75,6 +82,8 @@
     char *password;
     char *auth_header;
     int  auth_header_len;
+    char *timelimit_header;
+    int  timelimit_header_len;
     CURL *handle;
     char errormsg [CURL_ERROR_SIZE];
 } auth_url;
@@ -91,6 +100,7 @@
     free (url->stream_start);
     free (url->stream_end);
     free (url->auth_header);
+    free (url->timelimit_header);
     free (url);
 }
 
@@ -107,6 +117,12 @@
         auth_url *url = auth->state;
         if (strncasecmp (ptr, url->auth_header, url->auth_header_len) == 0)
             client->authenticated = 1;
+        if (strncasecmp (ptr, url->timelimit_header, url->timelimit_header_len) == 0)
+        {
+            unsigned int limit = 0;
+            sscanf (ptr+url->timelimit_header_len, "%u\r\n", &limit);
+            client->con->discon_time = global.time + limit;
+        }
     }
 
     return (int)bytes;
@@ -119,7 +135,7 @@
 }
 
 
-static auth_result auth_removeurl_client (auth_client *auth_user)
+static auth_result url_remove_client (auth_client *auth_user)
 {
     client_t *client = auth_user->client;
     auth_t *auth = client->auth;
@@ -127,12 +143,12 @@
     time_t duration = global.time - client->con->con_time;
     char *username, *password, *mount, *server;
     ice_config_t *config;
+    int port;
     char post[1024];
 
-    if (url->removeurl == NULL)
-        return AUTH_OK;
     config = config_get_config ();
     server = util_url_escape (config->hostname);
+    port = config->port;
     config_release_config ();
 
     if (client->username)
@@ -152,9 +168,9 @@
     mount = util_url_escape (mount);
 
     snprintf (post, sizeof (post),
-            "action=remove&server=%sclient=%lu&mount=%s"
+            "action=remove&server=%s&port=%d&client=%lu&mount=%s"
             "&user=%s&pass=%s&duration=%lu",
-            server, client->con->id, mount, username,
+            server, port, client->con->id, mount, username,
             password, (long unsigned)duration);
     free (server);
     free (mount);
@@ -168,20 +184,16 @@
     if (curl_easy_perform (url->handle))
         WARN2 ("auth to server %s failed with %s", url->removeurl, url->errormsg);
 
-    /* these are needed so the client is not added back onto the auth list */
-    auth_release (client->auth);
-    client->auth = NULL;
-
     return AUTH_OK;
 }
 
 
-static auth_result auth_addurl_client (auth_client *auth_user)
+static auth_result url_add_client (auth_client *auth_user)
 {
     client_t *client = auth_user->client;
     auth_t *auth = client->auth;
     auth_url *url = auth->state;
-    int res = 0;
+    int res = 0, port;
     char *agent, *user_agent, *username, *password;
     char *mount, *ipaddr, *server;
     ice_config_t *config;
@@ -192,6 +204,7 @@
 
     config = config_get_config ();
     server = util_url_escape (config->hostname);
+    port = config->port;
     config_release_config ();
     agent = httpp_getvar (client->parser, "user-agent");
     if (agent == NULL)
@@ -214,9 +227,9 @@
     ipaddr = util_url_escape (client->con->ip);
 
     snprintf (post, sizeof (post),
-            "action=auth&server=%s&client=%lu&mount=%s"
+            "action=auth&server=%s&port=%d&client=%lu&mount=%s"
             "&user=%s&pass=%s&ip=%s&agent=%s",
-            server, client->con->id, mount, username,
+            server, port, client->con->id, mount, username,
             password, ipaddr, user_agent);
     free (server);
     free (mount);
@@ -238,14 +251,7 @@
     }
     /* we received a response, lets see what it is */
     if (client->authenticated)
-    {
-        if (auth_postprocess_client (auth_user) < 0)
-        {
-            /* do cleanup, and exit as the remove does cleanup as well */
-            return AUTH_FAILED;
-        }
         return AUTH_OK;
-    }
     return AUTH_FAILED;
 }
 
@@ -253,7 +259,7 @@
 /* called by auth thread when a source starts, there is no client_t in
  * this case
  */
-static auth_result url_stream_start (auth_client *auth_user)
+static void url_stream_start (auth_client *auth_user)
 {
     char *mount, *server;
     ice_config_t *config = config_get_config ();
@@ -261,14 +267,16 @@
     auth_t *auth = mountinfo->auth;
     auth_url *url = auth->state;
     char *stream_start_url;
+    int port;
     char post [4096];
 
     if (url->stream_start == NULL)
     {
         config_release_config ();
-        return AUTH_OK;
+        return;
     }
     server = util_url_escape (config->hostname);
+    port = config->port;
     stream_start_url = strdup (url->stream_start);
     /* we don't want this auth disappearing from under us while
      * the connection is in progress */
@@ -277,7 +285,7 @@
     mount = util_url_escape (auth_user->mount);
 
     snprintf (post, sizeof (post),
-            "action=start&mount=%s&server=%s", mount, server);
+            "action=start&mount=%s&server=%s&port=%d", mount, server, port);
     free (server);
     free (mount);
 
@@ -290,11 +298,11 @@
 
     auth_release (auth);
     free (stream_start_url);
-    return AUTH_OK;
+    return;
 }
 
 
-static auth_result url_stream_end (auth_client *auth_user)
+static void url_stream_end (auth_client *auth_user)
 {
     char *mount, *server;
     ice_config_t *config = config_get_config ();
@@ -302,14 +310,16 @@
     auth_t *auth = mountinfo->auth;
     auth_url *url = auth->state;
     char *stream_end_url;
+    int port;
     char post [4096];
 
     if (url->stream_end == NULL)
     {
         config_release_config ();
-        return AUTH_OK;
+        return;
     }
     server = util_url_escape (config->hostname);
+    port = config->port;
     stream_end_url = strdup (url->stream_end);
     /* we don't want this auth disappearing from under us while
      * the connection is in progress */
@@ -318,7 +328,7 @@
     mount = util_url_escape (auth_user->mount);
 
     snprintf (post, sizeof (post),
-            "action=end&mount=%s&server=%s", mount, server);
+            "action=end&mount=%s&server=%s&port=%d", mount, server, port);
     free (server);
     free (mount);
 
@@ -331,7 +341,7 @@
 
     auth_release (auth);
     free (stream_end_url);
-    return AUTH_OK;
+    return;
 }
 
 
@@ -354,17 +364,20 @@
 {
     auth_url *url_info;
 
-    authenticator->authenticate = auth_addurl_client;
+    authenticator->authenticate = url_add_client;
+    authenticator->release_client = url_remove_client;
+
     authenticator->free = auth_url_clear;
     authenticator->adduser = auth_url_adduser;
     authenticator->deleteuser = auth_url_deleteuser;
     authenticator->listuser = auth_url_listuser;
-    authenticator->release_client = auth_removeurl_client;
+
     authenticator->stream_start = url_stream_start;
     authenticator->stream_end = url_stream_end;
 
     url_info = calloc(1, sizeof(auth_url));
     url_info->auth_header = strdup ("icecast-auth-user: 1\r\n");
+    url_info->timelimit_header = strdup ("icecast-auth-timelimit:");
 
     while(options) {
         if(!strcmp(options->name, "username"))
@@ -384,6 +397,11 @@
             free (url_info->auth_header);
             url_info->auth_header = strdup (options->value);
         }
+        if (strcmp(options->name, "timelimit-header") == 0)
+        {
+            free (url_info->timelimit_header);
+            url_info->timelimit_header = strdup (options->value);
+        }
         options = options->next;
     }
     url_info->handle = curl_easy_init ();
@@ -394,6 +412,8 @@
     }
     if (url_info->auth_header)
         url_info->auth_header_len = strlen (url_info->auth_header);
+    if (url_info->timelimit_header)
+        url_info->timelimit_header_len = strlen (url_info->timelimit_header);
 
     curl_easy_setopt (url_info->handle, CURLOPT_HEADERFUNCTION, handle_returned_header);
     curl_easy_setopt (url_info->handle, CURLOPT_WRITEFUNCTION, handle_returned_data);

Modified: icecast/branches/kh/icecast/src/connection.h
===================================================================
--- icecast/branches/kh/icecast/src/connection.h	2005-07-13 06:13:34 UTC (rev 9564)
+++ icecast/branches/kh/icecast/src/connection.h	2005-07-14 10:29:34 UTC (rev 9565)
@@ -28,9 +28,9 @@
     unsigned long id;
 
     time_t con_time;
+    time_t discon_time;
     uint64_t sent_bytes;
 
-
     int sock;
     int serversock;
     int error;

Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c	2005-07-13 06:13:34 UTC (rev 9564)
+++ icecast/branches/kh/icecast/src/source.c	2005-07-14 10:29:34 UTC (rev 9565)
@@ -530,6 +530,14 @@
 
     while (1)
     {
+        /* check for limited listener time */
+        if (client->con->discon_time)
+            if (global.time >= client->con->discon_time)
+            {
+                INFO1 ("time limit reached for client #%lu", client->con->id);
+                client->con->error = 1;
+            }
+
         /* jump out if client connection has died */
         if (client->con->error)
             break;



More information about the commits mailing list