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

📄 update.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 2 页
字号:
	* RETR reply after transfer should be "226"
	*/
	if (FtpRecvReply(ctrl_fd) < 0 || ftp_reply[0] != '2')
	{
		fprintf(stderr, "error while transfer\n");
		/* 释放内存 */
		ClearUpdateBlock(update_block.next);
		return UPDATE_CONN_ERROR;
	}
	else
	{
		#ifdef __UPDATE_DEBUG__
		printf("%.3s: transfer completed\n", ftp_reply);
		printf("file %s %d bytes got\n", filename, count);
		#endif
	}
	
	close(data_fd);
	FtpQuitServer(ctrl_fd);
	close(ctrl_fd);
			
	/* 写入Flash */
	result = UpdateFlashRom(update_block.next, count, fileType);
	
	ClearUpdateBlock(update_block.next);
	
	#ifdef __UPDATE_DEBUG__
	if (result == UPDATE_OK)
	{
		printf("Update OK.\n");
	}
	#endif

	return result;
}

static int FtpQuitServer(int ctrl_fd)
{
	/**
	* Command QUIT
	*/

	if (FtpCommand(ctrl_fd, ftp_quit_cmd, NULL) < 0)
	{
		fprintf(stderr, "QUIT error\n");
		return UPDATE_CONN_ERROR;
	}

	/**
	* QUIT reply should be "221"
	*/
	if (FtpRecvReply(ctrl_fd) < 0 || ftp_reply[0] != '2')
	{
		fprintf(stderr, "error recv QUIT\n");
		return UPDATE_CONN_ERROR;
	}
	else
	{
		#ifdef __UPDATE_DEBUG__
		printf("%.3s: quit from server\n", ftp_reply);
		#endif
	}
	
	return UPDATE_OK;
}

static int FtpCommand(int sockfd, char * cmd, const char * param)
{
	int len;
	memset(ftp_request, 0, FTP_REQ_LENGTH);
	len = sprintf(ftp_request, "%s %s\r\n", cmd, (param == NULL)? "" : param);
	#ifdef __FTP_DEBUG
	printf("%s %s\r\n", cmd, (param == NULL)? "" : param);
	#endif
	return send(sockfd, ftp_request, len, 0);
}
static int FtpRecvReply2(int sockfd)
{
	int len;
	char data;
	int ret;
	fd_set rset;
	struct timeval tv;
	FD_ZERO(&rset);
	FD_SET(sockfd, &rset);
	tv.tv_sec = 0;
	tv.tv_usec = 500;
	if ((len = recv(sockfd, ftp_reply, 3, 0)) <= 0)
	{
		memset(ftp_reply, 0, sizeof(ftp_reply));
		return -1;
	}
	while((ret = select(sockfd + 1, &rset, NULL, NULL, &tv))>0)
	{
		if ((len = recv(sockfd, &data, 1, 0)) <= 0)
		{
			memset(ftp_reply, 0, sizeof(ftp_reply));
			return -1;
		}
	}
	return len;
}

static int FtpRecvReply(int sockfd)
{
	int len;
	char data;
	if ((len = recv(sockfd, ftp_reply, 3, 0)) <= 0)
	{
		memset(ftp_reply, 0, sizeof(ftp_reply));
		return -1;
	}
	
	while (data != '\n')
	{
		if ((len = recv(sockfd, &data, 1, 0)) <= 0)
		{
			memset(ftp_reply, 0, sizeof(ftp_reply));
			return -1;
		}
	}
	
	return len;
}

/*************************************************************************************
* Part TFTP_Update
*************************************************************************************/
static int TftpUpdate()
{
	int sockfd, ret;
		
	#ifdef __UPDATE_DEBUG__
	printf("Begin tftp update...\n");
	#endif
	
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
	{
		perror("tftp socket");
		return UPDATE_CONN_ERROR;
	}
	memset(&tftp_server_addr, 0, addr_len);
	tftp_server_addr.sin_len = addr_len;
	tftp_server_addr.sin_family = AF_INET;
	tftp_server_addr.sin_port = htons(TFTP_SERVER_PORT);
	tftp_server_addr.sin_addr.s_addr = htonl(phoneconfig.conf_ftp.server);
	
	tftp_tid = 0;
	tftp_index = 1;
	
	if (TftpSendRRQ(sockfd, phoneconfig.conf_ftp.filename) < 0)
	{
		perror("send RRQ");
		close(sockfd);
		return UPDATE_CONN_ERROR;
	}
	
	ret = TftpGetUpdate(sockfd);
	close(sockfd);
	return ret; 
}

/*******************************************************
* 向服务器发送RRQ请求
* RRQ的报文格式
*
* 			 2     string        1      string       1 
*          -----------------------------------------------
*   RRQ   |  01 |  Filename  |   0  |    Mode    |   0  |
*          -----------------------------------------------
*
*******************************************************/
static int TftpSendRRQ(int sockfd, char * filename)
{
	int offset = 0;
	
	memset(tftp_lastdata.data, 0, TFTP_TMP_LENGTH);
	tftp_lastdata.data[1] = TFTP_OP_RRQ;
	offset += 2;
	offset += sprintf(& tftp_lastdata.data[offset], "%s", filename);
	offset++;
	offset += sprintf(& tftp_lastdata.data[offset], "%s", tftp_filemode);
	offset++;
	tftp_lastdata.length = offset;
	
	#ifdef __UPDATE_DEBUG__
	printf("send RRQ...get file %s\n", filename);
	#endif
	
	return sendto(sockfd, (void *) tftp_lastdata.data, offset, 0, (struct sockaddr *) &tftp_server_addr, addr_len);
}

/*******************************************************
* 向服务器发送ACK
* ACK的报文格式
*
*             2       2 bytes
*          -------------------
*   ACK   |  04   |  Block #  |
*          --------------------
*
*******************************************************/
static int TftpSendAck(int sockfd, unsigned short index)
{
	tftp_lastdata.data[0] = 0;
	tftp_lastdata.data[1] = TFTP_OP_ACK;
	memcpy(&tftp_lastdata.data[2], &index, 2);
	tftp_lastdata.length = 4;
		
	return sendto(sockfd, (void *) tftp_lastdata.data, 4, 0, (struct sockaddr *) &tftp_server_addr, addr_len);
}

static int TftpGetResponse(int sockfd, int * p_len)
{
	int len, flen;
	int retry = 3;
	
	flen = addr_len;
	while (retry > 0)
	{
#ifdef __UPDATE_DEBUG__
		printf("server port %u\n", tftp_tid);
#endif
		if (readable_timeo(sockfd, TFTP_TIMEOUT) <= 0)
		{
			if (--retry <= 0)
			{
				fprintf(stderr, "No answer from TFTP server after 3 try, Quit.\n");
				return UPDATE_CONN_ERROR;
			}
			/**
			* 重新发送上次的报文
			*/
			#ifdef __UPDATE_DEBUG__
			printf("ReSend last data\n", retry);
			#endif
			if (sendto(sockfd, (void *) tftp_lastdata.data, tftp_lastdata.length, 0, 
					(struct sockaddr *) &tftp_server_addr, addr_len) < 0)
			{
				perror("ReSend last data while timeout");
				return UPDATE_CONN_ERROR;
			}
			continue;
		}
		/**
		* 收到服务器端的应答
		*/
		if ((len = recvfrom(sockfd, (void *) &tftp_fileblock, sizeof(s_tftp_data), 0,
				(struct sockaddr *) &tftp_server_addr, &flen)) < 0)
		{
			perror("recv DATA");
			return UPDATE_CONN_ERROR;
		}
		/**
		* 收到其他端口发送的报文 丢弃该报文
		*/
		if (tftp_tid != 0 && tftp_tid != ntohs(tftp_server_addr.sin_port))
		{
			tftp_server_addr.sin_port = htons(tftp_tid);
			fprintf(stderr, "Got packet from other TID!\n");
			continue;
		}
		/**
		* 收到ERROR报文 返回错误
		*/
		if (ntohs(tftp_fileblock.op) == TFTP_OP_ERROR)
		{
			fprintf(stderr, "file not exist!\n");
			return UPDATE_FILE_NOTEXIST;	
		}
		/**
		* 收到其它无法识别的报文类型 丢弃
		*/
		else if (ntohs(tftp_fileblock.op) != TFTP_OP_DATA)
		{
			fprintf(stderr, "OP error!\n");
			continue;
		}
		/**
		* 若为RRQ的应答 记录服务器的端口
		*/
		tftp_tid = (tftp_tid == 0) ? ntohs(tftp_server_addr.sin_port) : tftp_tid;
		/**
		* 收到数据报文 比较数据块的编号 回送确认 
		*/
		if (tftp_index - 1 == ntohs(tftp_fileblock.index))
		{
			/* 服务器没有收到上次的ACK 重发 */
			if (TftpSendAck(sockfd, tftp_fileblock.index) < 0)
			{
				perror("RESend data ACK");
				return UPDATE_CONN_ERROR;
			}
			continue;
		}
		else if (tftp_index == ntohs(tftp_fileblock.index))
		{
			if (TftpSendAck(sockfd, tftp_fileblock.index) < 0)
			{
				perror("send data ACK");
				return UPDATE_CONN_ERROR;
			}
			*p_len = len;
			break;
		}
		else
		{
			return UPDATE_ERROR_UNKNOWN;
		}
	}
	if (retry <= 0)
	{
		return UPDATE_CONN_ERROR;
	}
	else
	{
		return UPDATE_OK;
	}
}

/*******************************************************
* 获得升级文件 进行升级操作
*******************************************************/
static int TftpGetUpdate(int sockfd)
{
	int len, flen;
	int offset = 0;
	int count = 0;
	int fileType;
	unsigned char done = 0;
	unsigned short index = 0;
	int result = UPDATE_OK;
	s_updateblock update_block;
	s_updateblock * p;
		
	update_block.next = NULL;
	fileType = 0;
	p = & update_block;
	while (!done)
	{
		if ((result = TftpGetResponse(sockfd, &len)) != UPDATE_OK)
		{
			break;
		}
		if ((count + len - 4) > COMPRESSED_IMAGE_ADDR)
		{
			fprintf(stderr, "file too long\n");
			result = UPDATE_NO_SPACE;
			break;
		}
		if (count == 0)
		{
			if (len > 4)
			{
				if ( memcmp(tftp_fileblock.fileblock, phoneconfig.bootFileHead, 4) == 0 )
					fileType = 1;
				if ( memcmp(tftp_fileblock.fileblock, phoneconfig.appFileHead, 4) == 0 )
					fileType = 2;
			}
			if (fileType != 1 && fileType != 2)
			{
				printf("file type error!\n\n");
				return UPDATE_INVALID_FILE;
			}
		}
		count += len - 4;
		if (tftp_index % 2 != 0)
		{
			if ((p -> next = ConstructBlockNode()) == NULL)
			{
				fprintf(stderr, "file too long\n");
				result = UPDATE_NO_SPACE;
				break;
			}
			p = p -> next;
			memcpy(p -> fileblock, tftp_fileblock.fileblock, len - 4);
			p -> length = len - 4;
		}
		else
		{
			memcpy(p -> fileblock + p -> length, tftp_fileblock.fileblock, len - 4);
			p -> length += len - 4;
		}
		if (len < TFTP_BLOCK_SIZE + 4)
		{
			done = 1;
		}
		tftp_index++;	
	}
	if (done)
	{
		#ifdef __UPDATE_DEBUG__
		printf("file %s %d bytes got\n", phoneconfig.conf_ftp.filename, count);
		#endif
		if (count == 0)
		{
			printf("file size is 0!!!\n\n");
			return UPDATE_INVALID_FILE;
		}
		/* 写入Flash */
		result = UpdateFlashRom(update_block.next, count, fileType);
		/*
		Program_Version_Flash_Mem((unsigned short *) ptr_file, (p - ptr_file));
		*/
	}
	#ifdef __UPDATE_DEBUG__
	if (result == UPDATE_OK)
	{
		printf("Update OK.\n");
	}
	#endif
	ClearUpdateBlock(update_block.next);
	return result;
}


/*******************************************************
* Part UPDATE_COMMON
*******************************************************/
static s_updateblock * ConstructBlockNode(void)
{
	s_updateblock * ptr_block;
	if ((ptr_block = (s_updateblock *) malloc(sizeof(s_updateblock))) == NULL)
	{
		return NULL;
	}
	if ((ptr_block -> fileblock = (unsigned char *) malloc(UPDATE_BUFFER)) == NULL)
	{
		free(ptr_block);
		return NULL;
	}
	memset(ptr_block -> fileblock, 0, UPDATE_BUFFER);
	ptr_block -> length = 0;
	ptr_block -> next = NULL;
	return ptr_block;
}

void ClearUpdateBlock(s_updateblock * ptr_updatefile)
{
	s_updateblock * p, * q;
	
	#ifdef __UPDATE_DEBUG__
	printf("Clear Update Node...\n");
	#endif
	
	if (ptr_updatefile == NULL)
	{
		return;
	}
	for (p = ptr_updatefile; p != NULL; p = q)
	{
		free(p -> fileblock);
		q = p -> next;
		free(p);
	}	
	return;
}

int UpdateFlashRom(s_updateblock * ptr_updatefile, int count, int fileT)
{
	s_updateblock * p;
	unsigned short * pAddr = (unsigned short *) COMPRESSED_IMAGE_ADDR;
	unsigned short * pBootAddr = (unsigned short *)ROM_BASE_ADRS;
	unsigned char * ptr;
	int offset = 0;
	#ifdef __UPDATE_DEBUG__
	CheckUpdateBlock(ptr_updatefile);
	#endif

	if (fileT == 1)
	{
		if (count > BOORROMSIZE)
		{
			printf("file too long!\n\n");
			return UPDATE_TOO_LONG;
		}
/*if (1)
{
printf("demo update OK!");
return UPDATE_OK;
}*/
	/** 	remove by chenguoyin 
		if ((ptr = (unsigned char *) malloc(300 * 1024)) == NULL)
		{
			fprintf(stderr, "error malloc boot\n");
			return -1;
		}
		for (p = ptr_updatefile; p != NULL; p = p -> next)
		{
			memcpy(ptr + offset, p -> fileblock, p -> length);
			offset += p -> length;
		}
		Program_Boot_Flash_Mem((unsigned short *) ptr, offset);
		free(ptr);
	
	**/
		
	        if ( gFlashType == SST )
    		{
        		if ( count> ( COMPRESSED_IMAGE_ADDR - ROM_BASE_ADRS - 4 - SST_BLOCK_SIZE_UINT16 * 2 * 2 ) )
       		 {
           			 printf("The Version is to Large!\n");
            			return UPDATE_TOO_LONG;
        		}
   		 }
   		 else
    		{
        		if (count > ( COMPRESSED_IMAGE_ADDR - ROM_BASE_ADRS - 4 - FLASH_SECTOR_SIZE * 2) )
        		{
            			printf("The Version is to Large!\n");
            			return UPDATE_TOO_LONG;
        		}
   		 }
             if ( Erase_Boot_Flash_Mem () != OK )
                     return UPDATE_WRITE_ERROR;
        	for (p = ptr_updatefile; p != NULL && count > 0; p = p -> next)
		{
			if (Program_Version_Flash_Mem((unsigned short *) p -> fileblock, pBootAddr, p -> length) != OK)
			{
				fprintf(stderr, "Write Flash ROM ERROR!\n");
				return UPDATE_WRITE_ERROR;
			}
			pBootAddr += p -> length / 2;
			count -= p -> length / 2;
		}
		
	}
	else if (fileT == 2)
	{
		if (count > APPSIZE)
		{
			printf("file too long!\n\n");
			return UPDATE_TOO_LONG;
		}
/*if (1)
{
printf("demo update OK!");
return UPDATE_OK;
}*/
		if (count > COMPRESSED_IMAGE_SIZE)
		{
			fprintf(stderr, "The Version is too Large!\n");
			return UPDATE_NO_SPACE;
		}

	      SetVersionUpdateFlag ( 0xff );/*2004-7-12 fujiangdong update begin*/

		if (Erase_Version_Flash_Mem () != OK)
		{
			fprintf(stderr, "Erase Flash ROM ERROR!\n");
			return UPDATE_WRITE_ERROR;
		}
		for (p = ptr_updatefile; p != NULL && count > 0; p = p -> next)
		{
			if (Program_Version_Flash_Mem((unsigned short *) p -> fileblock, pAddr, p -> length) != OK)
			{
				fprintf(stderr, "Write Flash ROM ERROR!\n");
				return UPDATE_WRITE_ERROR;
			}
			pAddr += p -> length / 2;
			count -= p -> length / 2;
		}
             SetVersionUpdateFlag ( 0x32 );/*2004-7-12 fujiangdong update begin*/
	}

	#ifdef __UPDATE_DEBUG__
	printf("Write Flash OK.\n");
	#endif
	return UPDATE_OK;
}

#ifdef __UPDATE_DEBUG__
static void CheckUpdateBlock(s_updateblock * ptr)
{
	s_updateblock * p;
	int i;
	
	for (p = ptr, i = 0; p != NULL; p = p -> next, i++)
	{
		/* none */
	}
	printf("There are %d blocks in the Update file\n", i);
	return;
}
#endif

#ifdef __cplusplus
}
#endif

⌨️ 快捷键说明

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