- get_interface_by_address() added - HTTP server initials added - code added to strip away padding on processing the IP layer by shrinking overall packet size - load of TCP fixes and improvements - TCP stream interface added - TCP window destroy() added and some bugs fixed
79 lines
2.6 KiB
C
79 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_destroy(TcpWindow * tcpw) {
|
|
dynmem_free(tcpw);
|
|
}
|
|
|
|
void tcpw_set_seqnum_offset(TcpWindow * tcpw, uint32_t offset) {
|
|
tcpw->firstByteOffset = offset;
|
|
tcpw->nextWritten = offset;
|
|
tcpw->firstUnACK = offset;
|
|
}
|
|
|
|
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(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;
|
|
|
|
}
|