Wiesner András 8ed6bc57ad - MemoryPool no more space bug fixed
- TCP client/server initial implementation
- TCPWindow reworked, now without MP
2023-11-05 17:06:31 +01:00

75 lines
2.6 KiB
C

//
// Created by epagris on 2023.01.16..
//
#include <memory.h>
#include <stdbool.h>
#include "tcp_window.h"
#include "../../../dynmem.h"
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
TcpWindow *tcpw_create(uint32_t size) {
uint32_t allocSize = sizeof(TcpWindow) + size; // calculate full allocation size
TcpWindow * tcpw = (TcpWindow *) dynmem_alloc(allocSize); // allocate data block at the end
memset(tcpw, 0, sizeof(TcpWindow));
tcpw->size = size;
return tcpw;
}
void tcpw_set_seqnum_offset(TcpWindow * tcpw, uint32_t offset) {
tcpw->firstByteOffset = offset;
}
#define TCP_WINDOW_MAX_WINSIZE_PADDING (16) // keep-out zone, this way allocated blocks will not block registry table growth TODO: not the best solution
static inline uint32_t tcpw_get_occupied_size(TcpWindow * tcpw) {
return tcpw->nextWritten - tcpw->firstUnACK;
}
uint32_t tcpw_get_max_window_size(TcpWindow * tcpw) {
return tcpw->size - tcpw_get_occupied_size(tcpw);
}
uint32_t tcpw_store_segment(TcpWindow * tcpw, const uint8_t * data, uint32_t size, uint32_t seqNum) {
// check that seqNum is the continuation of the previous content
if (seqNum != (tcpw->nextWritten)) { // if not, then cannot store
return 0;
}
// calculate copy size, limit if required
uint32_t freeArea = tcpw_get_max_window_size(tcpw);
uint32_t copySize = MIN(size, freeArea);
// determine first block size
uint32_t nextWriteIndex = (tcpw->nextWritten - tcpw->firstByteOffset); // determinte next write index
uint32_t spaceToBufEnd = tcpw->size - nextWriteIndex; // space to buffer end
uint32_t firstBlockSize = MIN(spaceToBufEnd, copySize); // first block size
uint32_t secondBlockSize = (firstBlockSize < copySize) ? copySize - firstBlockSize : 0; // second block size
memcpy(tcpw->data + nextWriteIndex, data, firstBlockSize); // copy first block
if (secondBlockSize > 0) { // copy second block if needed
memcpy(tcpw->data, data + firstBlockSize, secondBlockSize);
}
// adjust indices
tcpw->nextWritten += copySize; // advance next written
if ((tcpw->nextWritten - tcpw->firstByteOffset) >= tcpw->size) { // advance first byte offset
tcpw->firstByteOffset -= tcpw->size;
}
return copySize;
}
bool tcpw_acknowledge(TcpWindow * tcpw, uint32_t ackNum) {
bool invalid = tcpw_get_occupied_size(tcpw) == 0 || // storage is empty
ackNum > (tcpw->firstUnACK + tcpw_get_occupied_size(tcpw)); // acknowledgement sequence number exceeds what we have stored
if (invalid) {
return false;
}
tcpw->firstUnACK = ackNum;
return true;
}