- EthIntf: packet interception in both directions; DHCP automanage; config loading and storing; info printing
- utils: atoip(), lefttrim() - ARP: bunch of bugfixes - TCP, FTP: WIP - DHCP: mutex; query the FSM state
This commit is contained in:
parent
db50beb71a
commit
9532b6b274
@ -167,6 +167,7 @@ int ftps_data_recv(cbd d) {
|
|||||||
// accept new data connection
|
// accept new data connection
|
||||||
int ftps_data_accept_cb(cbd d) {
|
int ftps_data_accept_cb(cbd d) {
|
||||||
s.connData = d; // set data connection ID
|
s.connData = d; // set data connection ID
|
||||||
|
tcp_debug(d, true);
|
||||||
ETHLIB_OS_SEM_POST(s.dataConnHasOpened); // release data connection semaphore
|
ETHLIB_OS_SEM_POST(s.dataConnHasOpened); // release data connection semaphore
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -185,10 +186,19 @@ void ftps_process_event(uint32_t event) {
|
|||||||
uint32_t recvLen = tcp_recv(s.connCtrl, (uint8_t *)s.lineBuffer, FTPS_LINEBUF_LEN);
|
uint32_t recvLen = tcp_recv(s.connCtrl, (uint8_t *)s.lineBuffer, FTPS_LINEBUF_LEN);
|
||||||
s.lineBuffer[recvLen] = '\0';
|
s.lineBuffer[recvLen] = '\0';
|
||||||
|
|
||||||
|
// if recv len is zero in dicating that the connection was closed, by the peer,
|
||||||
|
// then reset the server state
|
||||||
|
if (recvLen == 0) {
|
||||||
|
s.connCtrl = 0;
|
||||||
|
s.connState = FTPS_IDLE;
|
||||||
|
// TODO: close data connection as well
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// right trim the line
|
// right trim the line
|
||||||
ftps_rtrim(s.lineBuffer);
|
ftps_rtrim(s.lineBuffer);
|
||||||
|
|
||||||
MSG("%s\n", s.lineBuffer);
|
// MSG("%s\n", s.lineBuffer);
|
||||||
|
|
||||||
// get first word: get pointer to first space and calculate compare length
|
// get first word: get pointer to first space and calculate compare length
|
||||||
char *spacePos = strchr(s.lineBuffer, ' ');
|
char *spacePos = strchr(s.lineBuffer, ' ');
|
||||||
@ -288,9 +298,10 @@ void ftps_process_event(uint32_t event) {
|
|||||||
tcp_send(s.connData, (const uint8_t *)"\r\n", 2); // sending listing data
|
tcp_send(s.connData, (const uint8_t *)"\r\n", 2); // sending listing data
|
||||||
tcp_send(s.connCtrl, (const uint8_t *)ftpClosingDataConn, strlen(ftpClosingDataConn)); // closing data connection
|
tcp_send(s.connCtrl, (const uint8_t *)ftpClosingDataConn, strlen(ftpClosingDataConn)); // closing data connection
|
||||||
close_connection(s.connData); // actually close connection
|
close_connection(s.connData); // actually close connection
|
||||||
s.connData = 0; // clear data connection CBD
|
s.connData = 0;
|
||||||
break;
|
resp = NULL; // clear data connection CBD
|
||||||
}
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ static int arpc_recv_cb(const Pckt * pckt, PcktSieveLayerTag tag) {
|
|||||||
|
|
||||||
if (weAreCalled) {
|
if (weAreCalled) {
|
||||||
arpc_respond(arpc, arpProps->SHA, arpProps->SPA);
|
arpc_respond(arpc, arpProps->SHA, arpProps->SPA);
|
||||||
|
//MSG("Megy a válasz!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -67,10 +67,12 @@ EthInterface *ethintf_new(EthIODef *io) {
|
|||||||
ethIntf->capabilities = 0;
|
ethIntf->capabilities = 0;
|
||||||
|
|
||||||
ethIntf->dhcp = NULL;
|
ethIntf->dhcp = NULL;
|
||||||
|
ethIntf->manageDhcp = true; // by default, enable automatic DHCP management
|
||||||
|
|
||||||
memset(ðIntf->evtCbTable, 0, sizeof(EthIntfEventCbTable));
|
memset(ðIntf->evtCbTable, 0, sizeof(EthIntfEventCbTable));
|
||||||
|
|
||||||
ethIntf->interceptCb = NULL;
|
ethIntf->interceptTxCb = NULL;
|
||||||
|
ethIntf->interceptRxCb = NULL;
|
||||||
|
|
||||||
ethIntf->linkState = false;
|
ethIntf->linkState = false;
|
||||||
|
|
||||||
@ -97,8 +99,8 @@ static ThreadReturnType task_ethintf(ThreadParamType param) {
|
|||||||
mq_pop(intf->rxQ);
|
mq_pop(intf->rxQ);
|
||||||
|
|
||||||
// packet interception, if defined
|
// packet interception, if defined
|
||||||
if (intf->interceptCb != NULL) {
|
if (intf->interceptRxCb != NULL) {
|
||||||
intf->interceptCb(intf, &rawPckt);
|
intf->interceptRxCb(intf, &rawPckt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// packet processing
|
// packet processing
|
||||||
@ -114,7 +116,7 @@ static ThreadReturnType task_ethintf(ThreadParamType param) {
|
|||||||
bool prev_ls = ethinf_get_link_state(intf); // get previous link state
|
bool prev_ls = ethinf_get_link_state(intf); // get previous link state
|
||||||
ethinf_set_link_state(intf, ls); // set new link state
|
ethinf_set_link_state(intf, ls); // set new link state
|
||||||
|
|
||||||
if ((intf->dhcp != NULL) && (ls != prev_ls)) { // no double start!
|
if ((intf->manageDhcp) && (intf->dhcp != NULL) && (ls != prev_ls)) { // no double start!
|
||||||
if (ls) { // if link is on
|
if (ls) { // if link is on
|
||||||
dhcp_start(intf->dhcp);
|
dhcp_start(intf->dhcp);
|
||||||
} else { // if link is off
|
} else { // if link is off
|
||||||
@ -155,6 +157,11 @@ void ethinf_transmit(EthInterface *intf, const RawPckt *rawPckt) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// packet interception, if defined
|
||||||
|
if (intf->interceptTxCb != NULL) {
|
||||||
|
intf->interceptTxCb(intf, rawPckt);
|
||||||
|
}
|
||||||
|
|
||||||
// push packet onto the message queue
|
// push packet onto the message queue
|
||||||
if (mq_push(intf->txQ, rawPckt)) {
|
if (mq_push(intf->txQ, rawPckt)) {
|
||||||
ethinf_push_notification(intf, ETH_IIE_TRANSMIT_NOTIFY, 0); // notify processing thread of the peding transmit
|
ethinf_push_notification(intf, ETH_IIE_TRANSMIT_NOTIFY, 0); // notify processing thread of the peding transmit
|
||||||
@ -222,6 +229,55 @@ void ethinf_down(EthInterface *intf) {
|
|||||||
intf->up = false;
|
intf->up = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ethinf_set_intercept_callback(EthInterface * intf, EthIntfInterceptCb cb) {
|
void ethinf_set_intercept_callback(EthInterface *intf, EthIntfInterceptCb cb, EthIntfInterceptDir dir) {
|
||||||
intf->interceptCb = cb;
|
if (dir & ETH_INTERCEPT_TX) {
|
||||||
|
intf->interceptTxCb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir & ETH_INTERCEPT_RX) {
|
||||||
|
intf->interceptRxCb = cb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ethinf_set_automatic_dhcp_management(EthInterface *intf, bool automg) {
|
||||||
|
intf->manageDhcp = automg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ethinf_set_config(EthInterface *intf, const EthInterfaceNetworkConfig *config) {
|
||||||
|
intf->ip = config->ip;
|
||||||
|
intf->router = config->router;
|
||||||
|
intf->netmask = config->netmask;
|
||||||
|
intf->dns = config->dns;
|
||||||
|
|
||||||
|
intf->manageDhcp = config->manageDhcp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ethinf_get_config(EthInterface *intf, EthInterfaceNetworkConfig *config) {
|
||||||
|
config->ip = intf->ip;
|
||||||
|
config->router = intf->router;
|
||||||
|
config->netmask = intf->netmask;
|
||||||
|
config->dns = intf->dns;
|
||||||
|
|
||||||
|
config->manageDhcp = intf->manageDhcp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ethinf_print_info(const EthInterface * intf) {
|
||||||
|
MSG("IP: " ANSI_COLOR_BYELLOW);
|
||||||
|
PRINT_IPv4(intf->ip);
|
||||||
|
MSG(ANSI_COLOR_RESET "\nRouter: ");
|
||||||
|
PRINT_IPv4(intf->router);
|
||||||
|
MSG("\nNetmask: ");
|
||||||
|
PRINT_IPv4(intf->netmask);
|
||||||
|
MSG("\nDNS: ");
|
||||||
|
PRINT_IPv4(intf->dns);
|
||||||
|
MSG("\n\n");
|
||||||
|
|
||||||
|
if (intf->dhcp != NULL) {
|
||||||
|
bool on = dhcp_get_fsm_state(intf->dhcp) != DHCP_STOPPED;
|
||||||
|
MSG("DHCP is %s" ANSI_COLOR_RESET "%s.", on ? (ANSI_COLOR_BGREEN "ON") : (ANSI_COLOR_BRED "OFF"), intf->manageDhcp ? "[automanaged]" : "");
|
||||||
|
} else {
|
||||||
|
MSG ("DHCP is " ANSI_COLOR_RED "absent" ANSI_COLOR_RESET ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
MSG("\n");
|
||||||
}
|
}
|
@ -48,6 +48,14 @@ struct EthInterface_;
|
|||||||
|
|
||||||
typedef void (*EthIntfEvtCb)(struct EthInterface_ *intf);
|
typedef void (*EthIntfEvtCb)(struct EthInterface_ *intf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frame interception direction.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
ETH_INTERCEPT_TX = 1,
|
||||||
|
ETH_INTERCEPT_RX = 2
|
||||||
|
} EthIntfInterceptDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function prototype for intercepting packets on an interface.
|
* Function prototype for intercepting packets on an interface.
|
||||||
* @param intf pointer to corresponding Ethernet interface
|
* @param intf pointer to corresponding Ethernet interface
|
||||||
@ -77,6 +85,7 @@ typedef struct EthInterface_ {
|
|||||||
EthernetAddress mac; ///< Ethernet address
|
EthernetAddress mac; ///< Ethernet address
|
||||||
uint32_t capabilities; ///< Ethernet interface capabilities
|
uint32_t capabilities; ///< Ethernet interface capabilities
|
||||||
DhcpState *dhcp; ///< DHCP control block (allocated only, if DHCP operation is initiated)
|
DhcpState *dhcp; ///< DHCP control block (allocated only, if DHCP operation is initiated)
|
||||||
|
bool manageDhcp; ///< Let the interface automatically manage the DHCP client (start/stop)
|
||||||
ip4_addr ip; ///< IP address
|
ip4_addr ip; ///< IP address
|
||||||
ip4_addr router; ///< Router IP address
|
ip4_addr router; ///< Router IP address
|
||||||
ip4_addr netmask; ///< Subnet mask
|
ip4_addr netmask; ///< Subnet mask
|
||||||
@ -91,10 +100,19 @@ typedef struct EthInterface_ {
|
|||||||
EthIntfEventCbTable evtCbTable; ///< Event callback table
|
EthIntfEventCbTable evtCbTable; ///< Event callback table
|
||||||
bool linkState; ///< Interface link state
|
bool linkState; ///< Interface link state
|
||||||
bool up; ///< Is the interface up?
|
bool up; ///< Is the interface up?
|
||||||
EthIntfInterceptCb interceptCb; ///< Intercept callback
|
EthIntfInterceptCb interceptTxCb; ///< Intercept TX callback
|
||||||
|
EthIntfInterceptCb interceptRxCb; ///< Intercept RX callback
|
||||||
|
|
||||||
} EthInterface;
|
} EthInterface;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ethernet interface configuration.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
ip4_addr ip, router, netmask, dns;
|
||||||
|
bool manageDhcp;
|
||||||
|
} EthInterfaceNetworkConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate a new Ethernet interface
|
* Allocate a new Ethernet interface
|
||||||
* @param io Low-level IO definitions
|
* @param io Low-level IO definitions
|
||||||
@ -183,6 +201,33 @@ void ethinf_down(EthInterface *intf);
|
|||||||
* @param intf pointer to Ethernet interface
|
* @param intf pointer to Ethernet interface
|
||||||
* @param cb intercept callback pointer
|
* @param cb intercept callback pointer
|
||||||
*/
|
*/
|
||||||
void ethinf_set_intercept_callback(EthInterface *intf, EthIntfInterceptCb cb);
|
void ethinf_set_intercept_callback(EthInterface *intf, EthIntfInterceptCb cb, EthIntfInterceptDir dir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn ON/OFF automatic DHCP client management.
|
||||||
|
* @param intf pointer to Ethernet interface
|
||||||
|
* @param automg automanagement enabled/disabled
|
||||||
|
*/
|
||||||
|
void ethinf_set_automatic_dhcp_management(EthInterface *intf, bool automg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set interface configuration.
|
||||||
|
* @param intf pointer to Ethernet interface
|
||||||
|
* @param config pointer to a filled config object
|
||||||
|
*/
|
||||||
|
void ethinf_set_config(EthInterface * intf, const EthInterfaceNetworkConfig * config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get interface configuration.
|
||||||
|
* @param intf pointer to Ethernet interface
|
||||||
|
* @param config pointer to an empty config object
|
||||||
|
*/
|
||||||
|
void ethinf_get_config(EthInterface *intf, EthInterfaceNetworkConfig *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Printf information on Ethernet interface.
|
||||||
|
* @param intf pointer to Ethernet interface
|
||||||
|
*/
|
||||||
|
void ethinf_print_info(const EthInterface * intf);
|
||||||
|
|
||||||
#endif // ETHERLIB_ETH_INTERFACE_H
|
#endif // ETHERLIB_ETH_INTERFACE_H
|
||||||
|
@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "../../utils.h"
|
|
||||||
#include "../../dynmem.h"
|
#include "../../dynmem.h"
|
||||||
|
#include "../../utils.h"
|
||||||
|
#include "../../pckt_assembler.h"
|
||||||
|
|
||||||
static bool filtArp(const PcktSieveFilterCondition *filtCond, const PcktProps *contProps, const PcktProps *ownProps, EthInterface *intf) {
|
static bool filtArp(const PcktSieveFilterCondition *filtCond, const PcktProps *contProps, const PcktProps *ownProps, EthInterface *intf) {
|
||||||
EthernetProps *ethProps = (EthernetProps *)contProps;
|
EthernetProps *ethProps = (EthernetProps *)contProps;
|
||||||
@ -56,7 +57,7 @@ void arp_send(const ConnBlock * connBlock, const ArpProps * props) {
|
|||||||
|
|
||||||
// allocate transmit buffer
|
// allocate transmit buffer
|
||||||
uint32_t txHeaderSize = ETH_ETHERNET_HEADER_SIZE + ETH_ARP_HEADER_SIZE;
|
uint32_t txHeaderSize = ETH_ETHERNET_HEADER_SIZE + ETH_ARP_HEADER_SIZE;
|
||||||
uint32_t txBufSize = MAX(txHeaderSize + 4, 60);
|
uint32_t txBufSize = MAX(txHeaderSize + 4, ETH_FRAME_MIN_SIZE);
|
||||||
uint8_t *txBuf = dynmem_alloc(txBufSize);
|
uint8_t *txBuf = dynmem_alloc(txBufSize);
|
||||||
memset(txBuf, 0, txBufSize);
|
memset(txBuf, 0, txBufSize);
|
||||||
|
|
||||||
@ -71,8 +72,11 @@ void arp_send(const ConnBlock * connBlock, const ArpProps * props) {
|
|||||||
dynmem_free(ethHeader);
|
dynmem_free(ethHeader);
|
||||||
|
|
||||||
// append CRC at the end
|
// append CRC at the end
|
||||||
|
//bool computeCRC = !(connBlock->sieve->intf->capabilities & ETHINF_CAP_TX_CRC_OFFLOAD);
|
||||||
|
//if (computeCRC) {
|
||||||
uint32_t crc = crc32(txBuf, txBufSize - 4);
|
uint32_t crc = crc32(txBuf, txBufSize - 4);
|
||||||
memcpy(txBuf + txBufSize - 4, &crc, 4);
|
memcpy(txBuf + txBufSize - 4, &crc, 4);
|
||||||
|
//}
|
||||||
|
|
||||||
// send packet
|
// send packet
|
||||||
RawPckt rpckt;
|
RawPckt rpckt;
|
||||||
|
@ -146,7 +146,7 @@ static inline cbd tcps_create_based_on_listening(const TcpState *source, uint16_
|
|||||||
target->rxAckNum = source->rxAckNum;
|
target->rxAckNum = source->rxAckNum;
|
||||||
target->remoteAddr = remoteAddr;
|
target->remoteAddr = remoteAddr;
|
||||||
target->remotePort = remotePort;
|
target->remotePort = remotePort;
|
||||||
target->connState = TCP_STATE_ESTAB;
|
target->connState = TCP_STATE_SYN_RCVD;
|
||||||
tcpw_set_seqnum_offset(target->txWin, target->txSeqNum);
|
tcpw_set_seqnum_offset(target->txWin, target->txSeqNum);
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
@ -168,12 +168,12 @@ static bool tcp_close(TcpState *tcps) {
|
|||||||
// take send semaphore
|
// take send semaphore
|
||||||
ETHLIB_OS_SEM_WAIT(tcps->txInProgress);
|
ETHLIB_OS_SEM_WAIT(tcps->txInProgress);
|
||||||
|
|
||||||
MSG("TX SEM\n");
|
//MSG("TX SEM\n");
|
||||||
|
|
||||||
// wait for the TX FIFO contents to get transmitted
|
// wait for the TX FIFO contents to get transmitted
|
||||||
osEventFlagsWait(tcps->eventFlags, EVTFLAG_ALL_ACKED, osFlagsWaitAll | osFlagsNoClear, osWaitForever); // FIXME: ez így nem lesz jó, mert, ha valamiért nem kapjuk meg az ACK-t, akkor itt ragadunk
|
// osEventFlagsWait(tcps->eventFlags, EVTFLAG_ALL_ACKED, osFlagsNoClear, 1000); // FIXME: ez így nem lesz jó, mert, ha valamiért nem kapjuk meg az ACK-t, akkor itt ragadunk
|
||||||
|
|
||||||
MSG("FLAG\n");
|
//MSG("FLAG\n");
|
||||||
|
|
||||||
// lock the mutex -----
|
// lock the mutex -----
|
||||||
ETHLIB_OS_MTX_LOCK(tcps->processMtx);
|
ETHLIB_OS_MTX_LOCK(tcps->processMtx);
|
||||||
@ -311,21 +311,40 @@ int tcp_receive_segment_cb(const Pckt *pckt, PcktSieveLayerTag tag) {
|
|||||||
// create connection based on the listening connection
|
// create connection based on the listening connection
|
||||||
ConnBlock connB;
|
ConnBlock connB;
|
||||||
cbd client_d = tcps_create_based_on_listening(tcps, tcpProps->SourcePort, ipProps->SourceIPAddr, &connB);
|
cbd client_d = tcps_create_based_on_listening(tcps, tcpProps->SourcePort, ipProps->SourceIPAddr, &connB);
|
||||||
|
TcpState *target = TCP_FETCH_STATE_FROM_CONNBLOCK(&connB);
|
||||||
|
|
||||||
|
ETHLIB_OS_MTX_LOCK(target->processMtx);
|
||||||
|
|
||||||
tcp_send_segment(&connB, flags, NULL, NULL, 0);
|
tcp_send_segment(&connB, flags, NULL, NULL, 0);
|
||||||
|
|
||||||
TcpState *target = TCP_FETCH_STATE_FROM_CONNBLOCK(&connB);
|
|
||||||
target->txSeqNum++;
|
target->txSeqNum++;
|
||||||
tcpw_set_seqnum_offset(target->txWin, target->txSeqNum);
|
tcpw_set_seqnum_offset(target->txWin, target->txSeqNum);
|
||||||
|
|
||||||
if ((client_d > 0) && (tcps->acceptCb != NULL)) {
|
if ((client_d > 0) && (tcps->acceptCb != NULL)) {
|
||||||
tcps->acceptCb(client_d);
|
tcps->acceptCb(client_d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ETHLIB_OS_MTX_UNLOCK(target->processMtx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case TCP_STATE_SYN_RCVD: /* SYN was received */
|
||||||
|
{
|
||||||
|
bool SYNAcked = (dataSize == 0) && (tcps->txSeqNum == tcpProps->AcknowledgementNumber) &&
|
||||||
|
(tcpProps->Flags & TCP_FLAG_ACK);
|
||||||
|
if (SYNAcked) {
|
||||||
|
tcps->connState = TCP_STATE_ESTAB;
|
||||||
|
osEventFlagsSet(tcps->eventFlags, EVTFLAG_ESTAB);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case TCP_STATE_ESTAB: /* Connection established */
|
case TCP_STATE_ESTAB: /* Connection established */
|
||||||
|
if (tcps->debug) {
|
||||||
|
MSG("data size: %d\n", dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
// if the other end tries to close down the connection
|
// if the other end tries to close down the connection
|
||||||
if (tcpProps->Flags & TCP_FLAG_FIN) {
|
if (tcpProps->Flags & TCP_FLAG_FIN) {
|
||||||
// send FIN, ACK
|
// send FIN, ACK
|
||||||
@ -333,6 +352,11 @@ int tcp_receive_segment_cb(const Pckt *pckt, PcktSieveLayerTag tag) {
|
|||||||
tcps->rxAckNum++; // advance acknowledgement number // TODO...
|
tcps->rxAckNum++; // advance acknowledgement number // TODO...
|
||||||
tcp_send_segment(&tcps->connBlock, flags, NULL, NULL, 0);
|
tcp_send_segment(&tcps->connBlock, flags, NULL, NULL, 0);
|
||||||
|
|
||||||
|
// invoke stream callback to inform application, that the connection is closing
|
||||||
|
if (tcps->streamCb != NULL) {
|
||||||
|
tcps->streamCb(tcps->d);
|
||||||
|
}
|
||||||
|
|
||||||
// step into next state
|
// step into next state
|
||||||
tcps->connState = TCP_STATE_LAST_ACK;
|
tcps->connState = TCP_STATE_LAST_ACK;
|
||||||
} else if ((dataSize > 0) && (tcps->rxAckNum == tcpProps->SequenceNumber)) { // incoming data segment with integrity in ack/seq
|
} else if ((dataSize > 0) && (tcps->rxAckNum == tcpProps->SequenceNumber)) { // incoming data segment with integrity in ack/seq
|
||||||
@ -357,9 +381,16 @@ int tcp_receive_segment_cb(const Pckt *pckt, PcktSieveLayerTag tag) {
|
|||||||
// release segment from retransmit window
|
// release segment from retransmit window
|
||||||
tcpw_acknowledge(tcps->txWin, tcpProps->AcknowledgementNumber);
|
tcpw_acknowledge(tcps->txWin, tcpProps->AcknowledgementNumber);
|
||||||
|
|
||||||
|
if (tcps->debug) {
|
||||||
|
MSG("occupied: %d\n", tcpw_get_occupied_size(tcps->txWin));
|
||||||
|
}
|
||||||
|
|
||||||
// set or clear all ACKed flag according to TX window state
|
// set or clear all ACKed flag according to TX window state
|
||||||
if (tcpw_get_occupied_size(tcps->txWin) == 0) {
|
if (tcpw_get_occupied_size(tcps->txWin) == 0) {
|
||||||
osEventFlagsSet(tcps->eventFlags, EVTFLAG_ALL_ACKED);
|
osEventFlagsSet(tcps->eventFlags, EVTFLAG_ALL_ACKED);
|
||||||
|
if (tcps->debug) {
|
||||||
|
MSG("All ACKed %d\n", tcps->d);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
osEventFlagsClear(tcps->eventFlags, EVTFLAG_ALL_ACKED);
|
osEventFlagsClear(tcps->eventFlags, EVTFLAG_ALL_ACKED);
|
||||||
}
|
}
|
||||||
@ -690,10 +721,15 @@ uint32_t tcp_send(cbd d, const uint8_t *data, uint32_t size) {
|
|||||||
TcpState *tcps = TCP_FETCH_STATE_FROM_CONNBLOCK(&connBlock);
|
TcpState *tcps = TCP_FETCH_STATE_FROM_CONNBLOCK(&connBlock);
|
||||||
|
|
||||||
// can send only data if connection is ESTABLISHED
|
// can send only data if connection is ESTABLISHED
|
||||||
if (tcps->connState != TCP_STATE_ESTAB) {
|
if ((tcps->connState != TCP_STATE_ESTAB) && (tcps->connState != TCP_STATE_SYN_RCVD)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// is the SYN_RCVD state wait for getting into the established state
|
||||||
|
if (tcps->connState == TCP_STATE_SYN_RCVD) {
|
||||||
|
osEventFlagsWait(tcps->eventFlags, EVTFLAG_ESTAB, osFlagsNoClear, osWaitForever);
|
||||||
|
}
|
||||||
|
|
||||||
// connection state is established...
|
// connection state is established...
|
||||||
|
|
||||||
uint32_t sizeLeft = size;
|
uint32_t sizeLeft = size;
|
||||||
@ -751,7 +787,11 @@ uint32_t tcp_recv(unsigned char d, uint8_t *data, uint32_t size) {
|
|||||||
// acquire TCP state
|
// acquire TCP state
|
||||||
TcpState *tcps = TCP_FETCH_STATE_FROM_CONNBLOCK(&connBlock);
|
TcpState *tcps = TCP_FETCH_STATE_FROM_CONNBLOCK(&connBlock);
|
||||||
|
|
||||||
|
if (tcps->connState == TCP_STATE_ESTAB) {
|
||||||
return eth_bfifo_pop(tcps->rxFifo, data, size);
|
return eth_bfifo_pop(tcps->rxFifo, data, size);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcp_print_report(const ConnBlock *connBlock) {
|
void tcp_print_report(const ConnBlock *connBlock) {
|
||||||
|
@ -244,15 +244,31 @@ void dhcp_request(DhcpState *s, ip4_addr reqAddr, ip4_addr dhcpServerAddr) {
|
|||||||
|
|
||||||
static void dhcp_retry_discover(struct Timer_ *timer, AlarmUserData user) {
|
static void dhcp_retry_discover(struct Timer_ *timer, AlarmUserData user) {
|
||||||
DhcpState *s = (DhcpState *)user.ptr;
|
DhcpState *s = (DhcpState *)user.ptr;
|
||||||
if (s->state != DHCP_BOUND) { // only retransmit DISCOVER if not BOUND
|
if ((s->enabled) && (s->state != DHCP_BOUND)) { // only retransmit DISCOVER if not BOUND
|
||||||
dhcp_start(s);
|
dhcp_start(s);
|
||||||
}
|
}
|
||||||
s->retryAlarmId = 0; // clear schedule ID
|
s->retryAlarmId = 0; // clear schedule ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char * dhcp_state_names[] = {
|
||||||
|
"DHCP INIT REBOOT",
|
||||||
|
"DHCP REBOOTING",
|
||||||
|
"DHCP INIT",
|
||||||
|
"DHCP REQUESTING",
|
||||||
|
"DHCP SELECTING",
|
||||||
|
"DHCP REBINDING",
|
||||||
|
"DHCP BOUND",
|
||||||
|
"DHCP RENEWING",
|
||||||
|
"DHCP STOPPED"
|
||||||
|
};
|
||||||
|
|
||||||
static void dhcp_process(DhcpState *s, DhcpProps *props, DhcpOption *opts) {
|
static void dhcp_process(DhcpState *s, DhcpProps *props, DhcpOption *opts) {
|
||||||
ETHLIB_OS_MTX_LOCK(s->procMtx); // LOCK!
|
ETHLIB_OS_MTX_LOCK(s->procMtx); // LOCK!
|
||||||
|
|
||||||
|
#ifdef DHCP_STATE_DEBUG
|
||||||
|
uint8_t oldState = s->state;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (s->state) {
|
switch (s->state) {
|
||||||
case DHCP_INIT: {
|
case DHCP_INIT: {
|
||||||
dhcp_discover(s); // send discover message
|
dhcp_discover(s); // send discover message
|
||||||
@ -280,6 +296,7 @@ static void dhcp_process(DhcpState *s, DhcpProps *props, DhcpOption *opts) {
|
|||||||
case DHCP_REQUESTING: {
|
case DHCP_REQUESTING: {
|
||||||
const DhcpOption *opt = dhcp_get_option(opts, DHCP_OPT_MsgType);
|
const DhcpOption *opt = dhcp_get_option(opts, DHCP_OPT_MsgType);
|
||||||
uint8_t msgType = opt->value[0];
|
uint8_t msgType = opt->value[0];
|
||||||
|
|
||||||
if (msgType == DHCPNAK) {
|
if (msgType == DHCPNAK) {
|
||||||
// dhcp_discover();
|
// dhcp_discover();
|
||||||
// s.state = DHCP_SELECTING;
|
// s.state = DHCP_SELECTING;
|
||||||
@ -325,6 +342,14 @@ static void dhcp_process(DhcpState *s, DhcpProps *props, DhcpOption *opts) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DHCP_STATE_DEBUG
|
||||||
|
uint8_t newState = s->state;
|
||||||
|
|
||||||
|
if (newState != oldState) {
|
||||||
|
MSG("# %s -> %s\n", dhcp_state_names[oldState], dhcp_state_names[newState]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ETHLIB_OS_MTX_UNLOCK(s->procMtx); // RELEASE!
|
ETHLIB_OS_MTX_UNLOCK(s->procMtx); // RELEASE!
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,11 +367,19 @@ static int dhcp_resp_cb(const Pckt *pckt, PcktSieveLayerTag tag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dhcp_start(DhcpState *s) {
|
void dhcp_start(DhcpState *s) {
|
||||||
|
//MSG("DHCP start!\n");
|
||||||
|
s->enabled = true;
|
||||||
s->state = DHCP_INIT;
|
s->state = DHCP_INIT;
|
||||||
dhcp_process(s, NULL, NULL);
|
dhcp_process(s, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dhcp_stop(DhcpState *s) {
|
void dhcp_stop(DhcpState *s) {
|
||||||
|
//MSG("DHCP stop!\n");
|
||||||
|
|
||||||
|
ETHLIB_OS_MTX_LOCK(s->procMtx); // LOCK!
|
||||||
|
|
||||||
|
s->enabled = false;
|
||||||
|
|
||||||
s->state = DHCP_STOPPED;
|
s->state = DHCP_STOPPED;
|
||||||
if (s->renewAlarmId != 0) { // unschedule renew alarm
|
if (s->renewAlarmId != 0) { // unschedule renew alarm
|
||||||
timer_unsched(E.tmr, s->renewAlarmId);
|
timer_unsched(E.tmr, s->renewAlarmId);
|
||||||
@ -382,6 +415,12 @@ void dhcp_initiate(EthInterface *intf) {
|
|||||||
cbdt_set_tag(E.cbdt, s->desc, tag);
|
cbdt_set_tag(E.cbdt, s->desc, tag);
|
||||||
s->intf = intf;
|
s->intf = intf;
|
||||||
s->renewAlarmId = 0;
|
s->renewAlarmId = 0;
|
||||||
|
s->retryAlarmId = 0;
|
||||||
|
s->enabled = false;
|
||||||
|
|
||||||
intf->dhcp = s;
|
intf->dhcp = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DhcpFSMState dhcp_get_fsm_state(const DhcpState *s) {
|
||||||
|
return s->state;
|
||||||
|
}
|
@ -61,6 +61,7 @@ typedef struct {
|
|||||||
ETHLIB_OS_MTX_TYPE procMtx; ///< Mutex protecting the state machine
|
ETHLIB_OS_MTX_TYPE procMtx; ///< Mutex protecting the state machine
|
||||||
uint32_t renewAlarmId; ///< IP renew alarm ID (valid if nonzero)
|
uint32_t renewAlarmId; ///< IP renew alarm ID (valid if nonzero)
|
||||||
uint32_t retryAlarmId; ///< DISCOVER retry alarm ID (valid if nonzero)
|
uint32_t retryAlarmId; ///< DISCOVER retry alarm ID (valid if nonzero)
|
||||||
|
bool enabled; ///< DHCP client is enabled
|
||||||
} DhcpState;
|
} DhcpState;
|
||||||
|
|
||||||
#define DHCP_RETRY_TIMEOUT_S (3)
|
#define DHCP_RETRY_TIMEOUT_S (3)
|
||||||
@ -83,4 +84,11 @@ void dhcp_start(DhcpState * s);
|
|||||||
*/
|
*/
|
||||||
void dhcp_stop(DhcpState * s);
|
void dhcp_stop(DhcpState * s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get DHCP FSM state.
|
||||||
|
* @param s pointer to DhcpState structure
|
||||||
|
* @return DHCP FSM state
|
||||||
|
*/
|
||||||
|
DhcpFSMState dhcp_get_fsm_state(const DhcpState * s);
|
||||||
|
|
||||||
#endif //ETHERLIB_DHCP_H
|
#endif //ETHERLIB_DHCP_H
|
||||||
|
3
timer.c
3
timer.c
@ -140,6 +140,9 @@ void timer_unsched(Timer *tmr, uint32_t id) {
|
|||||||
memset(alarm, 0, sizeof(AlarmAssignment));
|
memset(alarm, 0, sizeof(AlarmAssignment));
|
||||||
tmr->nSched--;
|
tmr->nSched--;
|
||||||
timer_update_nearest_alarm(tmr);
|
timer_update_nearest_alarm(tmr);
|
||||||
|
//MSG("Successful unsched of alarm #%x!\n", id);
|
||||||
|
} else {
|
||||||
|
//MSG("Could not unsched alarm #%x!\n", id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
44
utils.c
44
utils.c
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
static uint32_t crc32table[] = {/* CRC polynomial */
|
static uint32_t crc32table[] = {/* CRC polynomial */
|
||||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||||
@ -47,8 +49,7 @@ static uint32_t crc32table[] = { /* CRC polynomial */
|
|||||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
|
||||||
};
|
|
||||||
|
|
||||||
uint32_t crc32(const uint8_t *data, uint32_t size) {
|
uint32_t crc32(const uint8_t *data, uint32_t size) {
|
||||||
uint32_t checksum = ~0;
|
uint32_t checksum = ~0;
|
||||||
@ -81,3 +82,42 @@ uint16_t chksum(const uint8_t *data, uint32_t size, int swap) {
|
|||||||
uint16_t sum16 = sum ^ 0xFFFF;
|
uint16_t sum16 = sum ^ 0xFFFF;
|
||||||
return sum16;
|
return sum16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *trimleft(const char *str) {
|
||||||
|
while ((*str) <= ' ' && (*str != '\0')) {
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ATOIP_BUFLEN (20)
|
||||||
|
|
||||||
|
ip4_addr atoip(const char *str) {
|
||||||
|
// copy to internal buffer after trimming
|
||||||
|
char buffer[ATOIP_BUFLEN];
|
||||||
|
strncpy(buffer, trimleft(str), ATOIP_BUFLEN);
|
||||||
|
|
||||||
|
// separate the four fields
|
||||||
|
const char *parts[4];
|
||||||
|
parts[0] = buffer;
|
||||||
|
uint8_t partsFound = 1;
|
||||||
|
for (uint8_t i = 0; i < ATOIP_BUFLEN; i++) {
|
||||||
|
if (buffer[i] == '.') {
|
||||||
|
buffer[i] = '\0';
|
||||||
|
parts[partsFound++] = buffer + i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that all parts have been found
|
||||||
|
if (partsFound < 4) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert to binary representation
|
||||||
|
uint32_t nums[4];
|
||||||
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
|
nums[i] = atoi(parts[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return IPv4(nums[0], nums[1], nums[2], nums[3]);
|
||||||
|
}
|
||||||
|
16
utils.h
16
utils.h
@ -11,6 +11,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
|
#include "prefab/packet_parsers/ipv4_types.h"
|
||||||
|
|
||||||
#ifndef htonl
|
#ifndef htonl
|
||||||
#define htonl(a) \
|
#define htonl(a) \
|
||||||
((((a) >> 24) & 0x000000ff) | \
|
((((a) >> 24) & 0x000000ff) | \
|
||||||
@ -92,4 +94,18 @@ uint32_t crc32(const uint8_t * data, uint32_t size);
|
|||||||
*/
|
*/
|
||||||
uint16_t chksum(const uint8_t *data, uint32_t size, int swap);
|
uint16_t chksum(const uint8_t *data, uint32_t size, int swap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rip off whitespaces from the beginning of a string.
|
||||||
|
* @param str string to be trimmed
|
||||||
|
* @param pointer to the trimmed string
|
||||||
|
*/
|
||||||
|
const char *trimleft(const char *str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse string representation of an IPv4 address and convert to binary form.
|
||||||
|
* @param str string representation of an IPv4 address
|
||||||
|
* @return IPv4 address
|
||||||
|
*/
|
||||||
|
ip4_addr atoip(const char * str);
|
||||||
|
|
||||||
#endif //ETHERLIB_UTILS_H
|
#endif //ETHERLIB_UTILS_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user