Improve HTTP support (to better handle params) and redirect /video
params
This commit is contained in:
parent
5801152b03
commit
f08421a796
@ -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 },
|
||||
{ }
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user