📄 httpd.c
字号:
/***************************************************************************** * httpd.c ***************************************************************************** * Copyright (C) 2004-2005 VideoLAN * $Id: httpd.c 11100 2005-05-22 07:46:02Z courmisch $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * Remi Denis-Courmont <rem # videolan.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/#include <stdlib.h>#include <vlc/vlc.h>#ifdef ENABLE_HTTPD#include "vlc_httpd.h"#include "network.h"#include "vlc_tls.h"#include <string.h>#include <errno.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_FCNTL_H# include <fcntl.h>#endif#if defined( UNDER_CE )# include <winsock.h>#elif defined( WIN32 )# include <winsock2.h># include <ws2tcpip.h>#else# include <netdb.h> /* hostent ... */# include <sys/socket.h># include <netinet/in.h># ifdef HAVE_ARPA_INET_H# include <arpa/inet.h> /* inet_ntoa(), inet_aton() */# endif#endif#if defined(WIN32) && !defined(UNDER_CE)static const struct in6_addr in6addr_any = {{IN6ADDR_ANY_INIT}};#elif defined(UNDER_CE) && defined(AF_INET6)# undef AF_INET6#endif#ifndef PF_INET# define PF_INET AF_INET /* BeOS */#endif#if 0typedef struct httpd_t httpd_t;typedef struct httpd_host_t httpd_host_t;typedef struct httpd_url_t httpd_url_t;typedef struct httpd_client_t httpd_client_t;enum{ HTTPD_MSG_NONE, /* answer */ HTTPD_MSG_ANSWER, /* channel communication */ HTTPD_MSG_CHANNEL, /* http request */ HTTPD_MSG_GET, HTTPD_MSG_HEAD, HTTPD_MSG_POST, /* rtsp request */ HTTPD_MSG_OPTIONS, HTTPD_MSG_DESCRIBE, HTTPD_MSG_SETUP, HTTPD_MSG_PLAY, HTTPD_MSG_PAUSE, HTTPD_MSG_TEARDOWN, /* just to track the count of MSG */ HTTPD_MSG_MAX};enum{ HTTPD_PROTO_NONE, HTTPD_PROTO_HTTP, HTTPD_PROTO_RTSP,};typedef struct{ httpd_client_t *cl; /* NULL if not throught a connection e vlc internal */ int i_type; int i_proto; int i_version; /* for an answer */ int i_status; char *psz_status; /* for a query */ char *psz_url; char *psz_args; /* FIXME find a clean way to handle GET(psz_args) and POST(body) through the same code */ /* for rtp over rtsp */ int i_channel; /* options */ int i_name; char **name; int i_value; char **value; /* body */ int64_t i_body_offset; int i_body; uint8_t *p_body;} httpd_message_t;typedef struct httpd_callback_sys_t httpd_callback_sys_t;/* answer could be null, int this case no answer is requested */typedef int (*httpd_callback_t)( httpd_callback_sys_t *, httpd_client_t *, httpd_message_t *answer, httpd_message_t *query );/* create a new host */httpd_host_t *httpd_HostNew( vlc_object_t *, char *psz_host, int i_port );/* delete a host */void httpd_HostDelete( httpd_host_t * );/* register a new url */httpd_url_t *httpd_UrlNew( httpd_host_t *, char *psz_url );/* register callback on a url */int httpd_UrlCatch( httpd_url_t *, int i_msg, httpd_callback_t, httpd_callback_sys_t * );/* delete an url */void httpd_UrlDelete( httpd_url_t * );void httpd_ClientModeStream( httpd_client_t *cl );void httpd_ClientModeBidir( httpd_client_t *cl );static void httpd_ClientClean( httpd_client_t *cl );/* High level */typedef struct httpd_file_t httpd_file_t;typedef struct httpd_file_sys_t httpd_file_sys_t;typedef int (*httpd_file_callback_t)( httpd_file_sys_t*, httpd_file_t *, uint8_t *psz_request, uint8_t **pp_data, int *pi_data );httpd_file_t *httpd_FileNew( httpd_host_t *, char *psz_url, char *psz_mime, char *psz_user, char *psz_password, httpd_file_callback_t pf_fill, httpd_file_sys_t *p_sys );void httpd_FileDelete( httpd_file_t * );typedef struct httpd_redirect_t httpd_redirect_t;httpd_redirect_t *httpd_RedirectNew( httpd_host_t *, char *psz_url_dst, char *psz_url_src );void httpd_RedirectDelete( httpd_redirect_t * );#if 0typedef struct httpd_stream_t httpd_stream_t;httpd_stream_t *httpd_StreamNew( httpd_host_t * );int httpd_StreamHeader( httpd_stream_t *, uint8_t *p_data, int i_data );int httpd_StreamSend( httpd_stream_t *, uint8_t *p_data, int i_data );void httpd_StreamDelete( httpd_stream_t * );#endif/* Msg functions facilities */void httpd_MsgInit( httpd_message_t * );void httpd_MsgAdd( httpd_message_t *, char *psz_name, char *psz_value, ... );/* return "" if not found. The string is not allocated */char *httpd_MsgGet( httpd_message_t *, char *psz_name );void httpd_MsgClean( httpd_message_t * );#endif#if 0struct httpd_t{ VLC_COMMON_MEMBERS /* vlc_mutex_t lock; */ int i_host; httpd_host_t **host;};#endifstatic void httpd_ClientClean( httpd_client_t *cl );/* each host run in his own thread */struct httpd_host_t{ VLC_COMMON_MEMBERS httpd_t *httpd; /* ref count */ int i_ref; /* address/port and socket for listening at connections */ struct sockaddr_storage sock; int i_sock_size; int fd; vlc_mutex_t lock; /* all registered url (becarefull that 2 httpd_url_t could point at the same url) * This will slow down the url research but make my live easier * All url will have their cb trigger, but only the first one can answer * */ int i_url; httpd_url_t **url; int i_client; httpd_client_t **client; /* TLS data */ tls_server_t *p_tls;};struct httpd_url_t{ httpd_host_t *host; vlc_mutex_t lock; char *psz_url; char *psz_user; char *psz_password; struct { httpd_callback_t cb; httpd_callback_sys_t *p_sys; } catch[HTTPD_MSG_MAX];};/* status */enum{ HTTPD_CLIENT_RECEIVING, HTTPD_CLIENT_RECEIVE_DONE, HTTPD_CLIENT_SENDING, HTTPD_CLIENT_SEND_DONE, HTTPD_CLIENT_WAITING, HTTPD_CLIENT_DEAD, HTTPD_CLIENT_TLS_HS_IN, HTTPD_CLIENT_TLS_HS_OUT};/* mode */enum{ HTTPD_CLIENT_FILE, /* default */ HTTPD_CLIENT_STREAM, /* regulary get data from cb */ HTTPD_CLIENT_BIDIR, /* check for reading and get data from cb */};struct httpd_client_t{ httpd_url_t *url; int i_ref; struct sockaddr_storage sock; int i_sock_size; int fd; int i_mode; int i_state; int b_read_waiting; /* stop as soon as possible sending */ mtime_t i_activity_date; mtime_t i_activity_timeout; /* buffer for reading header */ int i_buffer_size; int i_buffer; uint8_t *p_buffer; /* */ httpd_message_t query; /* client -> httpd */ httpd_message_t answer; /* httpd -> client */ /* TLS data */ tls_session_t *p_tls;};/***************************************************************************** * Various functions *****************************************************************************//*char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";*/static void b64_decode( char *dest, char *src ){ int i_level; int last = 0; int b64[256] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 00-0F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 10-1F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, /* 20-2F */ 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, /* 30-3F */ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, /* 40-4F */ 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, /* 50-5F */ -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, /* 60-6F */ 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, /* 70-7F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 80-8F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 90-9F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* A0-AF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* B0-BF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* C0-CF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* D0-DF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* E0-EF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 /* F0-FF */ }; for( i_level = 0; *src != '\0'; src++ ) { int c; c = b64[(unsigned int)*src]; if( c == -1 ) { continue; } switch( i_level ) { case 0: i_level++; break; case 1: *dest++ = ( last << 2 ) | ( ( c >> 4)&0x03 ); i_level++; break; case 2: *dest++ = ( ( last << 4 )&0xf0 ) | ( ( c >> 2 )&0x0f ); i_level++; break; case 3: *dest++ = ( ( last &0x03 ) << 6 ) | c; i_level = 0; } last = c; } *dest = '\0';}static struct{ char *psz_ext; char *psz_mime;} http_mime[] ={ { ".htm", "text/html" }, { ".html", "text/html" }, { ".txt", "text/plain" }, { ".xml", "text/xml" }, { ".dtd", "text/dtd" }, { ".css", "text/css" }, /* image mime */ { ".gif", "image/gif" }, { ".jpe", "image/jpeg" }, { ".jpg", "image/jpeg" }, { ".jpeg", "image/jpeg" }, { ".png", "image/png" }, { ".mpjpeg","multipart/x-mixed-replace; boundary=This Random String" }, /* media mime */ { ".avi", "video/avi" }, { ".asf", "video/x-ms-asf" }, { ".m1a", "audio/mpeg" }, { ".m2a", "audio/mpeg" }, { ".m1v", "video/mpeg" }, { ".m2v", "video/mpeg" }, { ".mp2", "audio/mpeg" }, { ".mp3", "audio/mpeg" }, { ".mpa", "audio/mpeg" }, { ".mpg", "video/mpeg" }, { ".mpeg", "video/mpeg" }, { ".mpe", "video/mpeg" }, { ".mov", "video/quicktime" }, { ".moov", "video/quicktime" }, { ".ogg", "application/ogg" }, { ".ogm", "application/ogg" }, { ".wav", "audio/wav" }, { ".wma", "audio/x-ms-wma" }, { ".wmv", "video/x-ms-wmv" }, /* end */ { NULL, NULL }};static char *httpd_MimeFromUrl( char *psz_url ){ char *psz_ext; psz_ext = strrchr( psz_url, '.' ); if( psz_ext ) { int i; for( i = 0; http_mime[i].psz_ext != NULL ; i++ ) { if( !strcasecmp( http_mime[i].psz_ext, psz_ext ) ) { return http_mime[i].psz_mime; } } } return "application/octet-stream";}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -