diff options
| author | 2024-08-05 06:01:21 +0200 | |
|---|---|---|
| committer | 2024-08-05 06:01:21 +0200 | |
| commit | 972c3dc5d43a114ae59386d4edfdfb8ce0f3793e (patch) | |
| tree | 2568b6190dc0ca34478ccabc1191e504d1e8cfcf | |
| parent | Minor logging tweaks. (diff) | |
| download | penes-snac2-972c3dc5d43a114ae59386d4edfdfb8ce0f3793e.tar.gz penes-snac2-972c3dc5d43a114ae59386d4edfdfb8ce0f3793e.tar.xz penes-snac2-972c3dc5d43a114ae59386d4edfdfb8ce0f3793e.zip | |
Added support for listening on unix sockets.
| -rw-r--r-- | httpd.c | 19 | ||||
| -rw-r--r-- | snac.c | 1 | ||||
| -rw-r--r-- | xs.h | 77 | ||||
| -rw-r--r-- | xs_json.h | 2 | ||||
| -rw-r--r-- | xs_socket.h | 4 | ||||
| -rw-r--r-- | xs_unicode.h | 10 | ||||
| -rw-r--r-- | xs_unix_socket.h | 78 | ||||
| -rw-r--r-- | xs_version.h | 2 |
8 files changed, 172 insertions, 21 deletions
| @@ -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) | |||
| 761 | void httpd(void) | 762 | void 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 | } |
| @@ -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" |
| @@ -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) |
| 124 | xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key); | 124 | xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key); |
| 125 | xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data); | 125 | xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data); |
| 126 | xs_dict *xs_dict_gc(xs_dict *dict); | 126 | xs_dict *xs_dict_gc(const xs_dict *dict); |
| 127 | |||
| 128 | const 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, ".") | ||
| 130 | xs_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 | ||
| 128 | xs_val *xs_val_new(xstype t); | 133 | xs_val *xs_val_new(xstype t); |
| 129 | xs_number *xs_number_new(double f); | 134 | xs_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 | ||
| 1261 | xs_dict *xs_dict_gc(xs_dict *dict) | 1266 | xs_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 | ||
| 1287 | const 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 | |||
| 1308 | xs_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 | ||
| 1281 | xs_val *xs_val_new(xstype t) | 1342 | xs_val *xs_val_new(xstype t) |
| @@ -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 | ||
| 34 | int _xs_utf8_enc(char buf[4], unsigned int cpoint) | 34 | int 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 | ||
| 175 | xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint) | 175 | xs_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 | |||
| 17 | int 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 | |||
| 55 | int 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 */ | ||