Improve HTTP support (to better handle params) and redirect /video params

This commit is contained in:
Kamil Trzcinski 2022-09-07 11:15:09 +02:00
parent 5801152b03
commit f08421a796
6 changed files with 68 additions and 37 deletions

View File

@ -71,19 +71,19 @@ void camera_http_option(http_worker_t *worker, FILE *stream)
}
http_method_t http_methods[] = {
{ "GET /snapshot?", http_snapshot },
{ "GET /snapshot.jpg?", http_snapshot },
{ "GET /stream?", http_stream },
{ "GET /?action=snapshot", http_snapshot },
{ "GET /?action=stream", http_stream },
{ "GET /video?", http_detect_video },
{ "GET /video.html?", http_content, "text/html", html_video_html, 0, &html_video_html_len },
{ "GET /video.m3u8?", http_m3u8_video },
{ "GET /video.h264?", http_h264_video },
{ "GET /video.mkv?", http_mkv_video },
{ "GET /video.mp4?", http_mp4_video },
{ "POST /video?", http_webrtc_offer },
{ "GET /option?", camera_http_option },
{ "GET /?", http_content, "text/html", html_index_html, 0, &html_index_html_len },
{ "GET", "/snapshot", http_snapshot },
{ "GET", "/snapshot.jpg", http_snapshot },
{ "GET", "/stream", http_stream },
{ "GET", "/?action=snapshot", http_snapshot },
{ "GET", "/?action=stream", http_stream },
{ "GET", "/video", http_detect_video },
{ "GET", "/video.html", http_content, "text/html", html_video_html, 0, &html_video_html_len },
{ "GET", "/video.m3u8", http_m3u8_video },
{ "GET", "/video.h264", http_h264_video },
{ "GET", "/video.mkv", http_mkv_video },
{ "GET", "/video.mp4", http_mp4_video },
{ "POST", "/video", http_webrtc_offer },
{ "GET", "/option", camera_http_option },
{ "GET", "/", http_content, "text/html", html_index_html, 0, &html_index_html_len },
{ }
};

View File

@ -18,7 +18,7 @@ static const char *const VIDEO_HEADER =
buffer_lock_t *http_h264_buffer_for_res(http_worker_t *worker)
{
if (strstr(worker->client_method, HTTP_LOW_RES_PARAM) && http_jpeg_lowres.buf_list)
if (strstr(worker->request_params, HTTP_LOW_RES_PARAM) && http_h264_lowres.buf_list)
return &http_h264_lowres;
else
return &http_h264;

View File

@ -22,7 +22,7 @@ static const char *const LOCATION_REDIRECT =
"HTTP/1.0 307 Temporary Redirect\r\n"
"Access-Control-Allow-Origin: *\r\n"
"Connection: close\r\n"
"Location: %s\r\n"
"Location: %s?%s\r\n"
"\r\n";
void http_m3u8_video(struct http_worker_s *worker, FILE *stream)
@ -35,12 +35,12 @@ void http_detect_video(struct http_worker_s *worker, FILE *stream)
{
if (strstr(worker->user_agent, "Safari/") && !strstr(worker->user_agent, "Chrome/") && !strstr(worker->user_agent, "Chromium/")) {
// Safari only supports m3u8
fprintf(stream, LOCATION_REDIRECT, "video.m3u8");
fprintf(stream, LOCATION_REDIRECT, "video.m3u8", worker->request_params);
} else if (strstr(worker->user_agent, "Firefox/")) {
// Firefox only supports mp4
fprintf(stream, LOCATION_REDIRECT, "video.mp4");
fprintf(stream, LOCATION_REDIRECT, "video.mp4", worker->request_params);
} else {
// Chrome offers best latency with mkv
fprintf(stream, LOCATION_REDIRECT, "video.mkv");
fprintf(stream, LOCATION_REDIRECT, "video.mkv", worker->request_params);
}
}

View File

@ -22,7 +22,7 @@ static const char *const STREAM_BOUNDARY = "\r\n"
buffer_lock_t *http_jpeg_buffer_for_res(http_worker_t *worker)
{
if (strstr(worker->client_method, HTTP_LOW_RES_PARAM) && http_jpeg_lowres.buf_list)
if (strstr(worker->request_params, HTTP_LOW_RES_PARAM) && http_jpeg_lowres.buf_list)
return &http_jpeg_lowres;
else
return &http_jpeg;

View File

@ -56,21 +56,16 @@ error:
void *http_enum_params(http_worker_t *worker, FILE *stream, http_param_fn fn, void *opaque)
{
const char *params = strstr(worker->client_method, "?");
const char *params = worker->request_params;
if (!params) {
return NULL;
}
void *ret = NULL;
char *start = strdup(params + 1);
char *start = strdup(params);
char *string = start;
char *option;
// Drop after ` `
if ((option = strstr(start, " ")) != NULL) {
*option = 0;
}
while ((option = strsep(&string, "&")) != NULL) {
char *value = option;
char *key = strsep(&value, "=");
@ -99,6 +94,28 @@ static void http_process(http_worker_t *worker, FILE *stream)
worker->user_agent[0] = 0;
worker->content_length = -1;
// request_uri
worker->request_method = worker->client_method;
if ((worker->request_uri = strstr(worker->request_method, " ")) != NULL) {
*worker->request_uri++ = 0;
} else {
worker->request_uri = "";
}
if ((worker->request_version = strstr(worker->request_uri, " ")) != NULL) {
*worker->request_version++ = 0;
} else {
worker->request_version = "";
}
if ((worker->request_params = strstr(worker->request_uri, "?")) != NULL) {
*worker->request_params++ = 0;
} else {
worker->request_params = "";
}
// Consume headers
for(int i = 0; i < 50; i++) {
char line[BUFSIZE];
@ -118,21 +135,30 @@ static void http_process(http_worker_t *worker, FILE *stream)
worker->current_method = NULL;
for (int i = 0; worker->methods[i].name; i++) {
const char *name = worker->methods[i].name;
int nlen = strlen(worker->methods[i].name);
for (int i = 0; worker->methods[i].method; i++) {
http_method_t *method = &worker->methods[i];
if (strncmp(worker->client_method, name, nlen-1))
if (strcmp(worker->request_method, method->method))
continue;
// allow last character to match `?` or ` `
if (worker->client_method[nlen-1] == name[nlen-1] || (name[nlen-1] == '?' && worker->client_method[nlen-1] == ' ')) {
const char *params = strstr(method->uri, "?");
if (params) {
// match request_uri and params
if (strncmp(worker->request_uri, method->uri, params - method->uri))
continue;
if (!strstr(worker->request_params, params+1))
continue;
} else {
if (strcmp(worker->request_uri, method->uri))
continue;
}
worker->current_method = &worker->methods[i];
break;
}
}
LOG_INFO(worker, "Request '%s'", worker->client_method);
LOG_INFO(worker, "Request '%s' '%s' '%s'", worker->request_method, worker->request_uri, worker->request_params);
if (worker->current_method) {
worker->current_method->func(worker, stream);

View File

@ -16,7 +16,8 @@ typedef void *(*http_param_fn)(struct http_worker_s *worker, FILE *stream, const
#define BUFSIZE 256
typedef struct http_method_s {
const char *name;
const char *method;
const char *uri;
http_method_fn func;
const char *content_type;
const void *content_body;
@ -37,6 +38,10 @@ typedef struct http_worker_s {
char client_method[BUFSIZE];
char range_header[BUFSIZE];
char user_agent[BUFSIZE];
char *request_method;
char *request_uri;
char *request_params;
char *request_version;
http_method_t *current_method;
} http_worker_t;