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

📄 huahtftp.lib

📁 这是一个在在Dynamic C环境下实现的设备web服务器的建立
💻 LIB
📖 第 1 页 / 共 2 页
字号:
/*
 * tftp.lib
 *
 * Copyright (C) Z-World, Inc. All rights reserved.
 *
 * Trivial File Transfer Protocol (TFTP)
 * Based on RFCs:
 *   783 'THE TFTP PROTOCOL (REVISION 2)'
 *
 */

/* START LIBRARY DESCRIPTION *********************************************
TFTP.LIB
	Copyright (c) 2001, ZWorld.

DESCRIPTION:
	Trivial File Transfer Protocol.

	This standard protocol (internet RFC783) is a lighweight 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 upload of 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.  In conjunction
	with DHCP/BOOTP (see BOOTP.LIB), 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.  See the sample program samples\tcpip\dhcp_bootfile.c
   for an example of this use.

	The Dynamic C TFTP library contains the following functions.  Any of
	these functions will require approximately 600-800 bytes of free
	stack.  The data buffer for the file to put or get is always
	allocated in xmem (see xalloc()).  The tftp_struct structure, which
	is required for most of these functions, may be allocated either
	in root data memory or in xmem.  The tftp_struct structure is
	approximately 155 bytes long.

	  tftp_init()    Prepare for a TFTP session
	  tftp_initx()   Prepare for a TFTP session
	  tftp_tick()    Execute one non-blocking step in the TFTP session
	  tftp_tickx()   Execute one non-blocking step in the TFTP session
	  tftp_exec()    Prepare and execute a complete TFTP session, blocking
	                 until complete.

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


/*** BeginHeader */

#ifdef TFTP_DEBUG
	#define _tftp_nodebug debug
#else
	#define _tftp_nodebug nodebug
#endif

/*
 * UDP well-known port number for TFTP server.
 */
#define	IPPORT_TFTP			69

// Initial timeout value in milliseconds - default 3/4 sec.  Will double every retry.
#ifndef TFTP_TIMEOUT
#define TFTP_TIMEOUT		750
#endif

// Number of times to retransmit same packet after successive timeouts
// before giving up.
#ifndef TFTP_RETRIES
#define TFTP_RETRIES		5
#endif


// TFTP opcodes - for efficiency, these are in (16-bit) network order
#define TFTP_OP_RRQ		0x0100
#define TFTP_OP_WRQ		0x0200
#define TFTP_OP_DATA		0x0300
#define TFTP_OP_ACK		0x0400
#define TFTP_OP_ERROR	0x0500

// TFTP Client Mode - By wangtao to support large file!
#define	TFTP_BLOCK_MODE	0x80		/// One 512Bytes block!
#define	TFTP_FILE_MODE	0x40		/// Whole file!
#define	TFTP_USER_COPY	0x01		/// User defined data copiers!

#define	DATA_IN			0x01
#define	DATA_OUT		0x02
// Packet structure used by TFTP
typedef struct tftp_packet {
	word			opcode;
	union {
		char name_and_mode[514];	// For RRQ or WRQ
		struct {
			word	blocknum;
			char	data[512];
		} d;	// For DATA or ACK
		struct {
			word	errorcode;
			char	errmsg[512];
		} e;	// For ERROR
	} u;
};

/*
 * structure for send and receives
 */
typedef struct tftp_state {
	int 			(*udhandler)();		/// user data handler! by wangtao !
	unsigned char	tcmode;			/// TFTP Client Mode!
	byte			state;			// Current state.  LSB indicates read(0) or write(1).  Other bits
									// determine state within this:
#define TFTP_ST_INIT		0	// Initial (sending RRQ/WRQ)
#define TFTP_ST_WAIT		2	// Waiting for response (data if read, ack if write)
#define TFTP_ST_DONE		4	// Finished.
#define TFTP_ST_RETRY		6	// Resending previous packet (transient state)
	long			buf_addr;		// Physical address of buffer
	unsigned long	buf_len;		// Length of buffer! by wangtao !
	unsigned long	buf_used;		// Amount Tx or Rx from/to buffer! by wangtao
	word			next_blk;		// Next expected block number, 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
#define TFTP_F_EXIT		0x01			// Exit from receive processing flag
#define TFTP_F_TRUNC	0x02		// Received file truncated
	long			sbufaddr;		// Socket buffer address (0 if use UDP socket buffer pool)
	word			sbuflen;		// Socket buffer length.

	// Following fields not used after initial request has been acknowledged.
	char			mode;			// Translation mode as follows:
#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)
	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
									// sever if an error occurs.
};

/*** EndHeader */


/*** BeginHeader tftp_init, tftp_tick */

int tftp_init(struct tftp_state * ts);
int tftp_tick(struct tftp_state * ts);

/*** EndHeader */


/* START FUNCTION DESCRIPTION ********************************************
tftp_init                       <TFTP.LIB>

SYNTAX: int tftp_init(struct tftp_state * ts);

PARAMETER1:		Pointer to TFTP state.  This must have been set up according
               to the description here.

KEYWORDS:		tcpip dhcp bootp tftp

DESCRIPTION: 	This function is called to complete initialisation of the
               TFTP state structure.  Before calling this function, some
               fields in the struct 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 *)>
                 ts->rem_ip = <IP address of TFTP server 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 email address
               of the recipient.  The mail message must be ASCII-encoded
               and formatted with RFC822 headers.


RETURN VALUE:  0: OK
               -4: Error, socket NULL.
					-7: Server address zero.

SEE ALSO:      tftp_tick, tftp_exec, tftp_initx, tftp_tickx

END DESCRIPTION **********************************************************/

_tftp_nodebug int tftp_init(struct tftp_state * ts)
{
	if (!ts->my_tid)
		ts->my_tid = findfreeport(0, 0);	// Next unused UDP port, non-privileged.
	ts->retry = 0;
	ts->flags = 0;
	ts->state &= 0x01;				// Isolate to initial state.
	if (!ts->sock)
		return -4;
	if (!ts->rem_ip)
		return -7;
	return 0;
}

/* START FUNCTION DESCRIPTION ********************************************
tftp_tick                       <TFTP.LIB>

SYNTAX: int tftp_tick(struct tftp_state * ts);

PARAMETER1:		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.

KEYWORDS:		tcpip dhcp bootp tftp

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().

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 because buffer too
                   small to receive the complete file.

SEE ALSO:      tftp_init, tftp_exec, tftp_initx, tftp_tickx

END DESCRIPTION **********************************************************/

_tftp_nodebug int tftp_tick(struct tftp_state * ts)
{
	auto struct tftp_packet tp;	// 516 bytes
	auto char * p;
	auto int status;
	auto int udrc;	  /// by wangtao ! UserDataHandler's return code!
///	auto int len;
///	auto word newlen; by wangtao !
	auto long len;		/// by wangtao!
	auto long newlen;
	auto byte write;
	auto byte state;
	auto int retval;
#ifdef TFTP_ALLOW_BUG
	auto int rh_bug;
#endif

	write = ts->state & 0x01;
	state = ts->state & 0xFE;

	// Handle possible timeouts in states where waiting for response.
	if (state == TFTP_ST_WAIT) {
		if ((long)(MS_TIMER - ts->timeout) > 0) {
			ts->retry++;
			if (ts->retry > TFTP_RETRIES)
				goto _tftp_return_timeout;	// Timeout and all retries exhausted.
			if (!ts->next_blk)
				state &= 0x01;	// Go to reinit state temporarily
			else
				state |= 0x06;	// Go to retry state temporarily
		}
	}

	switch (state) {
	case TFTP_ST_INIT:
#ifdef TFTP_VERBOSE
		printf("TFTP INIT\r\n");
#endif
		tp.opcode = write ? TFTP_OP_WRQ : TFTP_OP_RRQ;
		strcpy(tp.u.name_and_mode, ts->file);
		switch(ts->mode) {
		case TFTP_MODE_NETASCII:
			p = "netascii"; break;
		case TFTP_MODE_MAIL:
			p = "mail"; break;
		default:
			p = "octet";
		}
		newlen = strlen(ts->file) + 1;
		strcpy(tp.u.name_and_mode + (word)newlen, p);
		newlen += strlen(p) + 1 + 2;
#ifdef TFTP_ALLOW_BUG
		rh_bug = 0;
#endif

		// Open to well-known port
		if(udp_waitopen(ts->sock, IF_ANY, ts->my_tid, ts->rem_ip, 0, NULL, 0, 0, 1000) <= 0)
			goto _tftp_return_openerr;	// ARP couldn't resolve the IP address within 1sec.
		// Send initial packet to his well-known port.  He will reply
		// from a different port, which we will later "bind to" on this
		// socket.
		udp_sendto(ts->sock, (byte *)&tp, (word)newlen, ts->rem_ip, IPPORT_TFTP);
		ts->timeout = MS_TIMER + (TFTP_TIMEOUT << ts->retry);
		ts->buf_used = 0;
		ts->next_blk = 0;
		ts->state = TFTP_ST_WAIT + write;
		break;
		case TFTP_ST_RETRY:

⌨️ 快捷键说明

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