分析TCP/IP協議棧程式碼之TCP(STM32平臺) .
阿新 • • 發佈:2019-02-04
// do some basic length calculations and store the result in static varibales
void init_len_info(unsigned char *buf)
{
//IP Packet長度
info_data_len = (buf[IP_TOTLEN_H_P] << 8) | (buf[IP_TOTLEN_L_P] & 0xff);
//減去IP首部長度
info_data_len -= IP_HEADER_LEN;
//TCP首部長度,因為TCP協議規定了只有四位來表明長度,所需要如下處理,4*6=24
info_hdr_len = (buf[TCP_HEADER_LEN_P] >> 4) * 4; // generate len in bytes;
//減去TCP首部長度
info_data_len -= info_hdr_len;
if(info_data_len <= 0)
{
info_data_len = 0;
}
}
// get a pointer to the start of tcp data in buf
// Returns 0 if there is no data
// You must call init_len_info once before calling this function
unsigned int get_tcp_data_pointer(void)
{
if(info_data_len)
{
//在buf中資料開始的位置
return((unsigned int)TCP_SRC_PORT_H_P + info_hdr_len);
}
else
{
return(0);
}
}
// fill in tcp data at position pos. pos=0 means start of
// tcp data. Returns the position at which the string after
// this string could be filled.
unsigned int fill_tcp_data_p(unsigned char *buf, unsigned int pos, const unsigned char *progmem_s)
{
char c;
// fill in tcp data at position pos
//
// with no options the data starts after the checksum + 2 more bytes (urgent ptr)
while((c = pgm_read_byte(progmem_s++)))
{
buf[TCP_CHECKSUM_L_P + 3 + pos] = c;
pos++;
}
return(pos);
}
// fill in tcp data at position pos. pos=0 means start of
// tcp data. Returns the position at which the string after
// this string could be filled.
unsigned int fill_tcp_data(unsigned char *buf, unsigned int pos, const char *s)
{
// fill in tcp data at position pos
//
// with no options the data starts after the checksum + 2 more bytes (urgent ptr)
while(*s)
{
buf[TCP_CHECKSUM_L_P + 3 + pos] = *s;
pos++;
s++;
}
return(pos);
}
// Make just an ack packet with no tcp data inside
// This will modify the eth/ip/tcp header
void make_tcp_ack_from_any(unsigned char *buf)
{
unsigned int j;
make_eth(buf);
// fill the header:
buf[TCP_FLAGS_P] = TCP_FLAGS_ACK_V;
if(info_data_len == 0)
{
// if there is no data then we must still acknoledge one packet
make_tcphead(buf, 1, 0, 1); // no options
}
else
{
make_tcphead(buf, info_data_len, 0, 1); // no options
}
// total length field in the IP header must be set:
// 20 bytes IP + 20 bytes tcp (when no options)
j = IP_HEADER_LEN + TCP_HEADER_LEN_PLAIN;
buf[IP_TOTLEN_H_P] = j >> 8;
buf[IP_TOTLEN_L_P] = j & 0xff;
make_ip(buf);
// calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + data len
j = checksum(&buf[IP_SRC_P], 8 + TCP_HEADER_LEN_PLAIN, 2);
buf[TCP_CHECKSUM_H_P] = j >> 8;
buf[TCP_CHECKSUM_L_P] = j & 0xff;
enc28j60PacketSend(IP_HEADER_LEN + TCP_HEADER_LEN_PLAIN + ETH_HEADER_LEN, buf);
}
// you must have called init_len_info at some time before calling this function
// dlen is the amount of tcp data (http data) we send in this packet
// You can use this function only immediately after make_tcp_ack_from_any
// This is because this function will NOT modify the eth/ip/tcp header except for
// length and checksum
void make_tcp_ack_with_data(unsigned char *buf, unsigned int dlen)
{
unsigned int j;
// fill the header:
// This code requires that we send only one data packet
// because we keep no state information. We must therefore set
// the fin here:
buf[TCP_FLAGS_P] = TCP_FLAGS_ACK_V | TCP_FLAGS_PUSH_V | TCP_FLAGS_FIN_V;
// total length field in the IP header must be set:
// 20 bytes IP + 20 bytes tcp (when no options) + len of data
j = IP_HEADER_LEN + TCP_HEADER_LEN_PLAIN + dlen;
buf[IP_TOTLEN_H_P] = j >> 8;
buf[IP_TOTLEN_L_P] = j & 0xff;
fill_ip_hdr_checksum(buf);
// zero the checksum
buf[TCP_CHECKSUM_H_P] = 0;
buf[TCP_CHECKSUM_L_P] = 0;
// calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + data len
j = checksum(&buf[IP_SRC_P], 8 + TCP_HEADER_LEN_PLAIN + dlen, 2);
buf[TCP_CHECKSUM_H_P] = j >> 8;
buf[TCP_CHECKSUM_L_P] = j & 0xff;
enc28j60PacketSend(IP_HEADER_LEN + TCP_HEADER_LEN_PLAIN + dlen + ETH_HEADER_LEN, buf);
}
void init_len_info(unsigned char *buf)
{
//IP Packet長度
info_data_len = (buf[IP_TOTLEN_H_P] << 8) | (buf[IP_TOTLEN_L_P] & 0xff);
//減去IP首部長度
info_data_len -= IP_HEADER_LEN;
//TCP首部長度,因為TCP協議規定了只有四位來表明長度,所需要如下處理,4*6=24
//減去TCP首部長度
info_data_len -= info_hdr_len;
if(info_data_len <= 0)
{
info_data_len = 0;
}
}
// get a pointer to the start of tcp data in buf
// Returns 0 if there is no data
// You must call init_len_info once before calling this function
{
if(info_data_len)
{
//在buf中資料開始的位置
return((unsigned int)TCP_SRC_PORT_H_P + info_hdr_len);
}
else
{
return(0);
}
}
// fill in tcp data at position pos. pos=0 means start of
// tcp data. Returns the position at which the string after
// this string could be filled.
{
char c;
// fill in tcp data at position pos
//
// with no options the data starts after the checksum + 2 more bytes (urgent ptr)
while((c = pgm_read_byte(progmem_s++)))
{
buf[TCP_CHECKSUM_L_P + 3 + pos] = c;
pos++;
}
return(pos);
}
// fill in tcp data at position pos. pos=0 means start of
// tcp data. Returns the position at which the string after
// this string could be filled.
unsigned int fill_tcp_data(unsigned char *buf, unsigned int pos, const char *s)
{
// fill in tcp data at position pos
//
// with no options the data starts after the checksum + 2 more bytes (urgent ptr)
while(*s)
{
buf[TCP_CHECKSUM_L_P + 3 + pos] = *s;
pos++;
s++;
}
return(pos);
}
// Make just an ack packet with no tcp data inside
// This will modify the eth/ip/tcp header
void make_tcp_ack_from_any(unsigned char *buf)
{
unsigned int j;
make_eth(buf);
// fill the header:
buf[TCP_FLAGS_P] = TCP_FLAGS_ACK_V;
if(info_data_len == 0)
{
// if there is no data then we must still acknoledge one packet
make_tcphead(buf, 1, 0, 1); // no options
}
else
{
make_tcphead(buf, info_data_len, 0, 1); // no options
}
// total length field in the IP header must be set:
// 20 bytes IP + 20 bytes tcp (when no options)
j = IP_HEADER_LEN + TCP_HEADER_LEN_PLAIN;
buf[IP_TOTLEN_H_P] = j >> 8;
buf[IP_TOTLEN_L_P] = j & 0xff;
make_ip(buf);
// calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + data len
j = checksum(&buf[IP_SRC_P], 8 + TCP_HEADER_LEN_PLAIN, 2);
buf[TCP_CHECKSUM_H_P] = j >> 8;
buf[TCP_CHECKSUM_L_P] = j & 0xff;
enc28j60PacketSend(IP_HEADER_LEN + TCP_HEADER_LEN_PLAIN + ETH_HEADER_LEN, buf);
}
// you must have called init_len_info at some time before calling this function
// dlen is the amount of tcp data (http data) we send in this packet
// You can use this function only immediately after make_tcp_ack_from_any
// This is because this function will NOT modify the eth/ip/tcp header except for
// length and checksum
void make_tcp_ack_with_data(unsigned char *buf, unsigned int dlen)
{
unsigned int j;
// fill the header:
// This code requires that we send only one data packet
// because we keep no state information. We must therefore set
// the fin here:
buf[TCP_FLAGS_P] = TCP_FLAGS_ACK_V | TCP_FLAGS_PUSH_V | TCP_FLAGS_FIN_V;
// total length field in the IP header must be set:
// 20 bytes IP + 20 bytes tcp (when no options) + len of data
j = IP_HEADER_LEN + TCP_HEADER_LEN_PLAIN + dlen;
buf[IP_TOTLEN_H_P] = j >> 8;
buf[IP_TOTLEN_L_P] = j & 0xff;
fill_ip_hdr_checksum(buf);
// zero the checksum
buf[TCP_CHECKSUM_H_P] = 0;
buf[TCP_CHECKSUM_L_P] = 0;
// calculate the checksum, len=8 (start from ip.src) + TCP_HEADER_LEN_PLAIN + data len
j = checksum(&buf[IP_SRC_P], 8 + TCP_HEADER_LEN_PLAIN + dlen, 2);
buf[TCP_CHECKSUM_H_P] = j >> 8;
buf[TCP_CHECKSUM_L_P] = j & 0xff;
enc28j60PacketSend(IP_HEADER_LEN + TCP_HEADER_LEN_PLAIN + dlen + ETH_HEADER_LEN, buf);
}