#ifndef ETHERLIB_TCP_CONNBLOCK_H #define ETHERLIB_TCP_CONNBLOCK_H #define TCP_EXTRACT_FILTCOND(fc) uint16_t local_port = ((fc)->uw[4]); uint16_t remote_port = ((fc)->uw[5]); ip4_addr remote_addr = ((fc)->u[0]) #define TCP_LOCAL_PORT_TO_FILTCOND(fc, local_port) ((fc)->uw[4]) = (local_port) #define TCP_REMOTE_PORT_TO_FILTCOND(fc, remote_port) ((fc)->uw[5]) = (remote_port) #define TCP_REMOTE_ADDR_TO_FILTCOND(fc, remote_addr) ((fc)->u[0] = (remote_addr)) #include #include "../packet_parsers/ipv4_types.h" #include "../../connection_block.h" #include "../packet_parsers/tcp_segment.h" #include "../../cbd_table.h" #include "../conn_blocks/tcp/tcp_window.h" #include "../../blocking_fifo.h" #include struct EthInterface_; /** * TCP segment flags */ typedef enum { TCP_FLAG_FIN = 0x01, TCP_FLAG_SYN = 0x02, TCP_FLAG_RESET = 0x04, TCP_FLAG_PUSH = 0x08, TCP_FLAG_ACK = 0x10, TCP_FLAG_URGENT = 0x20, TCP_FLAG_ECNECHO = 0x40, TCP_FLAG_CWR = 0x80, TCP_FLAG_NONCE = 0x100 } TcpFlag; /** * TCP connection block states. */ typedef enum { TCP_STATE_CLOSED = 0, TCP_STATE_LISTEN, TCP_STATE_SYN_RCVD, TCP_STATE_SYN_SENT, TCP_STATE_ESTAB, TCP_STATE_FIN_WAIT_1, TCP_STATE_FIN_WAIT_2, TCP_STATE_CLOSE_WAIT, TCP_STATE_CLOSING, TCP_STATE_LAST_ACK, TCP_STATE_TIME_WAIT } TcpConnectionState; typedef int (*StreamCallBackFn)(cbd d); typedef int (*TcpAcceptCbFn)(cbd d); #define EVTFLAG_ESTAB (0x00000001) #define EVTFLAG_ALL_ACKED (0x00000002) /** * TCP state. */ typedef struct { uint16_t localPort; ///< Local port uint16_t remotePort; ///< Remote port this CB is bound to ip4_addr remoteAddr; ///< Remote IP-address this CB is bound to TcpConnectionState connState; ///< TCP connection state uint16_t localMSS; ///< Local Maximum Segment Size uint16_t remoteMSS; ///< Remote Maximum Segment Size // --------------- uint32_t txSeqNum; ///< Seq. num of next transmitted octet (TX) uint32_t rxAckNum; ///< Seq. num of the next EXPECTED octet (RX) (Ack. number sent to the remote side) uint16_t localWindow; ///< Maximum number of bytes we are willing (able) to accept uint16_t remoteWindow; ///< Maximum number of bytes the peer is willing (able) to accept TcpWindow *txWin; ///< Transmit window OBJECT uint32_t lastTxSeqNumAcked; ///< Last txSeqNum that has received an ACK (used for differentiation between ACK and Keep-Alive segment) // --------------- ConnBlock connBlock; ///< Connection block (copy) cbd d; ///< Connection block descriptor // --------------- bool8_t isServer; ///< this connection is a server connection TODO: nem a legjobb elnevezés // --------------- uint8_t retryLimit; ///< Maximum number of retransmission reties uint8_t retries; ///< Current attempts number uint8_t retryTO; ///< Retry timeout // --------------- bool8_t debug; ///< Turns on/off debug mode // --------------- StreamCallBackFn streamCb; ///< Callback invoked on stream actions TcpAcceptCbFn acceptCb; ///< Callback invoked on detecting an incoming connection // --------------- ETHLIB_OS_SEM_TYPE txBufNotFull; ///< Semaphore protecting the transmit window ETHLIB_OS_SEM_TYPE txInProgress; ///< Transmission is in progress, transmit thread is blocked // --------------- ETHLIB_OS_MTX_TYPE processMtx; ///< a mutex protecting TCP state changes (this is how we can manipulate the internal state without raising race conditions) // --------------- osEventFlagsId_t eventFlags; ///< Semaphore for synchronizing on getting into established state // --------------- EthBlockingFifo * rxFifo; ///< Receive FIFO } TcpState; #define TCP_FETCH_STATE_FROM_CONNBLOCK(connBlock) ((TcpState *) (connBlock)->sieveLayer->tag.p) #define TCP_FETCH_STATE_FROM_SIEVE_LAYER(layer) ((TcpState *) (layer)->tag.p) /** * Create new TCP connection block * @param intf associated Ethernet interface * @param ipAddr local IP-address * @param port local port * @param cbFn receive callback function * @return TCP connection block */ cbd tcp_new_connblock(struct EthInterface_ *intf, ip4_addr ipAddr, uint16_t port, StreamCallBackFn cbFn); /** * Bind TCP connection to remote socket. * @param d connection block descriptor * @param remoteAddr remote socket address * @param remotePort remote socket port */ void tcp_bind(cbd d, ip4_addr remoteAddr, uint16_t remotePort); /** * Make the TCP connection listening for incoming connections. * @param d connection block descriptor */ void tcp_listen(cbd d); /** * Set callback invoked on detecting an incoming connection on a listening conncetion. * @param d cbd of the listening connection * @param acb function pointer of the callback */ void tcp_set_accept_callback(cbd d, TcpAcceptCbFn acb); /** * Send data over an existing TCP connection. * @param d pointer to existing connblock * @param data pointer to data to send * @param size data size in bytes * @return number of bytes sent */ uint32_t tcp_send(unsigned char d, const uint8_t *data, uint32_t size); uint32_t tcp_recv(unsigned char d, uint8_t * data, uint32_t size); /** * Turn TCP debugging ON/OFF * @param d * @param debug */ void tcp_debug(cbd d, bool debug); /** * Print TCP connblock report. * @param connBlock TCP connblock */ void tcp_print_report(const ConnBlock *connBlock); //int tcp_send_segment(const struct ConnBlock_ *connBlock, TcpFlag flags, TcpOption * opts, const uint8_t *data, uint32_t size); #endif //ETHERLIB_TCP_CONNBLOCK_H