summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordefault <nobody@localhost>2024-08-05 06:01:21 +0200
committerdefault <nobody@localhost>2024-08-05 06:01:21 +0200
commit972c3dc5d43a114ae59386d4edfdfb8ce0f3793e (patch)
tree2568b6190dc0ca34478ccabc1191e504d1e8cfcf
parente9b108a6e0f09d74ee605f1a854ecbdc12a65c92 (diff)
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 @@
#include "xs_io.h"
#include "xs_json.h"
#include "xs_socket.h"
+#include "xs_unix_socket.h"
#include "xs_httpd.h"
#include "xs_mime.h"
#include "xs_time.h"
@@ -761,8 +762,8 @@ srv_state *srv_state_op(xs_str **fname, int op)
void httpd(void)
/* starts the server */
{
- const char *address;
- const char *port;
+ const char *address = NULL;
+ const char *port = NULL;
xs *full_address = NULL;
int rs;
pthread_t threads[MAX_THREADS] = {0};
@@ -772,11 +773,19 @@ void httpd(void)
sem_t anon_job_sem;
address = xs_dict_get(srv_config, "address");
- port = xs_number_str(xs_dict_get(srv_config, "port"));
- full_address = xs_fmt("%s:%s", address, port);
+ if (*address == '/') {
+ rs = xs_unix_socket_server(address, NULL);
+ full_address = xs_fmt("unix:%s", address);
+ }
+ else {
+ port = xs_number_str(xs_dict_get(srv_config, "port"));
+ full_address = xs_fmt("%s:%s", address, port);
+
+ rs = xs_socket_server(address, port);
+ }
- if ((rs = xs_socket_server(address, port)) == -1) {
+ if (rs == -1) {
srv_log(xs_fmt("cannot bind socket to %s", full_address));
return;
}
diff --git a/snac.c b/snac.c
index 0df8691..25d3f5e 100644
--- a/snac.c
+++ b/snac.c
@@ -11,6 +11,7 @@
#include "xs_curl.h"
#include "xs_openssl.h"
#include "xs_socket.h"
+#include "xs_unix_socket.h"
#include "xs_url.h"
#include "xs_httpd.h"
#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
#define xs_dict_get(dict, key) xs_dict_get_def(dict, key, NULL)
xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key);
xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data);
-xs_dict *xs_dict_gc(xs_dict *dict);
+xs_dict *xs_dict_gc(const xs_dict *dict);
+
+const xs_val *xs_dict_get_path_sep(const xs_dict *dict, const char *path, const char *sep);
+#define xs_dict_get_path(dict, path) xs_dict_get_path_sep(dict, path, ".")
+xs_dict *xs_dict_set_path_sep(xs_dict *dict, const char *path, const xs_val *value, const char *sep);
+#define xs_dict_set_path(dict, path, value) xs_dict_set_path_sep(dict, path, value, ".")
xs_val *xs_val_new(xstype t);
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,
}
-xs_dict *xs_dict_gc(xs_dict *dict)
-/* collects garbage (leaked values) inside a dict */
+xs_dict *xs_dict_gc(const xs_dict *dict)
+/* creates a copy of dict, but garbage-collected */
{
xs_dict *nd = xs_dict_new();
const xs_str *k;
const xs_val *v;
int c = 0;
- /* shamelessly create a new dict with the same content */
- while (xs_dict_next(dict, &k, &v, &c))
- nd = xs_dict_set(nd, k, v);
-
- xs_free(dict);
+ while (xs_dict_next(dict, &k, &v, &c)) {
+ if (xs_type(v) == XSTYPE_DICT) {
+ xs *sd = xs_dict_gc(v);
+ nd = xs_dict_set(nd, k, sd);
+ }
+ else
+ nd = xs_dict_set(nd, k, v);
+ }
return nd;
}
+const xs_val *xs_dict_get_path_sep(const xs_dict *dict, const char *path, const char *sep)
+/* gets a value from dict given a path separated by sep */
+{
+ /* split by the separator */
+ xs *l = xs_split_n(path, sep, 1);
+
+ /* only one part? just get */
+ if (xs_list_len(l) == 1)
+ return xs_dict_get(dict, path);
+
+ const char *prefix = xs_list_get(l, 0);
+ const char *rest = xs_list_get(l, 1);
+ const xs_dict *sd = xs_dict_get(dict, prefix);
+
+ if (xs_type(sd) == XSTYPE_DICT)
+ return xs_dict_get_path_sep(sd, rest, sep);
+
+ return NULL;
+}
+
+
+xs_dict *xs_dict_set_path_sep(xs_dict *dict, const char *path, const xs_val *value, const char *sep)
+/* sets a value into dict given a path separated by sep;
+ intermediate dicts are created if needed */
+{
+ /* split by the separator */
+ xs *l = xs_split_n(path, sep, 1);
+
+ /* only one part? just set */
+ if (xs_list_len(l) == 1)
+ return xs_dict_set(dict, path, value);
+
+ const char *prefix = xs_list_get(l, 0);
+ const char *rest = xs_list_get(l, 1);
+
+ xs *nd = NULL;
+
+ /* does the first part of path exist? */
+ const xs_dict *cd = xs_dict_get(dict, prefix);
+
+ if (xs_type(cd) == XSTYPE_DICT)
+ nd = xs_dup(cd);
+ else
+ nd = xs_dict_new();
+
+ /* move down the path */
+ nd = xs_dict_set_path_sep(nd, rest, value, sep);
+
+ /* set */
+ return xs_dict_set(dict, prefix, nd);
+}
+
+
/** other values **/
xs_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)
break;
}
- v = xs_utf8_enc(v, cp);
+ v = xs_utf8_cat(v, cp);
}
else {
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)
host.sin_port = htons(atoi(serv));
if ((d = socket(AF_INET, SOCK_STREAM, 0)) != -1) {
- if (connect(d, (struct sockaddr *)&host, sizeof(host)) == -1)
+ if (connect(d, (struct sockaddr *)&host, sizeof(host)) == -1) {
+ close(d);
d = -1;
+ }
}
}
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 @@
#define _XS_UNICODE_H
- int _xs_utf8_enc(char buf[4], unsigned int cpoint);
+ int xs_utf8_enc(char buf[4], unsigned int cpoint);
int xs_is_utf8_cont_byte(char c);
unsigned int xs_utf8_dec(const char **str);
int xs_unicode_width(unsigned int cpoint);
@@ -22,7 +22,7 @@
int xs_unicode_is_alpha(unsigned int cpoint);
#ifdef _XS_H
- xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint);
+ xs_str *xs_utf8_cat(xs_str *str, unsigned int cpoint);
#endif
#ifdef XS_IMPLEMENTATION
@@ -31,7 +31,7 @@
#define xs_countof(a) (sizeof((a)) / sizeof((*a)))
#endif
-int _xs_utf8_enc(char buf[4], unsigned int cpoint)
+int xs_utf8_enc(char buf[4], unsigned int cpoint)
/* encodes an Unicode codepoint to utf-8 into buf and returns the size in bytes */
{
char *p = buf;
@@ -172,12 +172,12 @@ unsigned int xs_surrogate_enc(unsigned int cpoint)
#ifdef _XS_H
-xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint)
+xs_str *xs_utf8_cat(xs_str *str, unsigned int cpoint)
/* encodes an Unicode codepoint to utf-8 into str */
{
char tmp[4];
- int c = _xs_utf8_enc(tmp, cpoint);
+ int c = xs_utf8_enc(tmp, cpoint);
return xs_append_m(str, tmp, c);
}
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 @@
+/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */
+
+#ifndef _XS_UNIX_SOCKET_H
+
+#define _XS_UNIX_SOCKET_H
+
+ int xs_unix_socket_server(const char *path, const char *grp);
+ int xs_unix_socket_connect(const char *path);
+
+
+#ifdef XS_IMPLEMENTATION
+
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <grp.h>
+
+int xs_unix_socket_server(const char *path, const char *grp)
+/* opens a unix-type server socket */
+{
+ int rs = -1;
+
+ if ((rs = socket(AF_UNIX, SOCK_STREAM, 0)) != -1) {
+ struct sockaddr_un sun = {0};
+ mode_t mode = 0666;
+
+ sun.sun_family = AF_UNIX;
+ strncpy(sun.sun_path, path, sizeof(sun.sun_path));
+
+ unlink(path);
+
+ if (bind(rs, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
+ close(rs);
+ return -1;
+ }
+
+ listen(rs, SOMAXCONN);
+
+ if (grp != NULL) {
+ struct group *g = NULL;
+
+ /* if there is a group name, get its gid_t */
+ g = getgrnam(grp);
+
+ if (g != NULL && chown(path, -1, g->gr_gid) != -1)
+ mode = 0660;
+ }
+
+ chmod(path, mode);
+ }
+
+ return rs;
+}
+
+
+int xs_unix_socket_connect(const char *path)
+/* connects to a unix-type socket */
+{
+ int d = -1;
+
+ if ((d = socket(AF_UNIX, SOCK_STREAM, 0)) != -1) {
+ struct sockaddr_un sun = {0};
+
+ sun.sun_family = AF_UNIX;
+ strncpy(sun.sun_path, path, sizeof(sun.sun_path));
+
+ if (connect(d, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
+ close(d);
+ d = -1;
+ }
+ }
+
+ return d;
+}
+
+
+#endif /* XS_IMPLEMENTATION */
+
+#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 */