diff options
Diffstat (limited to 'multipart-replace-http-server.c')
-rw-r--r-- | multipart-replace-http-server.c | 185 |
1 files changed, 86 insertions, 99 deletions
diff --git a/multipart-replace-http-server.c b/multipart-replace-http-server.c index 195ad29..785bfe3 100644 --- a/multipart-replace-http-server.c +++ b/multipart-replace-http-server.c @@ -1,6 +1,5 @@ /* Copyright 2016 Luke Shumaker */ -#include <ctype.h> /* for isdigit */ #include <errno.h> #include <error.h> #include <fcntl.h> /* for open */ @@ -31,6 +30,7 @@ struct reader_thread_args { }; void *reader_thread(void *args_anon) { + pthread_setname_np(pthread_self(), "reader"); struct reader_thread_args *args = args_anon; multipart_replace_reader(args->stream, args->fd, args->boundary); error(EXIT_FAILURE, 0, "multipart_replace stream ended"); @@ -74,29 +74,95 @@ struct multipart_replace_stream *file_get(const char *filename) { return NULL; } +void connection_handler(int fd) { + FILE *netstream = fdopen(fd, "r"); + char *line_buf = NULL; + size_t line_cap = 0; + ssize_t line_len = 0; + + line_len = getline(&line_buf, &line_cap, netstream); + /* expect line to be "GET /path.mjpg HTTP/1.1" */ + if (strncmp(line_buf, "GET ", 4) != 0) { + dprintf(fd, + "HTTP/1.1 405 Method Not Allowed\r\n" + "Allow: GET\r\n" + "\r\n"); + close(fd); + return; + } + char *version = &line_buf[4]; + char *path = strsep(&version, " "); + if (strcmp(version, "HTTP/1.1\r\n") != 0 && strcmp(version, "HTTP/1.0\r\n")) { + close(fd); + return; + } + path = strdupa(path); + + /* run through the rest of the headers */ + while (strcmp(line_buf, "\r\n") != 0 && line_len >= 0) + line_len = getline(&line_buf, &line_cap, netstream); + + if (strcmp(path, "/") == 0) { + error(0, 0, "200 %s", path); + dprintf(fd, + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "\r\n" + "<!DOCTYPE html>\n" + "<html>\n" + "<head>\n" + " <title>multipart/x-mixed-replace HTTP server</title>\n" + "</head>\n" + "<body>\n" + " <ul>\n" + ); + for (size_t i = 0; i < filec; i++) + dprintf(fd, " <li><a href=\"%s\">%s</a></li>\n", filev[i].name, filev[i].name); + dprintf(fd, + " </ul>\n" + "</body>\n" + "</html>\n"); + close(fd); + return; + } + struct multipart_replace_stream *vidstream = file_get(path); + if (vidstream == NULL) { + error(0, 0, "404 %s", path); + dprintf(fd, + "HTTP/1.1 404 Not Found\r\n" + "\r\n"); + return; + } + + const char *boundary = "boundary" /* FIXME */; + error(0, 0, "200 %s", path); + dprintf(fd, + "HTTP/1.1 200 OK\r\n" + "Content-Type: multipart/x-mixed-replace;boundary=%s\r\n" + "\r\n", + boundary); + multipart_replace_writer(vidstream, fd, boundary); + close(fd); +} + +void *connection_thread(void *arg_anon) { + pthread_setname_np(pthread_self(), "connection"); + int fd = (int)(intptr_t)arg_anon; + error(0, 0, "Connection %d opened", fd); + connection_handler(fd); + error(0, 0, "Connection %d closed", fd); + return NULL; +} + + /* same error codes values as -getaddrinfo(); */ int sockstream_listen(const char *type, const char *addr) { int sock; if (strcmp(type, "fd") == 0) { - if (strcmp(addr, "stdin") == 0) { - sock = 0; - } else if (strcmp(addr, "stdout") == 0) { - sock = 1; - } else if (strcmp(addr, "stderr") == 0) { - sock = 2; - } else if (strcmp(addr, "systemd") == 0) { - sock = 3; /* <systemd/sd-daemon.h>:SD_LISTEN_FDS_START */ - } else { - for (size_t i = 0; addr[i] != '\0'; i++) - if (!isdigit(addr[i])) { - errno = EINVAL; - return -EAI_SYSTEM; - } - if (addr[0] == '\0') { - errno = EINVAL; - return -EAI_SYSTEM; - } - sock = atoi(addr); + sock = get_fd(addr); + if (sock < 0) { + errno = -sock; + return -EAI_SYSTEM; } /* make sure it's a socket */ struct stat st; @@ -195,85 +261,6 @@ int sockstream_listen(const char *type, const char *addr) { } } -void connection_handler(int fd) { - FILE *netstream = fdopen(fd, "r"); - char *line_buf = NULL; - size_t line_cap = 0; - ssize_t line_len = 0; - - line_len = getline(&line_buf, &line_cap, netstream); - /* expect line to be "GET /path.mjpg HTTP/1.1" */ - if (strncmp(line_buf, "GET ", 4) != 0) { - dprintf(fd, - "HTTP/1.1 405 Method Not Allowed\r\n" - "Allow: GET\r\n" - "\r\n"); - close(fd); - return; - } - char *version = &line_buf[4]; - char *path = strsep(&version, " "); - if (strcmp(version, "HTTP/1.1\r\n") != 0 && strcmp(version, "HTTP/1.0\r\n")) { - close(fd); - return; - } - path = strdupa(path); - - /* run through the rest of the headers */ - while (strcmp(line_buf, "\r\n") != 0 && line_len >= 0) - line_len = getline(&line_buf, &line_cap, netstream); - - if (strcmp(path, "/") == 0) { - error(0, 0, "200 %s", path); - dprintf(fd, - "HTTP/1.1 200 OK\r\n" - "Content-Type: text/html; charset=utf-8\r\n" - "\r\n" - "<!DOCTYPE html>\n" - "<html>\n" - "<head>\n" - " <title>multipart/x-mixed-replace HTTP server</title>\n" - "</head>\n" - "<body>\n" - " <ul>\n" - ); - for (size_t i = 0; i < filec; i++) - dprintf(fd, " <li><a href=\"%s\">%s</a></li>\n", filev[i].name, filev[i].name); - dprintf(fd, - " </ul>\n" - "</body>\n" - "</html>\n"); - close(fd); - return; - } - struct multipart_replace_stream *vidstream = file_get(path); - if (vidstream == NULL) { - error(0, 0, "404 %s", path); - dprintf(fd, - "HTTP/1.1 404 Not Found\r\n" - "\r\n"); - return; - } - - const char *boundary = "boundary" /* FIXME */; - error(0, 0, "200 %s", path); - dprintf(fd, - "HTTP/1.1 200 OK\r\n" - "Content-Type: multipart/x-mixed-replace;boundary=%s\r\n" - "\r\n", - boundary); - multipart_replace_writer(vidstream, fd, boundary); - close(fd); -} - -void *connection_thread(void *arg_anon) { - int fd = (int)(intptr_t)arg_anon; - error(0, 0, "Connection %d opened", fd); - connection_handler(fd); - error(0, 0, "Connection %d closed", fd); - return NULL; -} - void usage() { printf("Usage: %s [-h] ADDRTYPE ADDR [FILENAME...]\n", program_invocation_name); printf("Multiplex several multipart/x-mixed-replace streams over HTTP.\n" |