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

📄 tftp_client.c

📁 某个ARM9板子的实际bootloader 对裁剪
💻 C
字号:
/***************************************************************************** Copyright  Storlink Corp 2005.  All rights reserved.                *--------------------------------------------------------------------------* Name			: tftp_client.c* Description	: *		Handle TFTP Client function** History**	Date		Writer		Description*	-----------	-----------	-------------------------------------------------*	04/27/2005	Gary Chen	Create*****************************************************************************/#include <define.h>#include <net.h>#include "chksum.h"static UINT16 tftpc_get_sport(void);#define TFTP_BUF_SIZE			512#define TFTP_PKT_SIZE			(TFTP_HDR_SIZE + TFTP_BUF_SIZE)#define TFTP_TIMEOUT_NUM		5#define _DUMP_WAITING_CHAR		1static UINT64 wait_time;#ifdef _DUMP_WAITING_CHARstatic void show_waiting_char(void){	UINT64 current_time;		current_time =  sys_get_ticks();	if ((current_time - wait_time) > (BOARD_TPS / 4))	{		wait_time = current_time;		printf(".");	}}#else	#define show_waiting_char()#endif	/*----------------------------------------------------------------------* tftpc_get*	Get a file from server (with IP address)*	Handle binary only*----------------------------------------------------------------------*/int tftpc_get(char *filename, UINT32 server, char *buf, int len, int *total_size){	tftp_header_t	*tftp;	int 			s;	int				data_len, file_len;	char			*cp, *fp;	UINT16			sport, server_port;	int 			recv_len;	int				total_timeouts;	int				last_good_block;	int				actual_len, total;		*total_size = 0;		if ((s = udp_socket(server)) < 0)	{		return TFTP_NET_ERR;	}		if (!(tftp = (tftp_header_t *)malloc(TFTP_PKT_SIZE)))	{		udp_close(s);		return TFTP_NO_BUF;	}	    // build TFTP header    tftp->th_opcode = htons(TFTP_RRQ);	// read request    data_len = 2;        // add filename, including null character    cp = (char *)&tftp->th_stuff;    fp = filename;    file_len = strlen(filename);    memcpy(cp, filename, file_len+1);    cp += file_len + 1;    data_len += file_len + 1;    	// add mode, binary only	strcpy(cp, "OCTET");	cp += 5;	*cp++ = '\0';	data_len += 6;		sport = tftpc_get_sport();	    if (udp_sendto(s, (char *)tftp, data_len, server, sport, TFTP_PORT) < 0)    {    	free(tftp);		udp_close(s);        return TFTP_NET_ERR;    }        // wait response    // Read data    fp = buf;    total_timeouts = 0;    last_good_block = 0;    total = 0;    while (1)    {    	int rc;    	rc = udp_recvfrom(s, (char *)tftp, sport, &server_port, TFTP_PKT_SIZE, 3000);    	if (rc < 0)	// error    	{    		free(tftp);			udp_close(s);			return TFTP_NET_ERR;		}		else if (rc == 0) // timeout		{            if ((++total_timeouts > TFTP_TIMEOUT_NUM) || (last_good_block == 0))    		{    			free(tftp);				udp_close(s);				return TFTP_TIMEOUT;			}			            // Try resending last ACK            tftp->th_opcode = htons(TFTP_ACK);            tftp->th_block = htons(last_good_block);    		if (udp_sendto(s, (char *)tftp, 4, server, sport, server_port) < 0)    		{    			free(tftp);				udp_close(s);				return TFTP_NET_ERR;            }        }         else // got data        {        	data_len = rc;            if (ntohs(tftp->th_opcode) == TFTP_DATA)            {                actual_len = 0;                if (ntohs(tftp->th_block) == (last_good_block + 1))                {                    // Consume this data                    cp = tftp->th_data;                    data_len -= 4;  /* Sizeof TFTP header */                    actual_len = data_len;                    total += actual_len;					// printf("1: len = %d, data_len=%d ", len, data_len);					//if (data_len != 512)					//	printf("data_len=%d\n", data_len);						                    while (data_len-- > 0)                    {                        if (len > 0)                        {                            *fp++ = *cp++;                        }                        len --;                    	if (len <= 0 && data_len > 0)                    	{							// printf("TFTP_TOO_LARGE\n");							free(tftp);							udp_close(s);							return TFTP_TOO_LARGE;						}                    } 					// printf("\t2: len = %d\n", len);                    last_good_block++;                }                else                {                	// maybe re-transmit data block (same seq)                	// set actual_len to avoid returning                	actual_len = TFTP_BUF_SIZE;                }                	                // Send out the ACK                tftp->th_opcode = htons(TFTP_ACK);                tftp->th_block = htons(last_good_block);    			if (udp_sendto(s, (char *)tftp, 4, server, sport, server_port) < 0)    			{    				free(tftp);					udp_close(s);					return TFTP_NET_ERR;				}                if (len==0 || ((actual_len >= 0) && (actual_len < TFTP_BUF_SIZE)))                {    				free(tftp);					udp_close(s);					*total_size = total;                    return 0;                }            }             else if (ntohs(tftp->th_opcode) == TFTP_ERROR)            {            	int err;            	err = ntohs(tftp->th_code);    			free(tftp);				udp_close(s);                return err;            } else {                // What kind of packet is this?    			free(tftp);				udp_close(s);                return TFTP_UNKNOWN;            }        }        show_waiting_char();    }    	free(tftp);	udp_close(s);		return 0;}/*----------------------------------------------------------------------* tftpc_put*	PUT a file to server (with IP address)*	Handle binary only*----------------------------------------------------------------------*/int tftpc_put(char *filename, UINT32 server, char *buf, int len, int *total_size){	tftp_header_t	*tftp;	int 			s;	int				data_len, file_len;	char			*cp, *fp, *sfp;	UINT16			sport, server_port;	int 			recv_len;	int				total_timeouts;	int				last_good_block;	int				actual_len, total;	int 			rc;		*total_size = 0;	if ((s = udp_socket(server)) < 0)	{		return TFTP_NET_ERR;	}		if (!(tftp = (tftp_header_t *)malloc(TFTP_PKT_SIZE)))	{		udp_close(s);		return TFTP_NO_BUF;	}	    total_timeouts = 0;    while (1)    {        // Init TFTP Request Header Code - Write File        tftp->th_opcode = htons(TFTP_WRQ);        data_len=2;    	    	// add filename, including null character    	cp = (char *)&tftp->th_stuff;    	fp = filename;    	file_len = strlen(filename);    	memcpy(cp, filename, file_len+1);    	cp += file_len + 1;    	data_len += file_len + 1;    		// add mode, binary only		strcpy(cp, "OCTET");		cp += 5;		*cp++ = '\0';		data_len += 6;				// send request		sport = tftpc_get_sport();    	if (udp_sendto(s, (char *)tftp, data_len, server, sport, TFTP_PORT) < 0)    	{    		free(tftp);			udp_close(s);			return TFTP_NET_ERR;    	}        // Wait for ACK    	rc = udp_recvfrom(s, (char *)tftp, sport, &server_port, TFTP_PKT_SIZE, 3000);    	if (rc < 0)	// error    	{    		free(tftp);			udp_close(s);			return TFTP_NET_ERR;		}		else if (rc == 0) // timeout		{			if (++total_timeouts > TFTP_TIMEOUT_NUM)			{    			free(tftp);				udp_close(s);				return TFTP_TIMEOUT;			}		}		else		{			total_timeouts = 0;			if (ntohs(tftp->th_opcode) == TFTP_ACK)				break;			else if (ntohs(tftp->th_opcode) == TFTP_ERROR)			{				int err = ntohs(tftp->th_code);    			free(tftp);				udp_close(s);				return err;            }            else            {    			free(tftp);				udp_close(s);				return TFTP_UNKNOWN;            }        }        show_waiting_char();    }    // Send data    sfp = buf;    last_good_block = 1;    total = 0;    while (total <= len)    {        // Build packet of data to send        data_len = min(TFTP_BUF_SIZE, len - total);        tftp->th_opcode = htons(TFTP_DATA);        tftp->th_block = htons(last_good_block);        cp = tftp->th_data;        fp = sfp;        actual_len = data_len + 4;        while (data_len)        {        	*cp++ = *fp++;        	data_len--;        }            	if (udp_sendto(s, (char *)tftp, actual_len, server, sport, server_port) < 0)    	{    		free(tftp);			udp_close(s);			return TFTP_NET_ERR;		}				if (actual_len == 4) // no data			goto put_end;		        // Wait for ACK    	rc = udp_recvfrom(s, (char *)tftp, sport, &server_port, TFTP_PKT_SIZE, 3000);    	if (rc < 0)	// error    	{    		free(tftp);			udp_close(s);			return TFTP_NET_ERR;		}		else if (rc == 0) // timeout		{			if (++total_timeouts > TFTP_TIMEOUT_NUM)			{    			free(tftp);				udp_close(s);				return TFTP_TIMEOUT;			}		}		else		{			total_timeouts = 0;            if (ntohs(tftp->th_opcode) == TFTP_ACK)            {                if (ntohs(tftp->th_block) == last_good_block)                {                    sfp = fp;                    total += (actual_len - 4);                    last_good_block++;                }            }            else if (ntohs(tftp->th_opcode) == TFTP_ERROR)            {				int err = ntohs(tftp->th_code);    			free(tftp);				udp_close(s);				return err;			}            else            {    			free(tftp);				udp_close(s);				return TFTP_UNKNOWN;            }        }        show_waiting_char();    }put_end:        free(tftp);    udp_close(s);        *total_size = total;        return 0;}/*----------------------------------------------------------------------* tftpc_get_sport*----------------------------------------------------------------------*/static UINT16 tftpc_get_sport(void){	static int tftp_sport = 7700;		tftp_sport++;	if (tftp_sport >= 7800)		tftp_sport = 7700;			return tftp_sport;}/*----------------------------------------------------------------------* tftpc_get_sport*----------------------------------------------------------------------*/char *tftp_err_msg(int code){	switch (code)	{		case TFTP_NO_BUF:		return ("no free buffer");		case TFTP_NET_ERR:		return ("network error");		case TFTP_TIMEOUT:		return ("timeout");		case TFTP_TOO_LARGE:	return ("File is too large");		case TFTP_EUNDEF:		return ("not defined");		case TFTP_ENOTFOUND:	return ("file not found"); 		case TFTP_EACCESS:		return ("access violation");		case TFTP_ENOSPACE:		return ("disk full or allocation exceeded");		case TFTP_EBADOP:		return ("illegal TFTP operation");		case TFTP_EBADID:		return ("unknown transfer ID");		case TFTP_EEXISTS:		return ("file already exists");		case TFTP_ENOUSER:		return ("no such user");		default:				return ("Unknown!");	}}	

⌨️ 快捷键说明

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