📄 tcp.c
字号:
//-----------------------------------------------------------------------------
// TCP
//-----------------------------------------------------------------------------
#include <string.h>
#include "tcpip_stack.h"
#include "ip.h"
#include "tcp.h"
#include "http.h"
//-----------------------------------------------------------------------------
// TCP stack part internal variables
//-----------------------------------------------------------------------------
static TCB tcp_table[TCP_MAX_CONNECTIONS]; //TCP control block array
static u8 TCB_used; //number of TCBs in use
static u8 TCB_current; //TCB in use
static u16 num_received = 0;
//-----------------------------------------------------------------------------
//Name:Tcp_Sum()
//Funcionality: Calculates the TCP header checksum
//-----------------------------------------------------------------------------
u16 Tcp_Sum(u16 len_tcp, u8 src_addr[],u8 dest_addr[], u8 buff[])
{
u16 prot_tcp=6;
u16 padd=0;
u16 word16;
u32 sum;
int i;
if (len_tcp%2){
padd=1;
buff[len_tcp]=0;
}
sum=0;
for (i=0;i<len_tcp+padd;i=i+2){
word16 =((buff[i]<<8)&0xFF00)+(buff[i+1]&0xFF);
if (i!=16) sum = sum + (u32)word16;
}
for (i=0;i<4;i=i+2){
word16 =((src_addr[i]<<8)&0xFF00)+(src_addr[i+1]&0xFF);
sum= sum + (u32)word16;
}
for (i=0;i<4;i=i+2){
word16 =((dest_addr[i]<<8)&0xFF00)+(dest_addr[i+1]&0xFF);
sum=sum+ (u32) word16;
}
sum = sum + prot_tcp + len_tcp;
while (sum>>16)
sum = (sum & 0xFFFF)+(sum >> 16);
sum = ~sum;
sum = ((sum >> 8) & 0x00FF) + ((sum << 8) & 0xFF00);
return ((u16) sum);
}
//-----------------------------------------------------------------------------
//Name:Tcp_Ip_Init()
//Funcionality: Initialization of the TCB array, performaed at the application start-up
//for proper structure content definition
//-----------------------------------------------------------------------------
void Tcp_Ip_Init()
{
int i;
TCB_used = 0; //number of TCBs in use
for (i = 0; i < TCP_MAX_CONNECTIONS; i++)
{
tcp_table[i].src_port = 0;
tcp_table[i].dest_port = 0;
tcp_table[i].dest_ip[0] = 0;
tcp_table[i].dest_ip[1] = 0;
tcp_table[i].dest_ip[2] = 0;
tcp_table[i].dest_ip[3] = 0;
tcp_table[i].state = LISTEN;
tcp_table[i].src_seq = 0;
tcp_table[i].dest_seq = 0;
}
}
//-----------------------------------------------------------------------------
//Name:ClearTCB()
//Funcionality: used to free the TCB when a tcp connection was closed
//-----------------------------------------------------------------------------
void ClearTCB(u8 num_TCB)
{
tcp_table[num_TCB].src_port = 0;
tcp_table[num_TCB].dest_port = 0;
tcp_table[num_TCB].dest_ip[0] = 0;
tcp_table[num_TCB].dest_ip[1] = 0;
tcp_table[num_TCB].dest_ip[2] = 0;
tcp_table[num_TCB].dest_ip[3] = 0;
tcp_table[num_TCB].state = LISTEN;
tcp_table[num_TCB].src_seq = 0;
tcp_table[num_TCB].dest_seq = 0;
}
//-----------------------------------------------------------------------------
//Name:Rx_TCP_Frame()
//Funcionality: Analyses the received frame, checks whether a TCB exists. If yes
// then keeps the control settings of the TCB. If no, creates new TCB if possible.
// Returns the TCB array index.
//-----------------------------------------------------------------------------
u8 Rx_TCP_Frame(EthernetFrame *frame)
{
tcp_hdr *rx_tcp_hdr = (tcp_hdr *)((u8 *)frame + ETHER_HEADER_LENGTH + IP_HEADER_LENGTH);
ip_hdr *rx_ip_hdr = (ip_hdr *)((u8 *)frame + ETHER_HEADER_LENGTH);
TCB_current = TCP_MAX_CONNECTIONS; //default, means no TCB array member is free
u8 i;
//check the ports to find the right TCB
for(i=0; i < TCP_MAX_CONNECTIONS; i++){
if ((tcp_table[i].dest_ip[0] == rx_ip_hdr->srcIP[0]) &&
(tcp_table[i].dest_ip[1] == rx_ip_hdr->srcIP[1]) &&
(tcp_table[i].dest_ip[2] == rx_ip_hdr->srcIP[2]) &&
(tcp_table[i].dest_ip[3] == rx_ip_hdr->srcIP[3]) &&
tcp_table[i].dest_port == rx_tcp_hdr->src_port &&
tcp_table[i].src_port == rx_tcp_hdr->dst_port) {
num_received = 0;
num_received = rx_ip_hdr->length;
ChangeEndianess_16(num_received);
num_received -= ((4*((rx_tcp_hdr->data_off)>>4)) + sizeof(ip_hdr));
TCB_current = i;
}
}
if ((TCB_current == TCP_MAX_CONNECTIONS) && (TCB_used < TCP_MAX_CONNECTIONS)){ //not yet in the table and there is free space -> new one
for(i=0; i < TCP_MAX_CONNECTIONS; i++){
if (tcp_table[i].state == LISTEN){ //-> make new record
TCB_current = i;
tcp_table[TCB_current].src_port = rx_tcp_hdr->dst_port;
tcp_table[TCB_current].dest_port = rx_tcp_hdr->src_port;
memcpy(tcp_table[TCB_current].dest_ip, rx_ip_hdr->srcIP,IP_ADDR_LEN);
tcp_table[TCB_current].src_seq = TCP_START_SEQ;
memcpy(&(tcp_table[TCB_current].dest_seq), &(rx_tcp_hdr->seq),4);
ChangeEndianess_32(tcp_table[TCB_current].dest_seq);
TCB_used++;
break;
}
}
}
else if (TCB_used == TCP_MAX_CONNECTIONS) { //no free space, we have to RST connection
return TCP_MAX_CONNECTIONS;
}
return TCB_current;
}
//-----------------------------------------------------------------------------
//Name:Tx_TCP_Frame()
//Funcionality: enters a valid TCP header values, calculates a checksum and
// calls the IP stack part.
//-----------------------------------------------------------------------------
void Tx_TCP_Frame(EthernetFrame *frame, u8 control_bits, u8 *szData, u16 nLength)
{
tcp_hdr *tx_tcp_hdr = (tcp_hdr*)((u8 *)frame + IP_HEADER_LENGTH + ETHER_HEADER_LENGTH);
u8 *tcp_data = (u8 *)((u8*)frame + ETHER_HEADER_LENGTH + IP_HEADER_LENGTH + TCP_HEADER_LENGTH);
u8 *chksum_hdr = (u8*)tx_tcp_hdr;
u32 temp_seq;
u32 temp_ack;
//fill the data to be sent
memcpy(tcp_data, szData, nLength);
//fill the TCP header
tx_tcp_hdr->src_port = tcp_table[TCB_current].src_port;
tx_tcp_hdr->dst_port = tcp_table[TCB_current].dest_port;
tx_tcp_hdr->control = control_bits;
temp_ack = tcp_table[TCB_current].src_seq;
temp_seq = tcp_table[TCB_current].dest_seq + num_received;
ChangeEndianess_32(temp_ack);
ChangeEndianess_32(temp_seq);
memcpy(&(tx_tcp_hdr->seq),&temp_ack,4);
memcpy(&(tx_tcp_hdr->ack),&temp_seq,4);
tx_tcp_hdr->data_off = 0x70; //no fragmentation
tx_tcp_hdr->window = 0xf460; //should be counted, here const value
//compute the checksum
tx_tcp_hdr->checksum = Tcp_Sum(TCP_HEADER_LENGTH + nLength, srcIP, destIP, chksum_hdr);
Tx_Ip_Frame(frame, nLength + TCP_HEADER_LENGTH, IP_TCP);
//update the seq and ack fields
tcp_table[TCB_current].dest_seq += num_received;
tcp_table[TCB_current].src_seq += nLength;
}
//-----------------------------------------------------------------------------
//Name:Receive_TCP()
//Funcionality: Used as an entry point to the TCP stack part. Analyses TCP header
//and includes the TCP state machine (limited version, not all features involved)
//-----------------------------------------------------------------------------
void Receive_TCP(EthernetFrame *frame){
tcp_hdr *rx_tcp_hdr = (tcp_hdr *)((u8 *)frame + ETHER_HEADER_LENGTH + IP_HEADER_LENGTH);
u32 temp_seq;
u32 temp_ack;
TCB_current = Rx_TCP_Frame(frame); //if ok -> returns index of the communication channel
if (TCB_current == TCP_MAX_CONNECTIONS) return; //no free TCB
//Store the seq and ack numbers of the current frame for comparing with TCB values
memcpy(&temp_seq, &rx_tcp_hdr->seq, 4);
memcpy(&temp_ack, &rx_tcp_hdr->ack, 4);
ChangeEndianess_32(temp_seq);
ChangeEndianess_32(temp_ack);
switch (tcp_table[TCB_current].state)
{
case LISTEN:
//Passive Open
if (rx_tcp_hdr->control & TCP_SYN)
{
tcp_table[TCB_current].state = SYN_RECVD;
tcp_table[TCB_current].dest_seq += 0x1;
Tx_TCP_Frame(frame, TCP_ACK | TCP_SYN, 0, 0);
}
break;
case SYN_SENT:
{ //Active Open
}
break;
case SYN_RECVD:
{
if (rx_tcp_hdr->control & TCP_ACK)
{
// received ACK, enter ESTABLISHED
if ((temp_seq) == (tcp_table[TCB_current].dest_seq) &&
(temp_ack) == (tcp_table[TCB_current].src_seq+1)){ //check seq and ack numbers
tcp_table[TCB_current].src_seq++;
tcp_table[TCB_current].state = ESTABLISHED;
}
}
}
break;
case ESTABLISHED:
{
if (!(~(rx_tcp_hdr->control ^ (~(TCP_ACK | TCP_PSH)))))
switch (rx_tcp_hdr->dst_port) {
case 0x5000:{ //http port
Receive_HTTP(frame);
}
break;
}
if (!(~(rx_tcp_hdr->control ^ (~TCP_ACK)))){ //dostanu acknowledge, ze paket s http byl hostem prijat v poradku
Tx_TCP_Frame(frame, TCP_ACK | TCP_FIN , 0, 0);
tcp_table[TCB_current].state = CLOSE_WAIT;
}
}
break;
case CLOSE_WAIT:{
if (!(~(rx_tcp_hdr->control ^ (~TCP_ACK)))){
}
if (!(~(rx_tcp_hdr->control ^ (~(TCP_ACK | TCP_FIN))))){
}
memcpy(&(tcp_table[TCB_current].src_seq),&(rx_tcp_hdr->ack),4);
ChangeEndianess_32(tcp_table[TCB_current].src_seq);
tcp_table[TCB_current].dest_seq++;
Tx_TCP_Frame(frame, TCP_ACK, 0, 0);
ClearTCB(TCB_current); // free the used TCB
TCB_used --;
}
break;
case FIN_WAIT_1:
break;
case FIN_WAIT_2:
break;
case CLOSING:
break;
case LAST_ACK:
break;
case CLOSED:
break;
case TIME_WAIT:
break;
}
}
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -