📄 httpd.c
字号:
if( psz_mime && *psz_mime ) { stream->psz_mime = strdup( psz_mime ); } else { stream->psz_mime = strdup( httpd_MimeFromUrl( psz_url ) ); } stream->i_header = 0; stream->p_header = NULL; stream->i_buffer_size = 5000000; /* 5 Mo per stream */ stream->p_buffer = malloc( stream->i_buffer_size ); /* We set to 1 to make life simpler * (this way i_body_offset can never be 0) */ stream->i_buffer_pos = 1; stream->i_buffer_last_pos = 1; httpd_UrlCatch( stream->url, HTTPD_MSG_HEAD, httpd_StreamCallBack, (httpd_callback_sys_t*)stream ); httpd_UrlCatch( stream->url, HTTPD_MSG_GET, httpd_StreamCallBack, (httpd_callback_sys_t*)stream ); httpd_UrlCatch( stream->url, HTTPD_MSG_POST, httpd_StreamCallBack, (httpd_callback_sys_t*)stream ); return stream;}int httpd_StreamHeader( httpd_stream_t *stream, uint8_t *p_data, int i_data ){ vlc_mutex_lock( &stream->lock ); if( stream->p_header ) { free( stream->p_header ); stream->p_header = NULL; } stream->i_header = i_data; if( i_data > 0 ) { stream->p_header = malloc( i_data ); memcpy( stream->p_header, p_data, i_data ); } vlc_mutex_unlock( &stream->lock ); return VLC_SUCCESS;}int httpd_StreamSend( httpd_stream_t *stream, uint8_t *p_data, int i_data ){ int i_count; int i_pos; if( i_data < 0 || p_data == NULL ) { return VLC_SUCCESS; } vlc_mutex_lock( &stream->lock ); /* save this pointer (to be used by new connection) */ stream->i_buffer_last_pos = stream->i_buffer_pos; i_pos = stream->i_buffer_pos % stream->i_buffer_size; i_count = i_data; while( i_count > 0) { int i_copy; i_copy = __MIN( i_count, stream->i_buffer_size - i_pos ); /* Ok, we can't go past the end of our buffer */ memcpy( &stream->p_buffer[i_pos], p_data, i_copy ); i_pos = ( i_pos + i_copy ) % stream->i_buffer_size; i_count -= i_copy; p_data += i_copy; } stream->i_buffer_pos += i_data; vlc_mutex_unlock( &stream->lock ); return VLC_SUCCESS;}void httpd_StreamDelete( httpd_stream_t *stream ){ httpd_UrlDelete( stream->url ); vlc_mutex_destroy( &stream->lock ); if( stream->psz_mime ) free( stream->psz_mime ); if( stream->p_header ) free( stream->p_header ); if( stream->p_buffer ) free( stream->p_buffer ); free( stream );}/***************************************************************************** * Low level *****************************************************************************/static void httpd_HostThread( httpd_host_t * );/* create a new host */httpd_host_t *httpd_HostNew( vlc_object_t *p_this, const char *psz_host, int i_port ){ return httpd_TLSHostNew( p_this, psz_host, i_port, NULL, NULL, NULL, NULL );}httpd_host_t *httpd_TLSHostNew( vlc_object_t *p_this, const char *psz_hostname, int i_port, const char *psz_cert, const char *psz_key, const char *psz_ca, const char *psz_crl ){ httpd_t *httpd; httpd_host_t *host; tls_server_t *p_tls; char *psz_host; vlc_value_t lockval; int i; if( psz_hostname == NULL ) psz_hostname = ""; psz_host = strdup( psz_hostname ); if( psz_host == NULL ) { msg_Err( p_this, "memory error" ); return NULL; } /* to be sure to avoid multiple creation */ var_Create( p_this->p_libvlc, "httpd_mutex", VLC_VAR_MUTEX ); var_Get( p_this->p_libvlc, "httpd_mutex", &lockval ); vlc_mutex_lock( lockval.p_address ); if( !(httpd = vlc_object_find( p_this, VLC_OBJECT_HTTPD, FIND_ANYWHERE )) ) { msg_Info( p_this, "creating httpd" ); if( ( httpd = vlc_object_create( p_this, VLC_OBJECT_HTTPD ) ) == NULL ) { vlc_mutex_unlock( lockval.p_address ); free( psz_host ); return NULL; } httpd->i_host = 0; httpd->host = NULL; vlc_object_yield( httpd ); vlc_object_attach( httpd, p_this->p_vlc ); } /* verify if it already exist */ for( i = httpd->i_host - 1; i >= 0; i-- ) { host = httpd->host[i]; /* cannot mix TLS and non-TLS hosts */ if( ( ( httpd->host[i]->p_tls != NULL ) != ( psz_cert != NULL ) ) || ( host->i_port != i_port ) || strcmp( host->psz_hostname, psz_hostname ) ) continue; /* yep found */ host->i_ref++; vlc_mutex_unlock( lockval.p_address ); return host; } host = NULL; /* determine TLS configuration */ if ( psz_cert != NULL ) { p_tls = tls_ServerCreate( p_this, psz_cert, psz_key ); if ( p_tls == NULL ) { msg_Err( p_this, "TLS initialization error" ); goto error; } if ( ( psz_ca != NULL) && tls_ServerAddCA( p_tls, psz_ca ) ) { msg_Err( p_this, "TLS CA error" ); goto error; } if ( ( psz_crl != NULL) && tls_ServerAddCRL( p_tls, psz_crl ) ) { msg_Err( p_this, "TLS CRL error" ); goto error; } } else p_tls = NULL; /* create the new host */ host = vlc_object_create( p_this, VLC_OBJECT_HTTPD_HOST ); host->httpd = httpd; vlc_mutex_init( httpd, &host->lock ); host->i_ref = 1; host->fd = net_ListenTCP( p_this, psz_host, i_port ); if( host->fd == NULL ) { msg_Err( p_this, "cannot create socket(s) for HTTP host" ); goto error; } host->i_port = i_port; host->psz_hostname = psz_host; host->i_url = 0; host->url = NULL; host->i_client = 0; host->client = NULL; host->p_tls = p_tls; /* create the thread */ if( vlc_thread_create( host, "httpd host thread", httpd_HostThread, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) ) { msg_Err( p_this, "cannot spawn http host thread" ); goto error; } /* now add it to httpd */ TAB_APPEND( httpd->i_host, httpd->host, host ); vlc_mutex_unlock( lockval.p_address ); return host;error: free( psz_host ); if( httpd->i_host <= 0 ) { vlc_object_release( httpd ); vlc_object_detach( httpd ); vlc_object_destroy( httpd ); } vlc_mutex_unlock( lockval.p_address ); if( host != NULL ) { net_ListenClose( host->fd ); vlc_mutex_destroy( &host->lock ); vlc_object_destroy( host ); } if( p_tls != NULL ) tls_ServerDelete( p_tls ); return NULL;}/* delete a host */void httpd_HostDelete( httpd_host_t *host ){ httpd_t *httpd = host->httpd; vlc_value_t lockval; int i; var_Get( httpd->p_libvlc, "httpd_mutex", &lockval ); vlc_mutex_lock( lockval.p_address ); host->i_ref--; if( host->i_ref > 0 ) { /* still used */ vlc_mutex_unlock( lockval.p_address ); msg_Dbg( host, "httpd_HostDelete: host still used" ); return; } TAB_REMOVE( httpd->i_host, httpd->host, host ); host->b_die = 1; vlc_thread_join( host ); msg_Dbg( host, "HTTP host removed" ); for( i = 0; i < host->i_url; i++ ) { msg_Err( host, "url still registered: %s", host->url[i]->psz_url ); } for( i = 0; i < host->i_client; i++ ) { httpd_client_t *cl = host->client[i]; msg_Warn( host, "client still connected" ); httpd_ClientClean( cl ); TAB_REMOVE( host->i_client, host->client, cl ); free( cl ); i--; /* TODO */ } if( host->p_tls != NULL) tls_ServerDelete( host->p_tls ); net_ListenClose( host->fd ); free( host->psz_hostname ); vlc_mutex_destroy( &host->lock ); vlc_object_destroy( host ); vlc_object_release( httpd ); if( httpd->i_host <= 0 ) { msg_Dbg( httpd, "no host left, stopping httpd" ); vlc_object_detach( httpd ); vlc_object_destroy( httpd ); } vlc_mutex_unlock( lockval.p_address );}/* register a new url */static httpd_url_t *httpd_UrlNewPrivate( httpd_host_t *host, const char *psz_url, const char *psz_user, const char *psz_password, const vlc_acl_t *p_acl, vlc_bool_t b_check ){ httpd_url_t *url; int i; vlc_mutex_lock( &host->lock ); if( b_check ) { for( i = 0; i < host->i_url; i++ ) { if( !strcmp( psz_url, host->url[i]->psz_url ) ) { msg_Warn( host->httpd, "cannot add '%s' (url already defined)", psz_url ); vlc_mutex_unlock( &host->lock ); return NULL; } } } url = malloc( sizeof( httpd_url_t ) ); url->host = host; vlc_mutex_init( host->httpd, &url->lock ); url->psz_url = strdup( psz_url ); url->psz_user = strdup( psz_user ? psz_user : "" ); url->psz_password = strdup( psz_password ? psz_password : "" ); url->p_acl = ACL_Duplicate( host, p_acl ); for( i = 0; i < HTTPD_MSG_MAX; i++ ) { url->catch[i].cb = NULL; url->catch[i].p_sys = NULL; } TAB_APPEND( host->i_url, host->url, url ); vlc_mutex_unlock( &host->lock ); return url;}httpd_url_t *httpd_UrlNew( httpd_host_t *host, const char *psz_url, const char *psz_user, const char *psz_password, const vlc_acl_t *p_acl ){ return httpd_UrlNewPrivate( host, psz_url, psz_user, psz_password, p_acl, VLC_FALSE );}httpd_url_t *httpd_UrlNewUnique( httpd_host_t *host, const char *psz_url, const char *psz_user, const char *psz_password, const vlc_acl_t *p_acl ){ return httpd_UrlNewPrivate( host, psz_url, psz_user, psz_password, p_acl, VLC_TRUE );}/* register callback on a url */int httpd_UrlCatch( httpd_url_t *url, int i_msg, httpd_callback_t cb, httpd_callback_sys_t *p_sys ){ vlc_mutex_lock( &url->lock ); url->catch[i_msg].cb = cb; url->catch[i_msg].p_sys= p_sys; vlc_mutex_unlock( &url->lock ); return VLC_SUCCESS;}/* delete an url */void httpd_UrlDelete( httpd_url_t *url ){ httpd_host_t *host = url->host; int i; vlc_mutex_lock( &host->lock ); TAB_REMOVE( host->i_url, host->url, url ); vlc_mutex_destroy( &url->lock ); free( url->psz_url ); free( url->psz_user ); free( url->psz_password ); ACL_Destroy( url->p_acl ); for( i = 0; i < host->i_client; i++ ) { httpd_client_t *client = host->client[i]; if( client->url == url ) { /* TODO complete it */ msg_Warn( host, "force closing connections" ); httpd_ClientClean( client ); TAB_REMOVE( host->i_client, host->client, client ); free( client ); i--; } } free( url ); vlc_mutex_unlock( &host->lock );}void httpd_MsgInit( httpd_message_t *msg ){ msg->cl = NULL; msg->i_type = HTTPD_MSG_NONE; msg->i_proto = HTTPD_PROTO_NONE; msg->i_version = -1; msg->i_status = 0; msg->psz_status = NULL; msg->psz_url = NULL; msg->psz_args = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -