commit 972c3dc
default
·
2024-08-05 04:01:21 +0000 UTC
parent e9b108a
Added support for listening on unix sockets.
M
httpd.c
+14,
-5
1@@ -5,6 +5,7 @@
2 #include "xs_io.h"
3 #include "xs_json.h"
4 #include "xs_socket.h"
5+#include "xs_unix_socket.h"
6 #include "xs_httpd.h"
7 #include "xs_mime.h"
8 #include "xs_time.h"
9@@ -761,8 +762,8 @@ srv_state *srv_state_op(xs_str **fname, int op)
10 void httpd(void)
11 /* starts the server */
12 {
13- const char *address;
14- const char *port;
15+ const char *address = NULL;
16+ const char *port = NULL;
17 xs *full_address = NULL;
18 int rs;
19 pthread_t threads[MAX_THREADS] = {0};
20@@ -772,11 +773,19 @@ void httpd(void)
21 sem_t anon_job_sem;
22
23 address = xs_dict_get(srv_config, "address");
24- port = xs_number_str(xs_dict_get(srv_config, "port"));
25
26- full_address = xs_fmt("%s:%s", address, port);
27+ if (*address == '/') {
28+ rs = xs_unix_socket_server(address, NULL);
29+ full_address = xs_fmt("unix:%s", address);
30+ }
31+ else {
32+ port = xs_number_str(xs_dict_get(srv_config, "port"));
33+ full_address = xs_fmt("%s:%s", address, port);
34+
35+ rs = xs_socket_server(address, port);
36+ }
37
38- if ((rs = xs_socket_server(address, port)) == -1) {
39+ if (rs == -1) {
40 srv_log(xs_fmt("cannot bind socket to %s", full_address));
41 return;
42 }
M
snac.c
+1,
-0
1@@ -11,6 +11,7 @@
2 #include "xs_curl.h"
3 #include "xs_openssl.h"
4 #include "xs_socket.h"
5+#include "xs_unix_socket.h"
6 #include "xs_url.h"
7 #include "xs_httpd.h"
8 #include "xs_mime.h"
M
xs.h
+69,
-8
1@@ -123,7 +123,12 @@ const xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_v
2 #define xs_dict_get(dict, key) xs_dict_get_def(dict, key, NULL)
3 xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key);
4 xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data);
5-xs_dict *xs_dict_gc(xs_dict *dict);
6+xs_dict *xs_dict_gc(const xs_dict *dict);
7+
8+const xs_val *xs_dict_get_path_sep(const xs_dict *dict, const char *path, const char *sep);
9+#define xs_dict_get_path(dict, path) xs_dict_get_path_sep(dict, path, ".")
10+xs_dict *xs_dict_set_path_sep(xs_dict *dict, const char *path, const xs_val *value, const char *sep);
11+#define xs_dict_set_path(dict, path, value) xs_dict_set_path_sep(dict, path, value, ".")
12
13 xs_val *xs_val_new(xstype t);
14 xs_number *xs_number_new(double f);
15@@ -1258,24 +1263,80 @@ int xs_dict_next(const xs_dict *dict, const xs_str **key, const xs_val **value,
16 }
17
18
19-xs_dict *xs_dict_gc(xs_dict *dict)
20-/* collects garbage (leaked values) inside a dict */
21+xs_dict *xs_dict_gc(const xs_dict *dict)
22+/* creates a copy of dict, but garbage-collected */
23 {
24 xs_dict *nd = xs_dict_new();
25 const xs_str *k;
26 const xs_val *v;
27 int c = 0;
28
29- /* shamelessly create a new dict with the same content */
30- while (xs_dict_next(dict, &k, &v, &c))
31- nd = xs_dict_set(nd, k, v);
32-
33- xs_free(dict);
34+ while (xs_dict_next(dict, &k, &v, &c)) {
35+ if (xs_type(v) == XSTYPE_DICT) {
36+ xs *sd = xs_dict_gc(v);
37+ nd = xs_dict_set(nd, k, sd);
38+ }
39+ else
40+ nd = xs_dict_set(nd, k, v);
41+ }
42
43 return nd;
44 }
45
46
47+const xs_val *xs_dict_get_path_sep(const xs_dict *dict, const char *path, const char *sep)
48+/* gets a value from dict given a path separated by sep */
49+{
50+ /* split by the separator */
51+ xs *l = xs_split_n(path, sep, 1);
52+
53+ /* only one part? just get */
54+ if (xs_list_len(l) == 1)
55+ return xs_dict_get(dict, path);
56+
57+ const char *prefix = xs_list_get(l, 0);
58+ const char *rest = xs_list_get(l, 1);
59+ const xs_dict *sd = xs_dict_get(dict, prefix);
60+
61+ if (xs_type(sd) == XSTYPE_DICT)
62+ return xs_dict_get_path_sep(sd, rest, sep);
63+
64+ return NULL;
65+}
66+
67+
68+xs_dict *xs_dict_set_path_sep(xs_dict *dict, const char *path, const xs_val *value, const char *sep)
69+/* sets a value into dict given a path separated by sep;
70+ intermediate dicts are created if needed */
71+{
72+ /* split by the separator */
73+ xs *l = xs_split_n(path, sep, 1);
74+
75+ /* only one part? just set */
76+ if (xs_list_len(l) == 1)
77+ return xs_dict_set(dict, path, value);
78+
79+ const char *prefix = xs_list_get(l, 0);
80+ const char *rest = xs_list_get(l, 1);
81+
82+ xs *nd = NULL;
83+
84+ /* does the first part of path exist? */
85+ const xs_dict *cd = xs_dict_get(dict, prefix);
86+
87+ if (xs_type(cd) == XSTYPE_DICT)
88+ nd = xs_dup(cd);
89+ else
90+ nd = xs_dict_new();
91+
92+ /* move down the path */
93+ nd = xs_dict_set_path_sep(nd, rest, value, sep);
94+
95+ /* set */
96+ return xs_dict_set(dict, prefix, nd);
97+}
98+
99+
100 /** other values **/
101
102 xs_val *xs_val_new(xstype t)
+1,
-1
1@@ -274,7 +274,7 @@ static xs_val *_xs_json_load_lexer(FILE *f, js_type *t)
2 break;
3 }
4
5- v = xs_utf8_enc(v, cp);
6+ v = xs_utf8_cat(v, cp);
7 }
8 else {
9 char cc = c;
+3,
-1
1@@ -182,8 +182,10 @@ int xs_socket_connect(const char *addr, const char *serv)
2 host.sin_port = htons(atoi(serv));
3
4 if ((d = socket(AF_INET, SOCK_STREAM, 0)) != -1) {
5- if (connect(d, (struct sockaddr *)&host, sizeof(host)) == -1)
6+ if (connect(d, (struct sockaddr *)&host, sizeof(host)) == -1) {
7+ close(d);
8 d = -1;
9+ }
10 }
11 }
12
+5,
-5
1@@ -4,7 +4,7 @@
2
3 #define _XS_UNICODE_H
4
5- int _xs_utf8_enc(char buf[4], unsigned int cpoint);
6+ int xs_utf8_enc(char buf[4], unsigned int cpoint);
7 int xs_is_utf8_cont_byte(char c);
8 unsigned int xs_utf8_dec(const char **str);
9 int xs_unicode_width(unsigned int cpoint);
10@@ -22,7 +22,7 @@
11 int xs_unicode_is_alpha(unsigned int cpoint);
12
13 #ifdef _XS_H
14- xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint);
15+ xs_str *xs_utf8_cat(xs_str *str, unsigned int cpoint);
16 #endif
17
18 #ifdef XS_IMPLEMENTATION
19@@ -31,7 +31,7 @@
20 #define xs_countof(a) (sizeof((a)) / sizeof((*a)))
21 #endif
22
23-int _xs_utf8_enc(char buf[4], unsigned int cpoint)
24+int xs_utf8_enc(char buf[4], unsigned int cpoint)
25 /* encodes an Unicode codepoint to utf-8 into buf and returns the size in bytes */
26 {
27 char *p = buf;
28@@ -172,12 +172,12 @@ unsigned int xs_surrogate_enc(unsigned int cpoint)
29
30 #ifdef _XS_H
31
32-xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint)
33+xs_str *xs_utf8_cat(xs_str *str, unsigned int cpoint)
34 /* encodes an Unicode codepoint to utf-8 into str */
35 {
36 char tmp[4];
37
38- int c = _xs_utf8_enc(tmp, cpoint);
39+ int c = xs_utf8_enc(tmp, cpoint);
40
41 return xs_append_m(str, tmp, c);
42 }
+78,
-0
1@@ -0,0 +1,78 @@
2+/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */
3+
4+#ifndef _XS_UNIX_SOCKET_H
5+
6+#define _XS_UNIX_SOCKET_H
7+
8+ int xs_unix_socket_server(const char *path, const char *grp);
9+ int xs_unix_socket_connect(const char *path);
10+
11+
12+#ifdef XS_IMPLEMENTATION
13+
14+#include <sys/stat.h>
15+#include <sys/un.h>
16+#include <grp.h>
17+
18+int xs_unix_socket_server(const char *path, const char *grp)
19+/* opens a unix-type server socket */
20+{
21+ int rs = -1;
22+
23+ if ((rs = socket(AF_UNIX, SOCK_STREAM, 0)) != -1) {
24+ struct sockaddr_un sun = {0};
25+ mode_t mode = 0666;
26+
27+ sun.sun_family = AF_UNIX;
28+ strncpy(sun.sun_path, path, sizeof(sun.sun_path));
29+
30+ unlink(path);
31+
32+ if (bind(rs, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
33+ close(rs);
34+ return -1;
35+ }
36+
37+ listen(rs, SOMAXCONN);
38+
39+ if (grp != NULL) {
40+ struct group *g = NULL;
41+
42+ /* if there is a group name, get its gid_t */
43+ g = getgrnam(grp);
44+
45+ if (g != NULL && chown(path, -1, g->gr_gid) != -1)
46+ mode = 0660;
47+ }
48+
49+ chmod(path, mode);
50+ }
51+
52+ return rs;
53+}
54+
55+
56+int xs_unix_socket_connect(const char *path)
57+/* connects to a unix-type socket */
58+{
59+ int d = -1;
60+
61+ if ((d = socket(AF_UNIX, SOCK_STREAM, 0)) != -1) {
62+ struct sockaddr_un sun = {0};
63+
64+ sun.sun_family = AF_UNIX;
65+ strncpy(sun.sun_path, path, sizeof(sun.sun_path));
66+
67+ if (connect(d, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
68+ close(d);
69+ d = -1;
70+ }
71+ }
72+
73+ return d;
74+}
75+
76+
77+#endif /* XS_IMPLEMENTATION */
78+
79+#endif /* _XS_UNIX_SOCKET_H */
+1,
-1
1@@ -1 +1 @@
2-/* 3896c5f782089f0dca68455565bbcd65dd724c91 2024-07-01T08:55:34+02:00 */
3+/* fb6646ef1b1d5f24768bc829680eb70272755584 2024-08-05T05:32:08+02:00 */