Compare commits
2 Commits
240ed6bc25
...
bd73061462
Author | SHA1 | Date | |
---|---|---|---|
bd73061462
|
|||
9ee0e11c86
|
@@ -81,10 +81,10 @@ static async_evt_t async_e2a(unsigned int events) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int async_add_to_queue(evt_listen_t *evt) {
|
static int async_add_to_queue(evt_listen_t *evt) {
|
||||||
try_again:
|
while (sem_wait(&lock) != 0) {
|
||||||
if (sem_wait(&lock) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
goto try_again;
|
errno = 0;
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@@ -53,11 +53,10 @@ static int magic_init(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void magic_mime_type(const char *restrict filename, char *buf) {
|
static void magic_mime_type(const char *restrict filename, char *buf) {
|
||||||
retry:
|
while (sem_wait(&sem_magic) != 0) {
|
||||||
if (sem_wait(&sem_magic) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
goto retry;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
critical("Unable to lock magic semaphore");
|
critical("Unable to lock magic semaphore");
|
||||||
return;
|
return;
|
||||||
@@ -84,11 +83,10 @@ static void magic_mime_type(const char *restrict filename, char *buf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void magic_charset(const char *restrict filename, char *buf) {
|
static void magic_charset(const char *restrict filename, char *buf) {
|
||||||
retry:
|
while (sem_wait(&sem_magic) != 0) {
|
||||||
if (sem_wait(&sem_magic) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
goto retry;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
critical("Unable to lock magic semaphore");
|
critical("Unable to lock magic semaphore");
|
||||||
return;
|
return;
|
||||||
@@ -136,10 +134,10 @@ static cache_entry_t *cache_get_entry(cache_t *cache, const char *filename) {
|
|||||||
|
|
||||||
static cache_entry_t *cache_get_new_entry(cache_t *cache) {
|
static cache_entry_t *cache_get_new_entry(cache_t *cache) {
|
||||||
// globally lock cache
|
// globally lock cache
|
||||||
retry:
|
while (sem_wait(&sem_cache) != 0) {
|
||||||
if (sem_wait(&sem_cache) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
goto retry;
|
errno = 0;
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -376,11 +374,10 @@ static void cache_mark_entry_dirty(cache_entry_t *entry) {
|
|||||||
memset(entry->meta.filename_comp_gz, 0, sizeof(entry->meta.filename_comp_gz));
|
memset(entry->meta.filename_comp_gz, 0, sizeof(entry->meta.filename_comp_gz));
|
||||||
memset(entry->meta.filename_comp_br, 0, sizeof(entry->meta.filename_comp_br));
|
memset(entry->meta.filename_comp_br, 0, sizeof(entry->meta.filename_comp_br));
|
||||||
|
|
||||||
try_again_free:
|
while (sem_wait(&sem_free) != 0) {
|
||||||
if (sem_wait(&sem_free) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
goto try_again_free;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
error("Unable to lock semaphore");
|
error("Unable to lock semaphore");
|
||||||
errno = 0;
|
errno = 0;
|
||||||
@@ -389,11 +386,10 @@ static void cache_mark_entry_dirty(cache_entry_t *entry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to lock buffer
|
// try to lock buffer
|
||||||
try_again_lock:
|
while (sem_wait(&sem_lock) != 0) {
|
||||||
if (sem_wait(&sem_lock) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
goto try_again_lock;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
error("Unable to lock semaphore");
|
error("Unable to lock semaphore");
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
312
src/lib/config.c
312
src/lib/config.c
@@ -16,6 +16,152 @@
|
|||||||
|
|
||||||
config_t config;
|
config_t config;
|
||||||
|
|
||||||
|
static int config_parse_line(char *line, char *section, int *i, int *j) {
|
||||||
|
int mode = 0;
|
||||||
|
char *source, *target;
|
||||||
|
|
||||||
|
char *ptr = line;
|
||||||
|
char *comment = strpbrk(ptr, "#\r\n");
|
||||||
|
if (comment != NULL) comment[0] = 0;
|
||||||
|
|
||||||
|
unsigned long len = strlen(ptr);
|
||||||
|
char *end_ptr = (len > 0) ? ptr + len - 1 : ptr;
|
||||||
|
while (end_ptr[0] == ' ' || end_ptr[0] == '\t') {
|
||||||
|
end_ptr[0] = 0;
|
||||||
|
end_ptr--;
|
||||||
|
}
|
||||||
|
len = strlen(ptr);
|
||||||
|
if (len == 0) return 0;
|
||||||
|
|
||||||
|
if (ptr[0] == '[') {
|
||||||
|
if (ptr[len - 1] != ']') return -1;
|
||||||
|
ptr++;
|
||||||
|
int l = 0;
|
||||||
|
if (strncmp(ptr, "host", 4) == 0 && (ptr[4] == ' ' || ptr[4] == '\t')) {
|
||||||
|
ptr += 4;
|
||||||
|
while (ptr[0] == ' ' || ptr[0] == '\t' || ptr[0] == ']') ptr++;
|
||||||
|
while (ptr[l] != ' ' && ptr[l] != '\t' && ptr[l] != ']') l++;
|
||||||
|
if (l == 0) return -1;
|
||||||
|
snprintf(config.hosts[*i].name, sizeof(config.hosts[*i].name), "%.*s", l, ptr);
|
||||||
|
++(*i);
|
||||||
|
*section = 'h';
|
||||||
|
} else if (strncmp(ptr, "cert", 4) == 0 && (ptr[4] == ' ' || ptr[4] == '\t')) {
|
||||||
|
ptr += 4;
|
||||||
|
while (ptr[0] == ' ' || ptr[0] == '\t' || ptr[0] == ']') ptr++;
|
||||||
|
while (ptr[l] != ' ' && ptr[l] != '\t' && ptr[l] != ']') l++;
|
||||||
|
if (l == 0) return -1;
|
||||||
|
snprintf(config.certs[*j].name, sizeof(config.certs[*j].name), "%.*s", l, ptr);
|
||||||
|
++(*j);
|
||||||
|
*section = 'c';
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else if (*section == 0) {
|
||||||
|
if (len > 10 && strncmp(ptr, "geoip_dir", 9) == 0 && (ptr[9] == ' ' || ptr[9] == '\t')) {
|
||||||
|
source = ptr + 9;
|
||||||
|
target = config.geoip_dir;
|
||||||
|
} else if (len > 11 && strncmp(ptr, "dns_server", 10) == 0 && (ptr[10] == ' ' || ptr[10] == '\t')) {
|
||||||
|
source = ptr + 10;
|
||||||
|
target = config.dns_server;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if (*section == 'c') {
|
||||||
|
cert_config_t *cc = &config.certs[*j - 1];
|
||||||
|
if (len > 12 && strncmp(ptr, "certificate", 11) == 0 && (ptr[11] == ' ' || ptr[11] == '\t')) {
|
||||||
|
source = ptr + 11;
|
||||||
|
target = cc->full_chain;
|
||||||
|
} else if (len > 12 && strncmp(ptr, "private_key", 11) == 0 && (ptr[11] == ' ' || ptr[11] == '\t')) {
|
||||||
|
source = ptr + 11;
|
||||||
|
target = cc->priv_key;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if (*section == 'h') {
|
||||||
|
host_config_t *hc = &config.hosts[*i - 1];
|
||||||
|
if (len > 8 && strncmp(ptr, "webroot", 7) == 0 && (ptr[7] == ' ' || ptr[7] == '\t')) {
|
||||||
|
source = ptr + 7;
|
||||||
|
target = hc->local.webroot;
|
||||||
|
if (hc->type != 0 && hc->type != CONFIG_TYPE_LOCAL) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
hc->type = CONFIG_TYPE_LOCAL;
|
||||||
|
}
|
||||||
|
} else if (len > 5 && strncmp(ptr, "cert", 4) == 0 && (ptr[4] == ' ' || ptr[4] == '\t')) {
|
||||||
|
source = ptr + 4;
|
||||||
|
target = hc->cert_name;
|
||||||
|
} else if (len > 9 && strncmp(ptr, "dir_mode", 8) == 0 && (ptr[8] == ' ' || ptr[8] == '\t')) {
|
||||||
|
source = ptr + 8;
|
||||||
|
target = NULL;
|
||||||
|
mode = 1;
|
||||||
|
if (hc->type != 0 && hc->type != CONFIG_TYPE_LOCAL) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
hc->type = CONFIG_TYPE_LOCAL;
|
||||||
|
}
|
||||||
|
} else if (len > 9 && strncmp(ptr, "hostname", 8) == 0 && (ptr[8] == ' ' || ptr[8] == '\t')) {
|
||||||
|
source = ptr + 8;
|
||||||
|
target = hc->proxy.hostname;
|
||||||
|
if (hc->type != 0 && hc->type != CONFIG_TYPE_REVERSE_PROXY) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
hc->type = CONFIG_TYPE_REVERSE_PROXY;
|
||||||
|
}
|
||||||
|
} else if (len > 5 && strncmp(ptr, "port", 4) == 0 && (ptr[4] == ' ' || ptr[4] == '\t')) {
|
||||||
|
source = ptr + 4;
|
||||||
|
target = NULL;
|
||||||
|
mode = 2;
|
||||||
|
if (hc->type != 0 && hc->type != CONFIG_TYPE_REVERSE_PROXY) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
hc->type = CONFIG_TYPE_REVERSE_PROXY;
|
||||||
|
}
|
||||||
|
} else if (streq(ptr, "http")) {
|
||||||
|
if (hc->type != 0 && hc->type != CONFIG_TYPE_REVERSE_PROXY) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
hc->type = CONFIG_TYPE_REVERSE_PROXY;
|
||||||
|
hc->proxy.enc = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else if (streq(ptr, "https")) {
|
||||||
|
if (hc->type != 0 && hc->type != CONFIG_TYPE_REVERSE_PROXY) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
hc->type = CONFIG_TYPE_REVERSE_PROXY;
|
||||||
|
hc->proxy.enc = 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (source[0] == ' ' || source[0] == '\t') source++;
|
||||||
|
if (strlen(source) == 0) return -1;
|
||||||
|
|
||||||
|
if (target != NULL) {
|
||||||
|
strcpy(target, source);
|
||||||
|
} else if (mode == 1) {
|
||||||
|
if (streq(source, "forbidden")) {
|
||||||
|
config.hosts[*i - 1].local.dir_mode = URI_DIR_MODE_FORBIDDEN;
|
||||||
|
} else if (streq(source, "info")) {
|
||||||
|
config.hosts[*i - 1].local.dir_mode = URI_DIR_MODE_INFO;
|
||||||
|
} else if (streq(source, "list")) {
|
||||||
|
config.hosts[*i - 1].local.dir_mode = URI_DIR_MODE_LIST;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if (mode == 2) {
|
||||||
|
config.hosts[*i - 1].proxy.port = (unsigned short) strtoul(source, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int config_load(const char *filename) {
|
int config_load(const char *filename) {
|
||||||
FILE *file = fopen(filename, "r");
|
FILE *file = fopen(filename, "r");
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
@@ -25,162 +171,18 @@ int config_load(const char *filename) {
|
|||||||
|
|
||||||
memset(&config, 0, sizeof(config));
|
memset(&config, 0, sizeof(config));
|
||||||
|
|
||||||
int i = 0;
|
int i = 0, j = 0;
|
||||||
int j = 0;
|
|
||||||
int line_num = 0;
|
|
||||||
int mode = 0;
|
|
||||||
char section = 0;
|
char section = 0;
|
||||||
char *source, *target;
|
|
||||||
|
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
ssize_t read;
|
|
||||||
size_t line_len = 0;
|
size_t line_len = 0;
|
||||||
while ((read = getline(&line, &line_len, file)) != -1) {
|
for (int line_num = 1; getline(&line, &line_len, file) != -1; line_num++) {
|
||||||
line_num++;
|
if (config_parse_line(line, §ion, &i, &j) != 0) {
|
||||||
char *ptr = line;
|
critical("Unable to parse config file (line %i)", line_num);
|
||||||
char *comment = strpbrk(ptr, "#\r\n");
|
|
||||||
if (comment != NULL) comment[0] = 0;
|
|
||||||
|
|
||||||
unsigned long len = strlen(ptr);
|
|
||||||
char *end_ptr = (len > 0) ? ptr + len - 1 : ptr;
|
|
||||||
while (end_ptr[0] == ' ' || end_ptr[0] == '\t') {
|
|
||||||
end_ptr[0] = 0;
|
|
||||||
end_ptr--;
|
|
||||||
}
|
|
||||||
len = strlen(ptr);
|
|
||||||
if (len == 0) continue;
|
|
||||||
|
|
||||||
if (ptr[0] == '[') {
|
|
||||||
if (ptr[len - 1] != ']') goto err;
|
|
||||||
ptr++;
|
|
||||||
int l = 0;
|
|
||||||
if (strncmp(ptr, "host", 4) == 0 && (ptr[4] == ' ' || ptr[4] == '\t')) {
|
|
||||||
ptr += 4;
|
|
||||||
while (ptr[0] == ' ' || ptr[0] == '\t' || ptr[0] == ']') ptr++;
|
|
||||||
while (ptr[l] != ' ' && ptr[l] != '\t' && ptr[l] != ']') l++;
|
|
||||||
if (l == 0) goto err;
|
|
||||||
snprintf(config.hosts[i].name, sizeof(config.hosts[i].name), "%.*s", l, ptr);
|
|
||||||
i++;
|
|
||||||
section = 'h';
|
|
||||||
} else if (strncmp(ptr, "cert", 4) == 0 && (ptr[4] == ' ' || ptr[4] == '\t')) {
|
|
||||||
ptr += 4;
|
|
||||||
while (ptr[0] == ' ' || ptr[0] == '\t' || ptr[0] == ']') ptr++;
|
|
||||||
while (ptr[l] != ' ' && ptr[l] != '\t' && ptr[l] != ']') l++;
|
|
||||||
if (l == 0) goto err;
|
|
||||||
snprintf(config.certs[j].name, sizeof(config.certs[j].name), "%.*s", l, ptr);
|
|
||||||
j++;
|
|
||||||
section = 'c';
|
|
||||||
} else {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else if (section == 0) {
|
|
||||||
if (len > 10 && strncmp(ptr, "geoip_dir", 9) == 0 && (ptr[9] == ' ' || ptr[9] == '\t')) {
|
|
||||||
source = ptr + 9;
|
|
||||||
target = config.geoip_dir;
|
|
||||||
} else if (len > 11 && strncmp(ptr, "dns_server", 10) == 0 && (ptr[10] == ' ' || ptr[10] == '\t')) {
|
|
||||||
source = ptr + 10;
|
|
||||||
target = config.dns_server;
|
|
||||||
} else {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
} else if (section == 'c') {
|
|
||||||
cert_config_t *cc = &config.certs[j - 1];
|
|
||||||
if (len > 12 && strncmp(ptr, "certificate", 11) == 0 && (ptr[11] == ' ' || ptr[11] == '\t')) {
|
|
||||||
source = ptr + 11;
|
|
||||||
target = cc->full_chain;
|
|
||||||
} else if (len > 12 && strncmp(ptr, "private_key", 11) == 0 && (ptr[11] == ' ' || ptr[11] == '\t')) {
|
|
||||||
source = ptr + 11;
|
|
||||||
target = cc->priv_key;
|
|
||||||
} else {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
} else if (section == 'h') {
|
|
||||||
host_config_t *hc = &config.hosts[i - 1];
|
|
||||||
if (len > 8 && strncmp(ptr, "webroot", 7) == 0 && (ptr[7] == ' ' || ptr[7] == '\t')) {
|
|
||||||
source = ptr + 7;
|
|
||||||
target = hc->local.webroot;
|
|
||||||
if (hc->type != 0 && hc->type != CONFIG_TYPE_LOCAL) {
|
|
||||||
goto err;
|
|
||||||
} else {
|
|
||||||
hc->type = CONFIG_TYPE_LOCAL;
|
|
||||||
}
|
|
||||||
} else if (len > 5 && strncmp(ptr, "cert", 4) == 0 && (ptr[4] == ' ' || ptr[4] == '\t')) {
|
|
||||||
source = ptr + 4;
|
|
||||||
target = hc->cert_name;
|
|
||||||
} else if (len > 9 && strncmp(ptr, "dir_mode", 8) == 0 && (ptr[8] == ' ' || ptr[8] == '\t')) {
|
|
||||||
source = ptr + 8;
|
|
||||||
target = NULL;
|
|
||||||
mode = 1;
|
|
||||||
if (hc->type != 0 && hc->type != CONFIG_TYPE_LOCAL) {
|
|
||||||
goto err;
|
|
||||||
} else {
|
|
||||||
hc->type = CONFIG_TYPE_LOCAL;
|
|
||||||
}
|
|
||||||
} else if (len > 9 && strncmp(ptr, "hostname", 8) == 0 && (ptr[8] == ' ' || ptr[8] == '\t')) {
|
|
||||||
source = ptr + 8;
|
|
||||||
target = hc->proxy.hostname;
|
|
||||||
if (hc->type != 0 && hc->type != CONFIG_TYPE_REVERSE_PROXY) {
|
|
||||||
goto err;
|
|
||||||
} else {
|
|
||||||
hc->type = CONFIG_TYPE_REVERSE_PROXY;
|
|
||||||
}
|
|
||||||
} else if (len > 5 && strncmp(ptr, "port", 4) == 0 && (ptr[4] == ' ' || ptr[4] == '\t')) {
|
|
||||||
source = ptr + 4;
|
|
||||||
target = NULL;
|
|
||||||
mode = 2;
|
|
||||||
if (hc->type != 0 && hc->type != CONFIG_TYPE_REVERSE_PROXY) {
|
|
||||||
goto err;
|
|
||||||
} else {
|
|
||||||
hc->type = CONFIG_TYPE_REVERSE_PROXY;
|
|
||||||
}
|
|
||||||
} else if (streq(ptr, "http")) {
|
|
||||||
if (hc->type != 0 && hc->type != CONFIG_TYPE_REVERSE_PROXY) {
|
|
||||||
goto err;
|
|
||||||
} else {
|
|
||||||
hc->type = CONFIG_TYPE_REVERSE_PROXY;
|
|
||||||
hc->proxy.enc = 0;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else if (streq(ptr, "https")) {
|
|
||||||
if (hc->type != 0 && hc->type != CONFIG_TYPE_REVERSE_PROXY) {
|
|
||||||
goto err;
|
|
||||||
} else {
|
|
||||||
hc->type = CONFIG_TYPE_REVERSE_PROXY;
|
|
||||||
hc->proxy.enc = 1;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (source[0] == ' ' || source[0] == '\t') source++;
|
|
||||||
if (strlen(source) == 0) {
|
|
||||||
err:
|
|
||||||
critical("Unable to parse config file (line %i)", line);
|
|
||||||
free(line);
|
free(line);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target != NULL) {
|
|
||||||
strcpy(target, source);
|
|
||||||
} else if (mode == 1) {
|
|
||||||
if (streq(source, "forbidden")) {
|
|
||||||
config.hosts[i - 1].local.dir_mode = URI_DIR_MODE_FORBIDDEN;
|
|
||||||
} else if (streq(source, "info")) {
|
|
||||||
config.hosts[i - 1].local.dir_mode = URI_DIR_MODE_INFO;
|
|
||||||
} else if (streq(source, "list")) {
|
|
||||||
config.hosts[i - 1].local.dir_mode = URI_DIR_MODE_LIST;
|
|
||||||
} else {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
} else if (mode == 2) {
|
|
||||||
config.hosts[i - 1].proxy.port = (unsigned short) strtoul(source, NULL, 10);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
@@ -190,11 +192,14 @@ int config_load(const char *filename) {
|
|||||||
host_config_t *hc = &config.hosts[k];
|
host_config_t *hc = &config.hosts[k];
|
||||||
if (hc->type == CONFIG_TYPE_LOCAL) {
|
if (hc->type == CONFIG_TYPE_LOCAL) {
|
||||||
char *webroot = config.hosts[k].local.webroot;
|
char *webroot = config.hosts[k].local.webroot;
|
||||||
if (webroot[strlen(webroot) - 1] == '/') {
|
while (webroot[strlen(webroot) - 1] == '/') webroot[strlen(webroot) - 1] = 0;
|
||||||
webroot[strlen(webroot) - 1] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (hc->cert_name[0] == 0) goto err2;
|
|
||||||
|
if (hc->cert_name[0] == 0) {
|
||||||
|
critical("Unable to parse config file: host config (%s) does not contain a certificate", hc->name);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
int found = 0;
|
int found = 0;
|
||||||
for (int m = 0; m < j; m++) {
|
for (int m = 0; m < j; m++) {
|
||||||
if (streq(config.certs[m].name, hc->cert_name)) {
|
if (streq(config.certs[m].name, hc->cert_name)) {
|
||||||
@@ -204,8 +209,7 @@ int config_load(const char *filename) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
err2:
|
critical("Unable to parse config file: certificate (%s) for host config (%s) not found", hc->cert_name, hc->name);
|
||||||
critical("Unable to parse config file");
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -191,7 +191,8 @@ int http_parse_request(char *buf, http_req *req) {
|
|||||||
|
|
||||||
if (req->version[0] == 0) {
|
if (req->version[0] == 0) {
|
||||||
pos1 = (char *) strchr(ptr, ' ') + 1;
|
pos1 = (char *) strchr(ptr, ' ') + 1;
|
||||||
if (pos1 == NULL) goto err_hdr_fmt;
|
if (pos1 == NULL)
|
||||||
|
return http_error(HTTP_ERROR_HEADER_MALFORMED);
|
||||||
|
|
||||||
if (pos1 - ptr - 1 >= sizeof(req->method))
|
if (pos1 - ptr - 1 >= sizeof(req->method))
|
||||||
return http_error(HTTP_ERROR_HEADER_MALFORMED);
|
return http_error(HTTP_ERROR_HEADER_MALFORMED);
|
||||||
@@ -203,10 +204,8 @@ int http_parse_request(char *buf, http_req *req) {
|
|||||||
snprintf(req->method, sizeof(req->method), "%.*s", (int) (pos1 - ptr - 1), ptr);
|
snprintf(req->method, sizeof(req->method), "%.*s", (int) (pos1 - ptr - 1), ptr);
|
||||||
|
|
||||||
pos2 = (char *) strchr(pos1, ' ') + 1;
|
pos2 = (char *) strchr(pos1, ' ') + 1;
|
||||||
if (pos2 == NULL) {
|
if (pos2 == NULL)
|
||||||
err_hdr_fmt:
|
|
||||||
return http_error(HTTP_ERROR_HEADER_MALFORMED);
|
return http_error(HTTP_ERROR_HEADER_MALFORMED);
|
||||||
}
|
|
||||||
|
|
||||||
if (memcmp(pos2, "HTTP/", 5) != 0 || memcmp(pos2 + 8, "\r\n", 2) != 0)
|
if (memcmp(pos2, "HTTP/", 5) != 0 || memcmp(pos2 + 8, "\r\n", 2) != 0)
|
||||||
return http_error(HTTP_ERROR_INVALID_VERSION);
|
return http_error(HTTP_ERROR_INVALID_VERSION);
|
||||||
|
@@ -52,22 +52,20 @@ int mpmc_init(mpmc_t *ctx, int n_workers, int buf_size, void (*consumer)(void *o
|
|||||||
|
|
||||||
int mpmc_queue(mpmc_t *ctx, void *obj) {
|
int mpmc_queue(mpmc_t *ctx, void *obj) {
|
||||||
// wait for buffer to be emptied
|
// wait for buffer to be emptied
|
||||||
try_again_1:
|
while (sem_wait(&ctx->free) != 0) {
|
||||||
if (sem_wait(&ctx->free) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
goto try_again_1;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// lock wr field
|
// lock wr field
|
||||||
try_again_2:
|
while (sem_wait(&ctx->lck_wr) != 0) {
|
||||||
if (sem_wait(&ctx->lck_wr) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
goto try_again_2;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
sem_post(&ctx->free);
|
sem_post(&ctx->free);
|
||||||
return -1;
|
return -1;
|
||||||
|
@@ -105,19 +105,19 @@ proxy_ctx_t *proxy_get_by_conf(host_config_t *conf) {
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
try_again_1:
|
while (sem_wait(&available[n]) != 0) {
|
||||||
if (sem_wait(&available[n]) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
goto try_again_1;
|
errno = 0;
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try_again_2:
|
while (sem_wait(&lock) != 0) {
|
||||||
if (sem_wait(&lock) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
goto try_again_2;
|
errno = 0;
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
sem_post(&available[n]);
|
sem_post(&available[n]);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -269,24 +269,28 @@ int proxy_response_header(http_req *req, http_res *res, host_config_t *conf) {
|
|||||||
const char *location = http_get_header_field(&res->hdr, "Location");
|
const char *location = http_get_header_field(&res->hdr, "Location");
|
||||||
if (location != NULL) {
|
if (location != NULL) {
|
||||||
char *hostnames[] = {conf->name, conf->proxy.hostname};
|
char *hostnames[] = {conf->name, conf->proxy.hostname};
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(hostnames) / sizeof(hostnames[0]); i++) {
|
for (int i = 0; i < sizeof(hostnames) / sizeof(hostnames[0]); i++) {
|
||||||
char *hostname = hostnames[i];
|
char *hostname = hostnames[i];
|
||||||
|
found = 1;
|
||||||
|
|
||||||
p_len = snprintf(buf1, sizeof(buf1), "http://%s/", hostname);
|
p_len = snprintf(buf1, sizeof(buf1), "http://%s/", hostname);
|
||||||
if (strncmp(location, buf1, p_len) == 0) goto match;
|
if (strstarts(location, buf1)) break;
|
||||||
|
|
||||||
p_len = snprintf(buf1, sizeof(buf1), "https://%s/", hostname);
|
p_len = snprintf(buf1, sizeof(buf1), "https://%s/", hostname);
|
||||||
if (strncmp(location, buf1, p_len) == 0) goto match;
|
if (strstarts(location, buf1)) break;
|
||||||
|
|
||||||
p_len = snprintf(buf1, sizeof(buf1), "http://%s:%i/", hostname, conf->proxy.port);
|
p_len = snprintf(buf1, sizeof(buf1), "http://%s:%i/", hostname, conf->proxy.port);
|
||||||
if (strncmp(location, buf1, p_len) == 0) goto match;
|
if (strstarts(location, buf1)) break;
|
||||||
|
|
||||||
p_len = snprintf(buf1, sizeof(buf1), "https://%s:%i/", hostname, conf->proxy.port);
|
p_len = snprintf(buf1, sizeof(buf1), "https://%s:%i/", hostname, conf->proxy.port);
|
||||||
if (strncmp(location, buf1, p_len) == 0) goto match;
|
if (strstarts(location, buf1)) break;
|
||||||
|
|
||||||
|
found = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0) {
|
if (found) {
|
||||||
match:
|
|
||||||
strcpy(buf1, location + p_len - 1);
|
strcpy(buf1, location + p_len - 1);
|
||||||
http_remove_header_field(&res->hdr, "Location", HTTP_REMOVE_ALL);
|
http_remove_header_field(&res->hdr, "Location", HTTP_REMOVE_ALL);
|
||||||
http_add_header_field(&res->hdr, "Location", buf1);
|
http_add_header_field(&res->hdr, "Location", buf1);
|
||||||
|
10
src/logger.c
10
src/logger.c
@@ -102,11 +102,10 @@ void logmsgf(log_lvl_t level, const char *restrict format, ...) {
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
} else {
|
} else {
|
||||||
// wait for free slot in buffer
|
// wait for free slot in buffer
|
||||||
try_again_free:
|
while (sem_wait(&sem_buf_free) != 0) {
|
||||||
if (sem_wait(&sem_buf_free) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
goto try_again_free;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
err("Unable to lock semaphore");
|
err("Unable to lock semaphore");
|
||||||
errno = 0;
|
errno = 0;
|
||||||
@@ -117,11 +116,10 @@ void logmsgf(log_lvl_t level, const char *restrict format, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to lock buffer
|
// try to lock buffer
|
||||||
try_again_buf:
|
while (sem_wait(&sem_buf) != 0) {
|
||||||
if (sem_wait(&sem_buf) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
goto try_again_buf;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
err("Unable to lock semaphore");
|
err("Unable to lock semaphore");
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
12
src/server.c
12
src/server.c
@@ -82,10 +82,10 @@ static int ssl_servername_cb(SSL *ssl, int *ad, void *arg) {
|
|||||||
|
|
||||||
void server_free_client(client_ctx_t *ctx) {
|
void server_free_client(client_ctx_t *ctx) {
|
||||||
// try to lock clients list
|
// try to lock clients list
|
||||||
retry:
|
while (sem_wait(&sem_clients_lock) != 0) {
|
||||||
if (sem_wait(&sem_clients_lock) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
goto retry;
|
errno = 0;
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
critical("Unable to lock clients list");
|
critical("Unable to lock clients list");
|
||||||
return;
|
return;
|
||||||
@@ -140,10 +140,10 @@ static void accept_cb(void *arg) {
|
|||||||
client_ctx->cnx_e = -1, client_ctx->req_s = -1, client_ctx->req_e = -1, client_ctx->res_ts = -1;
|
client_ctx->cnx_e = -1, client_ctx->req_s = -1, client_ctx->req_e = -1, client_ctx->res_ts = -1;
|
||||||
|
|
||||||
// try to lock clients list
|
// try to lock clients list
|
||||||
retry:
|
while (sem_wait(&sem_clients_lock) != 0) {
|
||||||
if (sem_wait(&sem_clients_lock) != 0) {
|
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
goto retry;
|
errno = 0;
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
critical("Unable to lock clients list");
|
critical("Unable to lock clients list");
|
||||||
return;
|
return;
|
||||||
|
@@ -28,6 +28,32 @@ void tcp_acceptor_func(client_ctx_t *ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dig(const char *addr, char *host, size_t host_size) {
|
||||||
|
char buf[1024];
|
||||||
|
FILE *out;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
sprintf(buf, "dig @%s +short +time=1 -x %s", config.dns_server, addr);
|
||||||
|
if ((out = popen(buf, "r")) == NULL) {
|
||||||
|
error("Unable to start dig: %s");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long read = fread(buf, 1, sizeof(buf), out);
|
||||||
|
if ((ret = pclose(out)) != 0) {
|
||||||
|
error("Dig terminated with exit code %i", ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ptr = memchr(buf, '\n', read);
|
||||||
|
if (ptr == buf || ptr == NULL) return -1;
|
||||||
|
|
||||||
|
ptr[-1] = 0;
|
||||||
|
strncpy(host, buf, host_size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int tcp_acceptor(client_ctx_t *ctx) {
|
static int tcp_acceptor(client_ctx_t *ctx) {
|
||||||
struct sockaddr_in6 server_addr;
|
struct sockaddr_in6 server_addr;
|
||||||
|
|
||||||
@@ -55,35 +81,12 @@ static int tcp_acceptor(client_ctx_t *ctx) {
|
|||||||
|
|
||||||
logger_set_prefix("[%*s]%s", ADDRSTRLEN, ctx->socket.s_addr, ctx->log_prefix);
|
logger_set_prefix("[%*s]%s", ADDRSTRLEN, ctx->socket.s_addr, ctx->log_prefix);
|
||||||
|
|
||||||
int ret;
|
|
||||||
char buf[1024];
|
|
||||||
sock *client = &ctx->socket;
|
sock *client = &ctx->socket;
|
||||||
|
|
||||||
ctx->cnx_s = clock_micros();
|
ctx->cnx_s = clock_micros();
|
||||||
|
|
||||||
if (config.dns_server[0] != 0) {
|
ctx->host[0] = 0;
|
||||||
sprintf(buf, "dig @%s +short +time=1 -x %s", config.dns_server, ctx->socket.addr);
|
if (config.dns_server[0] != 0)
|
||||||
FILE *dig = popen(buf, "r");
|
dig(ctx->socket.addr, ctx->host, sizeof(ctx->host));
|
||||||
if (dig == NULL) {
|
|
||||||
error("Unable to start dig: %s");
|
|
||||||
goto dig_err;
|
|
||||||
}
|
|
||||||
unsigned long read = fread(buf, 1, sizeof(buf), dig);
|
|
||||||
ret = pclose(dig);
|
|
||||||
if (ret != 0) {
|
|
||||||
error("Dig terminated with exit code %i", ret);
|
|
||||||
goto dig_err;
|
|
||||||
}
|
|
||||||
char *ptr = memchr(buf, '\n', read);
|
|
||||||
if (ptr == buf || ptr == NULL) {
|
|
||||||
goto dig_err;
|
|
||||||
}
|
|
||||||
ptr[-1] = 0;
|
|
||||||
strncpy(ctx->host, buf, sizeof(ctx->host));
|
|
||||||
} else {
|
|
||||||
dig_err:
|
|
||||||
ctx->host[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->cc[0] = 0;
|
ctx->cc[0] = 0;
|
||||||
geoip_lookup_country(&client->_addr.sock, ctx->cc);
|
geoip_lookup_country(&client->_addr.sock, ctx->cc);
|
||||||
@@ -102,8 +105,8 @@ static int tcp_acceptor(client_ctx_t *ctx) {
|
|||||||
SSL_set_fd(client->ssl, client->socket);
|
SSL_set_fd(client->ssl, client->socket);
|
||||||
SSL_set_accept_state(client->ssl);
|
SSL_set_accept_state(client->ssl);
|
||||||
|
|
||||||
ret = SSL_accept(client->ssl);
|
int ret;
|
||||||
if (ret != 1) {
|
if ((ret = SSL_accept(client->ssl)) != 1) {
|
||||||
sock_error(client, ret);
|
sock_error(client, ret);
|
||||||
info("Unable to perform handshake");
|
info("Unable to perform handshake");
|
||||||
return -1;
|
return -1;
|
||||||
|
Reference in New Issue
Block a user