diff --git a/Makefile b/Makefile
index 5ab1387..6bd5674 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/documentation/sitefiles.md b/documentation/sitefiles.md
index 2cb55d4..be158cd 100644
--- a/documentation/sitefiles.md
+++ b/documentation/sitefiles.md
@@ -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
diff --git a/example/sitefile b/example/sitefile
index 3a17673..846e3a7 100644
--- a/example/sitefile
+++ b/example/sitefile
@@ -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
diff --git a/src/connections.c b/src/connections.c
index b444e2b..08ed7b0 100644
--- a/src/connections.c
+++ b/src/connections.c
@@ -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, ¤tTime) < 0) {
+ free(ret->currLine);
+ return 1;
+ }
+ memcpy(&ret->lastdata, ¤tTime, 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, ¤tTime) < 0)
+ return 1;
+ if (site->timeout > 0 &&
+ diff(&conn->lastdata, ¤tTime) > 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, ¤tTime, sizeof(struct timespec));
for (unsigned long i = 0; i < received; i++) {
if (processChar(conn, buff[i], site))
return 1;
diff --git a/src/include/connections.h b/src/include/connections.h
index a84266e..6c76a29 100644
--- a/src/include/connections.h
+++ b/src/include/connections.h
@@ -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
diff --git a/src/include/sitefile.h b/src/include/sitefile.h
index 4704b69..b93faf7 100644
--- a/src/include/sitefile.h
+++ b/src/include/sitefile.h
@@ -39,6 +39,7 @@ typedef struct {
SocketType type;
char *key;
char *cert;
+ int timeout;
} Sitefile;
Sitefile *parseSitefile(char *path);
diff --git a/src/include/sockets.h b/src/include/sockets.h
index 942ce05..f4b1c2b 100644
--- a/src/include/sockets.h
+++ b/src/include/sockets.h
@@ -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);
diff --git a/src/main.c b/src/main.c
index c1af31c..944c8be 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
diff --git a/src/runner.c b/src/runner.c
index 4e93863..43ea5fd 100644
--- a/src/runner.c
+++ b/src/runner.c
@@ -15,6 +15,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
+#define _GNU_SOURCE
#include
#include
#include
@@ -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);
diff --git a/src/sitefile.c b/src/sitefile.c
index f66b95b..7710709 100644
--- a/src/sitefile.c
+++ b/src/sitefile.c
@@ -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;
diff --git a/src/sockets.c b/src/sockets.c
index 1bad478..12d6b44 100644
--- a/src/sockets.c
+++ b/src/sockets.c
@@ -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);