mirror of
https://codeberg.org/grunfink/snac2.git
synced 2024-11-14 09:35:04 +00:00
Added support for listening on unix sockets.
This commit is contained in:
parent
e9b108a6e0
commit
972c3dc5d4
8 changed files with 172 additions and 21 deletions
17
httpd.c
17
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"));
|
||||
|
||||
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
1
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"
|
||||
|
|
75
xs.h
75
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))
|
||||
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);
|
||||
|
||||
xs_free(dict);
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -182,10 +182,12 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WITHOUT_GETADDRINFO */
|
||||
|
||||
|
|
10
xs_unicode.h
10
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);
|
||||
}
|
||||
|
|
78
xs_unix_socket.h
Normal file
78
xs_unix_socket.h
Normal 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 */
|
|
@ -1 +1 @@
|
|||
/* 3896c5f782089f0dca68455565bbcd65dd724c91 2024-07-01T08:55:34+02:00 */
|
||||
/* fb6646ef1b1d5f24768bc829680eb70272755584 2024-08-05T05:32:08+02:00 */
|
||||
|
|
Loading…
Reference in a new issue