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

📄 tftpc.c

📁 凌阳 Web服务器应用采用Microchip TCP / IP协议栈介绍
💻 C
📖 第 1 页 / 共 3 页
字号:
/*********************************************************************
 *
 *                  TFTP Client module for Microchip TCP/IP Stack
 *
 *********************************************************************
 * FileName:        TFTPc.c
 * Dependencies:    TFTPc.h
 *                  UDP.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     8/5/03  Original        (Rev 1.0)
 ********************************************************************/
#if defined(WIN32)
    #include <stdio.h>
    #define TFTP_DEBUG
#endif

#include "tftpc.h"
#include "arptsk.h"
#include "tick.h"

#define TFTP_CLIENT_PORT        65352L       // Some unique port on this
                                            // device.
#define TFTP_SERVER_PORT        (69L)
#define TFTP_BLOCK_SIZE         (0x200L)     // 512 bytes
#define TFTP_BLOCK_SIZE_MSB     (0x02)

typedef enum _TFTP_STATE
{
    SM_TFTP_WAIT = 0,
    SM_TFTP_READY,
    SM_TFTP_WAIT_FOR_DATA,
    SM_TFTP_WAIT_FOR_ACK,
    SM_TFTP_DUPLICATE_ACK,
    SM_TFTP_SEND_ACK,
    SM_TFTP_SEND_LAST_ACK
} TFTP_STATE;

typedef enum _TFTP_OPCODE
{
    TFTP_OPCODE_RRQ = 1,         // Get
    TFTP_OPCODE_WRQ,            // Put
    TFTP_OPCODE_DATA,           // Actual data
    TFTP_OPCODE_ACK,            // Ack for Get/Put
    TFTP_OPCODE_ERROR           // Error
} TFTP_OPCODE;



UDP_SOCKET _tftpSocket;         // TFTP Socket for TFTP server link
WORD _tftpError;

static struct  _MutExVar        // modified by lfei union to struct
{
    struct
    {
        NODE_INFO _hostInfo;
    }__attribute__ ((packed))  group1;

    struct
    {
        WORD_VAL _tftpBlockNumber;
        WORD_VAL _tftpDuplicateBlock;
        WORD_VAL _tftpBlockLength;
    }__attribute__ ((packed))  group2;
}__attribute__ ((packed))  MutExVar;     // Mutually Exclusive variable groups to conserve RAM.


static TFTP_STATE _tftpState;
static BYTE _tftpRetries;
static TICK _tftpStartTick;
static union
{
    struct
    {
        unsigned int bIsFlushed : 1;
        unsigned int bIsAcked : 1;
        unsigned int bIsClosed : 1;
        unsigned int bIsClosing : 1;
        unsigned int bIsReading : 1;
    }__attribute__ ((packed))  bits;
    BYTE Val;
}__attribute__ ((packed))  _tftpFlags;


// Private helper functions
static void _TFTPSendFileName(TFTP_OPCODE command, char *fileName);
static void _TFTPSendAck(WORD_VAL blockNumber);

// Blank out DEBUG statements if not enabled.
#if defined(TFTP_DEBUG)
    #define DEBUG(a)        a
#else
    #define DEBUG(a)
#endif


/*********************************************************************
 * Function:        void TFTPOpen(IP_ADDR *host)
 *
 * PreCondition:    UDP module is already initialized
 *                  and at least one UDP socket is available.
 *
 * Input:           host        - IP address of remote TFTP server
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Initiates ARP for given host and prepares
 *                  TFTP module for next sequence of function calls.
 *
 * Note:            Use TFTPIsOpened() to check if a connection was
 *                  successfully opened or not.
 *
 ********************************************************************/
void TFTPOpen(IP_ADDR *host)
{
/* commented by lfei 2007/03/05 ****
    DEBUG(printf("Opening a connection..."));
********************************/
//	print1("Setup a connection with remote server !\n");
    // Remember this address locally.
    MutExVar.group1._hostInfo.IPAddr.Val = host->Val;

    // Initiate ARP resolution.
    ARPResolve(&MutExVar.group1._hostInfo.IPAddr);

    // Wait for ARP to get resolved.
    _tftpState = SM_TFTP_WAIT;

    // Mark this as start tick to detect timeout condition.
    _tftpStartTick = TickGet();

    // Forget about all previous attempts.
    _tftpRetries = 1;

}



/*********************************************************************
 * Function:        TFTP_RESULT TFTPIsOpened(void)
 *
 * PreCondition:    TFTPOpen() is already called.
 *
 * Input:           None
 *
 * Output:          TFTP_OK if previous call to TFTPOpen is complete
 *
 *                  TFTP_TIMEOUT if remote host did not respond to
 *                          previous ARP request.
 *
 *                  TFTP_NOT_READY if remote has still not responded
 *                          and timeout has not expired.
 *
 * Side Effects:    None
 *
 * Overview:        Waits for ARP reply and opens a UDP socket
 *                  to perform further TFTP operations.
 *
 * Note:            Once opened, application may keep TFTP socket
 *                  open and future TFTP operations.
 *                  If TFTPClose() is called to close the connection
 *                  TFTPOpen() must be called again before performing
 *                  any other TFTP operations.
 ********************************************************************/
TFTP_RESULT TFTPIsOpened(void)
{
    switch(_tftpState)
    {
    default:
        DEBUG(printf("Resolving remote IP...\n"));

        // Check to see if adddress is resolved.
        if ( ARPIsResolved(&MutExVar.group1._hostInfo.IPAddr,
                           &MutExVar.group1._hostInfo.MACAddr) )
        {
            _tftpSocket = UDPOpen(TFTP_CLIENT_PORT,
                                  &MutExVar.group1._hostInfo,
                                  TFTP_SERVER_PORT);
            _tftpState = SM_TFTP_READY;
        }
        else
            break;

    case SM_TFTP_READY:
        // Wait for UDP to be ready.  Immediately after this user will
        // may TFTPGetFile or TFTPPutFile and we have to make sure that
        // UDP is read to transmit.  These functions do not check for
        // UDP to get ready.
        if ( UDPIsPutReady(_tftpSocket) )
            return TFTP_OK;
    }

    // Make sure that we do not do this forever.
    if ( TickGetDiff(TickGet(), _tftpStartTick) >= TFTP_ARP_TIMEOUT_VAL )
    {
        _tftpStartTick = TickGet();

        // Forget about all previous attempts.
        _tftpRetries = 1;

        return TFTP_TIMEOUT;
    }

    return TFTP_NOT_READY;
}



/*********************************************************************
 * Function:        void TFTPOpenFile(char *fileName,
 *                                    TFTP_FILE_MODE mode)
 *
 * PreCondition:    TFPTIsFileOpenReady() = TRUE
 *
 * Input:           fileName        - File name that is to be opened.
 *                  mode            - Mode of file access
 *                                    Must be
 *                                      TFTP_FILE_MODE_READ for read
 *                                      TFTP_FILE_MODE_WRITE for write
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Prepares and sends TFTP file name and mode packet.
 *
 * Note:            By default, this funciton uses "octet" or binary
 *                  mode of file transfer.
 *                  Use TFTPIsFileOpened() to check if file is
 *                  ready to be read or written.
 ********************************************************************/
void TFTPOpenFile(char *fileName, TFTP_FILE_MODE mode)
{
    // Set TFTP Server port.  If this is the first call, remotePort
    // must have been set by TFTPOpen().  But if caller does not do
    // TFTPOpen for every transfer, we must reset remote port.
    // Most TFTP servers accept connection TFTP port. but once
    // connection is established, they use other temp. port,
    UDPSocketInfo[_tftpSocket].remotePort = TFTP_SERVER_PORT;

    // Tell remote server about our intention.
    _TFTPSendFileName(mode, fileName);

    // Clear all flags.
    _tftpFlags.Val = 0;

    // Remember start tick for this operation.
    _tftpStartTick = TickGet();

    // Depending on mode of operation, remote server will respond with
    // specific block number.
    if ( mode == TFTP_FILE_MODE_READ )
    {
        // Remember that we are reading a file.
        _tftpFlags.bits.bIsReading = TRUE;


        // For read operation, server would respond with data block of 1.
        MutExVar.group2._tftpBlockNumber.Val = 1;

        // Next packet would be the data packet.
        _tftpState = SM_TFTP_WAIT_FOR_DATA;
    }

    else
    {
        // Remember that we are writing a file.
        _tftpFlags.bits.bIsReading = FALSE;

        // For write operation, server would respond with data block of 0.
        MutExVar.group2._tftpBlockNumber.Val = 0;

        // Next packet would be the ACK packet.
        _tftpState = SM_TFTP_WAIT_FOR_ACK;
    }
    
}




/*********************************************************************
 * Function:        TFTP_RESULT TFTPIsFileOpened(void)
 *
 * PreCondition:    TFTPOpenFile() is called.
 *
 * Input:           None
 *
 * Output:          TFTP_OK if file is ready to be read or written
 *
 *                  TFTP_RETRY if previous attempt was timed out
 *                  needs to be retried.
 *
 *                  TFTP_TIMEOUT if all attempts were exhausted.
 *
 *                  TFTP_NOT_ERROR if remote server responded with
 *                  error
 *
 *                  TFTP_NOT_READY if file is not yet opened.
 *
 * Side Effects:    None
 *
 * Overview:        Waits for remote server response regarding
 *                  previous attempt to open file.
 *                  If no response is received within specified
 *                  timeout, fnction returns with TFTP_RETRY
 *                  and application logic must issue another
 *                  TFTPFileOpen().
 *
 * Note:            None
 ********************************************************************/
TFTP_RESULT TFTPIsFileOpened(void)
{
    if ( _tftpFlags.bits.bIsReading )
        return TFTPIsGetReady();

    else
        return TFTPIsPutReady();
}




/*********************************************************************
 * Function:        TFTP_RESULT TFTPIsGetReady(void)
 *
 * PreCondition:    TFTPOpenFile() is called with TFTP_FILE_MODE_READ
 *                  and TFTPIsFileOpened() returned with TRUE.
 *
 * Input:           None
 *
 * Output:          TFTP_OK if it there is more data byte available
 *                  to read
 *
 *                  TFTP_TIMEOUT if timeout occurred waiting for
 *                  new data.
 *
 *                  TFTP_END_OF_FILE if end of file has reached.
 *
 *                  TFTP_ERROR if remote server returned ERROR.
 *                      Actual error code may be read by calling
 *                      TFTPGetError()
 *
 *                  TFTP_NOT_READY if still waiting for new data.
 *
 * Side Effects:    None
 *
 * Overview:        Waits for data block.  If data block does not
 *                  arrive within specified timeout, it automatically
 *                  sends out ack for previous block to remind

⌨️ 快捷键说明

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