?? tcp_ip.c
字號:
//##############################################################
//#
//# TCP_IP.C
//#
//# ADSP-21535 Embedded Web Server Project
//#
//# (c) ANALOG DEVICES 2002
//# eDSP Division
//# Stefan Hacker
//# 28-DEC-2002
//#
//# framework by Andreas Dannenberg (adannenb@et.htwk-leipzig.de)
//#
//# History:
//# 28-DEC-2002 initial document
//# 03-JAN-2003 ping works properly
//# 31-MAR-2003 fixed FIN bug for OPERA
//# 16-APR-2003 HS release 1.0
//#
#include "tcp_ip.h"
#include "globals.h"
#include "defBF533.h"
#include "string.h"
#include "ez_lan_types.h"
#define MC section("L1_code")
/******************************************************************************
* TCP_IP_STACK: TCP_init()
*
* Purpose:
* initializes the TCP State Machine
*
* Actions:
* - set State to CLOSED
* - set Socket Status
* - set Transmit Control
* - set TCP_Flags
*
*****************************************************************************/
MC void TCP_init()
{
TCP_StateMachine = CLOSED;
TCP_TransmitControl = 0;
TCP_Flags = 0;
TCP_SocketStatus = 0;
}
/******************************************************************************
* TCP_IP_STACK: TCP_PassiveOpen()
*
* Purpose:
* starts listening for an incoming connection if previously closed
*
* Actions:
*
*****************************************************************************/
MC void TCP_PassiveOpen(void)
{
if (TCP_StateMachine == CLOSED)
{
// let's do a passive open
TCP_Flags &= ~TCP_ACTIVE_OPEN;
TCP_StateMachine = LISTENING;
// reset, socket now active
TCP_SocketStatus = TCP_SOCK_ACTIVE;
}
}
/******************************************************************************
* TCP_IP_STACK: TCP_ActiveOpen()
*
* Purpose:
* does an active open = tries to establish a connection between
* 'Local_IP:TCP_LocalPort' and 'TCP_RemoteIP:TCP_RemotePort'
*
* Actions:
*
*****************************************************************************/
MC void TCP_ActiveOpen()
{
if ((TCP_StateMachine == CLOSED) || (TCP_StateMachine == LISTENING))
{
// let's do an active open
TCP_Flags |= TCP_ACTIVE_OPEN;
// we haven't Remote MAC yet
TCP_Flags &= ~TCP_IP_ADDR_RESOLVED;
// ask for MAC by sending a broadcast
TCP_Prep_ARP_REQUEST();
TCP_LastFrameSent = ARP_REQUEST;
TCP_StartRetryTimer();
// reset, socket now active
TCP_SocketStatus = TCP_SOCK_ACTIVE;
}
}
/******************************************************************************
* TCP_IP_STACK: TCP_Close()
*
* Purpose:
* closes an open connection
*
* Actions:
*
*****************************************************************************/
MC void TCP_Close()
{
switch (TCP_StateMachine)
{
case LISTENING :
case SYN_SENT :
{
// no connection, we can close right now
TCP_StateMachine = CLOSED;
TCP_Flags = 0;
TCP_SocketStatus = 0;
break;
}
case SYN_RECD :
case ESTABLISHED :
{
// request closing of stack
TCP_Flags |= TCP_CLOSE_REQUESTED;
break;
}
}
}
/******************************************************************************
* TCP_IP_STACK: TCP_ReleaseRxBuffer()
*
* Purpose:
* releases the receive-buffer and allow to store new data
*
* Actions:
*
*****************************************************************************/
MC void TCP_ReleaseRxBuffer()
{
// flag buffer available
TCP_SocketStatus &= ~TCP_SOCK_DATA_AVAILABLE;
}
/******************************************************************************
* TCP_IP_STACK: TCP_TransmitTxBuffer()
*
* Purpose:
* transmitts data stored in 'TCP_TX_BUF'
*
* Actions:
*
* Comments:
* number of bytes to transmit must have been written to 'TCPTxDataCount'
* data-count MUST NOT exceed 'MAX_TCP_TX_SIZE'
*
*****************************************************************************/
MC void TCP_TransmitTxBuffer()
{
if ((TCP_StateMachine == ESTABLISHED) || (TCP_StateMachine == CLOSE_WAIT))
if (TCP_SocketStatus & TCP_SOCK_TX_BUF_RELEASED)
{
// free tx-buffer
TCP_SocketStatus &= ~TCP_SOCK_TX_BUF_RELEASED;
// advance UNA
TCP_UNA_Seq_Nr += TCP_Tx_Data_Count;
TCP_TxFrame1Size = TCP_Tx_Data_Count + ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE;
TCP_TransmitControl |= TCP_SEND_FRAME1;
TCP_LastFrameSent = TCP_DATA_FRAME;
// see how ofen we need to resend
TCP_StartRetryTimer();
}
}
/******************************************************************************
* TCP_IP_STACK: TCP_StateMachine()
*
* Purpose:
* The TCP/IP statemachine.
*
* Note:
* Must be run, even if now new data is present, as status can update
* due to timeouts, too.
*
* Actions:
*
*****************************************************************************/
MC void TCP_State_Machine()
{
WORD *data = (WORD*) LAN_rx_packet.data;
// process LAN only if new data is available
if (LAN_rx_packet.busy)
{
// check for received frame type by XOR:
// either IA (individual address) or broadcast
if ((*data++ ^ *data++ ^ *data++) != 0xffff)
TCP_Proc_EthIA_Frame();
else
TCP_Proc_EthBroadcast_Frame();
}
// update TCP_StateMachine accordingly
if (TCP_Flags & TCP_TIMER_RUNNING)
if (TCP_Flags & TCP_TIMER_TYPE_RETRY)
{
if (TCP_Timer > TCP_RETRY_TIMEOUT)
{
// set a new timeout
TCP_RestartTimer();
// check RetryCounter
if (TCP_RetryCounter)
{
// resend last frame
TCP_HandleRetransmission();
TCP_RetryCounter--;
}
else
{
TCP_StopTimer();
TCP_HandleTimeout();
}
}
}
else if (TCP_Timer > TCP_FIN_TIMEOUT)
{
// reset all flags, stop retransmission...
TCP_StateMachine = CLOSED;
TCP_Flags = 0;
// clear all flags but data available
TCP_SocketStatus &= TCP_SOCK_DATA_AVAILABLE;
}
switch (TCP_StateMachine)
{
case CLOSED :
case LISTENING :
{
// stack has to open a connection?
if (TCP_Flags & TCP_ACTIVE_OPEN)
// IP resolved?
if (TCP_Flags & TCP_IP_ADDR_RESOLVED)
// buffer free?
if (!(TCP_TransmitControl & TCP_SEND_FRAME2))
{
// set local ISN
TCP_Seq_Nr = ((TCP_ISN_Gen_High << 16) | get_cycles());
TCP_UNA_Seq_Nr = TCP_Seq_Nr;
// we don't know what to ACK yet
TCP_Ack_Nr = 0;
// count SYN as a byte
TCP_UNA_Seq_Nr++;
// send SYN frame
TCP_Prep_TCP_FRAME(TCP_CODE_SYN);
TCP_LastFrameSent = TCP_SYN_FRAME;
// we NEED a retry-timeout
TCP_StartRetryTimer();
TCP_StateMachine = SYN_SENT;
}
break;
}
case SYN_RECD :
case ESTABLISHED :
{
// user has user initated a close?
if (TCP_Flags & TCP_CLOSE_REQUESTED)
// buffers free?
if (!(TCP_TransmitControl & (TCP_SEND_FRAME2 | TCP_SEND_FRAME1)))
// all data ACKed?
if (TCP_Seq_Nr == TCP_UNA_Seq_Nr)
{
TCP_UNA_Seq_Nr++;
TCP_Prep_TCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK);
TCP_LastFrameSent = TCP_FIN_FRAME;
TCP_StartRetryTimer();
TCP_StateMachine = FIN_WAIT_1;
}
break;
}
case CLOSE_WAIT :
{
// buffers free?
if (!(TCP_TransmitControl & (TCP_SEND_FRAME2 | TCP_SEND_FRAME1)))
// all data ACKed?
if (TCP_Seq_Nr == TCP_UNA_Seq_Nr)
{
// count FIN as a byte
TCP_UNA_Seq_Nr++;
// we NEED a retry-timeout
TCP_Prep_TCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK);
// time to say goodbye...
TCP_LastFrameSent = TCP_FIN_FRAME;
TCP_StartRetryTimer();
TCP_StateMachine = LAST_ACK;
}
break;
}
}
if (TCP_TransmitControl & TCP_SEND_FRAME2)
{
// copy TX_Buffer to LAN_tx_packet.data
TCP_Copy_Frame(TCP_TxFrame2Size, TCP_TxFrame2);
// allocate packet memory;
smc_allocate_packet();
// wait for allocation or flag error
if(LAN_state.alloc_success)
{
smc_hardware_send_packet();
}
else
{
TCP_StateMachine = CLOSED;
// indicate an error to user
TCP_SocketStatus = TCP_SOCK_ERR_ETHERNET;
// clear all flags, stop timers etc.
TCP_Flags = 0;
}
// clear tx-flag
TCP_TransmitControl &= ~TCP_SEND_FRAME2;
}
if (TCP_TransmitControl & TCP_SEND_FRAME1)
{
// build frame w/ actual SEQ, ACK....
TCP_Prep_TCP_DATA_FRAME();
TCP_Copy_Frame(TCP_TxFrame1Size, TCP_TxFrame1);
// allocate packet memory on LAN controller;
smc_allocate_packet();
// wait for allocation or flag error
if(LAN_state.alloc_success)
{
smc_hardware_send_packet();
}
else
{
TCP_StateMachine = CLOSED;
// indicate an error to user
TCP_SocketStatus = TCP_SOCK_ERR_ETHERNET;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -