mirror of
https://github.com/omar-polo/gmid.git
synced 2024-09-30 22:41:15 +02:00
added support for location blocks
This commit is contained in:
parent
c8b7433918
commit
252908e6bb
@ -1,5 +1,7 @@
|
|||||||
2021-01-24 Omar Polo <op@omarpolo.com>
|
2021-01-24 Omar Polo <op@omarpolo.com>
|
||||||
|
|
||||||
|
* server.c (open_dir): add directory listing (disabled by default)
|
||||||
|
|
||||||
* parse.y (vhost): added support for location blocks
|
* parse.y (vhost): added support for location blocks
|
||||||
|
|
||||||
* server.c (send_dir): make the directory index customizable
|
* server.c (send_dir): make the directory index customizable
|
||||||
|
3
gmid.1
3
gmid.1
@ -181,6 +181,9 @@ parameter will be added in the response.
|
|||||||
Set the directory index file.
|
Set the directory index file.
|
||||||
If not specified, it defaults to
|
If not specified, it defaults to
|
||||||
.Pa index.gmi
|
.Pa index.gmi
|
||||||
|
.It Ic auto Ic index Ar bool
|
||||||
|
If no index file is found, automatically generate a directory listing.
|
||||||
|
It's disabled by default.
|
||||||
.It Ic location Pa path Brq ...
|
.It Ic location Pa path Brq ...
|
||||||
Specify server configuration rules for a specific location.
|
Specify server configuration rules for a specific location.
|
||||||
The
|
The
|
||||||
|
3
gmid.c
3
gmid.c
@ -156,6 +156,9 @@ starts_with(const char *str, const char *prefix)
|
|||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
if (prefix == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
for (i = 0; prefix[i] != '\0'; ++i)
|
for (i = 0; prefix[i] != '\0'; ++i)
|
||||||
if (str[i] != prefix[i])
|
if (str[i] != prefix[i])
|
||||||
return 0;
|
return 0;
|
||||||
|
15
gmid.h
15
gmid.h
@ -17,10 +17,13 @@
|
|||||||
#ifndef GMID_H
|
#ifndef GMID_H
|
||||||
#define GMID_H
|
#define GMID_H
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -62,6 +65,7 @@ struct location {
|
|||||||
char *lang;
|
char *lang;
|
||||||
char *default_mime;
|
char *default_mime;
|
||||||
char *index;
|
char *index;
|
||||||
|
int auto_index; /* 0 auto, -1 off, 1 on */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vhost {
|
struct vhost {
|
||||||
@ -119,6 +123,7 @@ enum {
|
|||||||
S_OPEN,
|
S_OPEN,
|
||||||
S_INITIALIZING,
|
S_INITIALIZING,
|
||||||
S_SENDING_FILE,
|
S_SENDING_FILE,
|
||||||
|
S_SENDING_DIR,
|
||||||
S_SENDING_CGI,
|
S_SENDING_CGI,
|
||||||
S_CLOSING,
|
S_CLOSING,
|
||||||
};
|
};
|
||||||
@ -134,6 +139,7 @@ struct client {
|
|||||||
char sbuf[1024]; /* static buffer */
|
char sbuf[1024]; /* static buffer */
|
||||||
void *buf, *i; /* mmap buffer */
|
void *buf, *i; /* mmap buffer */
|
||||||
ssize_t len, off; /* mmap/static buffer */
|
ssize_t len, off; /* mmap/static buffer */
|
||||||
|
DIR *dir;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
struct vhost *host; /* host she's talking to */
|
struct vhost *host; /* host she's talking to */
|
||||||
};
|
};
|
||||||
@ -185,8 +191,10 @@ const char *mime(struct vhost*, const char*);
|
|||||||
const char *vhost_lang(struct vhost*, const char*);
|
const char *vhost_lang(struct vhost*, const char*);
|
||||||
const char *vhost_default_mime(struct vhost*, const char*);
|
const char *vhost_default_mime(struct vhost*, const char*);
|
||||||
const char *vhost_index(struct vhost*, const char*);
|
const char *vhost_index(struct vhost*, const char*);
|
||||||
|
int vhost_auto_index(struct vhost*, const char*);
|
||||||
int check_path(struct client*, const char*, int*);
|
int check_path(struct client*, const char*, int*);
|
||||||
void open_file(struct pollfd*, struct client*);
|
void open_file(struct pollfd*, struct client*);
|
||||||
|
void load_file(struct pollfd*, struct client*);
|
||||||
void check_for_cgi(char *, char*, struct pollfd*, struct client*);
|
void check_for_cgi(char *, char*, struct pollfd*, struct client*);
|
||||||
void mark_nonblock(int);
|
void mark_nonblock(int);
|
||||||
void handle_handshake(struct pollfd*, struct client*);
|
void handle_handshake(struct pollfd*, struct client*);
|
||||||
@ -194,7 +202,10 @@ void handle_open_conn(struct pollfd*, struct client*);
|
|||||||
void start_reply(struct pollfd*, struct client*, int, const char*);
|
void start_reply(struct pollfd*, struct client*, int, const char*);
|
||||||
void start_cgi(const char*, const char*, const char*, struct pollfd*, struct client*);
|
void start_cgi(const char*, const char*, const char*, struct pollfd*, struct client*);
|
||||||
void send_file(struct pollfd*, struct client*);
|
void send_file(struct pollfd*, struct client*);
|
||||||
void send_dir(struct pollfd*, struct client*);
|
void open_dir(struct pollfd*, struct client*);
|
||||||
|
void redirect_canonical_dir(struct pollfd*, struct client*);
|
||||||
|
int read_next_dir_entry(struct client*);
|
||||||
|
void send_directory_listing(struct pollfd*, struct client*);
|
||||||
void cgi_poll_on_child(struct pollfd*, struct client*);
|
void cgi_poll_on_child(struct pollfd*, struct client*);
|
||||||
void cgi_poll_on_client(struct pollfd*, struct client*);
|
void cgi_poll_on_client(struct pollfd*, struct client*);
|
||||||
void handle_cgi(struct pollfd*, struct client*);
|
void handle_cgi(struct pollfd*, struct client*);
|
||||||
|
1
lex.l
1
lex.l
@ -67,6 +67,7 @@ root return TROOT;
|
|||||||
cgi return TCGI;
|
cgi return TCGI;
|
||||||
lang return TLANG;
|
lang return TLANG;
|
||||||
index return TINDEX;
|
index return TINDEX;
|
||||||
|
auto return TAUTO;
|
||||||
|
|
||||||
[{}] return *yytext;
|
[{}] return *yytext;
|
||||||
|
|
||||||
|
3
parse.y
3
parse.y
@ -46,7 +46,7 @@ extern void yyerror(const char*);
|
|||||||
}
|
}
|
||||||
|
|
||||||
%token TDAEMON TIPV6 TPORT TPROTOCOLS TMIME TDEFAULT TTYPE TSERVER
|
%token TDAEMON TIPV6 TPORT TPROTOCOLS TMIME TDEFAULT TTYPE TSERVER
|
||||||
%token TLOCATION TCERT TKEY TROOT TCGI TLANG
|
%token TLOCATION TCERT TKEY TROOT TCGI TLANG TINDEX TAUTO
|
||||||
%token TERR
|
%token TERR
|
||||||
|
|
||||||
%token <str> TSTRING
|
%token <str> TSTRING
|
||||||
@ -138,4 +138,5 @@ locopt : TDEFAULT TTYPE TSTRING {
|
|||||||
free(loc->index);
|
free(loc->index);
|
||||||
loc->index = $2;
|
loc->index = $2;
|
||||||
}
|
}
|
||||||
|
| TAUTO TINDEX TBOOL { loc->auto_index = $3 ? 1 : -1; }
|
||||||
;
|
;
|
||||||
|
@ -199,9 +199,25 @@ run
|
|||||||
eq "$(head /dir/hello)" "20 text/plain" "Unexpected head for /"
|
eq "$(head /dir/hello)" "20 text/plain" "Unexpected head for /"
|
||||||
echo OK GET /dir/hello with location and default type
|
echo OK GET /dir/hello with location and default type
|
||||||
|
|
||||||
eq "$(head /dir/)" "20 text/plain" "Unexpected head for /dir"
|
eq "$(head /dir/)" "20 text/plain" "Unexpected head for /dir/"
|
||||||
eq "$(get /dir/|tail -1)" 'echo "# hello world"' "Unexpected body for /dir/"
|
eq "$(get /dir/|tail -1)" 'echo "# hello world"' "Unexpected body for /dir/"
|
||||||
echo OK GET /dir/ with location and custom index
|
echo OK GET /dir/ with location and custom index
|
||||||
|
|
||||||
check "should be running"
|
check "should be running"
|
||||||
quit
|
quit
|
||||||
|
|
||||||
|
config '' 'location "/dir/" { auto index on }'
|
||||||
|
checkconf
|
||||||
|
run
|
||||||
|
|
||||||
|
eq "$(head /)" "20 text/gemini" "Unexpected head for /"
|
||||||
|
eq "$(get /)" "# hello world$ln" "Unexpected body for /"
|
||||||
|
echo OK GET / with auto index
|
||||||
|
|
||||||
|
eq "$(head /dir)" "30 /dir/" "Unexpected head for /dir"
|
||||||
|
eq "$(head /dir/)" "20 text/gemini" "Unexpected head for /dir/"
|
||||||
|
eq "$(get /dir/|wc -l|xargs)" "3" "Unexpected body for /dir/"
|
||||||
|
echo OK GET /dir/ with auto index on
|
||||||
|
|
||||||
|
check "should be running"
|
||||||
|
quit
|
||||||
|
16
sample.conf
16
sample.conf
@ -25,3 +25,19 @@ server "it.example.com" {
|
|||||||
# optional
|
# optional
|
||||||
lang "it"
|
lang "it"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# a server block with a location
|
||||||
|
server "foo.com" {
|
||||||
|
cert "..."
|
||||||
|
key "..."
|
||||||
|
root "..."
|
||||||
|
|
||||||
|
location "/it/" {
|
||||||
|
lang "it"
|
||||||
|
}
|
||||||
|
|
||||||
|
location "/files" {
|
||||||
|
lang "en"
|
||||||
|
auto index on
|
||||||
|
}
|
||||||
|
}
|
||||||
|
227
server.c
227
server.c
@ -77,11 +77,28 @@ vhost_index(struct vhost *v, const char *path)
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vhost_auto_index(struct vhost *v, const char *path)
|
||||||
|
{
|
||||||
|
struct location *loc;
|
||||||
|
int auto_index = 0;
|
||||||
|
|
||||||
|
for (loc = v->locations; loc->match != NULL; ++loc) {
|
||||||
|
if (!fnmatch(loc->match, path, 0)) {
|
||||||
|
if (loc->auto_index)
|
||||||
|
auto_index = loc->auto_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return auto_index == 1;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
check_path(struct client *c, const char *path, int *fd)
|
check_path(struct client *c, const char *path, int *fd)
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
const char *p;
|
const char *p;
|
||||||
|
int flags;
|
||||||
|
|
||||||
assert(path != NULL);
|
assert(path != NULL);
|
||||||
|
|
||||||
@ -94,9 +111,10 @@ check_path(struct client *c, const char *path, int *fd)
|
|||||||
else
|
else
|
||||||
p = path;
|
p = path;
|
||||||
|
|
||||||
if ((*fd = openat(c->host->dirfd, p, O_RDONLY | O_NOFOLLOW)) == -1) {
|
flags = O_RDONLY | O_NOFOLLOW;
|
||||||
|
|
||||||
|
if (*fd == -1 && (*fd = openat(c->host->dirfd, p, flags)) == -1)
|
||||||
return FILE_MISSING;
|
return FILE_MISSING;
|
||||||
}
|
|
||||||
|
|
||||||
if (fstat(*fd, &sb) == -1) {
|
if (fstat(*fd, &sb) == -1) {
|
||||||
LOGN(c, "failed stat for %s: %s", path, strerror(errno));
|
LOGN(c, "failed stat for %s: %s", path, strerror(errno));
|
||||||
@ -117,7 +135,7 @@ open_file(struct pollfd *fds, struct client *c)
|
|||||||
{
|
{
|
||||||
switch (check_path(c, c->iri.path, &c->fd)) {
|
switch (check_path(c, c->iri.path, &c->fd)) {
|
||||||
case FILE_EXECUTABLE:
|
case FILE_EXECUTABLE:
|
||||||
if (c->host->cgi != NULL && starts_with(c->iri.path, c->host->cgi)) {
|
if (starts_with(c->iri.path, c->host->cgi)) {
|
||||||
start_cgi(c->iri.path, "", c->iri.query, fds, c);
|
start_cgi(c->iri.path, "", c->iri.query, fds, c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -125,27 +143,11 @@ open_file(struct pollfd *fds, struct client *c)
|
|||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
|
|
||||||
case FILE_EXISTS:
|
case FILE_EXISTS:
|
||||||
if ((c->len = filesize(c->fd)) == -1) {
|
load_file(fds, c);
|
||||||
LOGE(c, "failed to get file size for %s", c->iri.path);
|
|
||||||
close_conn(fds, c);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((c->buf = mmap(NULL, c->len, PROT_READ, MAP_PRIVATE,
|
|
||||||
c->fd, 0)) == MAP_FAILED) {
|
|
||||||
LOGW(c, "mmap: %s: %s", c->iri.path, strerror(errno));
|
|
||||||
close_conn(fds, c);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
c->i = c->buf;
|
|
||||||
c->next = S_SENDING_FILE;
|
|
||||||
start_reply(fds, c, SUCCESS, mime(c->host, c->iri.path));
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FILE_DIRECTORY:
|
case FILE_DIRECTORY:
|
||||||
close(c->fd);
|
open_dir(fds, c);
|
||||||
c->fd = -1;
|
|
||||||
send_dir(fds, c);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FILE_MISSING:
|
case FILE_MISSING:
|
||||||
@ -162,6 +164,25 @@ open_file(struct pollfd *fds, struct client *c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
load_file(struct pollfd *fds, struct client *c)
|
||||||
|
{
|
||||||
|
if ((c->len = filesize(c->fd)) == -1) {
|
||||||
|
LOGE(c, "failed to get file size for %s", c->iri.path);
|
||||||
|
start_reply(fds, c, TEMP_FAILURE, "internal server error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((c->buf = mmap(NULL, c->len, PROT_READ, MAP_PRIVATE,
|
||||||
|
c->fd, 0)) == MAP_FAILED) {
|
||||||
|
LOGW(c, "mmap: %s: %s", c->iri.path, strerror(errno));
|
||||||
|
start_reply(fds, c, TEMP_FAILURE, "internal server error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c->i = c->buf;
|
||||||
|
c->next = S_SENDING_FILE;
|
||||||
|
start_reply(fds, c, SUCCESS, mime(c->host, c->iri.path));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the inverse of this algorithm, i.e. starting from the start of the
|
* the inverse of this algorithm, i.e. starting from the start of the
|
||||||
@ -434,49 +455,157 @@ send_file(struct pollfd *fds, struct client *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
send_dir(struct pollfd *fds, struct client *c)
|
open_dir(struct pollfd *fds, struct client *c)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
|
int dirfd;
|
||||||
|
char *before_file;
|
||||||
|
|
||||||
/* guard against a re-entrant call: open_file -> send_dir ->
|
len = strlen(c->iri.path);
|
||||||
* open_file -> send_dir. This can happen only if:
|
if (len > 0 && !ends_with(c->iri.path, "/")) {
|
||||||
*
|
redirect_canonical_dir(fds, c);
|
||||||
* - user requested a dir, say foo/
|
|
||||||
* - we try to serve foo/$INDEX
|
|
||||||
* - foo/$INDEX is a directory.
|
|
||||||
*/
|
|
||||||
if (c->iri.path == c->sbuf) {
|
|
||||||
start_reply(fds, c, TEMP_REDIRECT, c->sbuf);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
strlcpy(c->sbuf, "/", sizeof(c->sbuf));
|
strlcpy(c->sbuf, "/", sizeof(c->sbuf));
|
||||||
|
|
||||||
len = strlen(c->iri.path);
|
|
||||||
if (len > 0 && c->iri.path[len-1] != '/') {
|
|
||||||
/* redirect to url with the trailing / */
|
|
||||||
strlcat(c->sbuf, c->iri.path, sizeof(c->sbuf));
|
strlcat(c->sbuf, c->iri.path, sizeof(c->sbuf));
|
||||||
|
if (!ends_with(c->sbuf, "/"))
|
||||||
strlcat(c->sbuf, "/", sizeof(c->sbuf));
|
strlcat(c->sbuf, "/", sizeof(c->sbuf));
|
||||||
start_reply(fds, c, TEMP_REDIRECT, c->sbuf);
|
before_file = strchr(c->sbuf, '\0');
|
||||||
|
len = strlcat(c->sbuf, vhost_index(c->host, c->iri.path),
|
||||||
|
sizeof(c->sbuf));
|
||||||
|
if (len >= sizeof(c->sbuf)) {
|
||||||
|
start_reply(fds, c, TEMP_FAILURE, "internal server error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c->iri.path = c->sbuf;
|
||||||
|
|
||||||
|
/* close later unless we have to generate the dir listing */
|
||||||
|
dirfd = c->fd;
|
||||||
|
c->fd = -1;
|
||||||
|
|
||||||
|
switch (check_path(c, c->iri.path, &c->fd)) {
|
||||||
|
case FILE_EXECUTABLE:
|
||||||
|
if (starts_with(c->iri.path, c->host->cgi)) {
|
||||||
|
start_cgi(c->iri.path, "", c->iri.query, fds, c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fallthrough */
|
||||||
|
|
||||||
|
case FILE_EXISTS:
|
||||||
|
load_file(fds, c);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FILE_DIRECTORY:
|
||||||
|
start_reply(fds, c, TEMP_REDIRECT, c->sbuf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FILE_MISSING:
|
||||||
|
*before_file = '\0';
|
||||||
|
|
||||||
|
if (!vhost_auto_index(c->host, c->iri.path)) {
|
||||||
|
start_reply(fds, c, NOT_FOUND, "not found");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->fd = dirfd;
|
||||||
|
c->next = S_SENDING_DIR;
|
||||||
|
|
||||||
|
if ((c->dir = fdopendir(c->fd)) == NULL) {
|
||||||
|
LOGE(c, "can't fdopendir(%d) (vhost:%s) %s: %s",
|
||||||
|
c->fd, c->host->domain, c->iri.path, strerror(errno));
|
||||||
|
start_reply(fds, c, TEMP_FAILURE, "internal server error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c->off = 0;
|
||||||
|
|
||||||
|
start_reply(fds, c, SUCCESS, "text/gemini");
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* unreachable */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
close(dirfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
redirect_canonical_dir(struct pollfd *fds, struct client *c)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
strlcpy(c->sbuf, "/", sizeof(c->sbuf));
|
||||||
strlcat(c->sbuf, c->iri.path, sizeof(c->sbuf));
|
strlcat(c->sbuf, c->iri.path, sizeof(c->sbuf));
|
||||||
|
len = strlcat(c->sbuf, "/", sizeof(c->sbuf));
|
||||||
if (!ends_with(c->sbuf, "/"))
|
|
||||||
strlcat(c->sbuf, "/", sizeof(c->sbuf));
|
|
||||||
|
|
||||||
len = strlcat(c->sbuf, vhost_index(c->host, c->iri.path),
|
|
||||||
sizeof(c->sbuf));
|
|
||||||
|
|
||||||
if (len >= sizeof(c->sbuf)) {
|
if (len >= sizeof(c->sbuf)) {
|
||||||
start_reply(fds, c, TEMP_FAILURE, "internal server error");
|
start_reply(fds, c, TEMP_FAILURE, "internal server error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(c->fd);
|
start_reply(fds, c, TEMP_REDIRECT, c->sbuf);
|
||||||
c->iri.path = c->sbuf;
|
}
|
||||||
open_file(fds, c);
|
|
||||||
|
int
|
||||||
|
read_next_dir_entry(struct client *c)
|
||||||
|
{
|
||||||
|
struct dirent *d;
|
||||||
|
|
||||||
|
do {
|
||||||
|
errno = 0;
|
||||||
|
if ((d = readdir(c->dir)) == NULL) {
|
||||||
|
if (errno != 0)
|
||||||
|
LOGE(c, "readdir: %s", strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} while (!strcmp(d->d_name, "."));
|
||||||
|
|
||||||
|
/* XXX: url escape */
|
||||||
|
snprintf(c->sbuf, sizeof(c->sbuf), "=> %s %s\n",
|
||||||
|
d->d_name, d->d_name);
|
||||||
|
c->len = strlen(c->sbuf);
|
||||||
|
c->off = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
send_directory_listing(struct pollfd *fds, struct client *c)
|
||||||
|
{
|
||||||
|
ssize_t r;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (c->len == 0) {
|
||||||
|
if (!read_next_dir_entry(c))
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (c->len > 0) {
|
||||||
|
switch (r = tls_write(c->ctx, c->sbuf + c->off, c->len)) {
|
||||||
|
case -1:
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
case TLS_WANT_POLLOUT:
|
||||||
|
fds->events = POLLOUT;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case TLS_WANT_POLLIN:
|
||||||
|
fds->events = POLLIN;
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
c->off += r;
|
||||||
|
c->len -= r;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
close_conn(fds, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -624,6 +753,9 @@ close_conn(struct pollfd *pfd, struct client *c)
|
|||||||
if (c->fd != -1)
|
if (c->fd != -1)
|
||||||
close(c->fd);
|
close(c->fd);
|
||||||
|
|
||||||
|
if (c->dir != NULL)
|
||||||
|
closedir(c->dir);
|
||||||
|
|
||||||
close(pfd->fd);
|
close(pfd->fd);
|
||||||
pfd->fd = -1;
|
pfd->fd = -1;
|
||||||
}
|
}
|
||||||
@ -658,6 +790,7 @@ do_accept(int sock, struct tls *ctx, struct pollfd *fds, struct client *clients)
|
|||||||
clients[i].fd = -1;
|
clients[i].fd = -1;
|
||||||
clients[i].waiting_on_child = 0;
|
clients[i].waiting_on_child = 0;
|
||||||
clients[i].buf = MAP_FAILED;
|
clients[i].buf = MAP_FAILED;
|
||||||
|
clients[i].dir = NULL;
|
||||||
clients[i].addr = addr;
|
clients[i].addr = addr;
|
||||||
|
|
||||||
connected_clients++;
|
connected_clients++;
|
||||||
@ -688,6 +821,10 @@ handle(struct pollfd *fds, struct client *client)
|
|||||||
send_file(fds, client);
|
send_file(fds, client);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case S_SENDING_DIR:
|
||||||
|
send_directory_listing(fds, client);
|
||||||
|
break;
|
||||||
|
|
||||||
case S_SENDING_CGI:
|
case S_SENDING_CGI:
|
||||||
handle_cgi(fds, client);
|
handle_cgi(fds, client);
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user