root/luci2/zhttpd/zhttpd.c @ 5793

Revision 5793, 3.2 KB (checked in by Cyrus, 3 years ago)

zhttpd (INCOMPLETE): Initial skeleton, and basics

Line 
1#include <signal.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <sys/epoll.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
9
10#include "zhttpd.h"
11#include "tcp.h"
12
13static volatile int running;
14zhttpd_context_t zhttpd = {.handler = NULL};
15
16static void daemonize() {
17    switch (fork()) {
18        case -1:
19            exit(1);
20        case 0:
21            break;
22        default:
23            exit(0);
24    }
25    setsid();
26    chdir("/");
27    int devnull = open("/dev/null", O_RDWR);
28    dup2(devnull, STDIN_FILENO);
29    dup2(devnull, STDOUT_FILENO);
30    dup2(devnull, STDERR_FILENO);
31    close(devnull);
32}
33
34static void sighandler(int signal) {
35    if (signal == SIGHUP) {
36        running = 2;
37    } else {
38        running = 0;
39    }
40}
41
42static void configure() {
43    zhttpd.threads = 32;
44    zhttpd.timeout = 5;
45    zhttpd.daemonize = 1;
46}
47
48static void cleanup() {
49    close(zhttpd.epollfd);
50    zthread_destroy(zhttpd.threadpool);
51    zhttpd_vfs_t *d = NULL;
52    for (zhttpd_vfs_t *c = zhttpd.vfs; c; c = d) {
53        c->handler->vfs_context_destroy(c->context);
54        d = c->next;
55        free(c);
56    }
57}
58
59static void run() {
60    running = 1;
61    zhttpd.threadpool = zthread_create(zhttpd.threads);
62    zhttpd.epollfd = epoll_create(0);
63    zhttpd_tcp_cloexec(zhttpd.epollfd);
64    struct epoll_event *events = malloc
65            (sizeof(struct epoll_event) * zhttpd.threads);
66
67    do {
68        int ready = zthread_step(zhttpd.threadpool, zhttpd.timeout);
69        int signals = epoll_wait(zhttpd.epollfd, events, zhttpd.threads,
70                (ready) ? 0 : 1000);
71        for (int i = 0; i < signals; i++) {
72            ((zthread_t*)events[i].data.ptr)->status = ZTHREAD_READY;
73        }
74    } while(running == 1);
75    free(events);
76}
77
78int main() {
79    struct sigaction action;
80    memset(&action, 0, sizeof(action));
81    action.sa_handler = sighandler;
82    sigaction(SIGHUP, &action, NULL);
83    sigaction(SIGTERM, &action, NULL);
84    action.sa_handler = SIG_IGN;
85    sigaction(SIGPIPE, &action, NULL);
86
87    int firstrun = 1;
88    do {
89        configure();
90        if (firstrun && zhttpd.daemonize) {
91            daemonize();
92            firstrun = 0;
93        }
94        run();
95        cleanup();
96    } while(running);
97    return 0;
98}
99
100int zhttpd_vfs_mount(const char *point, zhttpd_options_t *options) {
101    size_t pointlen = strlen(point);
102    const char *handlername = zhttpd_options_get(options, "handler");
103    if (!handlername) {
104        return ZHTTPD_EINVAL;
105    }
106
107    zhttpd_handler_t *handler = NULL;
108    for (zhttpd_handler_t *c = zhttpd.handler; c; c = c->next) {
109        if (!strcmp(handlername, c->name)) {
110            handler = c;
111            break;
112        }
113    }
114
115    if (!handler) {
116        return ZHTTPD_ENOENT;
117    }
118
119    zhttpd_vfs_t *mount = calloc(1, sizeof(zhttpd_vfs_t) + pointlen + 2);
120    if (!mount) {
121        return ZHTTPD_ENOMEM;
122    }
123
124    memcpy(mount->pattern, point, pointlen);
125    if (point[pointlen - 1] != '/') {
126        mount->pattern[pointlen++] = '/';
127    }
128    mount->patternlen = pointlen;
129    mount->handler = handler;
130    mount->context = handler->vfs_context_create(options);
131    mount->next = zhttpd.vfs;
132    zhttpd.vfs = mount;
133
134    return ZHTTPD_OK;
135}
136
137const char* zhttpd_options_get(zhttpd_options_t *options, const char *key) {
138    size_t keylen = strlen(key);
139    for (; options; options = options->next) {
140        if (!strcmp(key, options->option) && options->option[keylen] == '=') {
141            return &options->option[keylen + 1];
142        }
143    }
144    return NULL;
145}
146
147void zhttpd_register(zhttpd_handler_t *handler) {
148    handler->next = zhttpd.handler;
149    zhttpd.handler = handler;
150}
Note: See TracBrowser for help on using the browser.