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

📄 huahtftp.lib

📁 这是一个在在Dynamic C环境下实现的设备web服务器的建立
💻 LIB
📖 第 1 页 / 共 2 页
字号:
#ifdef TFTP_VERBOSE
			printf("TFTP: retry\n");
#endif
			if (write)
				goto _tftp_resend_data;
			else
				goto _tftp_resend_ack;
		case TFTP_ST_WAIT:
			tcp_tick(NULL);
			len = udp_recv(ts->sock, (byte *)&tp, sizeof(tp));
			if (len == -1)
				break;
			if (len < 0)
				goto _tftp_sock_err;
			if (len < 4)
				break;	// Min TFTP packet is 4 bytes; ignore less.
			len -= 4;	// Reduce len to actual data length
			// Reverse blocknum
			tp.u.d.blocknum = intel16(tp.u.d.blocknum);
#ifdef TFTP_VERBOSE
			printf("TFTP got opc=%d blk=%d length=%d\r\n", intel16(tp.opcode), tp.u.d.blocknum, len);
#endif
			switch (tp.opcode) {
			case TFTP_OP_DATA:
				if (write)
					break;	// Ignore data packets if writing
				if (tp.u.d.blocknum != ts->next_blk+1)	// Ignore if not expected block
					break;
				ts->retry = 0;	// Reset retry counter, since got data
				if (len < 512)	// TFTP last data packet
					ts->flags |= TFTP_F_EXIT;

				newlen = ts->buf_used + len;	// Total length of data obtained
				if ( (ts->udhandler == NULL) || ((ts->tcmode & TFTP_USER_COPY) == 0) )
				{
					if (newlen < ts->buf_used || newlen > ts->buf_len)	{ // Buffer overflow?
						len = ts->buf_len - ts->buf_used;
						ts->flags |= TFTP_F_TRUNC | TFTP_F_EXIT;
					}
					if (len > 0) {
						root2xmem(ts->buf_addr + ts->buf_used, tp.u.d.data, (unsigned)len);
						ts->buf_used += len;
					}
					if (ts->udhandler != NULL)
						udrc = ts->udhandler(ts, &len, DATA_IN);	/// by wangtao !
				}
				else if ( (ts->udhandler != NULL)&&(ts->tcmode & TFTP_USER_COPY) )	/// by wangtao !
				{
					if (len > 0) {
						root2xmem(ts->buf_addr, tp.u.d.data, (unsigned)len);
						ts->buf_used += len;
					}
					udrc = ts->udhandler(ts, &len, DATA_IN);	/// by wangtao !
				}

				ts->next_blk++;
_tftp_resend_ack:
				// Send an ACK for last block seen
				tp.opcode = TFTP_OP_ACK;
				tp.u.d.blocknum = intel16(ts->next_blk);
				udp_send(ts->sock, (byte *)&tp, 4);
#ifdef TFTP_VERBOSE
				printf("TFTP sent ack blk=%d\r\n", ts->next_blk);
#endif
				ts->timeout = MS_TIMER + (TFTP_TIMEOUT << ts->retry);
				// If len is < 512, then transmission is finished, either because a short packet was
				// transmitted, or because our own buffer was filled.  Really, we should linger on
				// to make sure that server doesn't retransmit the last packet (indicating that it
				// didn't get our ACK), but no great loss if we don't...
				if ( ts->flags & TFTP_F_EXIT)
					goto _tftp_return_complete;
				if ( (ts->udhandler != NULL) && (udrc != 0) ) /// by wangtao !
					goto _tftp_return_complete;
				break;
			case TFTP_OP_ACK:
				if (!write)
					break;	// Ignore ack packets if reading
#ifdef TFTP_ALLOW_BUG
				// Some versions of tftp server (e.g. RH Linux 7.0) had bug where 1st block was set to
				// 1 instead of 0.  Try to hack around this.  A very bad hack - don't use it!
				if (tp.u.d.blocknum == 1 && !ts->next_blk)
					rh_bug = 1;
				if ( //!(tp.u.d.blocknum == 1 && !ts->next_blk) &&
					tp.u.d.blocknum != ts->next_blk + rh_bug)	// Ignore if not expected block
					break;
#else
				if (tp.u.d.blocknum != ts->next_blk)	// Ignore if not expected block
					break;
#endif
				ts->retry = 0;	// Reset retry counter, since got acknowledgement
				if (ts->next_blk) {
					ts->buf_used += 512;
					if (ts->buf_used > ts->buf_len || !ts->buf_used)
						goto _tftp_return_complete;
				}
				ts->next_blk++;
_tftp_resend_data:
////////////adde by wangtao to support userdatahandler !
				if ( (ts->udhandler == NULL) || ( (ts->tcmode & TFTP_USER_COPY) == 0) )
				{
					len = ts->buf_len - ts->buf_used;
					if (len < 0 || len > 512) len = 512;	// Max size block
					if (len > 0)
						xmem2root(tp.u.d.data, ts->buf_addr + ts->buf_used, (unsigned)len);

					if (ts->udhandler != NULL)
						udrc = ts->udhandler(ts, &len, DATA_OUT);	/// by wangtao !
				}
				else if ( (ts->udhandler != NULL) && (ts->tcmode & TFTP_USER_COPY) )
				{
					udrc = ts->udhandler(ts, &len, DATA_OUT);
					if (len < 0 || len > 512)
						len = 512;	// Max size block
					if (len > 0)
						xmem2root(tp.u.d.data, ts->buf_addr, (unsigned)len);
				}

				tp.opcode = TFTP_OP_DATA;
				tp.u.d.blocknum = intel16(ts->next_blk);
				udp_send(ts->sock, (byte *)&tp, (unsigned)(len+4) );
#ifdef TFTP_VERBOSE
				printf("TFTP sent data blk=%d len=%d\r\n", ts->next_blk, len);
#endif
				ts->timeout = MS_TIMER + (TFTP_TIMEOUT << ts->retry);

				break;
			case TFTP_OP_ERROR:
				tp.u.e.errmsg[127] = 0;	// Truncate to 127 chars
#ifdef TFTP_VERBOSE
				printf("TFTP Error: code=%d msg=%s\r\n", intel16(tp.u.e.errorcode), tp.u.e.errmsg);
#endif
				strcpy(ts->file, tp.u.e.errmsg);
				goto _tftp_return_tftperr;
			default:
				break;
			}	// switch on opcode
			break;
			default:
				return 0;
	}	// switch on state

	// Indicate not yet complete
	return 1;

_tftp_return_tftperr:
	retval = -1;
	goto _tftp_bye;

_tftp_return_timeout:
	retval = -3;
	goto _tftp_bye;

_tftp_sock_err:
_tftp_return_openerr:
	retval = -2;
	goto _tftp_bye;

_tftp_return_complete:
	retval = 0;
	if (ts->flags & TFTP_F_TRUNC)
		retval = -5;
	else if ( ( ts->udhandler != NULL) && (udrc != 0) )
		retval = udrc;

_tftp_bye:
	ts->state = TFTP_ST_DONE;
	sock_close((sock_type *)ts->sock);
	return retval;
}

/*** BeginHeader tftp_initx, tftp_tickx */

int tftp_initx(long ts_addr);
int tftp_tickx(long ts_addr);

/*** EndHeader */

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

SYNTAX: int tftp_initx(long ts_addr);

PARAMETER1:		Physical address of TFTP state (struct tftp_state).

KEYWORDS:		tcpip dhcp bootp tftp

DESCRIPTION: 	This function is called to complete initialisation 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.


RETURN VALUE:  0: OK
               -1: Error, default socket in use.

SEE ALSO:      tftp_tick, tftp_exec, tftp_init, tftp_tickx

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

_tftp_nodebug int tftp_initx(long ts_addr)
{
	auto struct tftp_state ts;
	auto int rc;

	xmem2root(&ts, ts_addr, sizeof(ts));
	rc = tftp_init(&ts);
	root2xmem(ts_addr, &ts, sizeof(ts));
	return rc;
}



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

SYNTAX: int tftp_tickx(long ts_addr);

PARAMETER1:		Physical address of TFTP state (struct tftp_state).

KEYWORDS:		tcpip dhcp bootp tftp

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.

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_tick

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

_tftp_nodebug int tftp_tickx(long ts_addr)
{
	auto struct tftp_state ts;
	auto int rc;

	xmem2root(&ts, ts_addr, sizeof(ts));
	rc = tftp_tick(&ts);
	root2xmem(ts_addr, &ts, sizeof(ts));
	return rc;
}


/*** BeginHeader tftp_exec */

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

/*** EndHeader */

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

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

PARAMETER1:		0: get file from remote host; 1: put file to host.
PARAMETER2:    physical address of data buffer.
PARAMETER3:    length of data buffer.  This is both an input and a return
               parameter.  It should be initialised to the buffer
               length.  On return, it will be set to the actual length
               received (for a get), or unchanged (for a put).
PARAMETER4:    Data representation: 0=NETASCII, 1=OCTET (binary), 2=MAIL.
PARAMETER5:    Remote host name.
PARAMETER6:    Name of file on remote host, or email address for mail.
PARAMETER7:    UDP socket to use

KEYWORDS:		tcpip dhcp bootp tftp

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

RETURN VALUE:  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: sock parameter was NULL
               -7: host was NULL

SEE ALSO:      tftp_init, tftp_initx, tftp_tick, tftp_tickx

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

_tftp_nodebug
int tftp_exec( char put, long buf_addr, word * len, int mode,
			char * host, char * hostfile, udp_Socket * sock )
{
	auto struct tftp_state ts;
	auto int status;

	ts.state = put ? 1 : 0;
	ts.buf_addr = buf_addr;
	ts.buf_len = *len;
	if (!put)
		*len = 0;
	ts.my_tid = 0;	// Find an unused one
	ts.sock = sock;
	if (host) {
		ts.rem_ip = resolve(host);
		if (!ts.rem_ip) return -2;	// Host not resolved
	}
	else
		return -7;
	ts.mode = mode;
	strcpy(ts.file, hostfile);

	// Now do the transfer
	status = tftp_init(&ts);
	if (status) return status;
	while ((status = tftp_tick(&ts)) == 1);	// Loop until complete or error
	if (!put)
		*len = ts.buf_used;
	return status;
}

⌨️ 快捷键说明

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