mirror of https://github.com/CPunch/Laika.git
153 lines
4.2 KiB
C
153 lines
4.2 KiB
C
#include "lcontent.h"
|
|
#include "lmem.h"
|
|
#include "lerror.h"
|
|
|
|
#include "lsocket.h"
|
|
#include "lpeer.h"
|
|
|
|
size_t getSize(FILE *fd) {
|
|
size_t sz;
|
|
fseek(fd, 0L, SEEK_END);
|
|
sz = ftell(fd);
|
|
fseek(fd, 0L, SEEK_SET);
|
|
return sz;
|
|
}
|
|
|
|
bool isValidID(struct sLaika_contentContext *context, uint16_t id) {
|
|
struct sLaika_content *curr = context->headIn;
|
|
|
|
while (curr) {
|
|
if (curr->id == id)
|
|
return true;
|
|
|
|
curr = curr->next;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void freeContent(struct sLaika_content *content) {
|
|
fclose(content->fd);
|
|
laikaM_free(content);
|
|
}
|
|
|
|
void rmvFromOut(struct sLaika_contentContext *context, struct sLaika_content *content) {
|
|
struct sLaika_content *last = NULL, *curr = context->headOut;
|
|
|
|
while (curr) {
|
|
/* if found, remove it! */
|
|
if (curr == content) {
|
|
if (last)
|
|
last->next = curr->next;
|
|
else
|
|
context->headOut = curr->next;
|
|
|
|
freeContent(curr);
|
|
break;
|
|
}
|
|
|
|
last = curr;
|
|
curr = curr->next;
|
|
}
|
|
}
|
|
|
|
void sendContentError(struct sLaika_peer *peer, uint16_t id, CONTENT_ERRCODE err) {
|
|
laikaS_startOutPacket(peer, LAIKAPKT_CONTENT_ERROR);
|
|
laikaS_writeInt(&peer->sock, &id, sizeof(uint16_t));
|
|
laikaS_writeByte(&peer->sock, err);
|
|
laikaS_endOutPacket(peer);
|
|
}
|
|
|
|
void laikaF_initContext(struct sLaika_contentContext *context, struct sLaika_peer *peer) {
|
|
context->peer = peer;
|
|
context->headIn = NULL;
|
|
context->headOut = NULL;
|
|
context->nextID = 0;
|
|
}
|
|
|
|
void laikaF_cleanContext(struct sLaika_contentContext *context) {
|
|
struct sLaika_content *tmp, *curr;
|
|
|
|
/* free IN list */
|
|
curr = context->headIn;
|
|
while (curr) {
|
|
tmp = curr->next;
|
|
freeContent(curr);
|
|
curr = tmp;
|
|
}
|
|
|
|
/* free OUT list */
|
|
curr = context->headOut;
|
|
while (curr) {
|
|
tmp = curr->next;
|
|
freeContent(curr);
|
|
curr = tmp;
|
|
}
|
|
}
|
|
|
|
int laikaF_newOutContent(struct sLaika_contentContext *context, FILE *fd, CONTENT_TYPE type) {
|
|
struct sLaika_content *content = (struct sLaika_content*)laikaM_malloc(sizeof(struct sLaika_content));
|
|
struct sLaika_peer *peer = context->peer;
|
|
|
|
/* init content struct */
|
|
content->fd = fd;
|
|
content->sz = getSize(fd);
|
|
content->processed = 0;
|
|
content->id = context->nextID++;
|
|
content->type = type;
|
|
|
|
/* add to list */
|
|
content->next = context->headOut;
|
|
context->headOut = content;
|
|
|
|
/* 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->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) {
|
|
struct sLaika_content *content = (struct sLaika_content*)laikaM_malloc(sizeof(struct sLaika_content));
|
|
|
|
if (isValidID(context, id)) {
|
|
sendContentError(context->peer, id, CONTENT_ERR_ID_IN_USE);
|
|
LAIKA_ERROR("ID [%d] is in use!\n", id);
|
|
}
|
|
|
|
content->fd = tmpfile();
|
|
content->sz = sz;
|
|
content->processed = 0;
|
|
content->id = id;
|
|
content->type = type;
|
|
|
|
/* add to list */
|
|
content->next = context->headIn;
|
|
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;
|
|
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) {
|
|
tmp = curr->next;
|
|
rmvFromOut(context, curr);
|
|
curr = tmp;
|
|
continue;
|
|
}
|
|
|
|
laikaS_startVarPacket(peer, LAIKAPKT_CONTENT_CHUNK);
|
|
laikaS_writeInt(&peer->sock, &curr->id, sizeof(uint16_t));
|
|
laikaS_write(&peer->sock, buff, rd);
|
|
laikaS_endVarPacket(peer);
|
|
|
|
curr = curr->next;
|
|
}
|
|
} |