📄 httpd.c
字号:
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 NULL;}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(__APPLE__) && !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 = HTTPD_CL_BUFSIZE; 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( const httpd_client_t *cl, char *psz_ip ){ return net_GetPeerAddress( cl->fd, psz_ip, NULL ) ? NULL : psz_ip;}char* httpd_ServerIP( const httpd_client_t *cl, char *psz_ip ){ return net_GetSockAddress( cl->fd, psz_ip, NULL ) ? NULL : psz_ip;}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 ) ); if( !cl ) return NULL; 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, uint8_t *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 uint8_t *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 ) { /* enough 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( !memcmp( cl->p_buffer, "HTTP", 4 ) ) { cl->query.i_proto = HTTPD_PROTO_HTTP; cl->query.i_type = HTTPD_MSG_ANSWER; } else if( !memcmp( cl->p_buffer, "RTSP", 4 ) ) { cl->query.i_proto = HTTPD_PROTO_RTSP; cl->query.i_type = HTTPD_MSG_ANSWER; } else if( !memcmp( cl->p_buffer, "GET", 3 ) || !memcmp( cl->p_buffer, "HEAD", 4 ) || !memcmp( 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 && !memcmp( &cl->p_buffer[cl->i_buffer-2], "\n\n", 2 ) )|| ( cl->i_buffer >= 4 && !memcmp( &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 ) { /* FIXME: * assume strlen( "HTTP/1.x" ) = 8 */ cl->query.i_status = strtol( (char *)&cl->p_buffer[8], &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( (char *)cl->p_buffer, msg_type[i].name, strlen( msg_type[i].name ) ) ) { p = (char *)&cl->p_buffer[strlen((char *)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( (char *)cl->p_buffer, "HTTP/1." ) ) { cl->query.i_proto = HTTPD_PROTO_HTTP; } else if( strstr( (char *)cl->p_buffer, "RTSP/1." ) ) { cl->query.i_proto = HTTPD_PROTO_RTSP; } } else { char *p2; char *p3; while( *p == ' ' ) { p++; } p2 = strchr( p, ' ' ); if( p2 ) { *p2++ = '\0'; } if( !strncasecmp( p, "rtsp:", 5 ) ) { /* for rtsp url, you have rtsp://localhost:port/path */ p += 5; while( *p == '/' ) p++; while( *p && *p != '/' ) p++; } cl->query.psz_url = strdup( p ); if( ( p3 = strchr( cl->query.psz_url, '?' ) ) ) { *p3++ = '\0'; cl->query.psz_args = (uint8_t *)strdup( p3 ); } if( p2 ) { while( *p2 == ' ' ) { p2++; } if( !strncasecmp( p2, "HTTP/1.", 7 ) ) { cl->query.i_proto = HTTPD_PROTO_HTTP; cl->query.i_version = atoi( p2+7 ); } else if( !strncasecmp( p2, "RTSP/1.", 7 ) ) { cl->query.i_proto = HTTPD_PROTO_RTSP; cl->query.i_version = atoi( p2+7 ); } } p = p2; } } if( p ) { p = strchr( p, '\n' ); } if( p ) { while( *p == '\n' || *p == '\r' ) { p++; } while( p && *p != '\0' ) { char *line = p; char *eol = p = strchr( p, '\n' ); char *colon; while( eol && eol >= line && ( *eol == '\n' || *eol == '\r' ) ) { *eol-- = '\0'; } if( ( colon = strchr( line, ':' ) ) ) { char *name; char *value; *colon++ = '\0'; while( *colon == ' ' ) { colon++; } name = strdup( line ); value = strdup( colon ); TAB_APPEND( cl->query.i_name, cl->query.name, name );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -