[vlc-devel] [PATCH] Allow custom HTTP headers for httpd_Stream

Denis Charmet typx at dinauz.org
Sat Feb 15 23:21:47 CET 2014


This will end up useful for cubemap implementation and may allow to put mms stuff out of the core
---
 include/vlc_httpd.h |  14 +++--
 src/libvlccore.sym  |   1 +
 src/network/httpd.c | 159 +++++++++++++++++++++++++++++++++++++++-------------
 3 files changed, 129 insertions(+), 45 deletions(-)

diff --git a/include/vlc_httpd.h b/include/vlc_httpd.h
index 9eb0b15..859050f 100644
--- a/include/vlc_httpd.h
+++ b/include/vlc_httpd.h
@@ -71,6 +71,12 @@ VLC_API httpd_host_t *vlc_rtsp_HostNew( vlc_object_t * ) VLC_USED;
 /* delete a host */
 VLC_API void httpd_HostDelete( httpd_host_t * );
 
+typedef struct
+{
+    char * name;
+    char * value;
+} httpd_header;
+
 typedef struct httpd_message_t
 {
     httpd_client_t *cl; /* NULL if not throught a connection e vlc internal */
@@ -89,10 +95,8 @@ typedef struct httpd_message_t
     uint8_t *psz_args;
 
     /* options */
-    int     i_name;
-    char    **name;
-    int     i_value;
-    char    **value;
+    size_t       i_headers;
+    httpd_header *p_headers;
 
     /* body */
     int64_t i_body_offset;
@@ -139,7 +143,7 @@ VLC_API httpd_stream_t * httpd_StreamNew( httpd_host_t *, const char *psz_url, c
 VLC_API void httpd_StreamDelete( httpd_stream_t * );
 VLC_API int httpd_StreamHeader( httpd_stream_t *, uint8_t *p_data, int i_data );
 VLC_API int httpd_StreamSend( httpd_stream_t *, const block_t *p_block );
-
+VLC_API int httpd_StreamSetCustomHTTPHeaders(httpd_stream_t *, httpd_header *, size_t);
 
 /* Msg functions facilities */
 VLC_API void httpd_MsgAdd( httpd_message_t *, const char *psz_name, const char *psz_value, ... ) VLC_FORMAT( 3, 4 );
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 1ed906a..1b0b99c 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -162,6 +162,7 @@ httpd_StreamDelete
 httpd_StreamHeader
 httpd_StreamNew
 httpd_StreamSend
+httpd_StreamSetCustomHTTPHeaders
 httpd_UrlCatch
 httpd_UrlDelete
 httpd_UrlNew
diff --git a/src/network/httpd.c b/src/network/httpd.c
index ca41d27..ec3f984 100644
--- a/src/network/httpd.c
+++ b/src/network/httpd.c
@@ -645,6 +645,10 @@ struct httpd_stream_t
     uint8_t     *p_buffer;          /* buffer */
     int64_t     i_buffer_pos;       /* absolute position from begining */
     int64_t     i_buffer_last_pos;  /* a new connection will start with that */
+
+    /* custom headers */
+    size_t        i_custom_headers;
+    httpd_header * p_custom_headers;
 };
 
 static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys,
@@ -729,6 +733,25 @@ static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys,
 
         answer->i_status = 200;
 
+        bool b_has_content_type = false;
+        bool b_has_cache_control = false;
+
+        vlc_mutex_lock( &stream->lock );
+        for( size_t i = 0; i < stream->i_custom_headers; i++ )
+        {
+            if( strncasecmp( stream->p_custom_headers[i].name, "Content-Length", 14 ) )
+            {
+                httpd_MsgAdd( answer, stream->p_custom_headers[i].name,
+                              stream->p_custom_headers[i].value );
+
+                if( !strncasecmp( stream->p_custom_headers[i].name, "Content-Type", 12 ) )
+                    b_has_content_type = true;
+                else if( !strncasecmp( stream->p_custom_headers[i].name, "Cache-Control", 13 ) )
+                    b_has_cache_control = true;
+            }
+        }
+        vlc_mutex_unlock( &stream->lock );
+
         if( query->i_type != HTTPD_MSG_HEAD )
         {
             cl->b_stream_mode = true;
@@ -749,17 +772,17 @@ static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys,
         }
         else
         {
-            httpd_MsgAdd( answer, "Content-Length", "%d", 0 );
+            httpd_MsgAdd( answer, "Content-Length", "0" );
             answer->i_body_offset = 0;
         }
 
+        /* FIXME: move to http access_output */
         if( !strcmp( stream->psz_mime, "video/x-ms-asf-stream" ) )
         {
             bool b_xplaystream = false;
             int i;
 
-            httpd_MsgAdd( answer, "Content-type", "%s",
-                          "application/octet-stream" );
+            httpd_MsgAdd( answer, "Content-type", "application/octet-stream" );
             httpd_MsgAdd( answer, "Server", "Cougar 4.1.0.3921" );
             httpd_MsgAdd( answer, "Pragma", "no-cache" );
             httpd_MsgAdd( answer, "Pragma", "client-id=%lu",
@@ -767,10 +790,10 @@ static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys,
             httpd_MsgAdd( answer, "Pragma", "features=\"broadcast\"" );
 
             /* Check if there is a xPlayStrm=1 */
-            for( i = 0; i < query->i_name; i++ )
+            for( i = 0; i < query->i_headers; i++ )
             {
-                if( !strcasecmp( query->name[i],  "Pragma" ) &&
-                    strstr( query->value[i], "xPlayStrm=1" ) )
+                if( !strcasecmp( query->p_headers[i].name,  "Pragma" ) &&
+                    strstr( query->p_headers[i].value, "xPlayStrm=1" ) )
                 {
                     b_xplaystream = true;
                 }
@@ -781,11 +804,12 @@ static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys,
                 answer->i_body_offset = 0;
             }
         }
-        else
+        else if( !b_has_content_type )
         {
-            httpd_MsgAdd( answer, "Content-type",  "%s", stream->psz_mime );
+            httpd_MsgAdd( answer, "Content-type", stream->psz_mime );
         }
-        httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" );
+        if( !b_has_cache_control )
+            httpd_MsgAdd( answer, "Cache-Control", "no-cache" );
         return VLC_SUCCESS;
     }
 }
@@ -821,6 +845,7 @@ httpd_stream_t *httpd_StreamNew( httpd_host_t *host,
     stream->i_buffer_last_pos = 1;
     stream->b_has_keyframes = false;
     stream->i_last_keyframe_seen_pos = 0;
+    stream->p_custom_headers = NULL;
 
     httpd_UrlCatch( stream->url, HTTPD_MSG_HEAD, httpd_StreamCallBack,
                     (httpd_callback_sys_t*)stream );
@@ -1238,10 +1263,8 @@ static void httpd_MsgInit( httpd_message_t *msg )
     msg->psz_url    = NULL;
     msg->psz_args   = NULL;
 
-    msg->i_name     = 0;
-    msg->name       = NULL;
-    msg->i_value    = 0;
-    msg->value      = NULL;
+    msg->i_headers  = 0;
+    msg->p_headers  = NULL;
 
     msg->i_body_offset = 0;
     msg->i_body        = 0;
@@ -1254,13 +1277,12 @@ static void httpd_MsgClean( httpd_message_t *msg )
 
     free( msg->psz_url );
     free( msg->psz_args );
-    for( i = 0; i < msg->i_name; i++ )
+    for( i = 0; i < msg->i_headers; i++ )
     {
-        free( msg->name[i] );
-        free( msg->value[i] );
+        free( msg->p_headers[i].name );
+        free( msg->p_headers[i].value );
     }
-    free( msg->name );
-    free( msg->value );
+    free( msg->p_headers );
     free( msg->p_body );
     httpd_MsgInit( msg );
 }
@@ -1269,11 +1291,11 @@ const char *httpd_MsgGet( const httpd_message_t *msg, const char *name )
 {
     int i;
 
-    for( i = 0; i < msg->i_name; i++ )
+    for( i = 0; i < msg->i_headers; i++ )
     {
-        if( !strcasecmp( msg->name[i], name ))
+        if( !strcasecmp( msg->p_headers[i].name, name ))
         {
-            return msg->value[i];
+            return msg->p_headers[i].value;
         }
     }
     return NULL;
@@ -1298,9 +1320,19 @@ void httpd_MsgAdd( httpd_message_t *msg, const char *name, const char *psz_value
         free( value );
         return;
     }
-
-    TAB_APPEND( msg->i_name,  msg->name,  (char*)name );
-    TAB_APPEND( msg->i_value, msg->value, value );
+    httpd_header * p_tmp = realloc( msg->p_headers, sizeof(httpd_header) * (msg->i_headers + 1));
+    if(p_tmp)
+    {
+        msg->p_headers = p_tmp;
+        msg->p_headers[msg->i_headers].name = name;
+        msg->p_headers[msg->i_headers].value = value;
+        msg->i_headers++;
+    }
+    else
+    {
+        free(name);
+        free(value);
+    }
 }
 
 static void httpd_ClientInit( httpd_client_t *cl, mtime_t now )
@@ -1695,23 +1727,16 @@ static void httpd_ClientRecv( httpd_client_t *cl )
 
                         if( ( colon = strchr( line, ':' ) ) )
                         {
-                            char *name;
-                            char *value;
-
                             *colon++ = '\0';
                             while( *colon == ' ' )
                             {
                                 colon++;
                             }
-                            name = strdup( line );
-                            value = strdup( colon );
+                            httpd_MsgAdd( &cl->query, line, colon );
 
-                            TAB_APPEND( cl->query.i_name, cl->query.name, name );
-                            TAB_APPEND( cl->query.i_value,cl->query.value,value);
-
-                            if( !strcasecmp( name, "Content-Length" ) )
+                            if( !strcasecmp( line, "Content-Length" ) )
                             {
-                                cl->query.i_body = atol( value );
+                                cl->query.i_body = atol( colon );
                             }
                         }
 
@@ -1832,10 +1857,10 @@ static void httpd_ClientSend( httpd_client_t *cl )
         const char *psz_status = httpd_ReasonFromCode( cl->answer.i_status );
 
         i_size = strlen( "HTTP/1.") + 10 + 10 + strlen( psz_status ) + 5;
-        for( i = 0; i < cl->answer.i_name; i++ )
+        for( i = 0; i < cl->answer.i_headers; i++ )
         {
-            i_size += strlen( cl->answer.name[i] ) + 2 +
-                      strlen( cl->answer.value[i] ) + 2;
+            i_size += strlen( cl->answer.p_headers[i].name ) + 2 +
+                      strlen( cl->answer.p_headers[i].value ) + 2;
         }
 
         if( cl->i_buffer_size < i_size )
@@ -1850,10 +1875,10 @@ static void httpd_ClientSend( httpd_client_t *cl )
                       cl->answer.i_proto ==  HTTPD_PROTO_HTTP ? "HTTP/1" : "RTSP/1",
                       cl->answer.i_version,
                       cl->answer.i_status, psz_status );
-        for( i = 0; i < cl->answer.i_name; i++ )
+        for( i = 0; i < cl->answer.i_headers; i++ )
         {
-            p += sprintf( p, "%s: %s\r\n", cl->answer.name[i],
-                          cl->answer.value[i] );
+            p += sprintf( p, "%s: %s\r\n", cl->answer.p_headers[i].name,
+                          cl->answer.p_headers[i].value );
         }
         p += sprintf( p, "\r\n" );
 
@@ -2364,3 +2389,57 @@ static void* httpd_HostThread( void *data )
     vlc_mutex_unlock( &host->lock );
     return NULL;
 }
+
+int httpd_StreamSetCustomHTTPHeaders(httpd_stream_t * p_stream, httpd_header * p_headers, size_t i_headers )
+{
+    if( !p_stream )
+        return VLC_EGENERIC;
+
+    vlc_mutex_lock( &p_stream->lock );
+    if( p_stream->p_custom_headers )
+    {
+        for( size_t i = 0; i < p_stream->i_custom_headers; i++)
+        {
+            free( p_stream->p_custom_headers[i].name );
+            free( p_stream->p_custom_headers[i].value );
+        }
+        free( p_stream->p_custom_headers );
+        p_stream->p_custom_headers = NULL;
+        p_stream->i_custom_headers = 0;
+    }
+
+    if( !p_headers || !i_headers )
+    {
+        vlc_mutex_unlock( &p_stream->lock );
+        return VLC_SUCCESS;
+    }
+
+    p_stream->p_custom_headers = malloc(sizeof(httpd_header) * i_headers );
+    if( !p_stream->p_custom_headers )
+    {
+        vlc_mutex_unlock( &p_stream->lock );
+        return VLC_ENOMEM;
+    }
+
+    size_t j = 0;
+    for( size_t i = 0; i < i_headers; i++ )
+    {
+        if( unlikely( !p_headers[i].name || !p_headers[i].value ) )
+            continue;
+
+        p_stream->p_custom_headers[j].name = strdup( p_headers[i].name );
+        p_stream->p_custom_headers[j].value = strdup( p_headers[i].value );
+
+        if( unlikely( !p_stream->p_custom_headers[j].name ||
+                      !p_stream->p_custom_headers[j].value ) )
+        {
+            free( p_stream->p_custom_headers[j].name );
+            free( p_stream->p_custom_headers[j].value );
+            break;
+        }
+        j++;
+    }
+    p_stream->i_custom_headers = j;
+    vlc_mutex_unlock( &p_stream->lock );
+    return VLC_SUCCESS;
+}
-- 
1.9.rc1




More information about the vlc-devel mailing list