summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar default2024-08-05 06:01:21 +0200
committerGravatar default2024-08-05 06:01:21 +0200
commit972c3dc5d43a114ae59386d4edfdfb8ce0f3793e (patch)
tree2568b6190dc0ca34478ccabc1191e504d1e8cfcf
parentMinor logging tweaks. (diff)
downloadsnac2-972c3dc5d43a114ae59386d4edfdfb8ce0f3793e.tar.gz
snac2-972c3dc5d43a114ae59386d4edfdfb8ce0f3793e.tar.xz
snac2-972c3dc5d43a114ae59386d4edfdfb8ce0f3793e.zip
Added support for listening on unix sockets.
-rw-r--r--httpd.c19
-rw-r--r--snac.c1
-rw-r--r--xs.h77
-rw-r--r--xs_json.h2
-rw-r--r--xs_socket.h4
-rw-r--r--xs_unicode.h10
-rw-r--r--xs_unix_socket.h78
-rw-r--r--xs_version.h2
8 files changed, 172 insertions, 21 deletions
diff --git a/httpd.c b/httpd.c
index 287965e..fd3d9e4 100644
--- a/httpd.c
+++ b/httpd.c
@@ -5,6 +5,7 @@
5#include "xs_io.h" 5#include "xs_io.h"
6#include "xs_json.h" 6#include "xs_json.h"
7#include "xs_socket.h" 7#include "xs_socket.h"
8#include "xs_unix_socket.h"
8#include "xs_httpd.h" 9#include "xs_httpd.h"
9#include "xs_mime.h" 10#include "xs_mime.h"
10#include "xs_time.h" 11#include "xs_time.h"
@@ -761,8 +762,8 @@ srv_state *srv_state_op(xs_str **fname, int op)
761void httpd(void) 762void httpd(void)
762/* starts the server */ 763/* starts the server */
763{ 764{
764 const char *address; 765 const char *address = NULL;
765 const char *port; 766 const char *port = NULL;
766 xs *full_address = NULL; 767 xs *full_address = NULL;
767 int rs; 768 int rs;
768 pthread_t threads[MAX_THREADS] = {0}; 769 pthread_t threads[MAX_THREADS] = {0};
@@ -772,11 +773,19 @@ void httpd(void)
772 sem_t anon_job_sem; 773 sem_t anon_job_sem;
773 774
774 address = xs_dict_get(srv_config, "address"); 775 address = xs_dict_get(srv_config, "address");
775 port = xs_number_str(xs_dict_get(srv_config, "port"));
776 776
777 full_address = xs_fmt("%s:%s", address, port); 777 if (*address == '/') {
778 rs = xs_unix_socket_server(address, NULL);
779 full_address = xs_fmt("unix:%s", address);
780 }
781 else {
782 port = xs_number_str(xs_dict_get(srv_config, "port"));
783 full_address = xs_fmt("%s:%s", address, port);
784
785 rs = xs_socket_server(address, port);
786 }
778 787
779 if ((rs = xs_socket_server(address, port)) == -1) { 788 if (rs == -1) {
780 srv_log(xs_fmt("cannot bind socket to %s", full_address)); 789 srv_log(xs_fmt("cannot bind socket to %s", full_address));
781 return; 790 return;
782 } 791 }
diff --git a/snac.c b/snac.c
index 0df8691..25d3f5e 100644
--- a/snac.c
+++ b/snac.c
@@ -11,6 +11,7 @@
11#include "xs_curl.h" 11#include "xs_curl.h"
12#include "xs_openssl.h" 12#include "xs_openssl.h"
13#include "xs_socket.h" 13#include "xs_socket.h"
14#include "xs_unix_socket.h"
14#include "xs_url.h" 15#include "xs_url.h"
15#include "xs_httpd.h" 16#include "xs_httpd.h"
16#include "xs_mime.h" 17#include "xs_mime.h"
diff --git a/xs.h b/xs.h
index f250764..d1a874c 100644
--- a/xs.h
+++ b/xs.h
@@ -123,7 +123,12 @@ const xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_v
123#define xs_dict_get(dict, key) xs_dict_get_def(dict, key, NULL) 123#define xs_dict_get(dict, key) xs_dict_get_def(dict, key, NULL)
124xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key); 124xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key);
125xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data); 125xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data);
126xs_dict *xs_dict_gc(xs_dict *dict); 126xs_dict *xs_dict_gc(const xs_dict *dict);
127
128const xs_val *xs_dict_get_path_sep(const xs_dict *dict, const char *path, const char *sep);
129#define xs_dict_get_path(dict, path) xs_dict_get_path_sep(dict, path, ".")
130xs_dict *xs_dict_set_path_sep(xs_dict *dict, const char *path, const xs_val *value, const char *sep);
131#define xs_dict_set_path(dict, path, value) xs_dict_set_path_sep(dict, path, value, ".")
127 132
128xs_val *xs_val_new(xstype t); 133xs_val *xs_val_new(xstype t);
129xs_number *xs_number_new(double f); 134xs_number *xs_number_new(double f);
@@ -1258,24 +1263,80 @@ int xs_dict_next(const xs_dict *dict, const xs_str **key, const xs_val **value,
1258} 1263}
1259 1264
1260 1265
1261xs_dict *xs_dict_gc(xs_dict *dict) 1266xs_dict *xs_dict_gc(const xs_dict *dict)
1262/* collects garbage (leaked values) inside a dict */ 1267/* creates a copy of dict, but garbage-collected */
1263{ 1268{
1264 xs_dict *nd = xs_dict_new(); 1269 xs_dict *nd = xs_dict_new();
1265 const xs_str *k; 1270 const xs_str *k;
1266 const xs_val *v; 1271 const xs_val *v;
1267 int c = 0; 1272 int c = 0;
1268 1273
1269 /* shamelessly create a new dict with the same content */ 1274 while (xs_dict_next(dict, &k, &v, &c)) {
1270 while (xs_dict_next(dict, &k, &v, &c)) 1275 if (xs_type(v) == XSTYPE_DICT) {
1271 nd = xs_dict_set(nd, k, v); 1276 xs *sd = xs_dict_gc(v);
1272 1277 nd = xs_dict_set(nd, k, sd);
1273 xs_free(dict); 1278 }
1279 else
1280 nd = xs_dict_set(nd, k, v);
1281 }
1274 1282
1275 return nd; 1283 return nd;
1276} 1284}
1277 1285
1278 1286
1287const xs_val *xs_dict_get_path_sep(const xs_dict *dict, const char *path, const char *sep)
1288/* gets a value from dict given a path separated by sep */
1289{
1290 /* split by the separator */
1291 xs *l = xs_split_n(path, sep, 1);
1292
1293 /* only one part? just get */
1294 if (xs_list_len(l) == 1)
1295 return xs_dict_get(dict, path);
1296
1297 const char *prefix = xs_list_get(l, 0);
1298 const char *rest = xs_list_get(l, 1);
1299 const xs_dict *sd = xs_dict_get(dict, prefix);
1300
1301 if (xs_type(sd) == XSTYPE_DICT)
1302 return xs_dict_get_path_sep(sd, rest, sep);
1303
1304 return NULL;
1305}
1306
1307
1308xs_dict *xs_dict_set_path_sep(xs_dict *dict, const char *path, const xs_val *value, const char *sep)
1309/* sets a value into dict given a path separated by sep;
1310 intermediate dicts are created if needed */
1311{
1312 /* split by the separator */
1313 xs *l = xs_split_n(path, sep, 1);
1314
1315 /* only one part? just set */
1316 if (xs_list_len(l) == 1)
1317 return xs_dict_set(dict, path, value);
1318
1319 const char *prefix = xs_list_get(l, 0);
1320 const char *rest = xs_list_get(l, 1);
1321
1322 xs *nd = NULL;
1323
1324 /* does the first part of path exist? */
1325 const xs_dict *cd = xs_dict_get(dict, prefix);
1326
1327 if (xs_type(cd) == XSTYPE_DICT)
1328 nd = xs_dup(cd);
1329 else
1330 nd = xs_dict_new();
1331
1332 /* move down the path */
1333 nd = xs_dict_set_path_sep(nd, rest, value, sep);
1334
1335 /* set */
1336 return xs_dict_set(dict, prefix, nd);
1337}
1338
1339
1279/** other values **/ 1340/** other values **/
1280 1341
1281xs_val *xs_val_new(xstype t) 1342xs_val *xs_val_new(xstype t)
diff --git a/xs_json.h b/xs_json.h
index b65e825..a4112b0 100644
--- a/xs_json.h
+++ b/xs_json.h
@@ -274,7 +274,7 @@ static xs_val *_xs_json_load_lexer(FILE *f, js_type *t)
274 break; 274 break;
275 } 275 }
276 276
277 v = xs_utf8_enc(v, cp); 277 v = xs_utf8_cat(v, cp);
278 } 278 }
279 else { 279 else {
280 char cc = c; 280 char cc = c;
diff --git a/xs_socket.h b/xs_socket.h
index 1c73a22..1bd053a 100644
--- a/xs_socket.h
+++ b/xs_socket.h
@@ -182,8 +182,10 @@ int xs_socket_connect(const char *addr, const char *serv)
182 host.sin_port = htons(atoi(serv)); 182 host.sin_port = htons(atoi(serv));
183 183
184 if ((d = socket(AF_INET, SOCK_STREAM, 0)) != -1) { 184 if ((d = socket(AF_INET, SOCK_STREAM, 0)) != -1) {
185 if (connect(d, (struct sockaddr *)&host, sizeof(host)) == -1) 185 if (connect(d, (struct sockaddr *)&host, sizeof(host)) == -1) {
186 close(d);
186 d = -1; 187 d = -1;
188 }
187 } 189 }
188 } 190 }
189 191
diff --git a/xs_unicode.h b/xs_unicode.h
index 1799d89..2e9a754 100644
--- a/xs_unicode.h
+++ b/xs_unicode.h
@@ -4,7 +4,7 @@
4 4
5#define _XS_UNICODE_H 5#define _XS_UNICODE_H
6 6
7 int _xs_utf8_enc(char buf[4], unsigned int cpoint); 7 int xs_utf8_enc(char buf[4], unsigned int cpoint);
8 int xs_is_utf8_cont_byte(char c); 8 int xs_is_utf8_cont_byte(char c);
9 unsigned int xs_utf8_dec(const char **str); 9 unsigned int xs_utf8_dec(const char **str);
10 int xs_unicode_width(unsigned int cpoint); 10 int xs_unicode_width(unsigned int cpoint);
@@ -22,7 +22,7 @@
22 int xs_unicode_is_alpha(unsigned int cpoint); 22 int xs_unicode_is_alpha(unsigned int cpoint);
23 23
24#ifdef _XS_H 24#ifdef _XS_H
25 xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint); 25 xs_str *xs_utf8_cat(xs_str *str, unsigned int cpoint);
26#endif 26#endif
27 27
28#ifdef XS_IMPLEMENTATION 28#ifdef XS_IMPLEMENTATION
@@ -31,7 +31,7 @@
31#define xs_countof(a) (sizeof((a)) / sizeof((*a))) 31#define xs_countof(a) (sizeof((a)) / sizeof((*a)))
32#endif 32#endif
33 33
34int _xs_utf8_enc(char buf[4], unsigned int cpoint) 34int xs_utf8_enc(char buf[4], unsigned int cpoint)
35/* encodes an Unicode codepoint to utf-8 into buf and returns the size in bytes */ 35/* encodes an Unicode codepoint to utf-8 into buf and returns the size in bytes */
36{ 36{
37 char *p = buf; 37 char *p = buf;
@@ -172,12 +172,12 @@ unsigned int xs_surrogate_enc(unsigned int cpoint)
172 172
173#ifdef _XS_H 173#ifdef _XS_H
174 174
175xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint) 175xs_str *xs_utf8_cat(xs_str *str, unsigned int cpoint)
176/* encodes an Unicode codepoint to utf-8 into str */ 176/* encodes an Unicode codepoint to utf-8 into str */
177{ 177{
178 char tmp[4]; 178 char tmp[4];
179 179
180 int c = _xs_utf8_enc(tmp, cpoint); 180 int c = xs_utf8_enc(tmp, cpoint);
181 181
182 return xs_append_m(str, tmp, c); 182 return xs_append_m(str, tmp, c);
183} 183}
diff --git a/xs_unix_socket.h b/xs_unix_socket.h
new file mode 100644
index 0000000..5b64282
--- /dev/null
+++ b/xs_unix_socket.h
@@ -0,0 +1,78 @@
1/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */
2
3#ifndef _XS_UNIX_SOCKET_H
4
5#define _XS_UNIX_SOCKET_H
6
7 int xs_unix_socket_server(const char *path, const char *grp);
8 int xs_unix_socket_connect(const char *path);
9
10
11#ifdef XS_IMPLEMENTATION
12
13#include <sys/stat.h>
14#include <sys/un.h>
15#include <grp.h>
16
17int xs_unix_socket_server(const char *path, const char *grp)
18/* opens a unix-type server socket */
19{
20 int rs = -1;
21
22 if ((rs = socket(AF_UNIX, SOCK_STREAM, 0)) != -1) {
23 struct sockaddr_un sun = {0};
24 mode_t mode = 0666;
25
26 sun.sun_family = AF_UNIX;
27 strncpy(sun.sun_path, path, sizeof(sun.sun_path));
28
29 unlink(path);
30
31 if (bind(rs, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
32 close(rs);
33 return -1;
34 }
35
36 listen(rs, SOMAXCONN);
37
38 if (grp != NULL) {
39 struct group *g = NULL;
40
41 /* if there is a group name, get its gid_t */
42 g = getgrnam(grp);
43
44 if (g != NULL && chown(path, -1, g->gr_gid) != -1)
45 mode = 0660;
46 }
47
48 chmod(path, mode);
49 }
50
51 return rs;
52}
53
54
55int xs_unix_socket_connect(const char *path)
56/* connects to a unix-type socket */
57{
58 int d = -1;
59
60 if ((d = socket(AF_UNIX, SOCK_STREAM, 0)) != -1) {
61 struct sockaddr_un sun = {0};
62
63 sun.sun_family = AF_UNIX;
64 strncpy(sun.sun_path, path, sizeof(sun.sun_path));
65
66 if (connect(d, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
67 close(d);
68 d = -1;
69 }
70 }
71
72 return d;
73}
74
75
76#endif /* XS_IMPLEMENTATION */
77
78#endif /* _XS_UNIX_SOCKET_H */
diff --git a/xs_version.h b/xs_version.h
index 1f05b57..98a46d0 100644
--- a/xs_version.h
+++ b/xs_version.h
@@ -1 +1 @@
/* 3896c5f782089f0dca68455565bbcd65dd724c91 2024-07-01T08:55:34+02:00 */ /* fb6646ef1b1d5f24768bc829680eb70272755584 2024-08-05T05:32:08+02:00 */