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[] = {
|
http_method_t http_methods[] = {
|
||||||
{ "GET /snapshot?", http_snapshot },
|
{ "GET", "/snapshot", http_snapshot },
|
||||||
{ "GET /snapshot.jpg?", http_snapshot },
|
{ "GET", "/snapshot.jpg", http_snapshot },
|
||||||
{ "GET /stream?", http_stream },
|
{ "GET", "/stream", http_stream },
|
||||||
{ "GET /?action=snapshot", http_snapshot },
|
{ "GET", "/?action=snapshot", http_snapshot },
|
||||||
{ "GET /?action=stream", http_stream },
|
{ "GET", "/?action=stream", http_stream },
|
||||||
{ "GET /video?", http_detect_video },
|
{ "GET", "/video", http_detect_video },
|
||||||
{ "GET /video.html?", http_content, "text/html", html_video_html, 0, &html_video_html_len },
|
{ "GET", "/video.html", http_content, "text/html", html_video_html, 0, &html_video_html_len },
|
||||||
{ "GET /video.m3u8?", http_m3u8_video },
|
{ "GET", "/video.m3u8", http_m3u8_video },
|
||||||
{ "GET /video.h264?", http_h264_video },
|
{ "GET", "/video.h264", http_h264_video },
|
||||||
{ "GET /video.mkv?", http_mkv_video },
|
{ "GET", "/video.mkv", http_mkv_video },
|
||||||
{ "GET /video.mp4?", http_mp4_video },
|
{ "GET", "/video.mp4", http_mp4_video },
|
||||||
{ "POST /video?", http_webrtc_offer },
|
{ "POST", "/video", http_webrtc_offer },
|
||||||
{ "GET /option?", camera_http_option },
|
{ "GET", "/option", camera_http_option },
|
||||||
{ "GET /?", http_content, "text/html", html_index_html, 0, &html_index_html_len },
|
{ "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)
|
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;
|
return &http_h264_lowres;
|
||||||
else
|
else
|
||||||
return &http_h264;
|
return &http_h264;
|
||||||
|
@ -22,7 +22,7 @@ static const char *const LOCATION_REDIRECT =
|
|||||||
"HTTP/1.0 307 Temporary Redirect\r\n"
|
"HTTP/1.0 307 Temporary Redirect\r\n"
|
||||||
"Access-Control-Allow-Origin: *\r\n"
|
"Access-Control-Allow-Origin: *\r\n"
|
||||||
"Connection: close\r\n"
|
"Connection: close\r\n"
|
||||||
"Location: %s\r\n"
|
"Location: %s?%s\r\n"
|
||||||
"\r\n";
|
"\r\n";
|
||||||
|
|
||||||
void http_m3u8_video(struct http_worker_s *worker, FILE *stream)
|
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/")) {
|
if (strstr(worker->user_agent, "Safari/") && !strstr(worker->user_agent, "Chrome/") && !strstr(worker->user_agent, "Chromium/")) {
|
||||||
// Safari only supports m3u8
|
// 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/")) {
|
} else if (strstr(worker->user_agent, "Firefox/")) {
|
||||||
// Firefox only supports mp4
|
// Firefox only supports mp4
|
||||||
fprintf(stream, LOCATION_REDIRECT, "video.mp4");
|
fprintf(stream, LOCATION_REDIRECT, "video.mp4", worker->request_params);
|
||||||
} else {
|
} else {
|
||||||
// Chrome offers best latency with mkv
|
// 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)
|
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;
|
return &http_jpeg_lowres;
|
||||||
else
|
else
|
||||||
return &http_jpeg;
|
return &http_jpeg;
|
||||||
|
@ -56,21 +56,16 @@ error:
|
|||||||
|
|
||||||
void *http_enum_params(http_worker_t *worker, FILE *stream, http_param_fn fn, void *opaque)
|
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) {
|
if (!params) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ret = NULL;
|
void *ret = NULL;
|
||||||
char *start = strdup(params + 1);
|
char *start = strdup(params);
|
||||||
char *string = start;
|
char *string = start;
|
||||||
char *option;
|
char *option;
|
||||||
|
|
||||||
// Drop after ` `
|
|
||||||
if ((option = strstr(start, " ")) != NULL) {
|
|
||||||
*option = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((option = strsep(&string, "&")) != NULL) {
|
while ((option = strsep(&string, "&")) != NULL) {
|
||||||
char *value = option;
|
char *value = option;
|
||||||
char *key = strsep(&value, "=");
|
char *key = strsep(&value, "=");
|
||||||
@ -99,6 +94,28 @@ static void http_process(http_worker_t *worker, FILE *stream)
|
|||||||
worker->user_agent[0] = 0;
|
worker->user_agent[0] = 0;
|
||||||
worker->content_length = -1;
|
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
|
// Consume headers
|
||||||
for(int i = 0; i < 50; i++) {
|
for(int i = 0; i < 50; i++) {
|
||||||
char line[BUFSIZE];
|
char line[BUFSIZE];
|
||||||
@ -118,21 +135,30 @@ static void http_process(http_worker_t *worker, FILE *stream)
|
|||||||
|
|
||||||
worker->current_method = NULL;
|
worker->current_method = NULL;
|
||||||
|
|
||||||
for (int i = 0; worker->methods[i].name; i++) {
|
for (int i = 0; worker->methods[i].method; i++) {
|
||||||
const char *name = worker->methods[i].name;
|
http_method_t *method = &worker->methods[i];
|
||||||
int nlen = strlen(worker->methods[i].name);
|
|
||||||
|
|
||||||
if (strncmp(worker->client_method, name, nlen-1))
|
if (strcmp(worker->request_method, method->method))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// allow last character to match `?` or ` `
|
const char *params = strstr(method->uri, "?");
|
||||||
if (worker->client_method[nlen-1] == name[nlen-1] || (name[nlen-1] == '?' && worker->client_method[nlen-1] == ' ')) {
|
|
||||||
worker->current_method = &worker->methods[i];
|
if (params) {
|
||||||
break;
|
// 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) {
|
if (worker->current_method) {
|
||||||
worker->current_method->func(worker, stream);
|
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
|
#define BUFSIZE 256
|
||||||
|
|
||||||
typedef struct http_method_s {
|
typedef struct http_method_s {
|
||||||
const char *name;
|
const char *method;
|
||||||
|
const char *uri;
|
||||||
http_method_fn func;
|
http_method_fn func;
|
||||||
const char *content_type;
|
const char *content_type;
|
||||||
const void *content_body;
|
const void *content_body;
|
||||||
@ -37,6 +38,10 @@ typedef struct http_worker_s {
|
|||||||
char client_method[BUFSIZE];
|
char client_method[BUFSIZE];
|
||||||
char range_header[BUFSIZE];
|
char range_header[BUFSIZE];
|
||||||
char user_agent[BUFSIZE];
|
char user_agent[BUFSIZE];
|
||||||
|
char *request_method;
|
||||||
|
char *request_uri;
|
||||||
|
char *request_params;
|
||||||
|
char *request_version;
|
||||||
|
|
||||||
http_method_t *current_method;
|
http_method_t *current_method;
|
||||||
} http_worker_t;
|
} http_worker_t;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user