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) SRC = $(wildcard src/*.c)
OBJ = $(subst .c,.o,$(subst src,work,$(SRC))) 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 := -O2 -pipe -Wall -Wpedantic -Werror
CFLAGS += -Isrc/include -fpie $(shell pkg-config --cflags gnutls) CFLAGS += -Isrc/include -fpie $(shell pkg-config --cflags gnutls)
INSTALLDIR := /usr/bin INSTALLDIR := /usr/bin

View File

@@ -31,3 +31,4 @@ sitefiles also allow comments with #
* TLS * TLS
* ```key``` - The filepath of the private key to use if transport == TLS * ```key``` - The filepath of the private key to use if transport == TLS
* ```cert``` - The filepath of the certificate 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 transport TLS
define key domain.key define key domain.key
define cert domain.crt define cert domain.crt
define timeout 2000
set host localhost:8000 set host localhost:8000
read ^/$ site/index.html read ^/$ site/index.html

View File

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

View File

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

View File

@@ -39,6 +39,7 @@ typedef struct {
SocketType type; SocketType type;
char *key; char *key;
char *cert; char *cert;
int timeout;
} Sitefile; } Sitefile;
Sitefile *parseSitefile(char *path); 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): //extra arguments depend on type (similar to fcntl):
//tcp: (void) //tcp: (void)
//tls: (char *keyfile, char *certfile, char *ocspfile) //tls: (char *keyfile, char *certfile, char *ocspfile)
Stream *acceptStream(Listener *listener, int flags); Stream *acceptStream(Listener *listener);
//returns 1 on error, accepts fcntl flags //returns 1 on error, accepts fcntl flags
void freeListener(Listener *listener); void freeListener(Listener *listener);

View File

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

View File

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

View File

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

View File

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