1 /*****************************************************************************
2 * http.c: HTTP interface
3 *****************************************************************************
4 * Copyright (C) 2005 the VideoLAN team
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_access.h>
38 #include <sys/types.h>
40 /* Include dvbpsi headers */
41 #ifdef HAVE_DVBPSI_DR_H
42 # include <dvbpsi/dvbpsi.h>
43 # include <dvbpsi/descriptor.h>
44 # include <dvbpsi/pat.h>
45 # include <dvbpsi/pmt.h>
46 # include <dvbpsi/dr.h>
47 # include <dvbpsi/psi.h>
48 # include <dvbpsi/demux.h>
49 # include <dvbpsi/sdt.h>
52 # include "descriptor.h"
53 # include "tables/pat.h"
54 # include "tables/pmt.h"
55 # include "descriptors/dr.h"
58 # include "tables/sdt.h"
62 # include <vlc_httpd.h>
69 struct httpd_file_sys_t
75 static int HttpCallback( httpd_file_sys_t *p_args,
78 uint8_t **_pp_data, int *pi_data );
80 /*****************************************************************************
81 * HTTPOpen: Start the internal HTTP server
82 *****************************************************************************/
83 int HTTPOpen( access_t *p_access )
85 access_sys_t *p_sys = p_access->p_sys;
86 char *psz_address, *psz_cert = NULL, *psz_key = NULL,
87 *psz_ca = NULL, *psz_crl = NULL, *psz_user = NULL,
88 *psz_password = NULL, *psz_acl = NULL;
91 vlc_acl_t *p_acl = NULL;
94 vlc_mutex_init( &p_sys->httpd_mutex );
95 vlc_cond_init( &p_sys->httpd_cond );
96 p_sys->b_request_frontend_info = p_sys->b_request_mmi_info = false;
97 p_sys->i_httpd_timeout = 0;
99 psz_address = var_GetNonEmptyString( p_access, "dvb-http-host" );
100 if( psz_address != NULL )
102 char *psz_parser = strchr( psz_address, ':' );
105 *psz_parser++ = '\0';
106 i_port = atoi( psz_parser );
112 /* determine SSL configuration */
113 psz_cert = var_InheritString( p_access, "dvb-http-intf-cert" );
114 if ( psz_cert != NULL )
116 msg_Dbg( p_access, "enabling TLS for HTTP interface (cert file: %s)",
118 psz_key = var_InheritString( p_access, "dvb-http-intf-key" );
119 psz_ca = var_InheritString( p_access, "dvb-http-intf-ca" );
120 psz_crl = var_InheritString( p_access, "dvb-http-intf-crl" );
131 /* Ugly hack to allow to run several HTTP servers on different ports. */
132 sprintf( psz_tmp, ":%d", i_port + 1 );
133 config_PutPsz( p_access, "dvb-http-host", psz_tmp );
135 msg_Dbg( p_access, "base %s:%d", psz_address, i_port );
137 p_sys->p_httpd_host = httpd_TLSHostNew( VLC_OBJECT(p_access), psz_address,
138 i_port, psz_cert, psz_key, psz_ca,
145 if ( p_sys->p_httpd_host == NULL )
147 msg_Err( p_access, "cannot listen on %s:%d", psz_address, i_port );
153 psz_user = var_GetNonEmptyString( p_access, "dvb-http-user" );
154 psz_password = var_GetNonEmptyString( p_access, "dvb-http-password" );
155 psz_acl = var_GetNonEmptyString( p_access, "dvb-http-acl" );
157 if ( psz_acl != NULL )
159 p_acl = ACL_Create( p_access, false );
160 if( ACL_LoadFile( p_acl, psz_acl ) )
162 ACL_Destroy( p_acl );
167 /* Declare an index.html file. */
168 f = malloc( sizeof(httpd_file_sys_t) );
169 f->p_access = p_access;
170 f->p_file = httpd_FileNew( p_sys->p_httpd_host, "/index.html",
171 "text/html; charset=UTF-8",
172 psz_user, psz_password, p_acl,
176 free( psz_password );
179 ACL_Destroy( p_acl );
181 if ( f->p_file == NULL )
184 p_sys->p_httpd_file = NULL;
188 p_sys->p_httpd_file = f;
189 p_sys->p_httpd_redir = httpd_RedirectNew( p_sys->p_httpd_host,
190 "/index.html", "/" );
195 /*****************************************************************************
196 * HTTPClose: Stop the internal HTTP server
197 *****************************************************************************/
198 void HTTPClose( access_t *p_access )
200 access_sys_t *p_sys = p_access->p_sys;
202 if ( p_sys->p_httpd_host != NULL )
204 if ( p_sys->p_httpd_file != NULL )
206 /* Unlock the thread if it is stuck in HttpCallback */
207 vlc_mutex_lock( &p_sys->httpd_mutex );
208 if ( p_sys->b_request_frontend_info == true )
210 p_sys->b_request_frontend_info = false;
211 p_sys->psz_frontend_info = strdup("");
213 if ( p_sys->b_request_mmi_info == true )
215 p_sys->b_request_mmi_info = false;
216 p_sys->psz_mmi_info = strdup("");
218 vlc_cond_signal( &p_sys->httpd_cond );
219 vlc_mutex_unlock( &p_sys->httpd_mutex );
221 httpd_FileDelete( p_sys->p_httpd_file->p_file );
222 httpd_RedirectDelete( p_sys->p_httpd_redir );
225 httpd_HostDelete( p_sys->p_httpd_host );
228 vlc_mutex_destroy( &p_sys->httpd_mutex );
229 vlc_cond_destroy( &p_sys->httpd_cond );
233 static const char *psz_constant_header =
235 "<head><title>VLC DVB monitoring interface</title></head>\n"
236 "<body><a href=\"index.html\">Reload this page</a>\n"
237 "<h1>CAM info</h1>\n";
239 static const char *psz_constant_middle =
240 "<hr><h1>Frontend Info</h1>\n";
242 static const char *psz_constant_footer =
245 /****************************************************************************
246 * HttpCallback: Return the index.html file
247 ****************************************************************************/
248 static int HttpCallback( httpd_file_sys_t *p_args,
249 httpd_file_t *p_file,
250 uint8_t *_psz_request,
251 uint8_t **_pp_data, int *pi_data )
254 access_sys_t *p_sys = p_args->p_access->p_sys;
255 char *psz_request = (char *)_psz_request;
256 char **pp_data = (char **)_pp_data;
258 vlc_mutex_lock( &p_sys->httpd_mutex );
260 p_sys->i_httpd_timeout = mdate() + INT64_C(3000000); /* 3 s */
261 p_sys->psz_request = psz_request;
262 p_sys->b_request_frontend_info = true;
263 if ( p_sys->i_ca_handle )
265 p_sys->b_request_mmi_info = true;
269 p_sys->psz_mmi_info = strdup( "No available CAM interface\n" );
274 vlc_cond_wait( &p_sys->httpd_cond, &p_sys->httpd_mutex );
276 while ( p_sys->b_request_frontend_info || p_sys->b_request_mmi_info );
278 p_sys->i_httpd_timeout = 0;
279 vlc_mutex_unlock( &p_sys->httpd_mutex );
281 *pi_data = strlen( psz_constant_header )
282 + strlen( p_sys->psz_mmi_info )
283 + strlen( psz_constant_middle )
284 + strlen( p_sys->psz_frontend_info )
285 + strlen( psz_constant_footer ) + 1;
286 *pp_data = malloc( *pi_data );
288 sprintf( *pp_data, "%s%s%s%s%s", psz_constant_header,
289 p_sys->psz_mmi_info, psz_constant_middle,
290 p_sys->psz_frontend_info, psz_constant_footer );
291 free( p_sys->psz_frontend_info );
292 free( p_sys->psz_mmi_info );
297 /****************************************************************************
298 * HTTPExtractValue: Extract a GET variable from psz_request
299 ****************************************************************************/
300 const char *HTTPExtractValue( const char *psz_uri, const char *psz_name,
301 char *psz_value, int i_value_max )
303 const char *p = psz_uri;
305 while( (p = strstr( p, psz_name )) )
307 /* Verify that we are dealing with a post/get argument */
308 if( (p == psz_uri || *(p - 1) == '&' || *(p - 1) == '\n')
309 && p[strlen(psz_name)] == '=' )
318 p += strlen( psz_name );
321 if( strchr( p, '&' ) )
323 i_len = strchr( p, '&' ) - p;
327 /* for POST method */
328 if( strchr( p, '\n' ) )
330 i_len = strchr( p, '\n' ) - p;
331 if( i_len && *(p+i_len-1) == '\r' ) i_len--;
338 i_len = __MIN( i_value_max - 1, i_len );
341 strncpy( psz_value, p, i_len );
342 psz_value[i_len] = '\0';
346 strncpy( psz_value, "", i_value_max );
352 strncpy( psz_value, "", i_value_max );
358 #endif /* ENABLE_HTTPD */