> ## 7. TFTP Client

> `TFTP.LIB` implements the Trivial File Transfer Protocol (TFTP). This standard protocol (internet RFC783) is a lightweight protocol typically used to transfer bootstrap or configuration files from a server to a client host, such as a diskless workstation. TFTP allows data to be sent in either direction between client and server, using UDP as the underlying transport.

> This library fully implements TFTP, but as a client only.

> Compared with more capable protocols such as FTP, TFTP:

> - has no security or authentication
> - is not as fast because of the step-by-step protocol
> - uses fewer machine resources.

> Because of the lack of authentication, most TFTP servers restrict the set of accessible files to a small number of configuration files in a single directory. For uploading files, servers are usually configured to accept only certain file names that are writable by any user. If these restrictions are acceptable, TFTP has the advantage of requiring very little 'footprint' in the client host.

> #### 7.0.1 BOOTP/DHCP

> In conjunction with DHCP/BOOTP and appropriate server configuration, TFTP is often used to download a kernel image to a diskless host. The target TCP/IP board does not currently support loading the BIOS in this way, since the BIOS and application program are written to non-volatile flash memory. However, the downloaded file does not have to be a binary executable - it can be any reasonably small file, such as an application configuration file. TFTP and DHCP/BOOTP can thus be used to administer the configuration of multiple targets from a central server.

> Using TFTP with BOOTP/DHCP requires minimal additional effort for the programmer. Just `#define` the symbol `DHCP_USE_TFTP` to an integer representing the maximum allowable boot file size (1-65535). See the description of the variables `_bootpsize`, `_bootpdata` and `_bootperror` on page 6 for further details.

> #### 7.0.2 Data Structure for TFTP

> This data structure is used to send and receive. The `tftp_state` structure, which is required for many of the API functions in `TFTP.LIB`, may be allocated either in root data memory or in extended memory. This structure is approximately 155 bytes long.

>     typedef struct tftp_state {
>        byte state;           // Current state. LSB indicates read(0)
>                              // or write(1). Other bits determine
>                              // state within this (see below).
>        long buf_addr;        // Physical address of buffer
>        word buf_len;         // Length of buffer
>        word buf_used;        // Amount Tx or Rx from/to buffer
>        word next_blk;        // Next expected block #, or next to Tx
>        word my_tid;          // UDP port number used by this host
>        udp_Socket * sock;    // UDP socket to use
>        longword rem_ip;      // IP address of remote host
>        longword timeout;     // ms timer value for next timeout
>        char retry;           // retransmit retry counter
>        char flags;           // misc flags (see below).
>     // Following fields not used after initial request has been
>     // acknowledged.
>        char mode;            // Translation mode (see below).
>        char file[129];       // File name on remote host (TFTP
>                              // server)- NULL terminated. This
>                              // field will be overwritten with a
>                              // NULL-term error message from the
>                              // server if an error occurs.
>     };

> #### 7.0.2.1 Macros for tftp_state->mode

>     #define TFTP_MODE_NETASCII 0  // ASCII text
>     #define TFTP_MODE_OCTET 1     // 8-bit binary
>     #define TFTP_MODE_MAIL 2      // Mail (remote file name is
>                                   // email address e.g.
>                                   // user@host.blob.org)

> #### 7.0.3 Function Reference

> Any of the following functions will require approximately 600-800 bytes of free stack. The data buffer for the file to put or to get is always allocated in xram (see `xalloc()`).

> #### TFTP Session

> A session can be either a single download (get) or upload (put). The functions ending with 'x' are versions that use a data structure allocated in extended memory, for applications that are constrained in their use of root data memory.

> ## tftp_init

>     int tftp_init(struct tftp_state * ts);

> ### Description

> This function prepares for a TFTP session and is called to complete initialization of the TFTP state structure. Before calling this function, some fields in the structure `tftp_state` must be set up as follows:

>     ts->state    = <0 for read, 1 for write>
>     ts->buf_addr = <physical address of xmem buffer>
>     ts->buf_len  = <length of physical buffer, 0-65535>
>     ts->my_tid   = <UDP port number. Set 0 for default>

>     ts->sock     = <address of UDP socket (udp_Socket *),or NULL to use DHCP/BOOTP socket>

>     ts->rem_ip   = <IP address of TFTP server host, or zero to use default BOOTP host>

>     ts->mode     = <one of the following constants:
>                       TFTP_MODE_NETASCII (ASCII text)
>                       TFTP_MODE_OCTET (8-bit binary)
>                       TFTP_MODE_MAIL (Mail)>
>     strcpy(ts->file, <remote filename or mail address>)

> Note that mail mode can only be used to write mail to the TFTP server, and the file name is the e-mail address of the recipient. The e-mail message must be ASCII-encoded and formatted with `RFC822 headers`. Sending e-mail via TFTP is deprecated. Use SMTP instead since TFTP servers may not implement mail.

> ### Parameters

> #### ts

> Pointer to `tftp_state`.

> ### Return value

> `0`: OK.
> `-4`: Error, default socket in use.

> ### Library

> TFTP.LIB

> ## tftp_initx

>     int tftp_initx(long ts_addr);

> ### Description

> This function is called to complete initialization of the TFTP state structure, where the structure is possibly stored somewhere other than in the root data space. This is a wrapper function for `tftp_init()`. See that function description for details.

> ### Parameters

> #### ts_addr

> Physical address of TFTP state (struct `tftp_state`)

> ### Return value

> `0`: OK
> `-1`: Error, default socket in use

> ### Library

> TFTP.LIB

> ## tftp_tick

>     int tftp_tick(struct tftp_state * ts);

> ### Description

> This function is called periodically in order to take the next step in a TFTP process. Appropriate use of this function allows single or multiple transfers to occur without blocking. For multiple concurrent transfers, there must be a unique `tftp_state` structure, and a unique UDP socket, for each transfer in progress. This function calls `sock_tick()`.

> ### Parameters

> #### ts

> Pointer to TFTP state. This must have been set up using `tftp_init()`, and must be passed to each call of `tftp_tick()` without alteration.

> ### Return value

> `1`: OK, transfer not yet complete.
> `0`: OK, transfer complete
> `-1`: Error from remote side, transfer terminated. In this case, the ts_addr->file field
> will be overwritten with a `NULL`-terminated error message from the server.
> `-2`: Error, could not contact remote host or lost contact.
> `-3`: Timed out, transfer terminated.
> `-4`: (not used)
> `-5`: Transfer complete, but truncated -- buffer too small to receive the complete file.

> ### Library

> TFTP.LIB

> ## tftp_tickx

>     int tftp_tickx(long ts_addr);

> ### Description

> This function is a wrapper for calling `tftp_tick()`, where the structure is possibly stored somewhere other than in the root data space. See that function description for details.

> ### Parameters

> #### ts_addr

> Physical address of TFTP state (struct `tftp_state`).

> ### Return value

> `1`: OK, transfer not yet complete.
> `0`: OK, transfer complete
> `-1`: Error from remote side, transfer terminated. In this case, the ts_addr->file field
> will be overwritten with a `NULL`-terminated error message from the server.
> `-2`: Error, could not contact remote host or lost contact.
> `-3`: Timed out, transfer terminated.
> `-4`: (not used)
> `-5`: Transfer complete, but truncated -- buffer too small to receive the complete file.

> ### Library

> TFTP.LIB

> ## tftp_exec

>     int tftp_exec( char put, long buf_addr, word * len, int mode, char * host, char * hostfile, udp_Socket * sock );

> ### Description

> Prepare and execute a complete TFTP session, blocking until complete.This function is a wrapper for `tftp_init()` and `tftp_tick()`. It does not return until the complete file is transferred or an error occurs. Note that approximately 750 bytes of free stack will be required by this function.

> ### Parameters

> #### put

> `0`: get file from remote host; `1`: put file to host.

> #### buf_addr

> Physical address of data buffer.

> #### len

> Length of data buffer. This is both an input and a return parameter. It should be initialized to the buffer length. On return, it will be set to the actual length received (for a get), or unchanged (for a put).

> #### mode

> Data representation: 0=NETASCII, 1=OCTET (binary), 2=MAIL.

> #### host

> Remote host name, or `NULL` to use default BOOTP host.

> #### hostfile

> Name of file on remote host, or e-mail address for mail.

> #### sock

> UDP socket to use, or `NULL` to re-use BOOTP socket if available.

> ### Return value

> `0`: OK, transfer complete.
> `-1`: Error from remote side, transfer terminated. In this case, `ts_addr->file`
> will be overwritten with a `NULL`-terminated error message from the server.
> `-2`: Error, could not contact remote host or lost contact.
> `-3`: Timed out, transfer terminated
> `-4`: sock parameter was `NULL`, but BOOTP socket was unavailable.

> ### Library

> TFTP.LIB

Z-World http://www.zworld.com Voice: 530.757.3737 Fax: 530.757.3792 or 530.753.5141 sales@zworld.com