@ -93,6 +93,10 @@ typedef struct HTTPContext {
struct FFStream * stream ;
AVFormatContext fmt_ctx ;
int last_packet_sent ; /* true if last data packet was sent */
int suppress_log ;
char protocol [ 16 ] ;
char method [ 16 ] ;
char url [ 128 ] ;
UINT8 buffer [ IOBUFFER_MAX_SIZE ] ;
UINT8 pbuffer [ PACKET_MAX_SIZE ] ;
} HTTPContext ;
@ -161,11 +165,34 @@ static void http_log(char *fmt, ...)
va_list ap ;
va_start ( ap , fmt ) ;
if ( logfile )
if ( logfile ) {
vfprintf ( logfile , fmt , ap ) ;
fflush ( logfile ) ;
}
va_end ( ap ) ;
}
static void log_connection ( HTTPContext * c )
{
char buf1 [ 32 ] , buf2 [ 32 ] , * p ;
time_t ti ;
if ( c - > suppress_log )
return ;
/* XXX: reentrant function ? */
p = inet_ntoa ( c - > from_addr . sin_addr ) ;
strcpy ( buf1 , p ) ;
ti = time ( NULL ) ;
p = ctime ( & ti ) ;
strcpy ( buf2 , p ) ;
p = buf2 + strlen ( p ) - 1 ;
if ( * p = = ' \n ' )
* p = ' \0 ' ;
http_log ( " %s - - [%s] \" %s %s %s \" %d %lld \n " ,
buf1 , buf2 , c - > method , c - > url , c - > protocol , ( c - > http_error ? c - > http_error : 200 ) , c - > data_count ) ;
}
/* main loop of the http server */
static int http_server ( struct sockaddr_in my_addr )
{
@ -264,6 +291,7 @@ static int http_server(struct sockaddr_in my_addr)
c = * cp ;
if ( handle_http ( c , cur_time ) < 0 ) {
/* close and free the connection */
log_connection ( c ) ;
close ( c - > fd ) ;
if ( c - > fmt_in )
av_close_input_file ( c - > fmt_in ) ;
@ -408,11 +436,13 @@ static int handle_http(HTTPContext *c, long cur_time)
return 0 ;
}
/* parse http request and prepare header */
static int http_parse_request ( HTTPContext * c )
{
char * p ;
int post ;
int doing_asx ;
char cmd [ 32 ] ;
char info [ 1024 ] , * filename ;
char url [ 1024 ] , * q ;
@ -429,6 +459,9 @@ static int http_parse_request(HTTPContext *c)
p + + ;
}
* q = ' \0 ' ;
strlcpy ( c - > method , cmd , sizeof ( c - > method ) ) ;
if ( ! strcmp ( cmd , " GET " ) )
post = 0 ;
else if ( ! strcmp ( cmd , " POST " ) )
@ -445,6 +478,8 @@ static int http_parse_request(HTTPContext *c)
}
* q = ' \0 ' ;
strlcpy ( c - > url , url , sizeof ( c - > url ) ) ;
while ( isspace ( * p ) ) p + + ;
q = protocol ;
while ( ! isspace ( * p ) & & * p ! = ' \0 ' ) {
@ -455,6 +490,8 @@ static int http_parse_request(HTTPContext *c)
* q = ' \0 ' ;
if ( strcmp ( protocol , " HTTP/1.0 " ) & & strcmp ( protocol , " HTTP/1.1 " ) )
return - 1 ;
strlcpy ( c - > protocol , protocol , sizeof ( c - > protocol ) ) ;
/* find the filename and the optional info string in the request */
p = url ;
@ -463,12 +500,19 @@ static int http_parse_request(HTTPContext *c)
filename = p ;
p = strchr ( p , ' ? ' ) ;
if ( p ) {
strcpy ( info , p ) ;
strl cpy ( info , p , sizeof ( info ) ) ;
* p = ' \0 ' ;
} else {
info [ 0 ] = ' \0 ' ;
}
if ( strlen ( filename ) > 4 & & strcmp ( " .asx " , filename + strlen ( filename ) - 4 ) = = 0 ) {
doing_asx = 1 ;
filename [ strlen ( filename ) - 1 ] = ' f ' ;
} else {
doing_asx = 0 ;
}
stream = first_stream ;
while ( stream ! = NULL ) {
if ( ! strcmp ( stream - > filename , filename ) )
@ -479,30 +523,98 @@ static int http_parse_request(HTTPContext *c)
sprintf ( msg , " File '%s' not found " , url ) ;
goto send_error ;
}
c - > stream = stream ;
/* should do it after so that the size can be computed */
{
char buf1 [ 32 ] , buf2 [ 32 ] , * p ;
time_t ti ;
/* XXX: reentrant function ? */
p = inet_ntoa ( c - > from_addr . sin_addr ) ;
strcpy ( buf1 , p ) ;
ti = time ( NULL ) ;
p = ctime ( & ti ) ;
strcpy ( buf2 , p ) ;
p = buf2 + strlen ( p ) - 1 ;
if ( * p = = ' \n ' )
* p = ' \0 ' ;
http_log ( " %s - - [%s] \" %s %s %s \" %d %d \n " ,
buf1 , buf2 , cmd , url , protocol , 200 , 1024 ) ;
if ( doing_asx ) {
char * hostinfo = 0 ;
for ( p = c - > buffer ; * p & & * p ! = ' \r ' & & * p ! = ' \n ' ; ) {
if ( strncasecmp ( p , " Host: " , 5 ) = = 0 ) {
hostinfo = p + 5 ;
break ;
}
p = strchr ( p , ' \n ' ) ;
if ( ! p )
break ;
p + + ;
}
if ( hostinfo ) {
char * eoh ;
char hostbuf [ 260 ] ;
while ( isspace ( * hostinfo ) )
hostinfo + + ;
eoh = strchr ( hostinfo , ' \n ' ) ;
if ( eoh ) {
if ( eoh [ - 1 ] = = ' \r ' )
eoh - - ;
if ( eoh - hostinfo < sizeof ( hostbuf ) - 1 ) {
memcpy ( hostbuf , hostinfo , eoh - hostinfo ) ;
hostbuf [ eoh - hostinfo ] = 0 ;
c - > http_error = 200 ;
q = c - > buffer ;
q + = sprintf ( q , " HTTP/1.0 200 ASX Follows \r \n " ) ;
q + = sprintf ( q , " Content-type: video/x-ms-asf \r \n " ) ;
q + = sprintf ( q , " \r \n " ) ;
q + = sprintf ( q , " <ASX Version= \" 3 \" > \r \n " ) ;
q + = sprintf ( q , " <!-- Autogenerated by ffserver --> \r \n " ) ;
q + = sprintf ( q , " <ENTRY><REF HREF= \" http://%s/%s%s \" /></ENTRY> \r \n " ,
hostbuf , filename , info ) ;
q + = sprintf ( q , " </ASX> \r \n " ) ;
/* prepare output buffer */
c - > buffer_ptr = c - > buffer ;
c - > buffer_end = q ;
c - > state = HTTPSTATE_SEND_HEADER ;
return 0 ;
}
}
}
sprintf ( msg , " ASX file not handled " ) ;
goto send_error ;
}
c - > stream = stream ;
/* XXX: add there authenticate and IP match */
if ( post ) {
/* if post, it means a feed is being sent */
if ( ! stream - > is_feed ) {
/* However it might be a status report from WMP! Lets log the data
* as it might come in handy one day
*/
char * logline = 0 ;
for ( p = c - > buffer ; * p & & * p ! = ' \r ' & & * p ! = ' \n ' ; ) {
if ( strncasecmp ( p , " Pragma: log-line= " , 17 ) = = 0 ) {
logline = p ;
break ;
}
p = strchr ( p , ' \n ' ) ;
if ( ! p )
break ;
p + + ;
}
if ( logline ) {
char * eol = strchr ( logline , ' \n ' ) ;
logline + = 17 ;
if ( eol ) {
if ( eol [ - 1 ] = = ' \r ' )
eol - - ;
http_log ( " %.*s \n " , eol - logline , logline ) ;
c - > suppress_log = 1 ;
}
}
sprintf ( msg , " POST command not handled " ) ;
goto send_error ;
}
@ -535,7 +647,9 @@ static int http_parse_request(HTTPContext *c)
/* for asf, we need extra headers */
if ( ! strcmp ( c - > stream - > fmt - > name , " asf " ) ) {
q + = sprintf ( q , " Server: Cougar 4.1.0.3923 \r \n Cache-Control: no-cache \r \n Pragma: client-id=1234 \r \n Pragma: features= \" broadcast \" \r \n " ) ;
mime_type = " application/octet-stream " ;
/* mime_type = "application/octet-stream"; */
/* video/x-ms-asf seems better -- netscape doesn't crash any more! */
mime_type = " video/x-ms-asf " ;
}
q + = sprintf ( q , " Content-Type: %s \r \n " , mime_type ) ;
q + = sprintf ( q , " \r \n " ) ;