[vlc-devel] [PATCH] Allow custom HTTP headers for httpd_Stream
Denis Charmet
typx at dinauz.org
Sun Feb 16 01:21:18 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 | 166 +++++++++++++++++++++++++++++++++++++++-------------
3 files changed, 136 insertions(+), 45 deletions(-)
diff --git a/include/vlc_httpd.h b/include/vlc_httpd.h
index 9eb0b15..852a7a8 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_StreamSetHTTPHeaders(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..f6f8300 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -162,6 +162,7 @@ httpd_StreamDelete
httpd_StreamHeader
httpd_StreamNew
httpd_StreamSend
+httpd_StreamSetHTTPHeaders
httpd_UrlCatch
httpd_UrlDelete
httpd_UrlNew
diff --git a/src/network/httpd.c b/src/network/httpd.c
index ca41d27..b0fc79c 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_http_headers;
+ httpd_header * p_http_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_http_headers; i++ )
+ {
+ if( strncasecmp( stream->p_http_headers[i].name, "Content-Length", 14 ) )
+ {
+ httpd_MsgAdd( answer, stream->p_http_headers[i].name,
+ stream->p_http_headers[i].value );
+
+ if( !strncasecmp( stream->p_http_headers[i].name, "Content-Type", 12 ) )
+ b_has_content_type = true;
+ else if( !strncasecmp( stream->p_http_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,8 @@ 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->i_http_headers = 0;
+ stream->p_http_headers = NULL;
httpd_UrlCatch( stream->url, HTTPD_MSG_HEAD, httpd_StreamCallBack,
(httpd_callback_sys_t*)stream );
@@ -896,6 +922,12 @@ int httpd_StreamSend( httpd_stream_t *stream, const block_t *p_block )
void httpd_StreamDelete( httpd_stream_t *stream )
{
httpd_UrlDelete( stream->url );
+ for( size_t i = 0; i < stream->i_http_headers; i++ )
+ {
+ free( stream->p_http_headers[i].name );
+ free( stream->p_http_headers[i].value );
+ }
+ free( stream->p_http_headers );
vlc_mutex_destroy( &stream->lock );
free( stream->psz_mime );
free( stream->p_header );
@@ -1238,10 +1270,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 +1284,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 +1298,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 +1327,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 +1734,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 );
-
- TAB_APPEND( cl->query.i_name, cl->query.name, name );
- TAB_APPEND( cl->query.i_value,cl->query.value,value);
+ httpd_MsgAdd( &cl->query, line, colon );
- if( !strcasecmp( name, "Content-Length" ) )
+ if( !strcasecmp( line, "Content-Length" ) )
{
- cl->query.i_body = atol( value );
+ cl->query.i_body = atol( colon );
}
}
@@ -1832,10 +1864,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 +1882,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 +2396,57 @@ static void* httpd_HostThread( void *data )
vlc_mutex_unlock( &host->lock );
return NULL;
}
+
+int httpd_StreamSetHTTPHeaders(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_http_headers )
+ {
+ for( size_t i = 0; i < p_stream->i_http_headers; i++)
+ {
+ free( p_stream->p_http_headers[i].name );
+ free( p_stream->p_http_headers[i].value );
+ }
+ free( p_stream->p_http_headers );
+ p_stream->p_http_headers = NULL;
+ p_stream->i_http_headers = 0;
+ }
+
+ if( !p_headers || !i_headers )
+ {
+ vlc_mutex_unlock( &p_stream->lock );
+ return VLC_SUCCESS;
+ }
+
+ p_stream->p_http_headers = malloc(sizeof(httpd_header) * i_headers );
+ if( !p_stream->p_http_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_http_headers[j].name = strdup( p_headers[i].name );
+ p_stream->p_http_headers[j].value = strdup( p_headers[i].value );
+
+ if( unlikely( !p_stream->p_http_headers[j].name ||
+ !p_stream->p_http_headers[j].value ) )
+ {
+ free( p_stream->p_http_headers[j].name );
+ free( p_stream->p_http_headers[j].value );
+ break;
+ }
+ j++;
+ }
+ p_stream->i_http_headers = j;
+ vlc_mutex_unlock( &p_stream->lock );
+ return VLC_SUCCESS;
+}
--
1.9.rc1
More information about the vlc-devel
mailing list