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

📄 tftp.c

📁 motorola 针对coldfire 5275 评估板的Dbug bootloader源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * File:        tftp.c
 * Purpose:     Trivial File Transfer Protocol driver for reading a file
 *              from a remote host.
 *
 * Notes:       See RFC 1350
 *
 * Modifications:
 *
 */
#include "src/include/dbug.h"
#include "src/uif/net/net.h"

#ifdef DBUG_NETWORK

/********************************************************************/

/* The one and only TFTP connection */
TFTP_Connection tcxn;

/* Progress Indicators */
char hash[] = {'-','\\','|','/'};
int ihash = 0;

/********************************************************************/
static int
tftp_rwrq (void)
{
    NBUF *pNbuf;
    RWRQ *rwrq;
    int i, j, result;

    pNbuf = nbuf_alloc();
    if (pNbuf == NULL)
    {
        #if defined(DEBUG_PRINT)
            printf("TFTP: tftp_rwrq() couldn't allocate Tx buffer\n");
        #endif
        return 0;
    }

    rwrq = (RWRQ *)&pNbuf->data[TFTP_HDR_OFFSET];

    /* Indicate a R/WRQ */
    rwrq->opcode = tcxn.dir;

    /* Copy in filename */
    strcpy(&rwrq->filename_mode[0], tcxn.file);
    i = strlen(tcxn.file) + 1;

    /* Indicate transfer type */
    strcpy (&rwrq->filename_mode[i], OCTET);

    for (j=0; j<3; ++j)
    {
        pNbuf->length = (uint16)(i + strlen(OCTET) + 1 + 2);
        result = udp_send(tcxn.nif,
                          tcxn.server_ip,
                          tcxn.my_port,
                          tcxn.server_port,
                          pNbuf);
        if (result == 1)
            break;
    }

    if (result == 0)
        nbuf_free(pNbuf);

    return result;
}
/********************************************************************/
static int
tftp_ack (uint16 blocknum)
{
    ACK *ack;
    NBUF *pNbuf;
    int i, result;

    pNbuf = nbuf_alloc();
    if (pNbuf == NULL)
    {
        #if defined(DEBUG_PRINT)
            printf("TFTP: tftp_ack() couldn't allocate Tx buffer\n");
        #endif
        return 0;
    }

    ack = (ACK *)&pNbuf->data[TFTP_HDR_OFFSET];
    ack->opcode = TFTP_ACK;
    ack->blocknum = blocknum;
    
    for (i=0; i<3; ++i)
    {
        pNbuf->length = 4;
        result = udp_send(tcxn.nif,
                          tcxn.server_ip,
                          tcxn.my_port,
                          tcxn.server_port,
                          pNbuf);
        if (result == 1)
            break;
    }

    if (result == 0)
        nbuf_free(pNbuf);

    return result;
} 
/********************************************************************/
static int
tftp_error (uint16 error_code, uint16 server_port)
{
    ERROR *err;
    NBUF *pNbuf;
    int i, result;

    pNbuf = nbuf_alloc();
    if (pNbuf == NULL)
    {
        #if defined(DEBUG_PRINT)
            printf("TFTP: tftp_error() couldn't allocate Tx buffer\n");
        #endif
        return 0;
    }

    err = (ERROR *)&pNbuf->data[TFTP_HDR_OFFSET];
    err->opcode = TFTP_ERROR;
    err->code = error_code;
    err->msg[0] = '\0';

    for (i=0; i<3; ++i)
    {
        pNbuf->length = 5;
        result = udp_send(tcxn.nif,
                          tcxn.server_ip,
                          tcxn.my_port,
                          server_port,
                          pNbuf);
        if (result == 1)
            break;
    }

    if (result == 0)
        nbuf_free(pNbuf);

    return result;
}
/********************************************************************/
void
tftp_handler (NIF *nif, NBUF *pNbuf)
{
    union TFTPpacket *tftp_pkt;
    udp_frame_hdr *udpframe;
    static int cnt;
    (void) nif;

    tftp_pkt = (union TFTPpacket *)&pNbuf->data[pNbuf->offset];
    udpframe = (udp_frame_hdr *)&pNbuf->data[pNbuf->offset - UDP_HDR_SIZE];

    switch (tftp_pkt->generic.opcode)
    {
        case TFTP_DATA:
            /* Is this the expected block number? */
            if (tftp_pkt->data.blocknum == tcxn.exp_blocknum)
            {
                /* Is this is the first data block received? */
                if (tftp_pkt->data.blocknum == 1)
                {
                    /* Save the server's transfer ID */
                    tcxn.server_port = UDP_SOURCE(udpframe);

                    /* Mark the connection as open */
                    tcxn.open = TRUE;

                    /* Start progress indicator */
                    board_putchar(hash[0]);
                    cnt = 0;
                }
                else
                {   
                    /* Check the server's transfer ID */
                    if (tcxn.server_port != UDP_SOURCE(udpframe))
                    {
                        #if defined(DEBUG_PRINT)
                            printf("TFTP: Invalid server port: %d\n", \
                                    UDP_SOURCE(udpframe));
                        #endif

                        /* Send ERROR packet to source */
                        tftp_error(TFTP_ERR_TID, UDP_SOURCE(udpframe));
                        break;
                    }
                }

                /* Add the buffer to the TFTP queue */
                queue_add(&tcxn.queue, (QNODE *)pNbuf);
                
                /* Update number of the next block expected */
                tcxn.exp_blocknum++;

                /* Increment number of bytes received counter */
                tcxn.bytes_recv += (pNbuf->length - 4);

                /* Update progress indicator */
                if (++cnt == 50)
                {
                    ihash = (ihash + 1) % 4;
                    board_putchar(CTRL_BS);
                    board_putchar(hash[ihash]);
                    cnt = 0;
                }
            }
            else
            {
                if (tftp_pkt->data.blocknum < tcxn.exp_blocknum)
                {
                    /* Re-ACK this packet */
                    tftp_ack(tftp_pkt->data.blocknum);
                }

                #if defined(DEBUG_PRINT)
                    /* This is NOT the block expected */
                    printf("Exp: %d, ", tcxn.exp_blocknum);
                    printf("Rcv: %d\n", tftp_pkt->data.blocknum);
                #endif
                
                /* Free the network buffer */
                nbuf_free(pNbuf);
            }
            break;
        case TFTP_ERROR:
            printf("\nTFTP Error #%d: ",tftp_pkt->error.code);
            printf("%s\n",tftp_pkt->error.msg);
            tcxn.error = TRUE;
            /* Free the network buffer */
            nbuf_free(pNbuf);
            break;
        case TFTP_ACK:
            if (tftp_pkt->ack.blocknum == tcxn.exp_blocknum)
            {
                if (tftp_pkt->data.blocknum == 0)
                {   /* This is the first ACK received */

                    /* Save the server's transfer ID */
                    tcxn.server_port = UDP_SOURCE(udpframe);

                    /* Mark the connection as open */
                    tcxn.open = TRUE;
                }
                else
                {   /* Check the server's transfer ID */
                    if (tcxn.server_port != UDP_SOURCE(udpframe))
                    {
                        #if defined(DEBUG_PRINT)
                            printf("TFTP: Invalid server port: %d\n", \
                                    UDP_SOURCE(udpframe));
                        #endif

                        /*Send ERROR packet to source */
                        tftp_error(TFTP_ERR_TID, UDP_SOURCE(udpframe));
                        break;
                    }
                }

                tcxn.exp_blocknum++;
            }
            else
            {
                #if defined(DEBUG_PRINT)
                    /* This is NOT the block number expected */
                    printf("ACK Exp: %d, ", tcxn.exp_blocknum);
                    printf("ACK Rcv: %d\n", tftp_pkt->ack.blocknum);
                #endif
            }
            
            /* Free the network buffer */
            nbuf_free(pNbuf);
            break;
        case TFTP_RRQ:
        case TFTP_WRQ:
        default:
            /* Free the network buffer */
            nbuf_free(pNbuf);
            break;
    }
}

/********************************************************************/
void
tftp_end (int success)
{
    /* 
     * Following a successful transfer the caller should pass in 
     * TRUE, there should have been no ERROR packets received, and 
     * the connection should have been marked as closed by the 
     * tftp_in_char() routine.
     */
    if (success && !tcxn.error && (tcxn.open == FALSE))
    {
        printf("\bTFTP transfer completed \n");
        printf("Read %d bytes (%d blocks)\n",   \
            tcxn.bytes_recv, tcxn.exp_blocknum - 1);
    }
    else
    {
        /* Send error packet to stifle the server */
        tftp_error(TFTP_ERR_ILL, tcxn.server_port);

        printf("\bErrors in TFTP transfer.\n");
        printf("Read %d bytes (%d blocks)\n",   \
            tcxn.bytes_recv, tcxn.exp_blocknum - 1);
    }

    /* Free up any buffers left in the queue */
    while (!queue_isempty(&tcxn.queue))
        nbuf_free((NBUF *)queue_remove(&tcxn.queue));

    /* Free the UDP port */
    udp_free_port(tcxn.my_port);
}

/********************************************************************/
int
tftp_write (NIF *nif, char *fn, IP_ADDR_P server, uint32 begin, uint32 end)
{
    DATA *data;
    NBUF *pNbuf;

    uint32 i, retries, bytes_to_send;
    uint16 blocknum, this_size;
    uint8 success, *current;
    int result;

    if (fn == 0 || server == 0 || end < begin)
        return 0;

    /* Setup initial connection status */
    tcxn.nif = nif;
    tcxn.file = fn;
    tcxn.server_ip[0] = server[0];
    tcxn.server_ip[1] = server[1];
    tcxn.server_ip[2] = server[2];
    tcxn.server_ip[3] = server[3];
    tcxn.server_port = UDP_PORT_TFTP;
    tcxn.exp_blocknum = 0;
    tcxn.dir = TFTP_WRQ;
    tcxn.open = FALSE;
    tcxn.bytes_sent = 0;

⌨️ 快捷键说明

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