Added support for listening on unix sockets.

This commit is contained in:
default 2024-08-05 06:01:21 +02:00
parent e9b108a6e0
commit 972c3dc5d4
8 changed files with 172 additions and 21 deletions

19
httpd.c
View file

@ -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);
if ((rs = xs_socket_server(address, port)) == -1) {
rs = xs_socket_server(address, port);
}
if (rs == -1) {
srv_log(xs_fmt("cannot bind socket to %s", full_address));
return;
}

1
snac.c
View file

@ -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"

77
xs.h
View file

@ -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)

View file

@ -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;

View file

@ -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;
}
}
}

View file

@ -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);
}

78
xs_unix_socket.h Normal file
View file

@ -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 */

View file

@ -1 +1 @@
/* 3896c5f782089f0dca68455565bbcd65dd724c91 2024-07-01T08:55:34+02:00 */
/* fb6646ef1b1d5f24768bc829680eb70272755584 2024-08-05T05:32:08+02:00 */