123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- #include "xs.h"
- #include "xs_io.h"
- #include "xs_encdec.h"
- #include "xs_json.h"
- #include "xs_socket.h"
- #include "xs_httpd.h"
- #include "snac.h"
- #include <setjmp.h>
- #include <pthread.h>
- const char *susie =
- "iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQAAAAC"
- "CEkxzAAAAUUlEQVQoz43R0QkAMQwCUDdw/y3dwE"
- "vsvzlL4X1IoQkAisKmwfAFT3RgJHbQezpSRoXEq"
- "eqCL9BJBf7h3QbOCCxV5EVWMEMwG7K1/WODtlvx"
- "AYTtEsDU9F34AAAAAElFTkSuQmCC";
- int server_get_handler(d_char *req, char *q_path,
- char **body, int *b_size, char **ctype)
- {
- int status = 0;
- char *acpt = xs_dict_get(req, "accept");
- if (acpt == NULL)
- return 400;
-
- if (*q_path == '\0') {
-
- xs *fn = xs_fmt("%s/greeting.html", srv_basedir);
- FILE *f;
- if ((f = fopen(fn, "r")) != NULL) {
- d_char *s = xs_readall(f);
- fclose(f);
- status = 200;
-
- if (xs_str_in(s, "%userlist%") != -1) {
- char *host = xs_dict_get(srv_config, "host");
- xs *list = user_list();
- char *p, *uid;
- xs *ul = xs_str_new("<ul class=\"snac-user-list\">\n");
- p = list;
- while (xs_list_iter(&p, &uid)) {
- snac snac;
- if (user_open(&snac, uid)) {
- xs *u = xs_fmt(
- "<li><a href=\"%s\">@%s@%s (%s)</a></li>\n",
- snac.actor, uid, host,
- xs_dict_get(snac.config, "name"));
- ul = xs_str_cat(ul, u);
- user_free(&snac);
- }
- }
- ul = xs_str_cat(ul, "</ul>\n");
- s = xs_replace_i(s, "%userlist%", ul);
- }
- *body = s;
- }
- }
- else
- if (strcmp(q_path, "/susie.png") == 0) {
- status = 200;
- *body = xs_base64_dec(susie, b_size);
- *ctype = "image/png";
- }
- if (status != 0)
- srv_debug(1, xs_fmt("server_get_handler serving '%s' %d", q_path, status));
- return status;
- }
- void httpd_connection(int rs)
- {
- FILE *f;
- xs *req;
- char *method;
- int status = 0;
- char *body = NULL;
- int b_size = 0;
- char *ctype = NULL;
- xs *headers = NULL;
- xs *q_path = NULL;
- xs *payload = NULL;
- int p_size = 0;
- char *p;
- f = xs_socket_accept(rs);
- req = xs_httpd_request(f, &payload, &p_size);
- if (req == NULL) {
-
- fclose(f);
- return;
- }
- method = xs_dict_get(req, "method");
- q_path = xs_dup(xs_dict_get(req, "path"));
-
- if (xs_endswith(q_path, "/"))
- q_path = xs_crop(q_path, 0, -1);
- p = xs_dict_get(srv_config, "prefix");
- if (xs_startswith(q_path, p))
- q_path = xs_crop(q_path, strlen(p), 0);
- if (strcmp(method, "GET") == 0) {
-
- if (status == 0)
- status = server_get_handler(req, q_path, &body, &b_size, &ctype);
- if (status == 0)
- status = webfinger_get_handler(req, q_path, &body, &b_size, &ctype);
- if (status == 0)
- status = activitypub_get_handler(req, q_path, &body, &b_size, &ctype);
- if (status == 0)
- status = html_get_handler(req, q_path, &body, &b_size, &ctype);
- }
- else
- if (strcmp(method, "POST") == 0) {
- if (status == 0)
- status = activitypub_post_handler(req, q_path,
- payload, p_size, &body, &b_size, &ctype);
- if (status == 0)
- status = html_post_handler(req, q_path,
- payload, p_size, &body, &b_size, &ctype);
- }
-
- headers = xs_dict_new();
-
- if (status == 0) {
- srv_debug(1, xs_fmt("httpd_connection unattended %s %s", method, q_path));
- status = 404;
- }
- if (status == 404)
- body = xs_str_new("<h1>404 Not Found</h1>");
- if (status == 400)
- body = xs_str_new("<h1>400 Bad Request</h1>");
- if (status == 303)
- headers = xs_dict_append(headers, "location", body);
- if (status == 401)
- headers = xs_dict_append(headers, "WWW-Authenticate", "Basic realm=\"IDENTIFY\"");
- if (ctype == NULL)
- ctype = "text/html; charset=utf-8";
- headers = xs_dict_append(headers, "content-type", ctype);
- headers = xs_dict_append(headers, "x-creator", USER_AGENT);
- if (b_size == 0 && body != NULL)
- b_size = strlen(body);
- xs_httpd_response(f, status, headers, body, b_size);
- fclose(f);
- srv_archive("RECV", req, payload, p_size, status, headers, body, b_size);
- free(body);
- }
- static jmp_buf on_break;
- void term_handler(int s)
- {
- longjmp(on_break, 1);
- }
- static void *helper_thread(void *arg)
- {
- srv_log(xs_fmt("subthread start"));
- while (srv_running) {
- xs *list = user_list();
- char *p, *uid;
- p = list;
- while (xs_list_iter(&p, &uid)) {
- snac snac;
- if (user_open(&snac, uid)) {
- process_queue(&snac);
- user_free(&snac);
- }
- }
- sleep(3);
- }
- srv_log(xs_fmt("subthread stop"));
- return NULL;
- }
- void httpd(void)
- {
- char *address;
- int port;
- int rs;
- pthread_t htid;
- address = xs_dict_get(srv_config, "address");
- port = xs_number_get(xs_dict_get(srv_config, "port"));
- if ((rs = xs_socket_server(address, port)) == -1) {
- srv_log(xs_fmt("cannot bind socket to %s:%d", address, port));
- return;
- }
- srv_running = 1;
- signal(SIGPIPE, SIG_IGN);
- signal(SIGTERM, term_handler);
- signal(SIGINT, term_handler);
- srv_log(xs_fmt("httpd start %s:%d", address, port));
- pthread_create(&htid, NULL, helper_thread, NULL);
- if (setjmp(on_break) == 0) {
- for (;;) {
- httpd_connection(rs);
- }
- }
- srv_running = 0;
-
- pthread_join(htid, NULL);
- srv_log(xs_fmt("httpd stop %s:%d", address, port));
- }
|