<file_sep>================================================================================
MICROSOFT 基础类库: V9_BATCH_UP 项目概述
===============================================================================

应用程序向导已为您创建了这个 V9_BATCH_UP 应用程序。此应用程序不仅演示 Microsoft 基础类的基本使用方法，还可作为您编写应用程序的起点。

本文件概要介绍组成 V9_BATCH_UP 应用程序的每个文件的内容。

V9_BATCH_UP.vcproj
这是使用应用程序向导生成的 VC++ 项目的主项目文件。 
它包含生成该文件的 Visual C++ 的版本信息，以及有关使用应用程序向导选择的平台、配置和项目功能的信息。

V9_BATCH_UP.h
这是应用程序的主要头文件。它包括其他项目特定的头文件(包括 Resource.h)，并声明 CV9_BATCH_UPApp 应用程序类。

V9_BATCH_UP.cpp
这是包含应用程序类 CV9_BATCH_UPApp 的主要应用程序源文件。

V9_BATCH_UP.rc
这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ 中进行编辑。项目资源位于 2052 中。

res\V9_BATCH_UP.ico
这是用作应用程序图标的图标文件。此图标包括在主要资源文件 V9_BATCH_UP.rc 中。

res\V9_BATCH_UP.rc2
此文件包含不在 Microsoft Visual C++ 中进行编辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。


/////////////////////////////////////////////////////////////////////////////

应用程序向导创建一个对话框类:

V9_BATCH_UPDlg.h，V9_BATCH_UPDlg.cpp - 对话框
这些文件包含 CV9_BATCH_UPDlg 类。该类定义应用程序主对话框的行为。该对话框的模板位于 V9_BATCH_UP.rc 中，该文件可以在 Microsoft Visual C++ 中进行编辑。


/////////////////////////////////////////////////////////////////////////////

其他功能:

ActiveX 控件
应用程序包括对使用 ActiveX 控件的支持。

/////////////////////////////////////////////////////////////////////////////

其他标准文件:

StdAfx.h，StdAfx.cpp
这些文件用于生成名为 V9_BATCH_UP.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。

Resource.h
这是标准头文件，它定义新的资源 ID。
Microsoft Visual C++ 读取并更新此文件。

V9_BATCH_UP.manifest
	应用程序清单文件供 Windows XP 用来描述应用程序
	对特定版本并行程序集的依赖性。加载程序使用此
	信息从程序集缓存加载适当的程序集或
	从应用程序加载私有信息。应用程序清单可能为了重新分发而作为
	与应用程序可执行文件安装在相同文件夹中的外部 .manifest 文件包括，
	也可能以资源的形式包括在该可执行文件中。 
/////////////////////////////////////////////////////////////////////////////

其他注释:

应用程序向导使用“TODO:”指示应添加或自定义的源代码部分。

如果应用程序在共享的 DLL 中使用 MFC，则需要重新发布这些 MFC DLL；如果应用程序所用的语言与操作系统的当前区域设置不同，则还需要重新发布对应的本地化资源 MFC90XXX.DLL。有关这两个主题的更多信息，请参见 MSDN 文档中有关 Redistributing Visual C++ applications (重新发布 Visual C++ 应用程序)的章节。

/////////////////////////////////////////////////////////////////////////////
<file_sep>//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by V9_BATCH_UP.rc
//
#define IDM_ABOUTBOX                    0x0010
#define IDD_ABOUTBOX                    100
#define IDS_ABOUTBOX                    101
#define IDD_V9_BATCH_UP_DIALOG          102
#define IDR_MAINFRAME                   128
#define IDC_LIST1                       1000
#define IDC_LIST2                       1001
#define IDC_BUTTON1                     1002
#define IDC_BUTTON2                     1003
#define IDC_PROGRESS1                   1004
#define IDC_RADIO1                      1005
#define IDC_RADIO2                      1006
#define IDC_EDIT1                       1007
#define IDC_BUTTON3                     1008
#define IDC_EDIT2                       1013
#define IDC_STATIC1                     1014
#define IDC_STATIC2                     1015
#define IDC_STATIC3                     1016
#define IDC_STATIC4                     1017
#define IDC_STATIC5                     1018
#define IDC_STATIC11                    1019
#define IDC_STATIC15                    1020

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        132
#define _APS_NEXT_COMMAND_VALUE         32771
#define _APS_NEXT_CONTROL_VALUE         1021
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
<file_sep>CC = arm-hisiv200-linux-gcc

OPTIMIZER =	-O3

CFLAGS =$(OPTIMIZER) -Wall -D_GNU_SOURCE
OBJS = wibox_batch_up.o

PGM = wibox_batch_up

all:$(PGM)

$(PGM): $(OBJS)
	$(CC) -o $(PGM) $(OBJS) -lpthread 

clean:
	-rm -f *.o $(PGM)
<file_sep>// V9_BATCH_UPDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "V9_BATCH_UP.h"
#include "V9_BATCH_UPDlg.h"
#include <Winsock2.h> 
#include <stdio.h>
#include <process.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

static CV9_BATCH_UPDlg *pMain;
UINT __stdcall GetDevThread(void* lpParam) ;
UINT __stdcall updatemain(void* lpParam)  ;
UINT __stdcall tcp_client(void* lpParam)  ;

#define BATCH_UP_PORT 20000
#define BATCH_UP_PORT_C 20001
#define BATCH_STATUS_PORT 20002



//#define UPDATEDIR "updates\\910"
#define UPDATEDIR ".\\"
#define UPDATENAME "updates"
#define BUFFSIZE 1024

int file_md5(const char *file, char *md5);
int tar_gzip(const char *files, const char *tgz);
unsigned long long  file_len(const char *file);
int send_pack(SOCKET s, const char *buf, int len, int flags);
BOOL CreateCSV (char *file);
BOOL AddToCSV (char *file, struct DEVINFOLIST *host, int *status);

HANDLE  g_hThreadParameter; 
HANDLE  g_status[BOARD_MAX];
HANDLE  g_status_check[BOARD_MAX];


char md5[50] = {0};
unsigned long long g_file_len;




UINT __stdcall GetDevThread(void* lpParam)  
{
 

	CString str;

	
	DEVINFO devinfo;

	SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockSrv == INVALID_SOCKET)
	{
		str.Format ("%s", "socket error");
		AfxMessageBox(str);
		return -1; 
	}
	SOCKADDR_IN addrSrv; 
	memset(&addrSrv, 0, sizeof(SOCKADDR_IN));
	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 将INADDR_ANY转换为网络字节序，调用 htonl(long型)或htons(整型)  
	addrSrv.sin_family = AF_INET;  
	addrSrv.sin_port = htons(BATCH_UP_PORT);  
	if(bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)) == SOCKET_ERROR)
	{
		str.Format ("%s", "bind error");
		AfxMessageBox(str);
		return -1; 		
	}
	//if(listen(sockSrv, 30) == SOCKET_ERROR)
	//{
	//	str.Format ("%s", "listen error");
	//	AfxMessageBox(str);
	//	return -1; 
	//}

	SOCKADDR_IN  addrClient;  
	int addrClientsz;
	int len=sizeof(SOCKADDR);
	char ip[100];
	//char buf[100];
	while (1)
	{
		//SOCKET sockConn = recvfrom(sockSrv, (SOCKADDR*)&addrClient, &len); 
		addrClientsz = sizeof(SOCKADDR_IN);
		recvfrom(sockSrv, (char *)&devinfo, sizeof(devinfo), 0, (SOCKADDR *)&addrClient, &addrClientsz); 
		//sprintf(buf, "client %s connect to the server\n", inet_ntoa(addrClient.sin_addr));  
		//AfxMessageBox(buf);
		sprintf(ip, "%s", inet_ntoa(addrClient.sin_addr)); 
		//recv(sockConn, (char *)&devinfo.type, sizeof(devinfo.type), 0);
		devinfo.type = ntohl(devinfo.type);
		//sprintf(buf, "%x", ntohl(devinfo.type));
		//AfxMessageBox(buf);
		//recv(sockConn, devinfo.routeV, sizeof(devinfo.routeV), 0); 
		//AfxMessageBox(devinfo.routeV);
		//recv(sockConn, devinfo.kernelV, sizeof(devinfo.kernelV), 0); 
		//recv(sockConn, devinfo.appV, sizeof(devinfo.appV), 0); 
		//recv(sockConn, devinfo.recordV, sizeof(devinfo.recordV), 0); 
		//AfxMessageBox(devinfo.recordV);
		//recv(sockConn, devinfo.bsV, sizeof(devinfo.bsV), 0); 
			
		pMain->AddHost(ip, &devinfo);
		//pMain->listboard();
		//closesocket(sockConn);  
	}

	
	closesocket(sockSrv); 
	//WSACleanup();
	return 0;
}

UINT __stdcall GetStatusThread(void* lpParam) 
{
	CString str;
	SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
	if (sockSrv == INVALID_SOCKET)
	{
		str.Format ("%s", "socket error");
		AfxMessageBox(str);
		return -1; 
	}
	SOCKADDR_IN addrSrv; 
	memset(&addrSrv, 0, sizeof(SOCKADDR_IN));
	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 将INADDR_ANY转换为网络字节序，调用 htonl(long型)或htons(整型)  
	addrSrv.sin_family = AF_INET;  
	addrSrv.sin_port = htons(BATCH_STATUS_PORT);  
	if(bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)) == SOCKET_ERROR)
	{
		str.Format ("%s", "bind error");
		AfxMessageBox(str);
		return -1; 		
	}
	if(listen(sockSrv, 30) == SOCKET_ERROR)
	{
		str.Format ("%s", "listen error");
		AfxMessageBox(str);
		return -1; 
	}

	SOCKADDR_IN  addrClient;  
	int len=sizeof(SOCKADDR);
	char ip[100];
	char buf[10];
	int sta;
	while (1)
	{
		SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len); 
		//sprintf(buf, "client %s connect to the server\n", inet_ntoa(addrClient.sin_addr));  
		//AfxMessageBox(buf);
		sprintf(ip, "%s", inet_ntoa(addrClient.sin_addr)); 
		memset(buf, 0, sizeof(buf));
		recv(sockConn, buf, sizeof(buf), 0); 

		if(strncmp(buf, "status:", 7) != 0)
		{
			//closesocket(sockSrv);
			AfxMessageBox("板卡返回数据有误");
			closesocket(sockConn);
			continue;
		
		}
		if(strlen(buf) < 9)
		{
			//closesocket(sockSrv);
			AfxMessageBox("板卡返回数据有误");
			closesocket(sockConn);
			continue;
		
		}

		
		sta = atoi(buf+7);

		
		pMain->up_status(ip, sta);
		closesocket(sockConn);  
	}

	
	closesocket(sockSrv); 	

	return 0;
}


UINT __stdcall tcp_client(void* lpParam)
{
	int num = *(int *)lpParam;
	ReleaseSemaphore(g_hThreadParameter, 1, NULL);//信号量++  
	//int index = 0;
	//char buf[100] = {0};
	//sprintf(buf, "%d", num);

	//AfxMessageBox(buf);
	pMain->tcp_send(num);

	
	
	return 0;
}


int CV9_BATCH_UPDlg::updatefunc()
{
	if(BST_CHECKED==((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck())
	{
		tcp_update();
	}
	else if(BST_CHECKED==((CButton*)GetDlgItem(IDC_RADIO2))->GetCheck())
	{
		ftp_update();
	}


	((CButton*)GetDlgItem(IDOK))->EnableWindow(TRUE);
	((CButton*)GetDlgItem(IDC_BUTTON1))->EnableWindow(TRUE);
	((CButton*)GetDlgItem(IDC_BUTTON2))->EnableWindow(TRUE);
	return 0;
}

UINT __stdcall updatemain(void* lpParam)
{

	//while (pMain->updateflag)
	{
		pMain->updatefunc();
	}	

	return 0;
}

int CV9_BATCH_UPDlg::insertHost(DEVINFOLIST *pos, const char *ip, struct DEVINFO *info)
{
	struct DEVINFOLIST * p = (struct DEVINFOLIST *) malloc (sizeof (DEVINFOLIST));
	if (p == NULL)
	{
		AfxMessageBox("内存不足");
	}
	memset(p, 0, sizeof(DEVINFOLIST));
	strcpy(p->ip, ip);
	strcpy(p->name, info->name);
	p->type = info->type;
	strcpy(p->routeV, info->routeV);
	strcpy(p->kernelV, info->kernelV);
	strcpy(p->appV, info->appV);
	strcpy(p->recordV, info->recordV);
	strcpy(p->bsV, info->bsV);
	p->pNext = pos->pNext;
	pos->pNext = p;
	
	return 0;
}

int CV9_BATCH_UPDlg::insertUpdateHost(DEVINFOLIST *pos, DEVINFOLIST *info)
{
	struct DEVINFOLIST * p = (struct DEVINFOLIST *) malloc (sizeof (DEVINFOLIST));
	if (p == NULL)
	{
		AfxMessageBox("内存不足");
	}
	memcpy(p, info, sizeof(DEVINFOLIST));
	
	p->pNext = pos->pNext;
	pos->pNext = p;
	
	return 0;
}

int CV9_BATCH_UPDlg::delUpdateHost(DEVINFOLIST *pre, DEVINFOLIST *pos)
{
	pre->pNext = pos->pNext;
	free(pos);
	return 0;
}



int CV9_BATCH_UPDlg::listboard()
{
	DEVINFOLIST * p = m_pHost->pNext;
	CString str;
	int index = 0;
	m_listboard.DeleteAllItems();
	while(p != NULL)
	{
		str.Format ("%d", index+1);
		m_listboard.InsertItem(index, str);
		str.Format ("%s", p->ip);
		m_listboard.SetItemText(index, 1, str);
		str.Format ("%s", p->name);
		m_listboard.SetItemText(index, 2, str);
		str.Format ("0x%x", p->type);
		m_listboard.SetItemText(index, 3, str);
		str.Format ("%s", p->routeV);
		m_listboard.SetItemText(index, 4, str);
		str.Format ("%s", p->kernelV);
		m_listboard.SetItemText(index, 5, str);
		str.Format ("%s", p->appV);
		m_listboard.SetItemText(index, 6, str);
		str.Format ("%s", p->recordV);
		m_listboard.SetItemText(index, 7, str);
		str.Format ("%s", p->bsV);
		m_listboard.SetItemText(index, 8, str);

		p = p->pNext;
		index++;
	}

	char buf[10] = {0};
	sprintf(buf, "%d", index);
	GetDlgItem(IDC_STATIC15)->SetWindowText(buf);
	return 0;
}

int CV9_BATCH_UPDlg::listUpdateboard()
{
	DEVINFOLIST * p = m_pHostUpdate->pNext;
	CString str;
	int index = 0;
	m_updateboard.DeleteAllItems();
	while(p != NULL)
	{
		str.Format ("No.%d.%s@IP:%s type:0x%x", index+1, p->name, p->ip, p->type);
		m_updateboard.InsertItem(index, str);

		p = p->pNext;
		index++;
	}
	

	return 0;

}

BOOL CV9_BATCH_UPDlg::up_status(const char *ip, int sta)
{
	DEVINFOLIST * p = m_pHostUpdate->pNext;
	CString str;
	int index = 0;
	
	while(p != NULL)
	{
		if(strcmp(p->ip, ip) == 0)
		{
			if(status[index] != sta)
			{
				status[index] = sta;
				update_rec_flag(sta, p->ip, index);
				if(sta != UP_TRANS_SUC && sta != UP_MD5_SUC)
					ReleaseSemaphore(g_status[index], 1, NULL);//信号量++  
				break;

			}

		}
		p = p->pNext;
		index++;
	}	
	
	return true;
}



BOOL CV9_BATCH_UPDlg::AddHost(const char *ip, struct DEVINFO *info)
{
	CString str;
	struct DEVINFOLIST * p = m_pHost->pNext;
	struct DEVINFOLIST * pPre = m_pHost;
	int change_flag = 0;

	if (p == NULL)
	{
		//AfxMessageBox("NULL");
		insertHost(m_pHost, ip, info);
		listboard();
	} 
	else
	{
		//AfxMessageBox("not NULL");
		while (p != NULL)
		{
			//AfxMessageBox(ip);
			//AfxMessageBox(p->ip);
			if(strcmp(p->ip, ip) == 0)
			{	
				if(strcmp(p->name, info->name) != 0)
				{
					change_flag = 1;
					strcpy(p->name, info->name);
				}
				if(strcmp(p->routeV, info->routeV) != 0)
				{
					change_flag = 1;
					strcpy(p->routeV, info->routeV);
				}
				if(strcmp(p->kernelV, info->kernelV) != 0)
				{
					change_flag = 1;
					strcpy(p->kernelV, info->kernelV);
				}
				if(strcmp(p->appV, info->appV) != 0)
				{
					change_flag = 1;
					strcpy(p->appV, info->appV);
				}
				if(strcmp(p->recordV, info->recordV) != 0)
				{
					change_flag = 1;
					strcpy(p->recordV, info->recordV);
				}
				if(strcmp(p->bsV, info->bsV) != 0)
				{
					change_flag = 1;
					strcpy(p->bsV, info->bsV);
				}
				if(p->type != info->type)
				{
					change_flag = 1;
					p->type = info->type;
				}
				if(change_flag == 1)
					listboard();
				return FALSE;
			}
			else if(strcmp(p->ip, ip) > 0)
			{
				insertHost(pPre, ip, info);
				listboard();
				return TRUE;
			}
			else
			{
				pPre = p;
				p = p->pNext;
			}
		}
		insertHost(pPre, ip, info);
		listboard();
	}
	return TRUE;
}

BOOL CV9_BATCH_UPDlg::AddBoardUpdate (int nIndex)
{
	DEVINFOLIST * pPre = m_pHostUpdate;
	DEVINFOLIST * pHost = m_pHost->pNext;
	DEVINFOLIST *pUpdate = m_pHostUpdate->pNext;

	for (int i = 0; i < nIndex; i++)
	{
		pHost = pHost->pNext;
	}

	if (pUpdate== NULL)
	{
		insertUpdateHost(m_pHostUpdate, pHost);
		//listUpdateboard();
	}
	else
	{
		while (pUpdate != NULL)
		{
			if (strcmp(pUpdate->ip, pHost->ip) == 0)
			{
				return FALSE;
			}
			else if(strcmp(pUpdate->ip, pHost->ip) > 0)
			{
				insertUpdateHost(pPre, pHost);
				//listUpdateboard();
				return TRUE;
			}
			else
			{
				pPre = pUpdate;
				pUpdate = pUpdate->pNext;
			}
		}
		insertUpdateHost(pPre, pHost);
		//listUpdateboard();

	}

	return TRUE;
}

BOOL CV9_BATCH_UPDlg::DelBoardUpdate (const char *ip)
{
	DEVINFOLIST * pPre = m_pHostUpdate;
	DEVINFOLIST * pHost = m_pHostUpdate->pNext;
	DEVINFOLIST *pUpdate = m_pHostUpdate->pNext;

	if(pHost == NULL)
	{
		AfxMessageBox("NULL");
		return FALSE;
	}

	while(pHost != NULL)
	{
		if(strcmp(ip, pHost->ip) == 0)
		{
			break;
		}
		pPre = pHost;
		pHost = pHost->pNext;
	}

	delUpdateHost(pPre, pHost);


	return TRUE;
}

int CV9_BATCH_UPDlg::FindUpdates()
{
	WIN32_FIND_DATA FindData;
	int ret;
	char *psta,*pend;
	char namebuf[512] = UPDATEDIR"*.tar"; 
	char version[100] = {0};
	int have_file = 0;

	HANDLE hFind = FindFirstFile(namebuf, &FindData );  
	if(hFind == INVALID_HANDLE_VALUE)   
	{  
		AfxMessageBox("当前升级目录不存在任何升级包");
		return -1;  
	}  

	while (1)
	{
		//AfxMessageBox(FindData.cFileName);
		if (strncmp(FindData.cFileName, "route", 5) == 0)
		{
			//AfxMessageBox("route");
			strcpy(updatefile.route, FindData.cFileName);
			psta = updatefile.route + 5;
			pend = strstr(updatefile.route, ".tar");
			if (pend == NULL)
			{
				AfxMessageBox("升级文件名有误");
				memset(updatefile.route, 0, sizeof(updatefile.route));
				return -2;
			}
			memset(version, 0, sizeof(version));
			memcpy(version, psta+1, pend-psta-1);
			GetDlgItem(IDC_STATIC1)->SetWindowText(version);
			have_file = 1;
		}
		if (strncmp(FindData.cFileName, "kernel", 6) == 0)
		{
			//AfxMessageBox("kernel");
			strcpy(updatefile.kernel, FindData.cFileName);
			psta = updatefile.kernel + 6;
			pend = strstr(updatefile.kernel, ".tar");
			if (pend == NULL)
			{
				AfxMessageBox("升级文件名有误");
				memset(updatefile.kernel, 0, sizeof(updatefile.kernel));
				return -2;
			}
			memset(version, 0, sizeof(version));
			memcpy(version, psta+1, pend-psta-1);
			GetDlgItem(IDC_STATIC2)->SetWindowText(version);
			have_file = 1;
		}
		if (strncmp(FindData.cFileName, "app", 3) == 0)
		{
			//AfxMessageBox("v9-wibox");
			strcpy(updatefile.app, FindData.cFileName);
			psta = updatefile.app + 3;
			pend = strstr(updatefile.app, ".tar");
			if (pend == NULL)
			{
				AfxMessageBox("升级文件名有误");
				memset(updatefile.app, 0, sizeof(updatefile.app));
				return -2;
			}
			memset(version, 0, sizeof(version));
			memcpy(version, psta+1, pend-psta-1);
			GetDlgItem(IDC_STATIC3)->SetWindowText(version);
			have_file = 1;
		}
		if (strncmp(FindData.cFileName, "record", 6) == 0)
		{
			//AfxMessageBox("record");
			strcpy(updatefile.record, FindData.cFileName);
			psta = updatefile.record + 6;
			pend = strstr(updatefile.record, ".tar");
			if (pend == NULL)
			{
				AfxMessageBox("升级文件名有误");
				memset(updatefile.record, 0, sizeof(updatefile.record));
				return -2;
			}
			memset(version, 0, sizeof(version));
			memcpy(version, psta+1, pend-psta-1);
			GetDlgItem(IDC_STATIC4)->SetWindowText(version);
			have_file = 1;
		}
		if (strncmp(FindData.cFileName, "bs", 2) == 0)
		{
			//AfxMessageBox("bs");
			strcpy(updatefile.bs, FindData.cFileName);
			psta = updatefile.bs + 2;
			pend = strstr(updatefile.bs, ".tar");
			if (pend == NULL)
			{
				AfxMessageBox("升级文件名有误");
				memset(updatefile.bs, 0, sizeof(updatefile.bs));
				return -2;
			}
			memset(version, 0, sizeof(version));
			memcpy(version, psta+1, pend-psta-1);
			GetDlgItem(IDC_STATIC5)->SetWindowText(version);
			have_file = 1;
		}
		ret = FindNextFile(hFind,&FindData);  
		if (!ret)
		{
			//AfxMessageBox("FindNextFile error");
			break;  
		}
	}

	FindClose(hFind);

	if(have_file == 0)
	{
		AfxMessageBox("当前目录不存在任何升级文件,请确认整备完成后，重新打开进行升级");
		return -5;
	}

	return 0;
}


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CV9_BATCH_UPDlg 对话框




CV9_BATCH_UPDlg::CV9_BATCH_UPDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CV9_BATCH_UPDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CV9_BATCH_UPDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST2, m_listboard);
	DDX_Control(pDX, IDC_LIST1, m_updateboard);
}

BEGIN_MESSAGE_MAP(CV9_BATCH_UPDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_RADIO1, &CV9_BATCH_UPDlg::OnBnClickedRadio1)
	ON_BN_CLICKED(IDC_RADIO2, &CV9_BATCH_UPDlg::OnBnClickedRadio2)
	ON_BN_CLICKED(IDC_BUTTON1, &CV9_BATCH_UPDlg::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, &CV9_BATCH_UPDlg::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, &CV9_BATCH_UPDlg::OnBnClickedButton3)
	ON_BN_CLICKED(IDOK, &CV9_BATCH_UPDlg::OnBnClickedOk)
END_MESSAGE_MAP()


// CV9_BATCH_UPDlg 消息处理程序

BOOL CV9_BATCH_UPDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。
	pMain = this;

	m_pHost = (struct DEVINFOLIST *) malloc (sizeof (DEVINFOLIST));
	memset(m_pHost, 0, sizeof(DEVINFOLIST));
	m_pHost->pNext = NULL;

	m_pHostUpdate = (struct DEVINFOLIST *) malloc (sizeof (DEVINFOLIST));
	memset(m_pHostUpdate, 0, sizeof(DEVINFOLIST));
	m_pHostUpdate->pNext = NULL;

	memset(&updatefile, 0, sizeof(updatefile));

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	m_listboard.InsertColumn (0, "ID", LVCFMT_CENTER, 40);
	m_listboard.InsertColumn (1, "IP Address", LVCFMT_CENTER, 110);
	m_listboard.InsertColumn (2, "Board Name", LVCFMT_CENTER, 80);
	m_listboard.InsertColumn (3, "Type", LVCFMT_CENTER, 50);
	m_listboard.InsertColumn (4, "route Version", LVCFMT_CENTER, 100);
	m_listboard.InsertColumn (5, "kernel Version", LVCFMT_CENTER, 100);
	m_listboard.InsertColumn (6, "app Version", LVCFMT_CENTER, 100);
	m_listboard.InsertColumn (7, "record Version", LVCFMT_CENTER, 100);
	m_listboard.InsertColumn (8, "bs Version", LVCFMT_CENTER, 100);
	m_listboard.SetExtendedStyle( 
		LVS_EX_FULLROWSELECT | 
		LVS_EX_GRIDLINES | \
		LVS_EX_HEADERDRAGDROP);

	((CButton*)GetDlgItem(IDC_RADIO1))->SetCheck(TRUE);
	((CButton*)GetDlgItem(IDC_EDIT1))->EnableWindow(FALSE);

	int ret;
	ret = FindUpdates();
	if(ret == -2 || ret == -5)
	{
		//return FALSE;
	}

	WSADATA wsaData;    // 这结构是用于接收Windows Socket的结构信息的 
	int err;  

	CString str;
	err = WSAStartup( MAKEWORD( 2, 2 ), &wsaData );  
	if ( err != 0 ) 
	{  
		str.Format ("%s", "WSAStartup error");
		AfxMessageBox(str);
		return -1; 
	}  


	HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, GetDevThread, NULL, 0, NULL); 
	CloseHandle( hThread );

	hThread = (HANDLE)_beginthreadex(NULL, 0, GetStatusThread, NULL, 0, NULL); 
	CloseHandle( hThread );


	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void CV9_BATCH_UPDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CV9_BATCH_UPDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CV9_BATCH_UPDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CV9_BATCH_UPDlg::OnBnClickedRadio1()
{
	// TODO: 在此添加控件通知处理程序代码
	((CButton*)GetDlgItem(IDC_EDIT2))->EnableWindow(TRUE);
	((CButton*)GetDlgItem(IDC_EDIT1))->EnableWindow(FALSE);
}

void CV9_BATCH_UPDlg::OnBnClickedRadio2()
{
	// TODO: 在此添加控件通知处理程序代码
	((CButton*)GetDlgItem(IDC_EDIT1))->EnableWindow(TRUE);
	((CButton*)GetDlgItem(IDC_EDIT2))->EnableWindow(FALSE);
}

void CV9_BATCH_UPDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	CString str;
	POSITION pos = m_listboard.GetFirstSelectedItemPosition();
	if (pos == NULL)
	{
		AfxMessageBox(TEXT("没有选中任何板卡"));
	}
	else
	{
		while (pos)
		{
			int nItem = m_listboard.GetNextSelectedItem(pos);
			str = m_listboard.GetItemText (nItem, 0);
			AddBoardUpdate (atoi (str.GetBuffer ()) - 1);
			
		}
		listUpdateboard();
	}
}

void CV9_BATCH_UPDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	CString str;
	char buf[100] = {0};
	POSITION pos = m_updateboard.GetFirstSelectedItemPosition();
	if (pos == NULL)
	{
		AfxMessageBox(TEXT("没有选中任何板卡"));
	}
	else
	{
		while (pos)
		{
			int nItem = m_updateboard.GetNextSelectedItem(pos);
			str = m_updateboard.GetItemText (nItem, 0);
			//AfxMessageBox(str);
			char *p = strstr(str.GetBuffer (), "IP:");
			strcpy(buf, p+3);
			p = buf;
			while(*p != ' ')
			{
				p++;
			}
			*p = '\0';
			//AfxMessageBox(buf);
			DelBoardUpdate (buf);

		}
		listUpdateboard();	
	}
}

void CV9_BATCH_UPDlg::OnBnClickedButton3()
{
	// TODO: 在此添加控件通知处理程序代码
}

int CV9_BATCH_UPDlg::CProgressCtrlInit(int range)
{
	CProgressCtrl *pProgCtrl=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);
	pProgCtrl->SetRange(0,range);
	pProgCtrl->SetStep(1);
	pProgCtrl->SetPos(0);
	return 0;
}

int CV9_BATCH_UPDlg::CProgressCtrlUpdate(int num, const char *info)
{
	
	CProgressCtrl *pProgCtrl=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);
	for (int i=0;i<num;i++)
	{
		pProgCtrl->StepIt();
	}
	
	GetDlgItem(IDC_STATIC11)->SetWindowText(info);
	Sleep(500);
	return 0;
}

int CV9_BATCH_UPDlg::addfile(char *files, const char *file)
{
	if(file)
	{
		if(strlen(file) != 0)
		{
			strcat(files, UPDATEDIR);
			strcat(files, file);
			strcat(files, " ");
		}
	}
	return 0;
}

int CV9_BATCH_UPDlg::tar_gz()
{
	CProgressCtrlUpdate(1, "打包压缩升级文件中...");

	char files[1000] = {0};
	
	addfile(files, updatefile.route);
	addfile(files, updatefile.kernel);
	addfile(files, updatefile.app);
	addfile(files, updatefile.record);
	addfile(files, updatefile.bs);
	//AfxMessageBox(files);
	if(tar_gzip(files, UPDATENAME))
	{
		return -1;
	}
	
	return 0;
}

int CV9_BATCH_UPDlg::count_md5(char *md5)
{
	char file[200]= {0};
	sprintf(file, "%s.tar.gz", UPDATEDIR""UPDATENAME);
	memset(md5, 0, sizeof(md5));
	file_md5(file, md5);

	g_file_len = file_len(file);
	//char buf[100] = {0};
	//sprintf(buf, "tcp_num:%d", len);
	//AfxMessageBox(buf);


	return 0;
}

int CV9_BATCH_UPDlg::count_update_num()
{
	DEVINFOLIST * p = m_pHostUpdate->pNext;
	CString str;
	int index = 0;
	while(p != NULL)
	{
		p = p->pNext;
		index++;
	}
	return index;
}

DEVINFOLIST * CV9_BATCH_UPDlg::first_update(DEVINFOLIST *p ,int num)
{
	while(p != NULL)
	{
		if(num == 0)
		{
			break;
		}
		p = p->pNext;
		num--;
	}

	return p;

}


DEVINFOLIST * CV9_BATCH_UPDlg::next_update(DEVINFOLIST *p ,int num)
{

	int totle = update_num;
	while(p != NULL)
	{
		if(totle == 0)
		{
			break;
		}
		p = p->pNext;
		totle--;
	}

	return p;
}

int CV9_BATCH_UPDlg::update_rec_flag(int num, const char *ip, int index)
{
	char buf[100] = {0};
	switch (num)
	{
		case UP_START:
			sprintf(buf, "板卡:%s 发送url成功", ip);
			status[index] = UP_START;
			CProgressCtrlUpdate(1, buf);
		case UP_TRANS_SUC:
			sprintf(buf, "板卡:%s 文件下载成功", ip);
			status[index] = UP_TRANS_SUC;
			CProgressCtrlUpdate(1, buf);
			return 1;
		case UP_TRANS_ERR:
			sprintf(buf, "板卡:%s 文件下载失败", ip);
			CProgressCtrlUpdate(1, buf);
			return 0;
		case UP_MD5_SUC:
			sprintf(buf, "板卡:%s MD5校验成功", ip);
			status[index] = UP_MD5_SUC;
			//AfxMessageBox(buf);
			CProgressCtrlUpdate(1, buf);
			return 1;
		case UP_MD5_ERR:
			sprintf(buf, "板卡:%s MD5校验失败", ip);
			//AfxMessageBox(buf);
			CProgressCtrlUpdate(1, buf);
			return 0;
		case UP_UPDATE_SUC:
			sprintf(buf, "板卡:%s 更新文件成功", ip);
			status[index] = UP_UPDATE_SUC;
			//AfxMessageBox(buf);
			CProgressCtrlUpdate(1, buf);
			return 0;
		case UP_UPDATE_ERR:
			sprintf(buf, "板卡:%s 更新文件失败", ip);
			//AfxMessageBox(buf);
			CProgressCtrlUpdate(1, buf);
			return 0;
	}
	return -1;
}


int CV9_BATCH_UPDlg::tcp_send(int num)
{
	DEVINFOLIST * p = m_pHostUpdate->pNext;
	int index = 0;
	int index_totle = num;
	char buf[100] = {0};
	CString str;
	SOCKET sockSrv;
	SOCKADDR_IN servaddr;
	unsigned int len;
	unsigned long long send_len;
	char filename[100] = {0};
	sprintf(filename, "%s.tar.gz", UPDATEDIR""UPDATENAME);
	FILE *fp;
	char buf_send[BUFFSIZE] = {0};
	int read_len;
	int ret;
	char statusbuf[10] = {0};
	int status_update;
	int timeout = 1000*60*2;
	int sleep_flag = 0;

	p = first_update(p ,num);
	while(p != NULL)
	{
		send_len = 0;
		sprintf(buf, "正在升级板卡:%s", p->ip);
		CProgressCtrlUpdate(1, buf);
		//AfxMessageBox(buf);

		sockSrv = socket(AF_INET, SOCK_STREAM, 0);
		if (sockSrv == INVALID_SOCKET)
		{
			str.Format ("%s", "socket error");
			AfxMessageBox(str);
			return -1; 
		}

		if(setsockopt(sockSrv,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout)))
		{
			AfxMessageBox("设置超时时间出错");
		}
		memset(&servaddr, 0, sizeof(servaddr));
		servaddr.sin_family = AF_INET;
		servaddr.sin_port = htons(BATCH_UP_PORT_C);
		servaddr.sin_addr.s_addr = inet_addr(p->ip);

		if(connect(sockSrv, (SOCKADDR *)&servaddr, sizeof(servaddr)) == SOCKET_ERROR)
		{
			str.Format ("%s", "connect error");
			AfxMessageBox(str);
			//fclose(fp);
			
			closesocket(sockSrv);

			return -1; 
		}

		//update_type(1type)+md5(32byte)+filelen(8byte)+files
		if(send_pack(sockSrv, "1", 1, 0) < 0)
		{
			AfxMessageBox("send md5 error");
			//fclose(fp);
			
			closesocket(sockSrv);

			return -1;
		}

		if(send_pack(sockSrv, md5, 32, 0) < 0)
		{
			AfxMessageBox("send md5 error");
			//fclose(fp);
			
			closesocket(sockSrv);

			return -1;
		}
		//AfxMessageBox(md5);

		//str.Format ("%llu", g_file_len &0x00000000ffffffff);
		//AfxMessageBox(str);
		len = (g_file_len >> 32) & 0x00000000ffffffff;
		len = htonl(len);
		//str.Format ("%u", len);
		//AfxMessageBox(str);

		if(send_pack(sockSrv, (char *)&len, 4, 0) < 0)
		{
			AfxMessageBox("send file len error");
			//fclose(fp);
			
			closesocket(sockSrv);

			return -2;
		}

		len = (g_file_len & 0x00000000ffffffff);
		len = htonl(len);
		//str.Format ("%u", len);
		//AfxMessageBox(str);

		if(send_pack(sockSrv, (char *)&len, 4, 0) < 0)
		{
			AfxMessageBox("send file len error");
			//fclose(fp);
			
			closesocket(sockSrv);

			return -2;
		}

		
		fp = fopen(filename, "rb");
		if(fp == NULL)
		{
			AfxMessageBox("fopen file error");
			//fclose(fp);
			
			closesocket(sockSrv);

			return -3;
		}
		
		memset(buf_send, 0, BUFFSIZE); 

		sleep_flag = 0;
		while((read_len = fread(buf_send, sizeof(char), BUFFSIZE, fp)) > 0)
		{
			//str.Format ("%u", read_len);
			//AfxMessageBox(str);
			if((ret = send_pack(sockSrv, buf_send, read_len, 0)) < 0)
			{
				AfxMessageBox("send file error");
				fclose(fp);
				
				closesocket(sockSrv);

				return -4;
			}
			if(sleep_flag > 1024*100)
			{
				sleep_flag = 0;
				Sleep(5000);
			}
			sleep_flag++;
			send_len += read_len;
			memset(buf_send, 0, BUFFSIZE);  
		}

		if(send_len != g_file_len)
		{
			AfxMessageBox("发送文件大小与文件实际不符");
			fclose(fp);
			
			closesocket(sockSrv);

			return -5;
		}

		sprintf(buf, "板卡:%s 发送升级文件成功,请等待板卡升级...", p->ip);
		CProgressCtrlUpdate(1, buf);

		fclose(fp);
		shutdown(sockSrv, SD_SEND);

		memset(statusbuf, 0, sizeof(statusbuf));

		//Sleep(10000);
		//return "status:ret"
		if((ret = recv(sockSrv, statusbuf, sizeof(statusbuf), 0)) > 0)
		{
			if(strncmp(statusbuf, "status:", 7) != 0)
			{
				//closesocket(sockSrv);
				AfxMessageBox("板卡返回数据有误");
				index++;
				index_totle += update_num;
				p = next_update(p, num);
				closesocket(sockSrv);
				continue;

			}
			if(strlen(statusbuf) < 9)
			{
				//closesocket(sockSrv);
				AfxMessageBox("板卡返回数据有误");
				index++;
				index_totle += update_num;
				p = next_update(p, num);
				closesocket(sockSrv);
				continue;

			}
			status_update = atoi(statusbuf+7);
			update_rec_flag(status_update, p->ip, index_totle);
		}
		if (ret < 0)
		{
			ret = WSAGetLastError();
			closesocket(sockSrv);
			if(ret == WSAETIMEDOUT)
			{
				sprintf(buf, "板卡:%s 升级状态超时...", p->ip);
				AfxMessageBox(buf);
			}
			else
			{
				sprintf(buf, "板卡:%s 接收状态出错...", p->ip);
				AfxMessageBox(buf);
			}
			index++;
			index_totle += update_num;
			p = next_update(p, num);
			continue;
		}

		closesocket(sockSrv);

		index++;
		index_totle += update_num;
		p = next_update(p, num);	
	}

	return 0;
}


int CV9_BATCH_UPDlg::tcp_update()
{
	int tcp_num = 1;
	int tcp_flag = 1;
	int flag = 1; //1-suc 0-err
	int pro_num;
	int board_num = 0;

	memset(status, 0, sizeof(status));
	CEdit* pBoxOne; 
	CString str;
	char *p;
	pBoxOne = (CEdit*)GetDlgItem(IDC_EDIT2); 
	pBoxOne-> GetWindowText(str); 

	p = str.GetBuffer();
	if (strlen(p) != 0)
	{
		tcp_num = atoi(p);
	}
	else 
	{
		tcp_flag = 0;
	}

	if(tcp_num<1 || tcp_num > THREAD_MAX)
	{
		AfxMessageBox("tcp并发数只能在1~8之间");
		return 0;
	}

	update_num = count_update_num();
	board_num = update_num;
	//char buf[100] = {0};
	//sprintf(buf, "update_num:%d", update_num);
	//AfxMessageBox(buf);
	if (update_num == 0)
	{
		AfxMessageBox("请选择需要升级的板卡");
		return 0;
	}

	//sprintf(buf, "tcp_num:%d", tcp_num);
	//AfxMessageBox(buf);
	if ((tcp_flag != 0) && (update_num > tcp_num))
	{
		update_num = tcp_num;
	}

	memset(m_file_cvs, 0, sizeof(m_file_cvs));
	CreateCSV(m_file_cvs);
	//char buf[100] = {0};
	//sprintf(buf, "tcp_num:%d", tcp_num);
	//AfxMessageBox(buf);
	pro_num = 3+update_num*4;
	CProgressCtrlInit(pro_num);

	tar_gz();
	
	count_md5(md5);


	CProgressCtrlUpdate(1, "整备发送升级包...");

	//AfxMessageBox(md5);
	HANDLE hThread[8];

	g_hThreadParameter = CreateSemaphore(NULL, 0, 1, NULL);//当前0个资源，最大允许1个同时访问
	int i;
	for(i=0;i<board_num;i++)
	{
		g_status[i] = CreateSemaphore(NULL, 0, 1, NULL);
	}

	for(i=0;i<update_num;i++)
	{
		hThread[i] = (HANDLE)_beginthreadex(NULL, 0, tcp_client, &i, 0, NULL); 
		WaitForSingleObject(g_hThreadParameter, INFINITE);//等待信号量>0  
	}

	int nIndex = WaitForMultipleObjects(update_num, hThread, TRUE,INFINITE);
	if(nIndex == WAIT_FAILED)
	{
		AfxMessageBox("线程退出出错");
	}
	else if((nIndex >= WAIT_OBJECT_0) && (nIndex < tcp_num))
	{
		//AfxMessageBox("线程退出正常");
	}

	CloseHandle(g_hThreadParameter);  
	for(i=0;i<update_num;i++)
	{
		CloseHandle( hThread[i] );
	}

	int j =0 ;
	for(i=0;i<board_num;i++)
	{
		if( status[i] == UP_MD5_SUC)
		{
			g_status_check[j] = g_status[i];
			j++;
		}
	}

	char buf[100];
	if(j > 0)
	{
		nIndex = WaitForMultipleObjects(j, g_status_check, TRUE, 60*60*1000);
		if(nIndex == WAIT_FAILED)
		{
			sprintf(buf, "等待更新状态出错 %d", j);
			AfxMessageBox(buf);
		}
		else if((nIndex >= WAIT_OBJECT_0) && (nIndex < j))
		{
			//AfxMessageBox("线程退出正常");
		}
	}

	for(i=0;i<board_num;i++)
	{
		CloseHandle(g_status[i]);
	}

	for(i=0;i<board_num;i++)
	{
		if( status[i] != UP_UPDATE_SUC)
		{
			flag = 0;
			break;
		}
	}

	AddToCSV(m_file_cvs, m_pHostUpdate->pNext, status);

	int num;
	CProgressCtrl *pProgCtrl=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);
	num = pro_num - pProgCtrl->GetPos();
	if(flag == 1)
		CProgressCtrlUpdate(num, "升级成功");
	else
		CProgressCtrlUpdate(num, "升级失败");
	return 0;
}


int CV9_BATCH_UPDlg::ftp_update()
{
	DEVINFOLIST * p = m_pHostUpdate->pNext;
	SOCKET sockSrv;
	SOCKADDR_IN servaddr;
	CString str;
	char ftp_url[100] = {0};
	CEdit* pBoxOne; 
	pBoxOne = (CEdit*)GetDlgItem(IDC_EDIT1); 
	pBoxOne-> GetWindowText(str); 
	int timeout = 30000;
	int flag = 1;
	char statusbuf[10] = {0};
	int status_update;
	int ret;
	int index = 0;
	char buf[100] = {0};
	int board_num;

	//GetDlgItem(IDC_STATIC11)->SetWindowText("正在发送URL到各板卡..");
	memset(status, 0, sizeof(status));
	update_num = count_update_num();
	board_num = update_num;
	if (update_num == 0)
	{
		AfxMessageBox("请选择需要升级的板卡");
		return 0;
	}	

	if(strlen(str.GetBuffer()) == 0)
	{
		AfxMessageBox("请输入正确的url");
		return 0;
	}

	strcpy(ftp_url, str.GetBuffer());

	char *pstr = strstr(ftp_url, "//");
	if(pstr == NULL)
	{
		AfxMessageBox("请输入正确的url");
		return 0;
	}

	pstr = strchr(ftp_url, ':');
	if(pstr == NULL)
	{
		AfxMessageBox("请输入正确的url");
		return 0;
	}

	pstr = strchr(ftp_url, '@');
	if(pstr == NULL)
	{
		AfxMessageBox("请输入正确的url");
		return 0;
	}


	CreateCSV(m_file_cvs);
	int pro_num = 3*update_num + 2;
	CProgressCtrlInit(pro_num);

	CProgressCtrlUpdate(1, "整备发送ftp url...");

	int i;
	for(i=0;i<board_num;i++)
	{
		g_status[i] = CreateSemaphore(NULL, 0, 1, NULL);
	}


	while(p != NULL)
	{
		//AfxMessageBox(buf);

		sockSrv = socket(AF_INET, SOCK_STREAM, 0);
		if (sockSrv == INVALID_SOCKET)
		{
			str.Format ("%s", "socket error");
			AfxMessageBox(str);
			return -1; 
		}

		setsockopt(sockSrv,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout));
		memset(&servaddr, 0, sizeof(servaddr));
		servaddr.sin_family = AF_INET;
		servaddr.sin_port = htons(BATCH_UP_PORT_C);
		servaddr.sin_addr.s_addr = inet_addr(p->ip);

		if(connect(sockSrv, (SOCKADDR *)&servaddr, sizeof(servaddr)) == SOCKET_ERROR)
		{
			str.Format ("%s", "connect error");
			AfxMessageBox(str);
			//fclose(fp);
			
			closesocket(sockSrv);

			return -1; 
		}

		//update_type(1byte)+ftpurl(100byte)
		//1-tcp 2-ftp
		if(send_pack(sockSrv, "2", 1, 0) < 0)
		{
			AfxMessageBox("send md5 error");
			//fclose(fp);
			
			closesocket(sockSrv);

			return -1;
		}

		if(send_pack(sockSrv, ftp_url, sizeof(ftp_url), 0) < 0)
		{
			AfxMessageBox("send ftp_url error");
			//fclose(fp);
			
			closesocket(sockSrv);

			return -1;
		}


		//sprintf(buf, "板卡:%s 发送ftp url 成功", p->ip);
		update_rec_flag(UP_START, p->ip, index);
		#if 0 
		memset(statusbuf, 0, sizeof(statusbuf));
		while((ret = recv(sockSrv, statusbuf, sizeof(statusbuf), 0)) > 0)
		{
			if(strncmp(statusbuf, "status:", 7) != 0)
			{
				closesocket(sockSrv);
				break;
			}
			if(strlen(statusbuf) < 9)
			{
				closesocket(sockSrv);
				break;
			}
			status_update = atoi(statusbuf+7);
			if(update_rec_flag(status_update, p->ip, index) == 0)
				break;
		}
		if(ret < 0)
		{
			closesocket(sockSrv);
			AfxMessageBox("接收板卡升级状态超时或者错误");
		}
		#endif

		closesocket(sockSrv);

		p = p->pNext;
		index++;
	}


	int j =0 ;
	for(i=0;i<index;i++)
	{
		if( (status[i] == UP_START) || (status[i] == UP_TRANS_SUC ))
		{
			g_status_check[j] = g_status[i];
			j++;
		}
	}

	//char buf[100];
	if(j > 0)
	{
		ret = WaitForMultipleObjects(j, g_status_check, TRUE, 60*60*1000);
		if(ret == WAIT_FAILED)
		{
			sprintf(buf, "等待更新状态出错 %d", j);
			AfxMessageBox(buf);
		}
		else if((ret >= WAIT_OBJECT_0) && (ret < j))
		{
			//AfxMessageBox("线程退出正常");
		}
	}

	for(i=0;i<board_num;i++)
	{
		CloseHandle(g_status[i]);
	}

	
	for(i=0;i<index;i++)
	{
		if( status[i] != UP_UPDATE_SUC)
		{
			flag = 0;
			break;
		}
	}

	AddToCSV(m_file_cvs, m_pHostUpdate->pNext, status);
	int num;
	CProgressCtrl *pProgCtrl=(CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);
	num = pro_num - pProgCtrl->GetPos();
	if(flag == 1)
		CProgressCtrlUpdate(num, "升级成功");
	else
		CProgressCtrlUpdate(num, "升级失败");

	//GetDlgItem(IDC_STATIC11)->SetWindowText("发送URL到各板卡完成...");
	return 0;
}

void CV9_BATCH_UPDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	((CButton*)GetDlgItem(IDOK))->EnableWindow(FALSE);
	((CButton*)GetDlgItem(IDC_BUTTON1))->EnableWindow(FALSE);
	((CButton*)GetDlgItem(IDC_BUTTON2))->EnableWindow(FALSE);

	HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, updatemain, NULL, 0, NULL); 
	CloseHandle( hThread );

	//OnOK();
}
<file_sep>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <linux/sockios.h>

#define BATCH_UP_PORT 20000
#define BATCH_UP_PORT_C 20001
#define BATCH_STATUS_PORT 20002

#define BATCH_UP_IP "192.168.110.119"
#define ROUTE_PORT 60001
#define ROUTE_IP "192.168.111.1"

#define BUFFSIZE 1024
#define FILE_DIR "/mnt/cdrom/updates/"
#define MD5_FILE "md5.file"
#define FILE_NAME "updates.tar.gz"
#define TMP_FILE "/tmp/tmp.file"
#define BS_VERSION_FILE "/mnt/cdrom/wibox/web/WEB-INF/classes/wibox_config.properties"
#define BS_DIR "/mnt/cdrom/wibox"

int write_appV();
int write_recordV();

int restart_flag = 0;


enum update_status
{
	UP_START,
	UP_TRANS_SUC = 10,
	UP_TRANS_ERR,
	UP_MD5_SUC = 20,
	UP_MD5_ERR,
	UP_UPDATE_SUC = 30,
	UP_UPDATE_ERR		
};


struct DEVINFO
{
	char name[48];
	int type;
	char routeV[16];
	char kernelV[16];
	char appV[16];
	char recordV[16];
	char bsV[16];
	char str1[16];
	char str2[16];
};
struct DEVINFO devinfo;

void* send_devinfo(void *arg)
{
	unsigned char buf[1024] = {0};
	int sockfd;
	struct sockaddr_in servaddr;
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(BATCH_UP_PORT);
	inet_aton(BATCH_UP_IP, &servaddr.sin_addr);
	printf("send_devinfo start\n");
	
	if((sockfd = socket(AF_INET,SOCK_DGRAM,0)) < 0)
	{
		perror("send_devinfo, socket:");
		return NULL;
	}
	if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
	{
		perror("send_devinfo, connect:");
		return NULL;
	}
	
	while(1)
	{
		//printf("start connect\n");

		memcpy(buf, devinfo.name, sizeof(devinfo.name));
		int tmp = htonl(devinfo.type);
		int index = sizeof(devinfo.name);
		memcpy(buf+index, &tmp, sizeof(int));
		index += sizeof(int);
		memcpy(buf+index, devinfo.routeV, sizeof(devinfo.routeV));
		index += sizeof(devinfo.routeV);
		memcpy(buf+index, devinfo.kernelV, sizeof(devinfo.kernelV));
		index += sizeof(devinfo.kernelV);
		memcpy(buf+index, devinfo.appV, sizeof(devinfo.appV));
		index += sizeof(devinfo.appV);
		memcpy(buf+index, devinfo.recordV, sizeof(devinfo.recordV));
		index += sizeof(devinfo.recordV);
		memcpy(buf+index, devinfo.bsV, sizeof(devinfo.bsV));
		index += sizeof(devinfo.bsV);
		memcpy(buf+index, devinfo.str1, sizeof(devinfo.str1));
		index += sizeof(devinfo.str1);
		memcpy(buf+index, devinfo.str2, sizeof(devinfo.str2));
		//sendto(sockfd, buf, sizeof(devinfo), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
		write(sockfd, buf, sizeof(devinfo));
		sleep(1);
	}
	close(sockfd);
	
	printf("send_devinfo end\n");
	return NULL;
}

int md5_check(const char *file, const char *md5)
{
	char cmd[100] = {0};
	char md5_count[50] = {0};
	char md5_file_name[100] = {0};
	sprintf(md5_file_name, "%s%s", FILE_DIR, MD5_FILE);
	sprintf(cmd, "md5sum %s > %s", file, md5_file_name);
	system(cmd);
	FILE *fp = fopen(md5_file_name, "r");
	fscanf(fp, "%s", md5_count);
	fclose(fp);
	printf("md5 trans:%s\n", md5);
	printf("md5 count:%s\n", md5_count);
	return strncmp(md5_count, md5, 32);

}

int find_name(char *file, char *filein)
{
	char cmd[100] = {0};
	sprintf(cmd, "ls -lt %s|grep %s|head -n 1|awk '{print $NF}' > %s", FILE_DIR, filein, TMP_FILE);
	system(cmd);
	FILE *fp = fopen(TMP_FILE, "r");
	if(fp == NULL)
	{
		return -1;
	}
	fgets(file, 80, fp);
	char *p = file;
	while(*p != '\0')
	{
		if(*p == '\n')
			*p = '\0';
		p++;
	}
	fclose(fp);
	return 0;
}

int find_name_tar(char *file, char *filein)
{
	char cmd[100] = {0};
	sprintf(cmd, "tar tvf %s%s | awk '{print $NF}' > %s", FILE_DIR, filein, TMP_FILE);
	//printf(cmd);
	system(cmd);
	FILE *fp = fopen(TMP_FILE, "r");
	if(fp == NULL)
	{
		return -1;
	}
	fgets(file, 80, fp);
	char *p = file;
	while(*p != '\0')
	{
		if(*p == '\n')
			*p = '\0';
		p++;
	}

	fclose(fp);
	return 0;
}

int find_name_app(char *file, char *filein, char *app)
{
	char cmd[100] = {0};
	sprintf(cmd, "tar tvf %s%s | grep %s | awk '{print $NF}' > %s", FILE_DIR, file, app, TMP_FILE);
	system(cmd);
	FILE *fp = fopen(TMP_FILE, "r");
	if(fp == NULL)
	{
		return -1;
	}
	fgets(file, 80, fp);
	char *p = file;
	while(*p != '\0')
	{
		if(*p == '\n')
			*p = '\0';
		p++;
	}

	fclose(fp);
	return 0;
}


int update_route()
{
	char file[100] = {0};
	char file_x[200] = {0};
	if(find_name(file, "route") == 0)
	{
		if(strlen(file) == 0)
		{
			printf("updates.tar.gz has no route.tar.\n");
			return 0;
		}
	}
	else
	{
		return -2;
	}
	if(find_name_tar(file_x, file) == 0)
	{
		if(strlen(file_x) == 0)
		{
			printf("route.tar has no file.\n");
			return -1;
		}
		
		char cmd[300] = {0};
		sprintf(cmd, "tar xvf %s%s -C %s", FILE_DIR, file, FILE_DIR);
		//printf(cmd);
		system(cmd);

		memset(cmd, 0, sizeof(cmd));
		sprintf(cmd, "/root/package_push --file %s%s --ip %s", FILE_DIR, file_x, ROUTE_IP);
		int ret = system(cmd);
		if(ret == -1)
		{
			printf("system error\n");
			return -2;
		}
		if(WIFEXITED(ret))
		{
			if(WEXITSTATUS(ret) == 0)
			{
				//printf("cmd success\n");
			}
			else
			{
				printf("cmd error\n");
				return -3;
			}
		}
		else
		{
			printf("shell error\n");
			return -4;
		}

	}
		
	return 0;
}

int update_kernel()
{
	char file[100] = {0};
	char file_x[100] = {0};
	if(find_name(file, "kernel") == 0)
	{
		if(strlen(file) == 0)
		{
			printf("updates.tar.gz has no kernel.tar.\n");
			return 0;
		}
	}
	else
	{
		return -2;
	}

	char cmd[100] = {0};
	sprintf(cmd, "tar xvf %s%s -C %s", FILE_DIR, file, FILE_DIR);
	//printf(cmd);
	system(cmd);

	if(find_name_tar(file_x, file) == 0)
	{
		if(strlen(file_x) == 0)
		{
			printf("kernel.tar has no file.\n");
			return -1;
		}
		memset(cmd, 0, sizeof(cmd));
		sprintf(cmd, "dd if=%s%s of=/dev/mmcblk0p5 bs=1024k count=8", FILE_DIR, file_x);
		system(cmd);
	}
	else
		return -3;

	return 0;
}

int update_app()
{
	char file[100] = {0};
	char version[20] = {0};
	if(find_name(file, "app") == 0)
	{
		if(strlen(file) == 0)
		{
			printf("updates.tar.gz has no app.tar.\n");
			return 0;
		}
	}
	else
	{
		return -2;
	}

	char cmd[200] = {0};
	//printf("file :%s\n", file);

	printf("updating V9-Wibox or V9-StreamMonitor will kill their process\n");
	
	sprintf(cmd, "killall start_wdg;killall V9-Wibox;killall V9-StreamMonitor;killall V9-IpMonitor");
	system(cmd);

	memset(cmd, 0, sizeof(cmd));
	sprintf(cmd, "tar xvf %s%s -C %s", FILE_DIR, file, "/root/");
	system(cmd);



	memset(cmd, 0, sizeof(cmd));
	sprintf(cmd, "cd /root/;mv *.so /usr/lib/; chmod +x *");
	system(cmd);

	//printf("file :%s\n", file);
	char *p = strstr(file, ".tar");
	if(p == NULL)
	{
		printf("file name error\n");
		return -3;
	}
	memcpy(version, file+4, p-file-4);

	write_appV(version, devinfo.type);

	#if 0
	if(find_name_app(file, "app", "V9-Wibox") == 0)
	{
		if(strlen(file) != 0)
		{
			printf("V9-Wibox update\n");
			write_appV(version, 0x21);
		}
	}	

	if(find_name_app(file, "app", "V9-StreamMonitor") == 0)
	{
		if(strlen(file) != 0)
		{
			printf("V9-StreamMonitor update\n");
			write_appV(version, 0x12);
		}
	}	
	#endif


	return 0;
}

int update_record()
{
	char file[100] = {0};
	char version[20] = {0};
	if(find_name(file, "record") == 0)
	{
		if(strlen(file) == 0)
		{
			printf("updates.tar.gz has no record.tar.\n");
			return 0;
		}
	}
	else
	{
		return -2;
	}

	char cmd[100] = {0};
	sprintf(cmd, "tar xvf %s%s -C %s", FILE_DIR, file, FILE_DIR);
	system(cmd);

	memset(cmd, 0, sizeof(cmd));
	sprintf(cmd, "killall Record");
	system(cmd);

	memset(cmd, 0, sizeof(cmd));
	sprintf(cmd, "cd %s;cp Record /mnt/cdrom/record/Record;chmod +x /mnt/cdrom/record/Record", FILE_DIR);
	system(cmd);


	char *p = strstr(file, ".tar");
	if(p == NULL)
		return -3;
	memcpy(version, file+7, p-file-7);

	write_recordV(version);
	return 0;
}

int update_bs()
{
	char file[100] = {0};
	if(find_name(file, "bs") == 0)
	{
		if(strlen(file) == 0)
		{
			printf("updates.tar.gz has no bs.tar.\n");
			return 0;
		}
	}
	else
	{
		return -2;
	}

	char cmd[100] = {0};
	sprintf(cmd, "mkdir -p %s;killall nginx;killall java;tar xvf %s%s -C %s", BS_DIR,FILE_DIR, file, BS_DIR);
	system(cmd);

	
	return 0;
}

int tar_gzip_x(const char *file)
{
	char cmd[100] = {0};

	sprintf(cmd, "tar zxvf %s -C %s", file, FILE_DIR);
	int ret = system(cmd);
	if(ret == -1)
	{
		printf("system error\n");
		return -2;
	}
	if(WIFEXITED(ret))
	{
		if(WEXITSTATUS(ret) == 0)
		{
			//printf("cmd success\n");
		}
		else
		{
			printf("cmd error\n");
			return -3;
		}
	}
	else
	{
		printf("shell error\n");
		return -4;
	}

	return 0;
}

int clear_file()
{
	char cmd[100] = {0};
	printf("clear dir:%s\n", FILE_DIR);
	sprintf(cmd, "rm -f %s*", FILE_DIR);
	system(cmd);
	return 0;
}


int updatesfile(const char *file)
{
	int ret;
	ret = tar_gzip_x(file);
	if(ret != 0)
	{
		printf("tar zxvf error\n");
		return -1;
	}
	if(update_route())
	{
		printf("update_route error\n");
		return -2;
	}

	
	restart_flag = 1;
	
	if(update_kernel())
	{
		printf("update_kernel error\n");
		return -3;
	}
	if(update_app())
	{
		printf("update_app error\n");
		return -4;
	}
	if(update_record())
	{
		printf("update_record error\n");
		return -5;
	}
	if(update_bs())
	{
		printf("update_bs error\n");
		return -6;
	}

	printf("updates success\n");
	
	return 0;
}

int ftp_rec(const char *ftp_url)
{
	char user[20] = {0};
	char passwd[20] = {0};
	char port[6] = {0};
	char ip[16] = {0};

	char *ps = strstr(ftp_url, "//");
	if(ps == NULL)
	{
		printf("ftp url error\n");
		return -1;
	}
	char *pe = strchr(ps, ':');
	if(pe == NULL)
	{
		printf("ftp url error\n");
		return -1;
	}
	memcpy(user, ps+2, pe-ps-2);
	printf("user:%s\n", user);

	ps = pe;
	pe = strchr(ftp_url, '@');
	if(pe == NULL)
	{
		printf("ftp url error\n");
		return -1;
	}
	memcpy(passwd, ps+1, pe-ps-1);
	printf("passwd:%s\n", passwd);

	ps = pe;
	pe = strchr(ps, ':');
	if(pe == NULL)
	{
		printf("ftp url has no port, use default port 21\n");
		strcpy(port, "21");
		strcpy(ip, ps+1);
		printf("ip:%s\n", ip);	
		
	}
	else
	{
		memcpy(ip, ps+1, pe-ps-1);
		printf("ip:%s\n", ip);	

		ps = pe;
		strcpy(port, ps+1);
		printf("port:%s\n", port);
	}

	char cmd[100] = {0};
	sprintf(cmd, "cd %s;ftpget -u %s -p %s -P %s %s %s", FILE_DIR, user, passwd, port, ip, FILE_NAME);

	int ret = system(cmd);
	if(ret == -1)
	{
		printf("system error\n");
		return -2;
	}
	if(WIFEXITED(ret))
	{
		if(WEXITSTATUS(ret) == 0)
		{
			printf("cmd success\n");
		}
		else
		{
			printf("cmd error\n");
			return -3;
		}
	}
	else
	{
		printf("shell error\n");
		return -4;
	}


	return 0;
}

int ftp_update()
{
	int ret;
	char file[100] = {0};
	sprintf(file, "%s", FILE_DIR""FILE_NAME);

	
	ret = tar_gzip_x(file);
	if(ret != 0)
	{
		printf("tar zxvf error\n");
		return -1;
	}
	if(update_route())
	{
		printf("update_route error\n");
		return -2;
	}

	restart_flag = 1;
	if(update_kernel())
	{
		printf("update_kernel error\n");
		return -3;
	}
	if(update_app())
	{
		printf("update_app error\n");
		return -4;
	}
	if(update_record())
	{
		printf("update_record error\n");
		return -5;
	}
	if(update_bs())
	{
		printf("update_bs error\n");
		return -6;
	}
	

	return 0;
}

int send_update_flag(char *flag)
{
	int sockfd;

	struct sockaddr_in servaddr;
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(BATCH_STATUS_PORT);
	inet_aton(BATCH_UP_IP, &servaddr.sin_addr);
	int times =0;

	while(1)
	{
		times ++;
		if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
		{
			perror("send_update flag, socket");
			return -1;
		}
		if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
		{
			perror("send_update flag, connect");
			close(sockfd);
			if(times > 5)
			{
				return -2;
			}
			sleep(5);
			continue;
			
		}

		if(send(sockfd, flag, 10, 0) < 0)
		{
			perror("send_update flag, send");
			close(sockfd);
			return -1;		
		}
		close(sockfd);
		return 0;

	}

	
	return 0;
}

void* update_thread(void *arg)
{
	int ser_sock, cli_sock;
	socklen_t cli_len;
	unsigned int len; 
	int recv_len;
	unsigned long long file_len, recv_file_len;
	struct sockaddr_in ser_addr, cli_addr;
	char md5[50] = {0};
	char filename[100] = {0};
	char status_update[10] = {0};
	char buf[BUFFSIZE] = {0};
	char update_type[2] = {0};
	char ftp_url[100] = {0};
	sprintf(filename, "%s", FILE_DIR""FILE_NAME);
	FILE *fp;
	int ret;
	struct timeval tv;
	tv.tv_sec = 30;
	tv.tv_usec = 0;

	printf("update_thread start\n");

	if((ser_sock = socket(AF_INET,SOCK_STREAM,0)) < 0)
	{
		perror("socket error:");
		return NULL;
	}

	memset(&ser_addr, 0, sizeof(ser_addr));
	ser_addr.sin_family = AF_INET;
	ser_addr.sin_port = htons(BATCH_UP_PORT_C);
	ser_addr.sin_addr.s_addr = htons(INADDR_ANY);


	printf("bind ...\n");
	if(bind(ser_sock, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) == -1)
	{
		perror("bind, error:");
		return NULL;
	}

	printf("listen ...\n");
	if(listen(ser_sock, 10) == -1)
	{
		perror("listen, error:");
		return NULL;
	}

	while(1)
	{
		
		cli_len = sizeof(cli_addr);
		printf("accept ...\n");
		cli_sock = accept(ser_sock, (struct sockaddr *)&cli_addr, &cli_len);
		if(cli_sock  == -1)
		{
			perror("accept, error:");
			//close(cli_sock);
			//fclose(fp);
			continue;
		}

		
		ret=setsockopt(cli_sock,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv));
		
		printf("client %s connect to the server\n", inet_ntoa(cli_addr.sin_addr));  

		if(recv(cli_sock, update_type, 1, 0) != 1)
		{
			perror("recv update_type error");
			close(cli_sock);
			//fclose(fp);
			continue;			
		}

		//1-tcp 2-ftp
		printf("update_type:%s\n", update_type);
		//ftp
		if(atoi(update_type) == 2)
		{
			if(recv(cli_sock, ftp_url, 100, 0) != 100)
			{
				perror("recv ftp url error");
				close(cli_sock);
				//fclose(fp);
				continue;			
			}
			//close(cli_sock);
			close(cli_sock);
			clear_file();
			printf("ftp url:%s\n", ftp_url);
			ret = ftp_rec(ftp_url);
			if(ret == 0)
			{
				printf("ftp download file suc\n");
				//sprintf(status_update, "status:%d", UP_TRANS_SUC);
				sprintf(status_update, "status:%d", UP_TRANS_SUC);
			}else
			{
				printf("ftp download file error\n");
				//sprintf(status_update, "status:%d", UP_TRANS_ERR);
				sprintf(status_update, "status:%d", UP_TRANS_ERR);
			}
			if(send_update_flag(status_update))
			{
				printf("send status(ftp download file) error\n");
			}

					
			restart_flag = 0;
			ret = ftp_update();
			clear_file();
			if(ret == 0)
			{
				printf("ftp update suc\n");
				sprintf(status_update, "status:%d", UP_UPDATE_SUC);
			}else
			{
				printf("ftp update error\n");
				sprintf(status_update, "status:%d", UP_UPDATE_ERR);
			}
			if(send_update_flag(status_update))
			{
				printf("send status(ftp updates file) error\n");
			}

			
			#if 0
			if(send(cli_sock, status_update, sizeof(status_update), 0) < 0)
			{
				perror("send status error");
				close(cli_sock);
				continue;
			}
			#endif
			if(restart_flag == 1)
			{
				printf("the system will restart...\n");
				system("reboot");
			}		

			continue;
		}

		//tcp
		if(recv(cli_sock, md5, 32, 0) != 32)
		{
			perror("recv md5 error:");
			close(cli_sock);
			//fclose(fp);
			continue;			
		}
		printf("md5:%s\n", md5);

		if(recv(cli_sock, (char *)&len, 4, 0) != 4)
		{
			perror("recv file len error:");
			close(cli_sock);
			//fclose(fp);
			continue;			
		}
		len = ntohl(len);
		//printf("%u\n", len);
		file_len = ((unsigned long long)len << 32);
		if(recv(cli_sock, (char *)&len, 4, 0) != 4)
		{
			perror("recv file len error:");
			close(cli_sock);
			//fclose(fp);
			continue;			
		}
		len = ntohl(len);
		//printf("%u\n", len);
		file_len += len;

		printf("file_len:%llu\n", file_len);

		printf("filename :%s\n", filename);

		clear_file();


		fp = fopen(filename, "w");

		memset(buf, 0, BUFFSIZE);
		recv_file_len = 0;
		while((recv_len = recv(cli_sock, buf, BUFFSIZE, 0)) > 0)
		{
			recv_file_len += recv_len;
			//printf("%d %llu %x %x\n", recv_len, recv_file_len, buf[0], buf[1]);
			if(fwrite(buf, sizeof(char), recv_len, fp) < recv_len)
			{
				perror("recv file len error");
				break;			
			}

			memset(buf, 0, BUFFSIZE);
		}
		if(recv_len < 0)
		{
			if(errno == EWOULDBLOCK)
			{
				perror("recv file time out");
				close(cli_sock);
				fclose(fp);
				continue;
			}
		}

		if(recv_file_len != file_len)
		{
			printf("recv file len is diffent from file len\n");
			close(cli_sock);
			fclose(fp);
			continue;
		}
		
		fclose(fp);
		if(md5_check(filename, md5) != 0)
		{
			printf("md5 checking is not right");
			sprintf(status_update, "status:%d", UP_MD5_ERR);
			send(cli_sock, status_update, sizeof(status_update), 0);
			close(cli_sock);
			continue;
		}

		printf("send status md5\n");
		//sleep(30);
		//printf("sleep end\n");
		sprintf(status_update, "status:%d", UP_MD5_SUC);
		if(send(cli_sock, status_update, sizeof(status_update), 0) < 0)
		{
			perror("send status error");
			close(cli_sock);
			continue;
		}
		close(cli_sock);
		
		restart_flag = 0;
		if(updatesfile(filename) == 0)
		{
			//clear_file();
			printf("updates status success\n");
			sprintf(status_update, "status:%d", UP_UPDATE_SUC);

		}
		else
		{
			//clear_file();
			printf("updates status error\n");
			sprintf(status_update, "status:%d", UP_UPDATE_ERR);
		}

		if(send_update_flag(status_update))
		{
			printf("send updates flag error\n");
		}


		if(restart_flag == 1)
		{
			printf("the system will restart...\n");
			system("reboot");
		}

	}
	
	return NULL;
}

void mk_updates_dir()
{
	char cmd[100] = {0};
	sprintf(cmd, "mkdir -p %s", FILE_DIR);
	system(cmd);
}

int read_name(char *kernelV)
{
	FILE *fp = NULL;
	char *p;
	char cmd[100] = {0};
	char val[100] = {0};
	sprintf(cmd, "uname -a | awk '{print $3}' > /tmp/wibox.name");
	system(cmd);
	fp = fopen ( "/tmp/wibox.name", "rb" );
	if(fp == NULL)
		return -1;
	fgets(val, 80, fp);
	p = val;
	while(*p != '\0')
	{
		if(*p == '\n')
			*p = '\0';
		p++;
	}

	fclose(fp);
	system("rm /tmp/wibox.name");
	//printf("%s\n", val);
	p = strstr(val, "SNM");
	if(p)
	{
		memcpy(kernelV, val, p-1-val);
		return (p[4]-'0');
	}
	else 
		return 1;

}

int read_type()
{
	FILE *fp = NULL;
	char *p;
	char cmd[100] = {0};
	char val[100] = {0};
	sprintf(cmd, "i2c_read  0 0xa0 4001 2 1 | grep 0x > /tmp/wibox.type");
	system(cmd);
	fp = fopen ( "/tmp/wibox.type", "rb" );
	if(fp == NULL)
		return -1;
	fgets(val, 80, fp);
	p = val;
	while(*p != '\0')
	{
		if(*p == '\n')
			*p = '\0';
		p++;
	}

	fclose(fp);	
	system("rm /tmp/wibox.type");
	//printf("%s\n", val);
	p = strstr(val, "0x");
	if(p)return (strtol(p+2, NULL, 16));
	else return -1;

}

int read_appV(int type, char *appV)
{
	FILE *fp = NULL;
	if((type == 0x11) || (type == 0x21) )
		fp = fopen ( "/root/V9-Wibox.version", "rb" );
	else if(type == 0x12)
		fp = fopen ( "/root/V9-StreamMonitor.version", "rb" );
	if(fp == NULL)
		return -1;
	fgets(appV, 80, fp);
	char *p = appV;
	while(*p != '\0')
	{
		if(*p == '\n')
			*p = '\0';
		p++;
	}

	fclose(fp);	
	//printf("%s\n", val);
	return 0;
}

int write_appV(char *version, int type)
{
	FILE *fp = NULL;
	if((type == 0x11) || (type == 0x21) )
		fp = fopen ( "/root/V9-Wibox.version", "w" );
	else if(type == 0x12)
		fp = fopen ( "/root/V9-StreamMonitor.version", "w" );
	if(fp == NULL)
		return -1;
	fputs(version, fp);
	fclose(fp);		
	//printf("%s\n", val);
	return 0;
}


int read_recordV(char *recordV)
{
	FILE *fp = NULL;

	fp = fopen ( "/root/record.version", "rb" );

	if(fp == NULL)
		return -1;
	fgets(recordV, 100, fp);
	fclose(fp);	
	//printf("%s\n", val);
	return 0;
}

int write_recordV(char *version)
{
	FILE *fp = NULL;
	fp = fopen ( "/root/record.version", "w" );
	if(fp == NULL)
		return -1;
	fputs(version, fp);
	fclose(fp);	

	//printf("%s\n", val);
	return 0;
}


int read_rountV(char *rountV)
{
	int sockSrv;
	struct sockaddr_in servaddr;
	int len = 5;
	char opcode = 7;
	len = htonl(len);
	char buf[5] = {0};
	char rec_len;
	int index=0;

	while(1)
	{
		index++;
		sockSrv = socket(AF_INET, SOCK_STREAM, 0);
		if (sockSrv == -1)
		{
			perror("socket error");
			return -1; 
		}
		
		
		memset(&servaddr, 0, sizeof(servaddr));
		servaddr.sin_family = AF_INET;
		servaddr.sin_port = htons(ROUTE_PORT);
		servaddr.sin_addr.s_addr = inet_addr(ROUTE_IP);
		
		if(connect(sockSrv, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
		{
			perror("connect error");
			//fclose(fp);
			
			close(sockSrv);
			if(index>10)
			{
				return -3;
			}
			sleep(5);
			continue; 
		}


		memcpy(buf, &len, 4);
		buf[4] = opcode;

		if(send(sockSrv, buf, 5, 0) < 0)
		{
			perror("send error");
			//fclose(fp);
			
			close(sockSrv);
		
			return -2;		
		}

		if(recv(sockSrv, &rec_len, 1, 0) < 0)
		{
			perror("recv error");
			//fclose(fp);
			
			close(sockSrv);
		
			return -2;		
		}

		if(recv(sockSrv, rountV, 10, 0) < 0)
		{
			perror("recv error");
			//fclose(fp);
			
			close(sockSrv);
		
			return -2;		
		}

		close(sockSrv);
		return 0;
		//printf("rountV:%s\n", rountV);
	}

	return 0;
}


int read_bsV(char *bsV)
{
	FILE *fp = NULL;

	system("cat "BS_VERSION_FILE" |grep wibox.version|awk '{print $NF}' > "TMP_FILE"");


	fp = fopen (TMP_FILE, "rb" );

	if(fp == NULL)
		return -1;
	fgets(bsV, 100, fp);
	fclose(fp);	



	//printf("%s\n", val);
	return 0;
}


void read_version()
{
	int name_flag = 1;
	char version[100] = {0};
	memset(&devinfo, 0, sizeof(devinfo));

	name_flag = read_name(version);
	if(name_flag == 1)
	{
		sprintf(devinfo.name, "%s", "910");
	}
	else if(name_flag == 2)
	{
		sprintf(devinfo.name, "%s", "920");
	}
	else
	{
		printf("read name error\n");
	}
	if(name_flag == 1)
		devinfo.type = 0x21;
	else if(name_flag == 2)
	{
		devinfo.type = read_type();
	}
	
	sprintf(devinfo.kernelV, "%s", version);
	
	memset(version, 0, sizeof(version));
	read_appV(devinfo.type, version);
	sprintf(devinfo.appV, "%s", version);
	
	memset(version, 0, sizeof(version));
	read_recordV(version);
	sprintf(devinfo.recordV, "%s", version);
	
	memset(version, 0, sizeof(version));
	read_bsV(version);
	sprintf(devinfo.bsV, "%s", version);
	
	memset(version, 0, sizeof(version));
	if(devinfo.type == 0x21)
	{
		read_rountV(version);
		sprintf(devinfo.routeV, "%s", version);
	}

}


int main()
{
	int err=0;	
	pthread_t tDev;

	setbuf(stdout, NULL);
	setbuf(stderr, NULL);

	printf("wibox_batch_up version:1.0.0.1\n");

	printf("start wibox_batch_up\n");

	mk_updates_dir();

	read_version();


	err=pthread_create(&tDev,NULL,send_devinfo,NULL);
	if(err!=0)
	{
		printf("Create send_devinfo error: %s\n",strerror(errno));
		return 0;
	}

	err=pthread_create(&tDev,NULL,update_thread,NULL);
	if(err!=0)
	{
		printf("Create send_devinfo error: %s\n",strerror(errno));
		return 0;
	}

	while(1)
	{
		
	}
	return 0;
}
<file_sep>// V9_BATCH_UPDlg.h : 头文件
//

#pragma once
#include "afxcmn.h"

#define THREAD_MAX 8
#define BOARD_MAX 100


enum update_status
{
	UP_START,
	UP_TRANS_SUC = 10,
	UP_TRANS_ERR,
	UP_MD5_SUC = 20,
	UP_MD5_ERR,
	UP_UPDATE_SUC = 30,
	UP_UPDATE_ERR		
};

struct DEVINFO
{
	char name[48];
	int type;
	char routeV[16];
	char kernelV[16];
	char appV[16];
	char recordV[16];
	char bsV[16];
	char str1[16];
	char str2[16];
};

struct DEVINFOLIST
{
	int index;
	DEVINFOLIST * pNext;
	char ip[20];
	char name[48];
	int type;
	char routeV[16];
	char kernelV[16];
	char appV[16];
	char recordV[16];
	char bsV[16];
	char str1[16];
	char str2[16];
};

struct UPDATEFILE
{
	char route[100];
	char kernel[100];
	char app[100];
	char record[100];
	char bs[100];
};

// CV9_BATCH_UPDlg 对话框
class CV9_BATCH_UPDlg : public CDialog
{
// 构造
public:
	CV9_BATCH_UPDlg(CWnd* pParent = NULL);	// 标准构造函数

// 对话框数据
	enum { IDD = IDD_V9_BATCH_UP_DIALOG };
	
protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;
	DEVINFOLIST *m_pHost;
	DEVINFOLIST *m_pHostUpdate;
	UPDATEFILE updatefile;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	CListCtrl m_listboard;
	CListCtrl m_updateboard;
	int update_num;
	int status[BOARD_MAX];
	afx_msg void OnBnClickedRadio1();
	afx_msg void OnBnClickedRadio2();
	BOOL AddHost(const char * ip, struct DEVINFO *info); 
	BOOL up_status(const char *ip, int status);
	BOOL AddBoardUpdate(int nIndex);
	BOOL DelBoardUpdate (const char *ip);
	int insertHost(DEVINFOLIST *pos, const char *ip, struct DEVINFO *info);
	int insertUpdateHost(DEVINFOLIST *pos, DEVINFOLIST *info);
	int delUpdateHost(DEVINFOLIST *pre, DEVINFOLIST *pos);
	int listboard();
	int listUpdateboard();
	int FindUpdates();
	int tcp_update();
	int ftp_update();
	int tcp_send(int num);
	int tar_gz();
	int count_md5(char *md5);
	int addfile(char *files, const char *file);
	int updateflag;
	char m_file_cvs[100];
	DEVINFOLIST * CV9_BATCH_UPDlg::next_update(DEVINFOLIST *p ,int num);
	DEVINFOLIST * CV9_BATCH_UPDlg::first_update(DEVINFOLIST *p ,int num);
	int update_rec_flag(int num, const char *ip, int index);
	int updatefunc();
	int CProgressCtrlInit(int range);
	int CProgressCtrlUpdate(int num, const char *info);
	int count_update_num();
	afx_msg void OnBnClickedButton1();
	afx_msg void OnBnClickedButton2();
	afx_msg void OnBnClickedButton3();
	afx_msg void OnBnClickedOk();
};
<file_sep>#include "stdafx.h"
#include "openssl/md5.h"

enum update_status
{
	UP_START,
	UP_TRANS_SUC = 10,
	UP_TRANS_ERR,
	UP_MD5_SUC = 20,
	UP_MD5_ERR,
	UP_UPDATE_SUC = 30,
	UP_UPDATE_ERR		
};

struct DEVINFO
{
	char name[48];
	int type;
	char routeV[16];
	char kernelV[16];
	char appV[16];
	char recordV[16];
	char bsV[16];
	char str1[16];
	char str2[16];
};

struct DEVINFOLIST
{
	int index;
	DEVINFOLIST * pNext;
	char ip[20];
	char name[48];
	int type;
	char routeV[16];
	char kernelV[16];
	char appV[16];
	char recordV[16];
	char bsV[16];
	char str1[16];
	char str2[16];
};

int file_md5(const char *file, char *md5)
{
	CString str;

	FILE *fp = fopen(file, "rb");
	if(fp == NULL)
	{
		str = "无法打开升级文件";
		AfxMessageBox(str);
		return -1;
	}

	MD5_CTX ctx;
	MD5_Init (&ctx);
	unsigned char digest[16] = {0};  
	int len;
	unsigned char buffer[1024] = {0}; 

	while ((len = fread (buffer, 1, 1024, fp)) > 0)  
	{  
		MD5_Update (&ctx, buffer, len);  
	} 
	MD5_Final (digest, &ctx);  
	fclose(fp); 

	int i = 0;   
	char tmp[3] = {0};  
	for(i = 0; i < 16; i++ )  
	{  
		sprintf(tmp,"%02x", digest[i]); // sprintf并不安全 
		if(md5 == NULL)
		{
			str = "参数md5不能为NULL";
			AfxMessageBox(str);
			return -1;
		}
		strcat(md5, tmp); // strcat亦不是什么好东西  
	} 

	fclose(fp); 

	return 0;
}

int tar_gzip(const char *files, const char *tgz)
{
	//char cmd[200] = {0};
	char name_tar[100] = {0};
	char name_tgz[100] = {0};
	//int ret1, ret2;
	sprintf(name_tar, "%s.tar", tgz);
	sprintf(name_tgz, "%s.gz", name_tar);
	//sprintf(cmd, "cmd /c, 7z a -ttar %s %s ", name_tar, file);
	//ret1 = WinExec(cmd,SW_HIDE);
	////Sleep(1000);
	//sprintf(cmd, "cmd /c, 7z a -tgzip %s %s ", name_tgz, name_tar);
	//ret2 = WinExec(cmd,SW_HIDE);
	//sprintf(cmd, "%d %d", ret1, ret2);
	//CString str;
	//str = cmd;
	//AfxMessageBox(str);
	char strCommand[1000] = {0};
	STARTUPINFOA si = {sizeof(si)};
	si.cb = sizeof(STARTUPINFOA);
	si.lpReserved = NULL;
	si.lpDesktop = NULL;
	si.lpTitle = NULL;
	si.dwFlags = STARTF_USESHOWWINDOW;//隐藏窗口
	si.wShowWindow = SW_HIDE;
	si.cbReserved2 = NULL;
	si.lpReserved2 = NULL;
	PROCESS_INFORMATION pi;

	STARTUPINFOA si2 = {sizeof(si2)};
	si2.cb = sizeof(STARTUPINFOA);
	si2.lpReserved = NULL;
	si2.lpDesktop = NULL;
	si2.lpTitle = NULL;
	si2.dwFlags = STARTF_USESHOWWINDOW;//隐藏窗口
	si2.wShowWindow = SW_HIDE;
	si2.cbReserved2 = NULL;
	si2.lpReserved2 = NULL;
	PROCESS_INFORMATION pi2;

	DeleteFile(name_tar);
	DeleteFile(name_tgz);
	//Sleep(10000);
	sprintf(strCommand, "7z a -ttar %s %s ", name_tar, files);
	//AfxMessageBox(strCommand);
	BOOL bRet = CreateProcessA(NULL,strCommand,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
	if (bRet)
	{
		//等待运行完成
		if (!WaitForSingleObject(pi.hProcess,INFINITE))
		{
			memset(strCommand, 0, sizeof(strCommand));
			sprintf(strCommand, "7z a -tgzip %s %s ", name_tgz, name_tar);
			//Sleep(10000);
			//AfxMessageBox(strCommand);
			bRet = CreateProcessA(NULL,strCommand,NULL,NULL,FALSE,0,NULL,NULL,&si2,&pi2);
			if(!bRet)
			{
				AfxMessageBox("压缩文件出错");
				return -4;				
			}
			if (!WaitForSingleObject(pi2.hProcess,INFINITE))
			{
					
			}
			else
			{
				AfxMessageBox("压缩文件指令出错");
				return -3;
			}
			
			//Sleep(10000);
		}
		else
		{
			AfxMessageBox("打包文件指令错误");
			return -2;
		}
	}
	else
	{
		AfxMessageBox("打包文件出错");
		return -1;
	}
	return 0;

}

unsigned long long  file_len(const char *file)
{
	unsigned long long len;
	WIN32_FIND_DATA FindData; 
	HANDLE hFind = FindFirstFile(file, &FindData ); 
	len = ((unsigned long long)FindData.nFileSizeHigh << 32) + FindData.nFileSizeLow;
	FindClose(hFind);
	return len;
}


int send_pack(SOCKET s, const char *buf, int len, int flags)
{
	int times = 0;
	int ret;
	CString str;
	//str.Format ("len:%u %x %x", len, buf[0], buf[1]);
	//AfxMessageBox(str); 

	while((ret = send(s, buf, len, flags)) < 0)
	{
		//str.Format ("ret:%u", ret);
		//AfxMessageBox(str);	
		if(times > 3)
		{
			break;
		}
		times++;
	}
	return ret;
}

BOOL CreateCSV (char *file)
{
	CString str;

	CTime tm;
	tm = CTime::GetCurrentTime ();
	str = tm.Format ("LOG_%Y%m%d_%H%M%S.csv");
	strcpy (file, str);
	FILE *fp = fopen (file, "w");
	if(fp == NULL)
	{
		return FALSE;
	}
	
	char str2[256];
	sprintf (str2, "%s,%s,%s,%s,%s\n", "序号","板卡IP", "板卡名", "板卡类型", "更新状态");
	//fputs(str,fp);
	fwrite (str2, strlen (str2), 1, fp);

	fclose (fp);

	return TRUE;
}

BOOL AddToCSV (char *file, struct DEVINFOLIST *host, int *status)
{

	FILE *fp = fopen (file, "a");
	if (fp)
	{
		char str[256];
		int i = 0;
		while(host != NULL)
		{
			if(status[i] == UP_UPDATE_SUC)
				sprintf (str, "%d,%s,%s,0x%x,%s\n", i+1, host->ip, host->name, host->type, "success");
			else
				sprintf (str, "%d,%s,%s,0x%x,%s\n", i+1, host->ip, host->name, host->type, "error");
			//fputs(str,fp);
			fwrite (str, strlen (str), 1, fp);
			host = host->pNext;
			i++;
		}
		fclose (fp);
	}
	else
	{
		return FALSE;
	}
	
	return TRUE;
}



