mirror of
https://github.com/sigmasternchen/CFloor
synced 2025-03-15 20:28:56 +00:00
connection handling almost done
This commit is contained in:
parent
9f2fbfc18e
commit
ca311fb909
2 changed files with 115 additions and 11 deletions
125
src/networking.c
125
src/networking.c
|
@ -4,6 +4,7 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -44,10 +45,10 @@ void cleanup() {
|
||||||
unlink = true;
|
unlink = true;
|
||||||
} else if (diffms > networkingConfig.connectionTimeout) {
|
} else if (diffms > networkingConfig.connectionTimeout) {
|
||||||
unlink = true;
|
unlink = true;
|
||||||
linked_push(&connectionsToFree, connection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlink) {
|
if (unlink) {
|
||||||
|
linked_push(&connectionsToFree, connection);
|
||||||
unlinked++;
|
unlinked++;
|
||||||
linked_unlink(link);
|
linked_unlink(link);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +56,7 @@ void cleanup() {
|
||||||
link = linked_next(link);
|
link = linked_next(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
info("cleanup: %d/%d unlinked", unlinked, length);
|
debug("cleanup: %d/%d unlinked", unlinked, length);
|
||||||
|
|
||||||
link = linked_first(&connectionsToFree);
|
link = linked_first(&connectionsToFree);
|
||||||
|
|
||||||
|
@ -73,12 +74,8 @@ void cleanup() {
|
||||||
if (connection->currentHeader != NULL)
|
if (connection->currentHeader != NULL)
|
||||||
free(connection->currentHeader);
|
free(connection->currentHeader);
|
||||||
|
|
||||||
for (int i = 0; i < connection->headers.number; i++) {
|
headers_free(&(connections->headers));
|
||||||
if (connection->headers.headers[i].key != NULL)
|
|
||||||
free(connection->headers.headers[i].key);
|
|
||||||
if (connection->headers.headers[i].value != NULL)
|
|
||||||
free(connection->headers.headers[i].value);
|
|
||||||
}
|
|
||||||
if (connection->headers.headers != NULL)
|
if (connection->headers.headers != NULL)
|
||||||
free(connection->headers.headers);
|
free(connection->headers.headers);
|
||||||
|
|
||||||
|
@ -92,13 +89,119 @@ void cleanup() {
|
||||||
link = linked_next(link);
|
link = linked_next(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
info("cleanup: %d/%d freed", freed, length);
|
debug("cleanup: %d/%d freed", freed, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setSIGIO(int fd, bool enable) {
|
||||||
|
// set socket to non-blocking, asynchronous
|
||||||
|
|
||||||
|
int flags = fcntl(fd, F_GETFL);
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
if (enable) {
|
||||||
|
flags |= O_ASYNC;
|
||||||
|
} else {
|
||||||
|
flags &= O_ASYNC;
|
||||||
|
}
|
||||||
|
fcntl(fd, F_SETFL, flags);
|
||||||
|
|
||||||
|
// set signal owner
|
||||||
|
fcntl(fd, F_SETOWN, getpid());
|
||||||
|
}
|
||||||
|
|
||||||
|
int dumpHeaderBuffer(char* buffer, size_t size, struct connection* connection) {
|
||||||
|
if (connection->currentHeaderLength == 0) {
|
||||||
|
connection->currentHeader = malloc(size + 1);
|
||||||
|
if (connection->currentHeader == NULL) {
|
||||||
|
error("networking: couldn't allocate memory for header: %s", strerror(errno));
|
||||||
|
error("networking: aborting request");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char* tmp = realloc(connection->currentHeader, connection->currentHeaderLength + size + 1);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
error("networking: couldn't allocate memory for header: %s", strerror(errno));
|
||||||
|
error("networking: aborting request");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
connection->currentHeader = tmp;
|
||||||
|
}
|
||||||
|
memcpy(connection->currentHeader + connection->currentHeaderLength, buffer, size);
|
||||||
|
connection->currentHeaderLength += size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BUFFER_LENGTH (64)
|
||||||
|
|
||||||
pthread_t dataThreadId;
|
pthread_t dataThreadId;
|
||||||
void dataHandler(int signo) {
|
void dataHandler(int signo) {
|
||||||
info("data handler got called.");
|
debug("networking: data handler got called.");
|
||||||
|
|
||||||
|
for(link_t* link = linked_first(&connectionList); link != NULL; link = linked_next(link)) {
|
||||||
|
debug("networking: connection %p", link);
|
||||||
|
struct connection* connection = link->data;
|
||||||
|
if (connection->state != OPENED)
|
||||||
|
continue;
|
||||||
|
int tmp;
|
||||||
|
char c;
|
||||||
|
char buffer[BUFFER_LENGTH];
|
||||||
|
size_t length = 0;
|
||||||
|
bool dropConnection = false;
|
||||||
|
char last = 0;
|
||||||
|
if (connection->currentHeaderLength > 0)
|
||||||
|
last = connection->currentHeader[connection->currentHeaderLength];
|
||||||
|
while((tmp = read(connection->fd, &c, 1)) > 0) {
|
||||||
|
if (last == '\r' && c == '\n') {
|
||||||
|
if (dumpHeaderBuffer(&(buffer[0]), length, connection)) < 0) {
|
||||||
|
dropConnection = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
headers_parse(&(connecion->headers), connection->currentHeader, connection->currentHeaderLength);
|
||||||
|
|
||||||
|
connection->currentHeaderLength = 0;
|
||||||
|
free(connection->currentHeader);
|
||||||
|
connection->currentHeader = NULL;
|
||||||
|
length = 0;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length >= BUFFER_LENGTH) {
|
||||||
|
length = 0;
|
||||||
|
if (dumpHeaderBuffer(&(buffer[0]), BUFFER_LENGTH, connection) < 0) {
|
||||||
|
dropConnection = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tmp < 0) {
|
||||||
|
switch(errno) {
|
||||||
|
case EAGAIN:
|
||||||
|
// no more data to be ready
|
||||||
|
// ignore this error
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dropConnection = true;
|
||||||
|
error("networking: error reading socket: %s", strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (tmp == 0) {
|
||||||
|
error("networking: connection ended");
|
||||||
|
dropConnection = true;
|
||||||
|
}
|
||||||
|
if (length > 0) {
|
||||||
|
if (dumpHeaderBuffer(&(buffer[0]), length, connection) < 0) {
|
||||||
|
dropConnection = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dropConnection) {
|
||||||
|
debug("networking: dropping connection");
|
||||||
|
setSIGIO(connection->fd, false);
|
||||||
|
connection->state = ABORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void* dataThread(void* ignore) {
|
void* dataThread(void* ignore) {
|
||||||
signal_block_all();
|
signal_block_all();
|
||||||
|
@ -217,6 +320,8 @@ void* listenThread(void* _bind) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setSIGIO(tmp, true);
|
||||||
|
|
||||||
connection->state = OPENED;
|
connection->state = OPENED;
|
||||||
connection->client = client;
|
connection->client = client;
|
||||||
connection->bind = bindObj;
|
connection->bind = bindObj;
|
||||||
|
|
|
@ -50,7 +50,6 @@ struct connection {
|
||||||
struct headers headers;
|
struct headers headers;
|
||||||
size_t currentHeaderLength;
|
size_t currentHeaderLength;
|
||||||
char* currentHeader;
|
char* currentHeader;
|
||||||
handler_t handler;
|
|
||||||
struct timing timing;
|
struct timing timing;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue