Added timeouts and checked for POLLRDHUP events
This commit is contained in:
2
Makefile
2
Makefile
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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, ¤tTime) < 0) {
|
||||||
|
free(ret->currLine);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
memcpy(&ret->lastdata, ¤tTime, 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, ¤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));
|
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, ¤tTime, 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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
23
src/runner.c
23
src/runner.c
@@ -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)
|
||||||
connCount--;
|
goto remove;
|
||||||
memcpy(fds + i, fds + connCount,
|
if (updateConnection(connections + i, site))
|
||||||
sizeof(struct pollfd));
|
goto remove;
|
||||||
pending[id]--;
|
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) {
|
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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user