📄 httpd.c
字号:
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 ); 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; msg->i_channel = -1; msg->i_name = 0; msg->name = NULL; msg->i_value= 0; msg->value = NULL; msg->i_body_offset = 0; msg->i_body = 0; msg->p_body = 0;}void httpd_MsgClean( httpd_message_t *msg ){ int i; if( msg->psz_status ) { free( msg->psz_status ); } if( msg->psz_url ) { free( msg->psz_url ); } if( msg->psz_args ) { free( msg->psz_args ); } for( i = 0; i < msg->i_name; i++ ) { free( msg->name[i] ); free( msg->value[i] ); } if( msg->name ) { free( msg->name ); } if( msg->value ) { free( msg->value ); } if( msg->p_body ) { free( msg->p_body ); } httpd_MsgInit( msg );}char *httpd_MsgGet( httpd_message_t *msg, char *name ){ int i; for( i = 0; i < msg->i_name; i++ ) { if( !strcasecmp( msg->name[i], name )) { return msg->value[i]; } } return "";}void httpd_MsgAdd( httpd_message_t *msg, char *name, char *psz_value, ... ){ va_list args; char *value = NULL; va_start( args, psz_value );#if defined(HAVE_VASPRINTF) && !defined(SYS_DARWIN) && !defined(SYS_BEOS) vasprintf( &value, psz_value, args );#else { int i_size = strlen( psz_value ) + 4096; /* FIXME stupid system */ value = calloc( i_size, sizeof( char ) ); vsnprintf( value, i_size, psz_value, args ); value[i_size - 1] = 0; }#endif va_end( args ); name = strdup( name ); TAB_APPEND( msg->i_name, msg->name, name ); TAB_APPEND( msg->i_value, msg->value, value );}static void httpd_ClientInit( httpd_client_t *cl ){ cl->i_state = HTTPD_CLIENT_RECEIVING; cl->i_activity_date = mdate(); cl->i_activity_timeout = I64C(10000000); cl->i_buffer_size = 10000; cl->i_buffer = 0; cl->p_buffer = malloc( cl->i_buffer_size ); cl->i_mode = HTTPD_CLIENT_FILE; cl->b_read_waiting = VLC_FALSE; httpd_MsgInit( &cl->query ); httpd_MsgInit( &cl->answer );}void httpd_ClientModeStream( httpd_client_t *cl ){ cl->i_mode = HTTPD_CLIENT_STREAM;}void httpd_ClientModeBidir( httpd_client_t *cl ){ cl->i_mode = HTTPD_CLIENT_BIDIR;}char* httpd_ClientIP( httpd_client_t *cl ){#ifdef HAVE_GETNAMEINFO char sz_ip[INET6_ADDRSTRLEN + 2]; int i; if( (cl->sock.ss_family == AF_INET6) && IN6_IS_ADDR_V4MAPPED( &((const struct sockaddr_in6 *) &cl->sock)->sin6_addr) ) { /* If client is using IPv4 but server is using IPv6 */ struct sockaddr_in a; memset( &a, 0, sizeof( a ) ); a.sin_family = AF_INET; a.sin_port = ((const struct sockaddr_in6 *)&cl->sock)->sin6_port; a.sin_addr.s_addr = ((const uint32_t *)&((const struct sockaddr_in6 *) &cl->sock)->sin6_addr)[3]; i = getnameinfo( (const struct sockaddr *)&a, sizeof( a ), &sz_ip[1], INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST ); } else i = getnameinfo( (const struct sockaddr *)&cl->sock, cl->i_sock_size, &sz_ip[1], INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST ); if( i != 0 ) /* FIXME: msg_Err */ return NULL; if( strchr( &sz_ip[1], ':' ) != NULL ) { *sz_ip = '['; i = strlen( sz_ip ); sz_ip[i++] = ']'; sz_ip[i] = '\0'; return strdup( sz_ip ); } return strdup( &sz_ip[1] );#else /* FIXME not thread safe */ return strdup( inet_ntoa( ((const struct sockaddr_in *)&cl->sock)->sin_addr ) );#endif}static void httpd_ClientClean( httpd_client_t *cl ){ if( cl->fd >= 0 ) { if( cl->p_tls != NULL ) tls_ServerSessionClose( cl->p_tls ); net_Close( cl->fd ); cl->fd = -1; } httpd_MsgClean( &cl->answer ); httpd_MsgClean( &cl->query ); if( cl->p_buffer ) { free( cl->p_buffer ); cl->p_buffer = NULL; }}static httpd_client_t *httpd_ClientNew( int fd, struct sockaddr_storage *sock, int i_sock_size, tls_session_t *p_tls ){ httpd_client_t *cl = malloc( sizeof( httpd_client_t ) ); cl->i_ref = 0; cl->fd = fd; memcpy( &cl->sock, sock, sizeof( cl->sock ) ); cl->i_sock_size = i_sock_size; cl->url = NULL; cl->p_tls = p_tls; httpd_ClientInit( cl ); return cl;}static int httpd_NetRecv( httpd_client_t *cl, char *p, int i_len ){ tls_session_t *p_tls; p_tls = cl->p_tls; if( p_tls != NULL) return tls_Recv( p_tls, p, i_len ); return recv( cl->fd, p, i_len, 0 );}static int httpd_NetSend( httpd_client_t *cl, const char *p, int i_len ){ tls_session_t *p_tls; p_tls = cl->p_tls; if( p_tls != NULL) return tls_Send( p_tls, p, i_len ); return send( cl->fd, p, i_len, 0 );}static void httpd_ClientRecv( httpd_client_t *cl ){ int i_len; if( cl->query.i_proto == HTTPD_PROTO_NONE ) { /* enought to see if it's rtp over rtsp or RTSP/HTTP */ i_len = httpd_NetRecv( cl, &cl->p_buffer[cl->i_buffer], 4 - cl->i_buffer ); if( i_len > 0 ) { cl->i_buffer += i_len; } if( cl->i_buffer >= 4 ) { /*fprintf( stderr, "peek=%4.4s\n", cl->p_buffer );*/ /* detect type */ if( cl->p_buffer[0] == '$' ) { /* RTSP (rtp over rtsp) */ cl->query.i_proto = HTTPD_PROTO_RTSP; cl->query.i_type = HTTPD_MSG_CHANNEL; cl->query.i_channel = cl->p_buffer[1]; cl->query.i_body = (cl->p_buffer[2] << 8)|cl->p_buffer[3]; cl->query.p_body = malloc( cl->query.i_body ); cl->i_buffer = 0; } else if( !strncmp( cl->p_buffer, "HTTP", 4 ) ) { cl->query.i_proto = HTTPD_PROTO_HTTP; cl->query.i_type = HTTPD_MSG_ANSWER; } else if( !strncmp( cl->p_buffer, "RTSP", 4 ) ) { cl->query.i_proto = HTTPD_PROTO_RTSP; cl->query.i_type = HTTPD_MSG_ANSWER; } else if( !strncmp( cl->p_buffer, "GET", 3 ) || !strncmp( cl->p_buffer, "HEAD", 4 ) || !strncmp( cl->p_buffer, "POST", 4 ) ) { cl->query.i_proto = HTTPD_PROTO_HTTP; cl->query.i_type = HTTPD_MSG_NONE; } else { cl->query.i_proto = HTTPD_PROTO_RTSP; cl->query.i_type = HTTPD_MSG_NONE; } } } else if( cl->query.i_body > 0 ) { /* we are reading the body of a request or a channel */ i_len = httpd_NetRecv( cl, &cl->query.p_body[cl->i_buffer], cl->query.i_body - cl->i_buffer ); if( i_len > 0 ) { cl->i_buffer += i_len; } if( cl->i_buffer >= cl->query.i_body ) { cl->i_state = HTTPD_CLIENT_RECEIVE_DONE; } } else { /* we are reading a header -> char by char */ for( ;; ) { i_len = httpd_NetRecv (cl, &cl->p_buffer[cl->i_buffer], 1 ); if( i_len <= 0 ) { break; } cl->i_buffer++; if( cl->i_buffer + 1 >= cl->i_buffer_size ) { cl->i_buffer_size += 1024; cl->p_buffer = realloc( cl->p_buffer, cl->i_buffer_size ); } if( ( cl->i_buffer >= 2 && !strncmp( &cl->p_buffer[cl->i_buffer-2], "\n\n", 2 ) )|| ( cl->i_buffer >= 4 && !strncmp( &cl->p_buffer[cl->i_buffer-4], "\r\n\r\n", 4 ) ) ) { char *p; /* we have finished the header so parse it and set i_body */ cl->p_buffer[cl->i_buffer] = '\0'; if( cl->query.i_type == HTTPD_MSG_ANSWER ) { cl->query.i_status = strtol( &cl->p_buffer[strlen( "HTTP/1.x" )], &p, 0 ); while( *p == ' ' ) { p++; } cl->query.psz_status = strdup( p ); } else { static const struct { char *name; int i_type; int i_proto; } msg_type[] = { { "GET", HTTPD_MSG_GET, HTTPD_PROTO_HTTP }, { "HEAD", HTTPD_MSG_HEAD, HTTPD_PROTO_HTTP }, { "POST", HTTPD_MSG_POST, HTTPD_PROTO_HTTP }, { "OPTIONS", HTTPD_MSG_OPTIONS, HTTPD_PROTO_RTSP }, { "DESCRIBE", HTTPD_MSG_DESCRIBE, HTTPD_PROTO_RTSP }, { "SETUP", HTTPD_MSG_SETUP, HTTPD_PROTO_RTSP }, { "PLAY", HTTPD_MSG_PLAY, HTTPD_PROTO_RTSP }, { "PAUSE", HTTPD_MSG_PAUSE, HTTPD_PROTO_RTSP }, { "TEARDOWN", HTTPD_MSG_TEARDOWN, HTTPD_PROTO_RTSP }, { NULL, HTTPD_MSG_NONE, HTTPD_PROTO_NONE } }; int i; p = NULL; cl->query.i_type = HTTPD_MSG_NONE; /*fprintf( stderr, "received new request=%s\n", cl->p_buffer);*/ for( i = 0; msg_type[i].name != NULL; i++ ) { if( !strncmp( cl->p_buffer, msg_type[i].name, strlen( msg_type[i].name ) ) ) { p = &cl->p_buffer[strlen(msg_type[i].name) + 1 ]; cl->query.i_type = msg_type[i].i_type; if( cl->query.i_proto != msg_type[i].i_proto ) { p = NULL; cl->query.i_proto = HTTPD_PROTO_NONE; cl->query.i_type = HTTPD_MSG_NONE; } break; } } if( p == NULL ) { if( strstr( cl->p_buffer, "HTTP/1." ) ) { cl->query.i_proto = HTTPD_PROTO_HTTP; } else if( strstr( cl->p_buffer, "RTSP/1." ) ) { cl->query.i_proto = HTTPD_PROTO_RTSP; } } else { char *p2; char *p3; while( *p == ' ' ) { p++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -