⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp.c

📁 本附件为嵌入式Web的相关资料
💻 C
📖 第 1 页 / 共 4 页
字号:
	ps = &TCBStubs[hTCP];
	LoadTCB(hTCP);

	if(ps->txHead != MyTCB.txUnackedTail)
	{
		SendTCP(hTCP, PSH | ACK);

		// Clear timeout info
		MyTCB.retryCount = 0;
		MyTCB.retryInterval = TCP_START_TIMEOUT_VAL;
		ps->eventTime = TickGet() + TCP_START_TIMEOUT_VAL;
		ps->Flags.bTimerEnabled = TRUE;
	}
	SaveTCB(hTCP);
}



/*********************************************************************
* Function:        WORD TCPIsPutReady(TCP_SOCKET hTCP)
*
* PreCondition:    TCPInit() is already called.
*
* Input:           hTCP: handle of socket to test
*
* Output:          Number of bytes that can be immediately placed 
*				   in the transmit buffer.
*
* Side Effects:    None
*
* Overview:        None
*
* Note:            None
********************************************************************/
WORD TCPIsPutReady(TCP_SOCKET hTCP)
{
	TCB_STUB	*ps;

	ps = &TCBStubs[hTCP];

	if(ps->txHead >= ps->txTail)
		return (ps->bufferRxStart - ps->bufferTxStart - 1) - (ps->txHead - ps->txTail);
	else
		return ps->txTail - ps->txHead - 1;
}


/*********************************************************************
* Function:        BOOL TCPPut(TCP_SOCKET hTCP, BYTE byte)
*
* PreCondition:    TCPIsPutReady(s) != 0
*
* Input:           hTCP: socket handle to use
*                  byte: a data byte to send
*
* Output:          TRUE if given byte was put in transmit buffer
*                  FALSE if transmit buffer is full.
*
* Side Effects:    None
*
* Overview:        None
*
* Note:            None
********************************************************************/
BOOL TCPPut(TCP_SOCKET hTCP, BYTE byte)
{
	TCB_STUB *ps;
	WORD wFreeTXSpace;

	ps = &TCBStubs[hTCP];

	wFreeTXSpace = TCPIsPutReady(hTCP);
	
    if(!wFreeTXSpace)
    {
		TCPFlush(hTCP);	
		return FALSE;
    }

    /***
    if(wFreeTXSpace == 0u)
		return FALSE;
	else if(wFreeTXSpace == 1u) // About to run out of space, lets transmit so the remote node might send an ACK back faster
		TCPFlush(hTCP);	
    ***/

	MACSetWritePtr(ps->txHead);
	MACPut(byte);
	if(++ps->txHead >= ps->bufferRxStart)
		ps->txHead = ps->bufferTxStart;

    // Send the last byte as a separate packet (likely will make the remote node send back ACK faster)
	if(wFreeTXSpace == 1u)
		TCPFlush(hTCP);

    return TRUE;
}

/*********************************************************************
* Function:        WORD TCPPutArray(TCP_SOCKET hTCP, BYTE *data, WORD len)
*
* PreCondition:    None
*
* Input:           hTCP    - Socket handle to use
*                  data    - Pointer to data to put
*				   len     - Count of bytes to put
*
* Output:          Count of bytes actually placed in the TX buffer
*
* Side Effects:    None
*
* Overview:        None
*
* Note:            None
********************************************************************/
WORD TCPPutArray(TCP_SOCKET hTCP, BYTE *data, WORD len)
{
	WORD wActualLen;
	WORD wFreeTXSpace;
	WORD wRightLen = 0;
	TCB_STUB *ps;

	ps = &TCBStubs[hTCP];

	wFreeTXSpace = TCPIsPutReady(hTCP);
	if(wFreeTXSpace == 0u)
	{
		TCPFlush(hTCP);
		return 0;
	}
	
	wActualLen = wFreeTXSpace;
	if(wFreeTXSpace > len)
		wActualLen = len;
	
	// See if we need a two part put
	if(ps->txHead + wActualLen >= ps->bufferRxStart)
	{
		wRightLen = ps->bufferRxStart-ps->txHead;
		MACSetWritePtr(ps->txHead);
		MACPutArray(data, wRightLen);
		data += wRightLen;
		wActualLen -= wRightLen;
		ps->txHead = ps->bufferTxStart;
	}

	MACSetWritePtr(ps->txHead);
	MACPutArray(data, wActualLen);
	ps->txHead += wActualLen;

	// Send these bytes right now if we are out of TX buffer space
	if(wFreeTXSpace <= len)
		TCPFlush(hTCP);

	return wActualLen + wRightLen;
}
// Note: This function is slow.  Performance could be enhanced 
// if the array was copied into RAM and then TCPPutArray() was 
// called instead.
WORD TCPPutROMArray(TCP_SOCKET hTCP, ROM BYTE *data, WORD len)
{
	WORD wActualLen;

	wActualLen = TCPIsPutReady(hTCP);
	if(wActualLen > len)
		wActualLen = len;
	len = wActualLen;

	while(len--)
	{
		TCPPut(hTCP, *data++);
	}

	return wActualLen;
}


/*********************************************************************
* Function:        WORD TCPPutString(TCP_SOCKET hTCP, BYTE *data)
*
* PreCondition:    None
*
* Input:           hTCP    - Socket handle to use
*                  data    - Pointer to null terminated string to put
*
* Output:          Count of bytes actually placed in the TX buffer
*
* Side Effects:    None
*
* Overview:        None
*
* Note:            None
********************************************************************/
WORD TCPPutString(TCP_SOCKET hTCP, BYTE *data)
{
	return TCPPutArray(hTCP, data, strlen(data));
}
// Note: This function is slow.  Performance could be enhanced 
// if the string was copied into RAM and then TCPPutString() was 
// called instead.
WORD TCPPutROMString(TCP_SOCKET hTCP, ROM BYTE *data)
{
	WORD len = 0;

	while(*data)
	{
		if(TCPPut(hTCP, *data++))
			len++;
		else
			break;
	}

	return len;
}


/*********************************************************************
* Function:        void TCPDiscard(TCP_SOCKET hTCP)
*
* PreCondition:    TCPInit() is already called.
*
* Input:           hTCP       - socket handle
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        Removes all pending data from the socket's RX 
*				   buffer.
*
* Note:            None
********************************************************************/
void TCPDiscard(TCP_SOCKET hTCP)
{
	TCB_STUB *ps;

	ps = &TCBStubs[hTCP];
	LoadTCB(hTCP);

	// Delete all data in the RX buffer
	ps->rxTail = ps->rxHead;

	// Send a Window update message to the remote node
	SendTCP(hTCP, ACK);

	SaveTCB(hTCP);
}


/*********************************************************************
* Function:        WORD TCPIsGetReady(TCP_SOCKET hTCP)
*
* PreCondition:    TCPInit() is already called.
*
* Input:           hTCP       - socket to test
*
* Output:          Number of bytes that are available in socket 'hTCP' 
*				   for immediate retrieval
*
* Side Effects:    None
*
* Overview:        None
*
* Note:            None
********************************************************************/
WORD TCPIsGetReady(TCP_SOCKET hTCP)
{
	TCB_STUB	*ps;

	ps = &TCBStubs[hTCP];

	if(ps->rxHead == ps->rxTail)
		return 0;
	else if(ps->rxHead > ps->rxTail)
		return ps->rxHead - ps->rxTail;
	else
		return (ps->bufferEnd - ps->rxTail + 1) + (ps->rxHead - ps->bufferRxStart);
}


/*********************************************************************
* Function:        BOOL TCPGet(TCP_SOCKET hTCP, BYTE *byte)
*
* PreCondition:    TCPInit() is already called
*
* Input:           hTCP    - socket
*                  byte    - Pointer to a byte.
*
* Output:          TRUE if a byte was read.
*                  FALSE if byte was not read.
*
* Side Effects:    None
*
* Overview:        None
*
* Note:            None
********************************************************************/
BOOL TCPGet(TCP_SOCKET hTCP, BYTE *byte)
{
	TCB_STUB	*ps;
	WORD GetReadyCount;

	GetReadyCount = TCPIsGetReady(hTCP);
	if(GetReadyCount == 0u)
		return FALSE;

	ps = &TCBStubs[hTCP];
	MACSetReadPtr(ps->rxTail);
	*byte = MACGet();
	if(++ps->rxTail > ps->bufferEnd)
		ps->rxTail = ps->bufferRxStart;

	// Send a window update if we've run out of data
	if(GetReadyCount == 1u)
	{
		LoadTCB(hTCP);
		SendTCP(hTCP, ACK);
		SaveTCB(hTCP);
	}

	return TRUE;
}


/*********************************************************************
* Function:        WORD TCPGetArray(TCP_SOCKET hTCP, BYTE *buffer,
*                                      WORD len)
*
* PreCondition:    TCPInit() is already called
*
* Input:           hTCP    - socket handle
*                  buffer  - Buffer to hold received data.
*                  len     - Buffer length
*
* Output:          Number of bytes loaded into buffer.
*
* Side Effects:    None
*
* Overview:        None
*
* Note:            None
********************************************************************/
WORD TCPGetArray(TCP_SOCKET hTCP, BYTE *buffer, WORD len)
{
	WORD ActualLen;
	WORD RightLen = 0;
	TCB_STUB *ps;

	ps = &TCBStubs[hTCP];

	ActualLen = TCPIsGetReady(hTCP);
	if(ActualLen > len)
		ActualLen = len;

	// See if we need a two part get
	if(ps->rxTail + ActualLen > ps->bufferEnd)
	{
		RightLen = ps->bufferEnd - ps->rxTail + 1;
		MACSetReadPtr(ps->rxTail);
		MACGetArray(buffer, RightLen);
		buffer += RightLen;
		ActualLen -= RightLen;
		ps->rxTail = ps->bufferRxStart;
	}

	MACSetReadPtr(ps->rxTail);
	MACGetArray(buffer, ActualLen);
	ps->rxTail += ActualLen;

	return ActualLen + RightLen;
}


/*********************************************************************
* Function:        WORD TCPGetString(TCP_SOCKET hTCP, BYTE *buffer,
*                                      WORD len)
*
* PreCondition:    TCPInit() is already called
*
* Input:           hTCP    - socket handle
*                  buffer  - Buffer to hold received data.
*                  len     - Buffer length
*
* Output:          Number of bytes loaded into buffer, not including the null terminator
*
* Side Effects:    None
*
* Overview:        None
*
* Note:            None
********************************************************************/
WORD TCPGetString(TCP_SOCKET hTCP, BYTE *buffer, WORD len)
{
	WORD ActualLen = 0;

	TCPGet(hTCP, buffer);
	while(*buffer)
	{
		ActualLen++;
		TCPGet(hTCP, ++buffer);
	}

	return ActualLen;
}


/*********************************************************************
* Function:        void TCPTick(void)
*
* PreCondition:    TCPInit() is already called.
*
* Input:           None
*
* Output:          Each socket FSM is executed for any timeout
*                  situation.
*
* Side Effects:    None
*
* Overview:        None
*
* Note:            None
********************************************************************/
void TCPTick(void)
{
	TCP_SOCKET hTCP;
	TCB_STUB *ps;
	DWORD SEQSave;

	// Periodically all "not closed" sockets must perform timed operations
	for(hTCP = 0; hTCP < MAX_TCP_SOCKETS; hTCP++)
	{
		ps = &TCBStubs[hTCP];

		// The TCP_CLOSED, TCP_LISTEN, and sometimes the TCP_ESTABLISHED 
		// state don't need any timeout events
		if(!ps->Flags.bTimerEnabled)
			continue;

		// If timeout has not occured, do not do anything.
		if((signed)(TickGet() - ps->eventTime) < 0)
			continue;

		// Load up extended MyTCB information
		LoadTCB(hTCP);

		// This will be one more attempt.
		MyTCB.retryCount++;

		// Update timeout value if there is need to wait longer.
		MyTCB.retryInterval <<= 1;

		// Restart timeout reference.
		ps->eventTime = TickGet() + MyTCB.retryInterval;

		// A timeout has occured.  Respond to this timeout condition
		// depending on what state this socket is in.
		switch(ps->smState)
		{
			case TCP_SYN_SENT:
				// Keep sending SYN until we hear from remote node.
				// This may be for infinite time, in that case
				// caller must detect it and do something.
				MyTCB.retryInterval = TCP_START_TIMEOUT_VAL;
				MyTCB.retryCount = 0;
				SendTCP(hTCP, SYN);
				break;
	
			case TCP_SYN_RECEIVED:
				// We must receive ACK before timeout expires.
				// If not, resend SYN+ACK.
				// Abort, if maximum attempts counts are reached.
				if(MyTCB.retryCount <= MAX_RETRY_COUNTS)
				{
					SendTCP(hTCP, SYN | ACK);
				}
				else
				{
					if(ps->Flags.bServer)
					{
						SendTCP(hTCP, RST);
						CloseSocket(hTCP);
					}
					else
					{
						ps->smState = TCP_SYN_SENT;
						MyTCB.retryInterval = TCP_START_TIMEOUT_VAL;
						MyTCB.retryCount = 0;
						SendTCP(hTCP, SYN);
					}
				}
				break;
	
			case TCP_ESTABLISHED:
				// Retransmit any unacknowledged data
				if(MyTCB.retryCount <= MAX_RETRY_COUNTS)
				{
					SEQSave = MyTCB.MySEQ;

					// Roll back unacknowledged TX tail pointer
					MyTCB.MySEQ -= (LONG)(SHORT)(MyTCB.txUnackedTail - ps->txTail);
					if(MyTCB.txUnackedTail < ps->txTail)
						MyTCB.MySEQ -= (LONG)(SHORT)(ps->bufferRxStart - ps->bufferTxStart);
					MyTCB.txUnackedTail = ps->txTail;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -