- generic Queue implemented - PacketRegistry allocation bug fixed - TCP implementation initials - ALIGN to type macros added
116 lines
3.8 KiB
C
116 lines
3.8 KiB
C
#include "tcp_connblock.h"
|
|
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "../packet_parsers/packet_parsers.h"
|
|
#include "../../utils.h"
|
|
#include "../../dynmem.h"
|
|
#include "etherlib/pckt_assembler.h"
|
|
#include "etherlib/eth_interface.h"
|
|
#include "ipv4_connblock.h"
|
|
#include "etherlib/prefab/packet_parsers/tcp_segment.h"
|
|
#include "etherlib/gen_queue.h"
|
|
#include "etherlib_options.h"
|
|
|
|
static bool filtTcp(const PcktSieveFilterCondition *filtCond, const PcktProps *contProps, const PcktProps *ownProps, EthInterface *intf) {
|
|
IPv4Props *ipProps = (IPv4Props *) contProps;
|
|
TcpProps *tcpProps = (TcpProps *) ownProps;
|
|
|
|
return ipProps->Protocol == ETH_UDP_PACKET_CLASS && (TCP_PORT_FROM_FILTCOND(filtCond) == tcpProps->DestinationPort);
|
|
}
|
|
|
|
/**
|
|
* TCP state.
|
|
*/
|
|
typedef struct {
|
|
uint16_t localPort;
|
|
uint16_t remotePort;
|
|
ip4_addr remoteAddr;
|
|
uint32_t sequenceNumber;
|
|
uint32_t ackNumber;
|
|
uint16_t window;
|
|
uint8_t * txWindow;
|
|
uint8_t * rxWindow;
|
|
Queue * txQueue;
|
|
Queue * rxQueue;
|
|
} TcpState;
|
|
|
|
void tcps_init(TcpState *tcps, uint16_t localPort) {
|
|
tcps->sequenceNumber = (uint32_t) rand();
|
|
tcps->localPort = localPort;
|
|
tcps->remotePort = 0;
|
|
tcps->remoteAddr = 0;
|
|
tcps->ackNumber = 0;
|
|
tcps->window = 0;
|
|
tcps->txWindow = dynmem_alloc(ETHLIB_DEF_TCP_WINDOW_SIZE);
|
|
tcps->rxWindow = dynmem_alloc(ETHLIB_DEF_TCP_WINDOW_SIZE);
|
|
/*tcps->txQueue = Q_CREATE_T(ETHLIB_DEF_TCP_QUEUE_SIZE, TcpQueueTicker);
|
|
tcps->rxQueue = Q_CREATE_T(ETHLIB_DEF_TCP_QUEUE_SIZE, TcpQueueTicker);*/
|
|
}
|
|
|
|
void tcp_bind(ConnBlock * connBlock, ip4_addr remoteAddr, uint16_t remotePort) {
|
|
TcpState * tcps = (TcpState *) connBlock->tag;
|
|
tcps->remoteAddr = remoteAddr;
|
|
tcps->remotePort = remotePort;
|
|
}
|
|
|
|
int tcps_receive_data_segment(TcpState * tcps, const Pckt * pckt) {
|
|
|
|
}
|
|
|
|
ConnBlock tcp_new_connblock(EthInterface *intf, ip4_addr ipAddr, uint16_t port, SieveCallBackFn cbFn) {
|
|
ConnBlock tcpConnB;
|
|
ConnBlock ipConnB = ipv4_new_connblock(intf, ipAddr, NULL); // create new IPv4 connection block
|
|
|
|
PcktSieveFilterCondition filtCond;
|
|
packfiltcond_zero(&filtCond);
|
|
TCP_PORT_TO_FILTCOND(&filtCond, port);
|
|
|
|
PcktSieveLayerTag tag; // store TCP state into sieve layer's tag
|
|
tag.p = dynmem_alloc(sizeof(TcpState));
|
|
memset(tag.p, 0, sizeof(TcpState));
|
|
|
|
tcpConnB.sieveLayer = packsieve_new_layer(ipConnB.sieveLayer, &filtCond, false, filtTcp, cbFn, tag, ETH_TCP_PACKET_CLASS);
|
|
ASSERT_NULL(tcpConnB.sieveLayer);
|
|
|
|
tcpConnB.intf = intf;
|
|
|
|
SNPRINTF(tcpConnB.sieveLayer->infoTag, PCKT_SIEVE_INFOTAG_LEN, "TCP port: %d", port);
|
|
|
|
return tcpConnB;
|
|
}
|
|
|
|
int tcp_send_segment(const struct ConnBlock_ *connBlock, const uint8_t *data, uint32_t size) {
|
|
// allocate headers
|
|
PcktHeaderElement *tcpHeader = ALLOC_HEADER_ELEMENT(TcpProps);
|
|
PcktHeaderElement *ipHeader = ALLOC_HEADER_ELEMENT(IPv4Props);
|
|
PcktHeaderElement *ethHeader = ALLOC_HEADER_ELEMENT(EthernetProps);
|
|
tcpHeader->next = NULL;
|
|
tcpHeader->prev = ipHeader;
|
|
ipHeader->next = tcpHeader;
|
|
ipHeader->prev = ethHeader;
|
|
ethHeader->next = ipHeader;
|
|
ethHeader->prev = NULL;
|
|
|
|
// prepare headers
|
|
TcpProps *tcpProps = HEADER_FETCH_PROPS(TcpProps, tcpHeader);
|
|
IPv4Props *ipProps = HEADER_FETCH_PROPS(IPv4Props, ipHeader);
|
|
EthernetProps *ethProps = HEADER_FETCH_PROPS(EthernetProps, ethHeader);
|
|
|
|
// get TCP state
|
|
PcktSieveLayer *layer = connBlock->sieveLayer; // TCP layer
|
|
TcpState *tcpState = (TcpState *) layer->tag.p;
|
|
|
|
// fetch sieve layers and fill transmit headers
|
|
tcpProps->SourcePort = tcpState->localPort;
|
|
tcpProps->DestinationPort = tcpState->remotePort;
|
|
tcpProps->SequenceNumber = tcpState->sequenceNumber;
|
|
tcpProps->AcknowledgementNumber = tcpState->ackNumber;
|
|
tcpProps->Window = tcpState->window;
|
|
tcpProps->Checksum = 0;
|
|
tcpProps->UrgentPtr = 0;
|
|
|
|
return 0;
|
|
}
|