]> git.sesse.net Git - vlc/blob - modules/access/dvb/http.c
Remove useless <fcntl.h> inclusions
[vlc] / modules / access / dvb / http.c
1 /*****************************************************************************
2  * http.c: HTTP interface
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  *
6  * Authors: Christophe Massiot <massiot@via.ecp.fr>
7  *
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.
12  *
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.
17  *
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  *****************************************************************************/
22
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_access.h>
33
34 #ifdef HAVE_UNISTD_H
35 #   include <unistd.h>
36 #endif
37
38 #include <sys/types.h>
39
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>
50 #else
51 #   include "dvbpsi.h"
52 #   include "descriptor.h"
53 #   include "tables/pat.h"
54 #   include "tables/pmt.h"
55 #   include "descriptors/dr.h"
56 #   include "psi.h"
57 #   include "demux.h"
58 #   include "tables/sdt.h"
59 #endif
60
61 #ifdef ENABLE_HTTPD
62 #   include <vlc_httpd.h>
63 #   include <vlc_acl.h>
64 #endif
65
66 #include "dvb.h"
67
68 #ifdef ENABLE_HTTPD
69 struct httpd_file_sys_t
70 {
71     access_t         *p_access;
72     httpd_file_t     *p_file;
73 };
74
75 static int HttpCallback( httpd_file_sys_t *p_args,
76                          httpd_file_t *p_file,
77                          uint8_t *_p_request,
78                          uint8_t **_pp_data, int *pi_data );
79
80 /*****************************************************************************
81  * HTTPOpen: Start the internal HTTP server
82  *****************************************************************************/
83 int HTTPOpen( access_t *p_access )
84 {
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;
89     int           i_port       = 0;
90     char          psz_tmp[10];
91     vlc_acl_t     *p_acl = NULL;
92     httpd_file_sys_t *f;
93
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;
98
99     psz_address = var_GetNonEmptyString( p_access, "dvb-http-host" );
100     if( psz_address != NULL )
101     {
102         char *psz_parser = strchr( psz_address, ':' );
103         if( psz_parser )
104         {
105             *psz_parser++ = '\0';
106             i_port = atoi( psz_parser );
107         }
108     }
109     else
110         return VLC_SUCCESS;
111
112     /* determine SSL configuration */
113     psz_cert = var_InheritString( p_access, "dvb-http-intf-cert" );
114     if ( psz_cert != NULL )
115     {
116         msg_Dbg( p_access, "enabling TLS for HTTP interface (cert file: %s)",
117                  psz_cert );
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" );
121
122         if ( i_port <= 0 )
123             i_port = 8443;
124     }
125     else
126     {
127         if ( i_port <= 0 )
128             i_port= 8082;
129     }
130
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 );
134
135     msg_Dbg( p_access, "base %s:%d", psz_address, i_port );
136
137     p_sys->p_httpd_host = httpd_TLSHostNew( VLC_OBJECT(p_access), psz_address,
138                                             i_port, psz_cert, psz_key, psz_ca,
139                                             psz_crl );
140     free( psz_cert );
141     free( psz_key );
142     free( psz_ca );
143     free( psz_crl );
144
145     if ( p_sys->p_httpd_host == NULL )
146     {
147         msg_Err( p_access, "cannot listen on %s:%d", psz_address, i_port );
148         free( psz_address );
149         return VLC_EGENERIC;
150     }
151     free( psz_address );
152
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" );
156
157     if ( psz_acl != NULL )
158     {
159         p_acl = ACL_Create( p_access, false );
160         if( ACL_LoadFile( p_acl, psz_acl ) )
161         {
162             ACL_Destroy( p_acl );
163             p_acl = NULL;
164         }
165     }
166
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,
173                                HttpCallback, f );
174
175     free( psz_user );
176     free( psz_password );
177     free( psz_acl );
178     if ( p_acl != NULL )
179         ACL_Destroy( p_acl );
180
181     if ( f->p_file == NULL )
182     {
183         free( f );
184         p_sys->p_httpd_file = NULL;
185         return VLC_EGENERIC;
186     }
187
188     p_sys->p_httpd_file = f;
189     p_sys->p_httpd_redir = httpd_RedirectNew( p_sys->p_httpd_host,
190                                               "/index.html", "/" );
191
192     return VLC_SUCCESS;
193 }
194
195 /*****************************************************************************
196  * HTTPClose: Stop the internal HTTP server
197  *****************************************************************************/
198 void HTTPClose( access_t *p_access )
199 {
200     access_sys_t *p_sys = p_access->p_sys;
201
202     if ( p_sys->p_httpd_host != NULL )
203     {
204         if ( p_sys->p_httpd_file != NULL )
205         {
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 )
209             {
210                 p_sys->b_request_frontend_info = false;
211                 p_sys->psz_frontend_info = strdup("");
212             }
213             if ( p_sys->b_request_mmi_info == true )
214             {
215                 p_sys->b_request_mmi_info = false;
216                 p_sys->psz_mmi_info = strdup("");
217             }
218             vlc_cond_signal( &p_sys->httpd_cond );
219             vlc_mutex_unlock( &p_sys->httpd_mutex );
220
221             httpd_FileDelete( p_sys->p_httpd_file->p_file );
222             httpd_RedirectDelete( p_sys->p_httpd_redir );
223         }
224
225         httpd_HostDelete( p_sys->p_httpd_host );
226     }
227
228     vlc_mutex_destroy( &p_sys->httpd_mutex );
229     vlc_cond_destroy( &p_sys->httpd_cond );
230 }
231
232
233 static const char *psz_constant_header =
234     "<html>\n"
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";
238
239 static const char *psz_constant_middle =
240     "<hr><h1>Frontend Info</h1>\n";
241
242 static const char *psz_constant_footer =
243     "</body></html>\n";
244
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 )
252 {
253     VLC_UNUSED(p_file);
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;
257
258     vlc_mutex_lock( &p_sys->httpd_mutex );
259
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 )
264     {
265         p_sys->b_request_mmi_info = true;
266     }
267     else
268     {
269         p_sys->psz_mmi_info = strdup( "No available CAM interface\n" );
270     }
271
272     do
273     {
274         vlc_cond_wait( &p_sys->httpd_cond, &p_sys->httpd_mutex );
275     }
276     while ( p_sys->b_request_frontend_info || p_sys->b_request_mmi_info );
277
278     p_sys->i_httpd_timeout = 0;
279     vlc_mutex_unlock( &p_sys->httpd_mutex );
280
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 );
287
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 );
293
294     return VLC_SUCCESS;
295 }
296
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 )
302 {
303     const char *p = psz_uri;
304
305     while( (p = strstr( p, psz_name )) )
306     {
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)] == '=' )
310             break;
311         p++;
312     }
313
314     if( p )
315     {
316         int i_len;
317
318         p += strlen( psz_name );
319         if( *p == '=' ) p++;
320
321         if( strchr( p, '&' ) )
322         {
323             i_len = strchr( p, '&' ) - p;
324         }
325         else
326         {
327             /* for POST method */
328             if( strchr( p, '\n' ) )
329             {
330                 i_len = strchr( p, '\n' ) - p;
331                 if( i_len && *(p+i_len-1) == '\r' ) i_len--;
332             }
333             else
334             {
335                 i_len = strlen( p );
336             }
337         }
338         i_len = __MIN( i_value_max - 1, i_len );
339         if( i_len > 0 )
340         {
341             strncpy( psz_value, p, i_len );
342             psz_value[i_len] = '\0';
343         }
344         else
345         {
346             strncpy( psz_value, "", i_value_max );
347         }
348         p += i_len;
349     }
350     else
351     {
352         strncpy( psz_value, "", i_value_max );
353     }
354
355     return p;
356 }
357
358 #endif /* ENABLE_HTTPD */