Added timeouts and checked for POLLRDHUP events

This commit is contained in:
Nate Choe
2022-01-29 16:37:54 -06:00
parent c46ed581c3
commit ab2e28ed10
11 changed files with 47 additions and 16 deletions

View File

@@ -1,6 +1,6 @@
SRC = $(wildcard src/*.c)
OBJ = $(subst .c,.o,$(subst src,work,$(SRC)))
LIBS = -pthread -pie $(shell pkg-config --libs gnutls)
LIBS = -pthread -pie -lrt $(shell pkg-config --libs gnutls)
CFLAGS := -O2 -pipe -Wall -Wpedantic -Werror
CFLAGS += -Isrc/include -fpie $(shell pkg-config --cflags gnutls)
INSTALLDIR := /usr/bin

View File

@@ -31,3 +31,4 @@ sitefiles also allow comments with #
* TLS
* ```key``` - The filepath of the private key to use if transport == TLS
* ```cert``` - The filepath of the certificate to use if transport == TLS
* ```timeout``` - The amount of time to wait for data before closing the connection in ms

View File

@@ -1,6 +1,7 @@
define transport TLS
define key domain.key
define cert domain.crt
define timeout 2000
set host localhost:8000
read ^/$ site/index.html

View File

@@ -53,6 +53,13 @@ int newConnection(Stream *stream, Connection *ret) {
ret->body = NULL;
//pointers to things that are allocated within functions should be
//initialized to NULL so that free() doens't fail.
struct timespec currentTime;
if (clock_gettime(CLOCK_MONOTONIC, &currentTime) < 0) {
free(ret->currLine);
return 1;
}
memcpy(&ret->lastdata, &currentTime, sizeof(struct timespec));
return 0;
}
@@ -195,14 +202,26 @@ static int processChar(Connection *conn, char c, Sitefile *site) {
return 0;
}
long diff(struct timespec *t1, struct timespec *t2) {
return (t2->tv_sec - t1->tv_sec) * 1000 +
(t2->tv_nsec - t1->tv_nsec) / 1000000;
}
int updateConnection(Connection *conn, Sitefile *site) {
char buff[300];
for (;;) {
struct timespec currentTime;
if (clock_gettime(CLOCK_MONOTONIC, &currentTime) < 0)
return 1;
if (site->timeout > 0 &&
diff(&conn->lastdata, &currentTime) > site->timeout)
return 1;
ssize_t received = recvStream(conn->stream, buff, sizeof(buff));
if (received < 0)
return errno != EAGAIN;
if (received == 0)
break;
memcpy(&conn->lastdata, &currentTime, sizeof(struct timespec));
for (unsigned long i = 0; i < received; i++) {
if (processChar(conn, buff[i], site))
return 1;

View File

@@ -37,6 +37,9 @@ typedef struct Connection {
Stream *stream;
ConnectionSteps progress;
struct timespec lastdata;
//the last time that data was received from this connection.
RequestType type;
char *path;
//ephemeral

View File

@@ -39,6 +39,7 @@ typedef struct {
SocketType type;
char *key;
char *cert;
int timeout;
} Sitefile;
Sitefile *parseSitefile(char *path);

View File

@@ -44,7 +44,7 @@ Listener *createListener(SocketType type, uint16_t port, int backlog, ...);
//extra arguments depend on type (similar to fcntl):
//tcp: (void)
//tls: (char *keyfile, char *certfile, char *ocspfile)
Stream *acceptStream(Listener *listener, int flags);
Stream *acceptStream(Listener *listener);
//returns 1 on error, accepts fcntl flags
void freeListener(Listener *listener);

View File

@@ -145,7 +145,7 @@ int main(int argc, char **argv) {
createLog("swebs started");
for (;;) {
Stream *stream = acceptStream(listener, O_NONBLOCK);
Stream *stream = acceptStream(listener);
if (stream == NULL) {
createLog("Accepting a stream failed");
continue;

View File

@@ -15,6 +15,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
@@ -49,15 +50,21 @@ void *runServer(RunnerArgs *args) {
poll(fds, connCount, -1);
for (int i = 1; i < connCount; i++) {
if (updateConnection(connections + i, site)) {
connCount--;
memcpy(fds + i, fds + connCount,
sizeof(struct pollfd));
pending[id]--;
}
if (fds[i].revents & POLLRDHUP)
goto remove;
if (updateConnection(connections + i, site))
goto remove;
continue;
remove:
connCount--;
memcpy(fds + i, fds + connCount,
sizeof(struct pollfd));
memcpy(connections + i, fds + connCount,
sizeof(struct pollfd));
pending[id]--;
}
if (fds[0].revents == POLLIN) {
if (fds[0].revents & POLLIN) {
if (connCount >= allocConns) {
allocConns *= 2;
struct pollfd *newfds = realloc(fds,
@@ -76,7 +83,7 @@ void *runServer(RunnerArgs *args) {
if (read(notify, &stream, sizeof(stream)) < sizeof(stream))
exit(EXIT_FAILURE);
fds[connCount].fd = stream->fd;
fds[connCount].events = POLLIN;
fds[connCount].events = POLLIN | POLLRDHUP;
if (newConnection(stream, connections + connCount))
exit(EXIT_FAILURE);

View File

@@ -175,6 +175,7 @@ Sitefile *parseSitefile(char *path) {
ret->type = TCP;
ret->key = NULL;
ret->cert = NULL;
ret->timeout = 0;
int allocatedLength = 50;
ret->size = 0;
ret->content = malloc(allocatedLength * sizeof(SiteCommand));
@@ -237,6 +238,8 @@ setValue:
ret->key = copyString(argv[2]);
else if (strcmp(argv[1], "cert") == 0)
ret->cert = copyString(argv[2]);
else if (strcmp(argv[1], "timeout") == 0)
ret->timeout = atoi(argv[2]);
else
goto error;
continue;

View File

@@ -91,7 +91,7 @@ error:
return NULL;
}
Stream *acceptStream(Listener *listener, int flags) {
Stream *acceptStream(Listener *listener) {
Stream *ret = malloc(sizeof(Stream));
if (ret == NULL)
return NULL;
@@ -126,10 +126,6 @@ Stream *acceptStream(Listener *listener, int flags) {
goto error;
break;
}
{
int flags = fcntl(ret->fd, F_GETFD);
fcntl(ret->fd, F_SETFD, flags | O_NONBLOCK);
}
return ret;
error:
close(ret->fd);