Commit 1ffcc4e5 authored by Denis Charmet's avatar Denis Charmet
Browse files

Allow custom HTTP headers for httpd_Stream

This will end up useful for cubemap implementation and may allow to put mms stuff out of the core
parent 956a6bc8
......@@ -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 );
......
......@@ -162,6 +162,7 @@ httpd_StreamDelete
httpd_StreamHeader
httpd_StreamNew
httpd_StreamSend
httpd_StreamSetHTTPHeaders
httpd_UrlCatch
httpd_UrlDelete
httpd_UrlNew
......
......@@ -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;
......@@ -1252,22 +1282,25 @@ static void httpd_MsgClean( httpd_message_t *msg )
{
free( msg->psz_url );
free( msg->psz_args );
for (int i = 0; i < msg->i_name; i++) {
free( msg->name[i] );
free( msg->value[i] );
for( size_t i = 0; i < msg->i_headers; 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 );
}
const char *httpd_MsgGet( const httpd_message_t *msg, const char *name )
{
for (int i = 0; i < msg->i_name; i++ )
if( !strcasecmp( msg->name[i], name ))
return msg->value[i];
for( size_t i = 0; i < msg->i_headers; i++ )
{
if( !strcasecmp( msg->p_headers[i].name, name ))
{
return msg->p_headers[i].value;
}
}
return NULL;
}
......@@ -1290,9 +1323,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 )
......@@ -1687,23 +1730,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 );
}
}
......@@ -1820,10 +1856,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 )
......@@ -1838,10 +1874,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" );
......@@ -2324,3 +2360,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;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment