From 45517a03cf9c51185ac3bea7f71fb88d1beeafe6 Mon Sep 17 00:00:00 2001 From: Micah Moore Date: Wed, 7 Dec 2022 19:10:50 -0500 Subject: [PATCH] threads in main.c, handling video --- src/http.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/main.c | 41 +++++++++++++++++++++++++++++++++------ 2 files changed, 91 insertions(+), 7 deletions(-) diff --git a/src/http.c b/src/http.c index 6dc6570..b73967f 100644 --- a/src/http.c +++ b/src/http.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include "http.h" #include "hexdump.h" @@ -376,6 +378,46 @@ static bool get_handle_login(struct http_transaction *ta) { return send_response(ta); } +/* Lists the .mp4 files in the given directory in the proper format. */ +static char *list_videos(DIR* dir) { + + json_t *list = json_array(); + + struct dirent *file; + while ((file = readdir(dir)) != NULL) { + char *suffix = strrchr(file->d_name, '.'); + if (suffix != NULL && !strcmp(suffix, ".mp4")) { + + // stat the file + char fname[PATH_MAX]; + struct stat st; + snprintf(fname, sizeof(fname), "%s/%s", server_root, file->d_name); + int rc = stat(fname, &st); + if (rc == -1) + perror("Could not list videos."); + + // json components + json_t *entry = json_object(); + json_t *size = json_integer(st.st_size); + json_t *name = json_string(file->d_name); + rc = json_object_set(entry, "size", size); + if (rc) + perror("JSON append failed."); + rc = json_object_set(entry, "name", name); + if (rc) + perror("JSON append failed."); + + // add entry + rc = json_array_append_new(list, entry); + if (rc) + perror("JSON append failed."); + } + } + + return json_dumps(list, 0); +} + + static int val_api_url(struct http_transaction *ta) { char *req_path = bufio_offset2ptr(ta->client->bufio, ta->req_path); if (!strcmp(req_path, "/api/login")) { @@ -413,7 +455,20 @@ handle_api(struct http_transaction *ta) } else { - // Handle video api + DIR* dir = opendir(server_root); + char *json = list_videos(dir); + fprintf(stderr, "json: %s\n", json); + + http_add_header(&ta->resp_headers, "Content-Type", "application/json"); + + + char *body = buffer_ensure_capacity(&ta->resp_body, MAX_HEADER_LEN); + int len = snprintf(body, strlen(json) + 2, "%s\n", json); + int length = len > MAX_HEADER_LEN ? MAX_HEADER_LEN - 1 : len; + ta->resp_body.len += length; + ta->resp_status = HTTP_OK; + + return send_response(ta); } return false; diff --git a/src/main.c b/src/main.c index d328ada..445c2d5 100644 --- a/src/main.c +++ b/src/main.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "buffer.h" #include "hexdump.h" #include "http.h" @@ -34,6 +35,17 @@ int token_expiration_time = 24 * 60 * 60; // root from which static files are served char * server_root; +static void *thr_func(void *c) { + + struct http_client *client = c; + while (http_handle_transaction(client)); + bufio_close(client->bufio); + + return NULL; +} + + + /* * A non-concurrent, iterative server that serves one client at a time. * For each client, it handles exactly 1 HTTP transaction. @@ -41,18 +53,35 @@ char * server_root; static void server_loop(char *port_string) { + int max_clients = 16; + int num_clients = 0; + pthread_t *threads = malloc(max_clients * sizeof(pthread_t)); + int accepting_socket = socket_open_bind_listen(port_string, 10000); while (accepting_socket != -1) { fprintf(stderr, "Waiting for client...\n"); int client_socket = socket_accept_client(accepting_socket); - if (client_socket == -1) - return; - struct http_client client; - http_setup_client(&client, bufio_create(client_socket)); - http_handle_transaction(&client); - bufio_close(client.bufio); + if (client_socket == -1){ + return; + } + struct http_client *client = malloc(sizeof(struct http_client)); + http_setup_client(client, bufio_create(client_socket)); + + int rc = pthread_create(&threads[num_clients++], NULL, thr_func, client); + + if (rc) { + perror(NULL); + } else if (num_clients >= max_clients) { + max_clients *= 2; + threads = realloc(threads, max_clients * sizeof(pthread_t)); + + } } + for (int i = 0; i < num_clients; i++) { + pthread_join(threads[i], NULL); + } + } static void