Added timeouts and checked for POLLRDHUP events
This commit is contained in:
2
Makefile
2
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -39,6 +39,7 @@ typedef struct {
|
||||
SocketType type;
|
||||
char *key;
|
||||
char *cert;
|
||||
int timeout;
|
||||
} Sitefile;
|
||||
|
||||
Sitefile *parseSitefile(char *path);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
23
src/runner.c
23
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 <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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user