?? tcp_ip.c
字號(hào):
TCP_StateMachine = CLOSED;
TCP_Flags = 0;
TCP_SocketStatus = TCP_SOCK_ERR_CONN_RESET;
}
// drop segment
break;
}
// SYN??
if (TCPCode & TCP_CODE_SYN)
{
// get remote's ISN
TCP_Ack_Nr = TCPSegSeq;
// and increment by one...
TCP_Ack_Nr++;
if (TCPCode & TCP_CODE_ACK)
{
// stop retransmission, other TCP got our SYN
TCP_StopTimer();
// advance our sequence number
TCP_Seq_Nr = TCP_UNA_Seq_Nr;
// ACK this ISN
TCP_Prep_TCP_FRAME(TCP_CODE_ACK);
// user may send data now :-)
TCP_StateMachine = ESTABLISHED;
TCP_SocketStatus |= TCP_SOCK_CONNECTED;
TCP_SocketStatus |= TCP_SOCK_TX_BUF_RELEASED;
}
else
{
// our SYN isn't ACKed yet, now continue with sending
// SYN_ACK frames
TCP_StopTimer();
TCP_Prep_TCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK);
TCP_LastFrameSent = TCP_SYN_ACK_FRAME;
TCP_StartRetryTimer();
TCP_StateMachine = SYN_RECD;
}
}
break;
}
default :
{
// drop segment if IP doesn't belong to current session
if (memcmp(&TCP_RemoteIP, &TCP_Recd_Frame_IP, 4)) break;
// drop segment if port doesn't match
if (TCPSegSourcePort != TCP_RemotePort) break;
// drop if it's not the segment we expect
if (TCPSegSeq != TCP_Ack_Nr) break;
// RST??
if (TCPCode & TCP_CODE_RST)
{
// close the state machine
// reset all flags, stop retransmission
// indicate an error to user
TCP_StateMachine = CLOSED;
TCP_Flags = 0;
TCP_SocketStatus = TCP_SOCK_ERR_CONN_RESET;
break;
}
// SYN??
if (TCPCode & TCP_CODE_SYN)
{
// is NOT allowed here! send a reset,
TCP_Prep_TCP_FRAME(TCP_CODE_RST);
// close connection...
// reset all flags, stop retransmission...
// fatal error!
// ...and drop the frame
TCP_StateMachine = CLOSED;
TCP_Flags = 0;
TCP_SocketStatus = TCP_SOCK_ERR_REMOTE;
break;
}
// drop segment if the ACK bit is off
if (!(TCPCode & TCP_CODE_ACK)) break;
// is our last data sent ACKed?
if (TCPSegAck == TCP_UNA_Seq_Nr)
{
// stop retransmission
TCP_StopTimer();
// advance our sequence number
TCP_Seq_Nr = TCP_UNA_Seq_Nr;
// change state if necessary
switch (TCP_StateMachine)
{
// ACK of our SYN?
case SYN_RECD :
{
// user may send data now
TCP_StateMachine = ESTABLISHED;
TCP_SocketStatus |= TCP_SOCK_CONNECTED;
break;
}
// ACK of our FIN?
case FIN_WAIT_1 :
{
TCP_StateMachine = FIN_WAIT_2;
break;
}
// ACK of our FIN?
case CLOSING :
{
TCP_StateMachine = TIME_WAIT;
break;
}
// ACK of our FIN?
case LAST_ACK :
{
// reset all flags, stop retransmission...
// clear all flags but data available
TCP_StateMachine = CLOSED;
TCP_Flags = 0;
TCP_SocketStatus &= TCP_SOCK_DATA_AVAILABLE;
break;
}
case TIME_WAIT :
{
// ACK a retransmission of remote FIN
// restart TIME_WAIT timeout
TCP_Prep_TCP_FRAME(TCP_CODE_ACK);
TCP_RestartTimer();
break;
}
}
// if true, give the frame buffer back to user
if (TCP_StateMachine == ESTABLISHED)
TCP_SocketStatus |= TCP_SOCK_TX_BUF_RELEASED;
}
if ((TCP_StateMachine == ESTABLISHED) || (TCP_StateMachine == FIN_WAIT_1) || (TCP_StateMachine == FIN_WAIT_2))
// data available?
if (NrOfDataBytes)
// rx data-buffer empty?
if (!(TCP_SocketStatus & TCP_SOCK_DATA_AVAILABLE))
{
// ignore window, checksum, urgent pointer
data +=3;
// fetch data and tell the user
// indicate the new data to user
memcpy(&TCP_RxTCPBuffer, data, NrOfDataBytes);
TCP_Rx_Data_Count = NrOfDataBytes;
TCP_SocketStatus |= TCP_SOCK_DATA_AVAILABLE;
TCP_Ack_Nr += NrOfDataBytes;
// ACK rec'd data
TCP_Prep_TCP_FRAME(TCP_CODE_ACK);
}
// FIN??
if (TCPCode & TCP_CODE_FIN)
{
switch (TCP_StateMachine)
{
case SYN_RECD :
case ESTABLISHED :
{
TCP_StateMachine = CLOSE_WAIT;
break;
}
// if our FIN was ACKed, we automatically
// enter FIN_WAIT_2 (look above) and therefore
// TIME_WAIT
case FIN_WAIT_1 :
{
TCP_StateMachine = CLOSING;
TCP_SocketStatus &= ~TCP_SOCK_CONNECTED;
break;
}
case FIN_WAIT_2 :
{
TCP_StartTimeWaitTimer();
TCP_StateMachine = TIME_WAIT;
TCP_SocketStatus &= ~TCP_SOCK_CONNECTED;
break;
}
case TIME_WAIT :
{
TCP_RestartTimer();
break;
}
}
// ACK remote's FIN flag
TCP_Ack_Nr++;
TCP_Prep_TCP_FRAME(TCP_CODE_ACK);
}
}
}
}
/******************************************************************************
* TCP_IP_STACK: TCP_Prep_ARP_REQUEST()
*
* Purpose:
* prepares the TxFrame2-buffer to send an ARP-request
*
* Actions:
*
*****************************************************************************/
MC void TCP_Prep_ARP_REQUEST(void)
{
// Ethernet
// we don't know opposites MAC!
memset(&TCP_TxFrame2[ETH_DA_OFS], 0xFF, 6);
memcpy(&TCP_TxFrame2[ETH_SA_OFS], &TCP_MyMAC, 6);
*(WORD*)&TCP_TxFrame2[ETH_TYPE_OFS] = FRAME_ARP;
// ARP
*(WORD *)&TCP_TxFrame2[ARP_HARDW_OFS] = HARDW_ETH10;
*(WORD *)&TCP_TxFrame2[ARP_PROT_OFS] = FRAME_IP;
*(WORD *)&TCP_TxFrame2[ARP_HLEN_PLEN_OFS] = IP_HLEN_PLEN;
*(WORD *)&TCP_TxFrame2[ARP_OPCODE_OFS] = OP_ARP_REQUEST;
memcpy( &TCP_TxFrame2[ARP_SENDER_HA_OFS], &TCP_MyMAC, 6);
memcpy( &TCP_TxFrame2[ARP_SENDER_IP_OFS], &TCP_Local_IP, 4);
// we don't know remote's MAC!
memset( &TCP_TxFrame2[ARP_TARGET_HA_OFS], 0x00, 6);
if (((TCP_RemoteIP[0] ^ TCP_Local_IP[0]) & TCP_SubnetMask[0]) || ((TCP_RemoteIP[1] ^ TCP_Local_IP[1]) & TCP_SubnetMask[1]))
// IP not in subnet, use gateway
memcpy(&TCP_TxFrame2[ARP_TARGET_IP_OFS], &TCP_GatewayIP, 4);
else
// other IP is next to us...
memcpy(&TCP_TxFrame2[ARP_TARGET_IP_OFS], &TCP_RemoteIP, 4);
TCP_TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
TCP_TransmitControl |= TCP_SEND_FRAME2;
}
/******************************************************************************
* TCP_IP_STACK: TCP_Prep_ARP_ANSWER()
*
* Purpose:
* prepares the TxFrame2-buffer to send an ARP-answer (reply)
*
* Actions:
*
*****************************************************************************/
MC void TCP_Prep_ARP_ANSWER(void)
{
// Ethernet
memcpy( &TCP_TxFrame2[ETH_DA_OFS], &TCP_Recd_Frame_MAC, 6);
memcpy( &TCP_TxFrame2[ETH_SA_OFS], &TCP_MyMAC, 6);
*(WORD*)&TCP_TxFrame2[ETH_TYPE_OFS] = FRAME_ARP;
// ARP
*(WORD*)&TCP_TxFrame2[ARP_HARDW_OFS] = HARDW_ETH10;
*(WORD*)&TCP_TxFrame2[ARP_PROT_OFS] = FRAME_IP;
*(WORD*)&TCP_TxFrame2[ARP_HLEN_PLEN_OFS] = IP_HLEN_PLEN;
*(WORD*)&TCP_TxFrame2[ARP_OPCODE_OFS] = OP_ARP_ANSWER;
memcpy( &TCP_TxFrame2[ARP_SENDER_HA_OFS], &TCP_MyMAC, 6);
memcpy( &TCP_TxFrame2[ARP_SENDER_IP_OFS], &TCP_Local_IP, 4);
memcpy( &TCP_TxFrame2[ARP_TARGET_HA_OFS], &TCP_Recd_Frame_MAC, 6);
memcpy( &TCP_TxFrame2[ARP_TARGET_IP_OFS], &TCP_Recd_Frame_IP, 4);
TCP_TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
TCP_TransmitControl |= TCP_SEND_FRAME2;
}
/******************************************************************************
* TCP_IP_STACK: TCP_Prep_ICMP_ECHO_REPLY()
*
* Purpose:
* prepares the TxFrame2-buffer to send an ICMP-echo-reply
*
* Actions:
*
*****************************************************************************/
MC void TCP_Prep_ICMP_ECHO_REPLY(void)
{
WORD ICMPDataCount;
BYTE *bicmp = (BYTE*) LAN_rx_packet.data;
bicmp += ICMP_DATA_OFS;
// don't overload TX-buffer
if (TCP_Recd_IP_Frame_Length > MAX_ETH_TX_SIZE)
ICMPDataCount = MAX_ETH_TX_SIZE - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
else
ICMPDataCount = TCP_Recd_IP_Frame_Length - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
// Ethernet
memcpy( &TCP_TxFrame2[ETH_DA_OFS], &TCP_Recd_Frame_MAC, 6);
memcpy( &TCP_TxFrame2[ETH_SA_OFS], &TCP_MyMAC, 6);
*(WORD*)&TCP_TxFrame2[ETH_TYPE_OFS] = FRAME_IP;
// IP
*(WORD*)&TCP_TxFrame2[IP_VER_IHL_TOS_OFS] = swap_bytes(IP_VER_IHL);
*(WORD*)&TCP_TxFrame2[IP_TOTAL_LENGTH_OFS] = swap_bytes(IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount);
*(WORD*)&TCP_TxFrame2[IP_IDENT_OFS] = 0;
*(WORD*)&TCP_TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
*(WORD*)&TCP_TxFrame2[IP_TTL_PROT_OFS] = swap_bytes((DEFAULT_TTL << 8) | PROT_ICMP);
*(WORD*)&TCP_TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
memcpy( &TCP_TxFrame2[IP_SOURCE_OFS], &TCP_Local_IP, 4);
memcpy( &TCP_TxFrame2[IP_DESTINATION_OFS], &TCP_Recd_Frame_IP, 4);
*(WORD*)&TCP_TxFrame2[IP_HEAD_CHKSUM_OFS] = TCP_CalcChecksum(&TCP_TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
// ICMP
*(WORD*)&TCP_TxFrame2[ICMP_TYPE_CODE_OFS] = swap_bytes(ICMP_ECHO_REPLY << 8);
// initialize checksum field
*(WORD*)&TCP_TxFrame2[ICMP_CHKSUM_OFS] = 0;
// get data to echo...
memcpy( &TCP_TxFrame2[ICMP_DATA_OFS], bicmp, ICMPDataCount);
// compute checksum
*(WORD*)&TCP_TxFrame2[ICMP_CHKSUM_OFS] = TCP_CalcChecksum(&TCP_TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0);
TCP_TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount;
TCP_TransmitControl |= TCP_SEND_FRAME2;
}
/******************************************************************************
* TCP_IP_STACK: TCP_Prep_TCP_FRAME()
*
* Purpose:
* prepares the TxFrame2-buffer to send a general TCP frame
* the TCPCode-field is passed as an argument
*
* Actions:
*
*****************************************************************************/
MC void TCP_Prep_TCP_FRAME(WORD TCPCode)
{
// Ethernet
memcpy( &TCP_TxFrame2[ETH_DA_OFS], &TCP_RemoteMAC, 6);
memcpy( &TCP_TxFrame2[ETH_SA_OFS], &TCP_MyMAC, 6);
*(WORD*)&TCP_TxFrame2[ETH_TYPE_OFS] = FRAME_IP;
// IP
*(WORD*)&TCP_TxFrame2[IP_VER_IHL_TOS_OFS] = swap_bytes(IP_VER_IHL | IP_TOS_D);
// if SYN, we want to use the MSS option
if (TCPCode & TCP_CODE_SYN)
*(WORD*)&TCP_TxFrame2[IP_TOTAL_LENGTH_OFS] = swap_bytes(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE);
else
*(WORD*)&TCP_TxFrame2[IP_TOTAL_LENGTH_OFS] = swap_bytes(IP_HEADER_SIZE + TCP_HEADER_SIZE);
*(WORD*)&TCP_TxFrame2[IP_IDENT_OFS] = 0;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -