📄 httpd.c
字号:
{ httpd_file_t *file = malloc( sizeof( httpd_file_t ) ); if( ( file->url = httpd_UrlNewUnique( host, psz_url, psz_user, psz_password, p_acl ) ) == NULL ) { free( file ); return NULL; } file->psz_url = strdup( psz_url ); if( psz_mime && *psz_mime ) { file->psz_mime = strdup( psz_mime ); } else { file->psz_mime = strdup( httpd_MimeFromUrl( psz_url ) ); } file->pf_fill = pf_fill; file->p_sys = p_sys; httpd_UrlCatch( file->url, HTTPD_MSG_HEAD, httpd_FileCallBack, (httpd_callback_sys_t*)file ); httpd_UrlCatch( file->url, HTTPD_MSG_GET, httpd_FileCallBack, (httpd_callback_sys_t*)file ); httpd_UrlCatch( file->url, HTTPD_MSG_POST, httpd_FileCallBack, (httpd_callback_sys_t*)file ); return file;}void httpd_FileDelete( httpd_file_t *file ){ httpd_UrlDelete( file->url ); free( file->psz_url ); free( file->psz_mime ); free( file );}/***************************************************************************** * High Level Functions: httpd_handler_t (for CGIs) *****************************************************************************/struct httpd_handler_t{ httpd_url_t *url; httpd_handler_callback_t pf_fill; httpd_handler_sys_t *p_sys;};static int httpd_HandlerCallBack( httpd_callback_sys_t *p_sys, httpd_client_t *cl, httpd_message_t *answer, httpd_message_t *query ){ httpd_handler_t *handler = (httpd_handler_t*)p_sys; uint8_t *psz_args = query->psz_args; char psz_remote_addr[NI_MAXNUMERICHOST]; if( answer == NULL || query == NULL ) { return VLC_SUCCESS; } answer->i_proto = HTTPD_PROTO_NONE; answer->i_type = HTTPD_MSG_ANSWER; /* We do it ourselves, thanks */ answer->i_status = 0; answer->psz_status = NULL; if( httpd_ClientIP( cl, psz_remote_addr ) == NULL ) *psz_remote_addr = '\0'; handler->pf_fill( handler->p_sys, handler, query->psz_url, psz_args, query->i_type, query->p_body, query->i_body, psz_remote_addr, NULL, &answer->p_body, &answer->i_body ); if( query->i_type == HTTPD_MSG_HEAD ) { char *p = (char *)answer->p_body; while ( (p = strchr( p, '\r' )) != NULL ) { if( p[1] && p[1] == '\n' && p[2] && p[2] == '\r' && p[3] && p[3] == '\n' ) { break; } } if( p != NULL ) { p[4] = '\0'; answer->i_body = strlen((char*)answer->p_body) + 1; answer->p_body = realloc( answer->p_body, answer->i_body ); } } if( strncmp( (char *)answer->p_body, "HTTP/1.", 7 ) ) { int i_status, i_headers; char *psz_headers, *psz_new, *psz_status; if( !strncmp( (char *)answer->p_body, "Status: ", 8 ) ) { /* Apache-style */ i_status = strtol( (char *)&answer->p_body[8], &psz_headers, 0 ); if( *psz_headers ) psz_headers++; if( *psz_headers ) psz_headers++; i_headers = answer->i_body - (psz_headers - (char *)answer->p_body); } else { i_status = 200; psz_headers = (char *)answer->p_body; i_headers = answer->i_body; } switch( i_status ) { case 200: psz_status = "OK"; break; case 401: psz_status = "Unauthorized"; break; default: if( (i_status < 0) || (i_status > 999) ) i_status = 500; psz_status = "Undefined"; break; } answer->i_body = sizeof("HTTP/1.0 xxx \r\n") + strlen(psz_status) + i_headers - 1; psz_new = (char *)malloc( answer->i_body + 1); sprintf( psz_new, "HTTP/1.0 %03d %s\r\n", i_status, psz_status ); memcpy( &psz_new[strlen(psz_new)], psz_headers, i_headers ); free( answer->p_body ); answer->p_body = (uint8_t *)psz_new; } return VLC_SUCCESS;}httpd_handler_t *httpd_HandlerNew( httpd_host_t *host, const char *psz_url, const char *psz_user, const char *psz_password, const vlc_acl_t *p_acl, httpd_handler_callback_t pf_fill, httpd_handler_sys_t *p_sys ){ httpd_handler_t *handler = malloc( sizeof( httpd_handler_t ) ); if( ( handler->url = httpd_UrlNewUnique( host, psz_url, psz_user, psz_password, p_acl ) ) == NULL ) { free( handler ); return NULL; } handler->pf_fill = pf_fill; handler->p_sys = p_sys; httpd_UrlCatch( handler->url, HTTPD_MSG_HEAD, httpd_HandlerCallBack, (httpd_callback_sys_t*)handler ); httpd_UrlCatch( handler->url, HTTPD_MSG_GET, httpd_HandlerCallBack, (httpd_callback_sys_t*)handler ); httpd_UrlCatch( handler->url, HTTPD_MSG_POST, httpd_HandlerCallBack, (httpd_callback_sys_t*)handler ); return handler;}void httpd_HandlerDelete( httpd_handler_t *handler ){ httpd_UrlDelete( handler->url ); free( handler );}/***************************************************************************** * High Level Functions: httpd_redirect_t *****************************************************************************/struct httpd_redirect_t{ httpd_url_t *url; char *psz_dst;};static int httpd_RedirectCallBack( httpd_callback_sys_t *p_sys, httpd_client_t *cl, httpd_message_t *answer, httpd_message_t *query ){ httpd_redirect_t *rdir = (httpd_redirect_t*)p_sys; char *p_body; if( answer == NULL || query == NULL ) { return VLC_SUCCESS; } answer->i_proto = query->i_proto; answer->i_version= query->i_version; answer->i_type = HTTPD_MSG_ANSWER; answer->i_status = 301; answer->psz_status = strdup( "Moved Permanently" ); answer->i_body = asprintf( &p_body, "<?xml version=\"1.0\" encoding=\"ascii\" ?>\n" "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" " "\"http://www.w3.org/TR/xhtml10/DTD/xhtml10strict.dtd\">\n" "<html>\n" "<head>\n" "<title>Redirection</title>\n" "</head>\n" "<body>\n" "<h1>You should be " "<a href=\"%s\">redirected</a></h1>\n" "<hr />\n" "<p><a href=\"http://www.videolan.org\">VideoLAN</a>\n</p>" "<hr />\n" "</body>\n" "</html>\n", rdir->psz_dst ); answer->p_body = (unsigned char *)p_body; /* XXX check if it's ok or we need to set an absolute url */ httpd_MsgAdd( answer, "Location", "%s", rdir->psz_dst ); httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body ); return VLC_SUCCESS;}httpd_redirect_t *httpd_RedirectNew( httpd_host_t *host, const char *psz_url_dst, const char *psz_url_src ){ httpd_redirect_t *rdir = malloc( sizeof( httpd_redirect_t ) ); if( !( rdir->url = httpd_UrlNewUnique( host, psz_url_src, NULL, NULL, NULL ) ) ) { free( rdir ); return NULL; } rdir->psz_dst = strdup( psz_url_dst ); /* Redirect apply for all HTTP request and RTSP DESCRIBE resquest */ httpd_UrlCatch( rdir->url, HTTPD_MSG_HEAD, httpd_RedirectCallBack, (httpd_callback_sys_t*)rdir ); httpd_UrlCatch( rdir->url, HTTPD_MSG_GET, httpd_RedirectCallBack, (httpd_callback_sys_t*)rdir ); httpd_UrlCatch( rdir->url, HTTPD_MSG_POST, httpd_RedirectCallBack, (httpd_callback_sys_t*)rdir ); httpd_UrlCatch( rdir->url, HTTPD_MSG_DESCRIBE, httpd_RedirectCallBack, (httpd_callback_sys_t*)rdir ); return rdir;}void httpd_RedirectDelete( httpd_redirect_t *rdir ){ httpd_UrlDelete( rdir->url ); free( rdir->psz_dst ); free( rdir );}/***************************************************************************** * High Level Funtions: httpd_stream_t *****************************************************************************/struct httpd_stream_t{ vlc_mutex_t lock; httpd_url_t *url; char *psz_mime; /* Header to send as first packet */ uint8_t *p_header; int i_header; /* circular buffer */ int i_buffer_size; /* buffer size, can't be reallocated smaller */ 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 */};static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys, httpd_client_t *cl, httpd_message_t *answer, httpd_message_t *query ){ httpd_stream_t *stream = (httpd_stream_t*)p_sys; if( answer == NULL || query == NULL || cl == NULL ) { return VLC_SUCCESS; } if( answer->i_body_offset > 0 ) { int64_t i_write; int i_pos;#if 0 fprintf( stderr, "httpd_StreamCallBack i_body_offset=%lld\n", answer->i_body_offset );#endif if( answer->i_body_offset >= stream->i_buffer_pos ) { /* fprintf( stderr, "httpd_StreamCallBack: no data\n" ); */ return VLC_EGENERIC; /* wait, no data available */ } if( answer->i_body_offset + stream->i_buffer_size < stream->i_buffer_pos ) { /* this client isn't fast enough */#if 0 fprintf( stderr, "fixing i_body_offset (old=%lld new=%lld)\n", answer->i_body_offset, stream->i_buffer_last_pos );#endif answer->i_body_offset = stream->i_buffer_last_pos; } i_pos = answer->i_body_offset % stream->i_buffer_size; i_write = stream->i_buffer_pos - answer->i_body_offset; if( i_write > HTTPD_CL_BUFSIZE ) { i_write = HTTPD_CL_BUFSIZE; } else if( i_write <= 0 ) { return VLC_EGENERIC; /* wait, no data available */ } /* Don't go past the end of the circular buffer */ i_write = __MIN( i_write, stream->i_buffer_size - i_pos ); /* using HTTPD_MSG_ANSWER -> data available */ answer->i_proto = HTTPD_PROTO_HTTP; answer->i_version= 0; answer->i_type = HTTPD_MSG_ANSWER; answer->i_body = i_write; answer->p_body = malloc( i_write ); memcpy( answer->p_body, &stream->p_buffer[i_pos], i_write ); answer->i_body_offset += i_write; return VLC_SUCCESS; } else { answer->i_proto = HTTPD_PROTO_HTTP; answer->i_version= 0; answer->i_type = HTTPD_MSG_ANSWER; answer->i_status = 200; answer->psz_status = strdup( "OK" ); if( query->i_type != HTTPD_MSG_HEAD ) { httpd_ClientModeStream( cl ); vlc_mutex_lock( &stream->lock ); /* Send the header */ if( stream->i_header > 0 ) { answer->i_body = stream->i_header; answer->p_body = malloc( stream->i_header ); memcpy( answer->p_body, stream->p_header, stream->i_header ); } answer->i_body_offset = stream->i_buffer_last_pos; vlc_mutex_unlock( &stream->lock ); } else { httpd_MsgAdd( answer, "Content-Length", "%d", 0 ); answer->i_body_offset = 0; } if( !strcmp( stream->psz_mime, "video/x-ms-asf-stream" ) ) { vlc_bool_t b_xplaystream = VLC_FALSE; int i; httpd_MsgAdd( answer, "Content-type", "%s", "application/octet-stream" ); httpd_MsgAdd( answer, "Server", "Cougar 4.1.0.3921" ); httpd_MsgAdd( answer, "Pragma", "no-cache" ); httpd_MsgAdd( answer, "Pragma", "client-id=%d", rand()&0x7fff ); httpd_MsgAdd( answer, "Pragma", "features=\"broadcast\"" ); /* Check if there is a xPlayStrm=1 */ for( i = 0; i < query->i_name; i++ ) { if( !strcasecmp( query->name[i], "Pragma" ) && strstr( query->value[i], "xPlayStrm=1" ) ) { b_xplaystream = VLC_TRUE; } } if( !b_xplaystream ) { answer->i_body_offset = 0; } } else { httpd_MsgAdd( answer, "Content-type", "%s", stream->psz_mime ); } httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" ); return VLC_SUCCESS; }}httpd_stream_t *httpd_StreamNew( httpd_host_t *host, const char *psz_url, const char *psz_mime, const char *psz_user, const char *psz_password, const vlc_acl_t *p_acl ){ httpd_stream_t *stream = malloc( sizeof( httpd_stream_t ) ); if( ( stream->url = httpd_UrlNewUnique( host, psz_url, psz_user, psz_password, p_acl ) ) == NULL ) { free( stream ); return NULL; } vlc_mutex_init( host, &stream->lock );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -