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

📄 tcp.c

📁 凌阳SPCE3200 系统开发板随机自带源程序。共安排了32个子目录
💻 C
📖 第 1 页 / 共 4 页
字号:
/*********************************************************************
 *
 *                  TCP Module for Microchip TCP/IP Stack
 *
 *********************************************************************
 * FileName:        TCP.C
 * Dependencies:    string.h
 *                  StackTsk.h
 *                  Helpers.h
 *                  IP.h
 *                  MAC.h
 *                  ARP.h
 *                  Tick.h
 *                  TCP.h
 * Processor:       PIC18
 * Complier:        MCC18 v1.00.50 or higher
 *                  HITECH PICC-18 V8.10PL1 or higher
 * Company:         Microchip Technology, Inc.
 *
 * Software License Agreement
 *
 * This software is owned by Microchip Technology Inc. ("Microchip") 
 * and is supplied to you for use exclusively as described in the 
 * associated software agreement.  This software is protected by 
 * software and other intellectual property laws.  Any use in 
 * violation of the software license may subject the user to criminal 
 * sanctions as well as civil liability.  Copyright 2006 Microchip
 * Technology Inc.  All rights reserved.
 *
 * This software is provided "AS IS."  MICROCHIP DISCLAIMS ALL 
 * WARRANTIES, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, NOT LIMITED 
 * TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND 
 * INFRINGEMENT.  Microchip shall in no event be liable for special, 
 * incidental, or consequential damages.
 *
 *
 * Author               Date    Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Nilesh Rajbharti     5/8/01  Original        (Rev 1.0)
 * Nilesh Rajbharti     5/22/02 Rev 2.0 (See version.log for detail)
 * Nilesh Rajbharti     11/1/02 Fixed TCPTick() SYN Retry bug.
 * Nilesh Rajbharti     12/5/02	Modified TCPProcess()
 *                              to include localIP as third param.
 *                              This was done to allow this function
 *                              to calculate checksum correctly.
 * Roy Schofield		10/1/04	TCPConnect() startTick bug fix.
 * Howard Schlunder		1/3/05	Fixed HandleTCPSeg() unexpected 
 * 								discard problem identified by Richard
 *				 				Shelquist.
 * Howard Schlunder		1/16/06	Fixed an imporbable RX checksum bug 
 *								when using a Microchip Ethernet controller)
********************************************************************/
#define THIS_IS_TCP

#include <string.h>

#include "StackTsk.h"
#include "Helpers.h"
#include "IP.h"
#include "MAC.h"
#include "Tick.h"
#include "TCP.h"

/*
 * Max TCP data length is MAC_TX_BUFFER_SIZE - sizeof(TCP_HEADER) -
 * sizeof(IP_HEADER) - sizeof(ETHER_HEADER)
 */
#define MAX_TCP_DATA_LEN    (MAC_TX_BUFFER_SIZE - 54)


/*
 * TCP Timeout value to begin with.
 */
#define TCP_START_TIMEOUT_VAL   ((TICK)TICK_SECOND * (TICK)60)

/*
 * TCP Flags as defined by rfc793
 */
#define FIN     (0x01)
#define SYN     (0x02)
#define RST     (0x04)
#define PSH     (0x08)
#define ACK     (0x10)
#define URG     (0x20)


/*
 * TCP Header def. as per rfc 793.
 */

typedef struct _TCP_HEADER
{
    WORD    SourcePort;
    WORD    DestPort;
    DWORD   SeqNumber;
    DWORD   AckNumber;

    struct
    {
        unsigned int Reserved3      : 4;
        unsigned int Val            : 4;
    }__attribute__ ((packed))  DataOffset;


    union
    {
        struct
        {
            unsigned int flagFIN    : 1;
            unsigned int flagSYN    : 1;
            unsigned int flagRST    : 1;
            unsigned int flagPSH    : 1;
            unsigned int flagACK    : 1;
            unsigned int flagURG    : 1;
            unsigned int Reserved2  : 2;
        }__attribute__ ((packed))  bits;
        BYTE byte;
    }__attribute__ ((packed))  Flags;

    WORD    Window;
    WORD    Checksum;
    WORD    UrgentPointer;

}__attribute__ ((packed))  TCP_HEADER;


/*
 * TCP Options as defined by rfc 793
 */
#define TCP_OPTIONS_END_OF_LIST     (0x00)
#define TCP_OPTIONS_NO_OP           (0x01)
#define TCP_OPTIONS_MAX_SEG_SIZE    (0x02)
typedef struct _TCP_OPTIONS
{
    BYTE        Kind;
    BYTE        Length;
    WORD_VAL    MaxSegSize;
}__attribute__ ((packed))  TCP_OPTIONS;

#define SwapPseudoTCPHeader(h)  (h.TCPLength = swaps(h.TCPLength))

/*
 * Pseudo header as defined by rfc 793.
 */
typedef struct _PSEUDO_HEADER
{
    IP_ADDR SourceAddress;
    IP_ADDR DestAddress;
    BYTE Zero;
    BYTE Protocol;
    WORD TCPLength;
}__attribute__ ((packed))  PSEUDO_HEADER;

/*
 * Local temp port numbers.
 */
static WORD _NextPort;

/*
 * Starting segment sequence number for each new connection.
 */
static DWORD ISS;

/*
 * These are all sockets supported by this TCP.
 */
#ifdef MCHP_C18
// Allow the linker to place the next TCB array into a separate 
// memory bank.  This is needed because the TCB array is very 
// large.
#pragma udata SocketMemory	
#endif
SOCKET_INFO TCB[MAX_SOCKETS];


static void HandleTCPSeg(TCP_SOCKET s,
                         NODE_INFO *remote,
                         TCP_HEADER *h,
                         WORD len);

static void TransmitTCP(NODE_INFO *remote,
                        TCP_PORT localPort,
                        TCP_PORT remotePort,
                        DWORD seq,
                        DWORD ack,
                        BYTE flags,
                        BUFFER buffer,
                        WORD len);

static TCP_SOCKET FindMatchingSocket(TCP_HEADER *h,
                                     NODE_INFO *remote);
static void SwapTCPHeader(TCP_HEADER* header);
static void CloseSocket(SOCKET_INFO* ps);

#define SendTCP(remote, localPort, remotePort, seq, ack, flags)     \
        TransmitTCP(remote, localPort, remotePort, seq, ack, flags, \
                    INVALID_BUFFER, 0)

#define LOCAL_PORT_START_NUMBER (1024)
#define LOCAL_PORT_END_NUMBER   (5000)



/*********************************************************************
 * Function:        void TCPInit(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          TCP is initialized.
 *
 * Side Effects:    None
 *
 * Overview:        Initialize all socket info.
 *
 * Note:            This function is called only one during lifetime
 *                  of the application.
 ********************************************************************/
void TCPInit(void)
{
    TCP_SOCKET s;
    SOCKET_INFO* ps;


    // Initialize all sockets.
    for ( s = 0; s < MAX_SOCKETS; s++ )
    {
        ps = &TCB[s];

        ps->smState             = TCP_CLOSED;
        ps->Flags.bServer       = FALSE;
        ps->Flags.bIsPutReady   = TRUE;
        ps->Flags.bFirstRead    = TRUE;
        ps->Flags.bIsTxInProgress = FALSE;
        ps->Flags.bIsGetReady   = FALSE;
        ps->Flags.bACKValid 	= FALSE;
        ps->TxBuffer            = INVALID_BUFFER;
        ps->TimeOut             = TCP_START_TIMEOUT_VAL;
    }

    _NextPort = LOCAL_PORT_START_NUMBER;
    ISS = 0;
}



/*********************************************************************
 * Function:        TCP_SOCKET TCPListen(TCP_PORT port)
 *
 * PreCondition:    TCPInit() is already called.
 *
 * Input:           port    - A TCP port to be opened.
 *
 * Output:          Given port is opened and returned on success
 *                  INVALID_SOCKET if no more sockets left.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
TCP_SOCKET TCPListen(TCP_PORT port)
{
    TCP_SOCKET s;
    SOCKET_INFO* ps;

    for ( s = 0; s < MAX_SOCKETS; s++ )
    {
        ps = &TCB[s];

        if ( ps->smState == TCP_CLOSED )
        {
            /*
             * We have a CLOSED socket.
             * Initialize it with LISTENing state info.
             */
            ps->smState             = TCP_LISTEN;
            ps->localPort           = port;
            ps->remotePort          = 0;

            /*
             * There is no remote node IP address info yet.
             */
            ps->remote.IPAddr.Val   = 0x00;

            /*
             * If a socket is listened on, it is a SERVER.
             */
            ps->Flags.bServer       = TRUE;

            ps->Flags.bIsGetReady   = FALSE;
            ps->TxBuffer            = INVALID_BUFFER;
            ps->Flags.bIsPutReady   = TRUE;

            return s;
        }
    }
    return INVALID_SOCKET;
}



/*********************************************************************
 * Function:        TCP_SOCKET TCPConnect(NODE_INFO* remote,
 *                                      TCP_PORT remotePort)
 *
 * PreCondition:    TCPInit() is already called.
 *
 * Input:           remote      - Remote node address info
 *                  remotePort  - remote port to be connected.
 *
 * Output:          A new socket is created, connection request is
 *                  sent and socket handle is returned.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            By default this function is not included in
 *                  source.  You must define STACK_CLIENT_MODE to
 *                  be able to use this function.
 ********************************************************************/
#ifdef STACK_CLIENT_MODE
TCP_SOCKET TCPConnect(NODE_INFO *remote, TCP_PORT remotePort)
{
    TCP_SOCKET s;
    SOCKET_INFO* ps;
    BOOL lbFound;


    lbFound = FALSE;
    /*
     * Find an available socket
     */
    for ( s = 0; s < MAX_SOCKETS; s++ )
    {
        ps = &TCB[s];
        if ( ps->smState == TCP_CLOSED )
        {
            lbFound = TRUE;
            break;
        }
    }

    /*
     * If there is no socket available, return error.
     */
    if ( lbFound == FALSE )
        return INVALID_SOCKET;

    /*
     * Each new socket that is opened by this node, gets
     * next sequential port number.
     */
    ps->localPort = ++_NextPort;
    if ( _NextPort > LOCAL_PORT_END_NUMBER )
        _NextPort = LOCAL_PORT_START_NUMBER;

    /*
     * This is a client socket.
     */
    ps->Flags.bServer = FALSE;

    /*
     * This is the port, we are trying to connect to.
     */
    ps->remotePort = remotePort;

    /*
     * Each new socket that is opened by this node, will
     * start with next segment seqeuence number.
     */
    ps->SND_SEQ = ++ISS;
    ps->SND_ACK = 0;

    memcpy((BYTE*)&ps->remote, (const void*)remote, sizeof(ps->remote));

    /*
     * Send SYN message.
     */
    SendTCP(&ps->remote,
            ps->localPort,
            ps->remotePort,
            ps->SND_SEQ,
            ps->SND_ACK,
            SYN);

    ps->smState = TCP_SYN_SENT;
    ps->SND_SEQ++;
	
	// Allow TCPTick() to operate properly
	ps->startTick = TickGet(); 	

    return s;
}
#endif



/*********************************************************************
 * Function:        BOOL TCPIsConnected(TCP_SOCKET s)
 *
 * PreCondition:    TCPInit() is already called.
 *
 * Input:           s       - Socket to be checked for connection.
 *
 * Output:          TRUE    if given socket is connected
 *                  FALSE   if given socket is not connected.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            A socket is said to be connected if it is not
 *                  in LISTEN and CLOSED mode.  Socket may be in
 *                  SYN_RCVD or FIN_WAIT_1 and may contain socket
 *                  data.
 ********************************************************************/
BOOL TCPIsConnected(TCP_SOCKET s)
{
    return ( TCB[s].smState == TCP_EST );
}



/*********************************************************************
 * Function:        void TCPDisconnect(TCP_SOCKET s)
 *
 * PreCondition:    TCPInit() is already called     AND
 *                  TCPIsPutReady(s) == TRUE
 *
 * Input:           s       - Socket to be disconnected.
 *
 * Output:          A disconnect request is sent for given socket.
 *
 * Side Effects:    None
 *

⌨️ 快捷键说明

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