181 lines
8.7 KiB
C#
181 lines
8.7 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Net;
|
|||
|
|
using System.Net.Sockets;
|
|||
|
|
using System.Threading;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
using Common;
|
|||
|
|
using Dao;
|
|||
|
|
using Domain;
|
|||
|
|
using RCUHost.Protocols;
|
|||
|
|
|
|||
|
|
namespace RCUHost.Implement
|
|||
|
|
{
|
|||
|
|
public class UpdateHostFTPReceiver : GenericReceiverBase, IUpdateHostFTPReceiver
|
|||
|
|
{
|
|||
|
|
private static log4net.ILog logger = log4net.LogManager.GetLogger(typeof(UpdateHostFTPReceiver));
|
|||
|
|
public IHostUpdateStatusRepository HostUpdateStatusRepository { get; set; }
|
|||
|
|
private IList<UpdateHostWorker> updateHostList = new List<UpdateHostWorker>();
|
|||
|
|
|
|||
|
|
public void Update(HostUpdate hostUpdate, FileType fileType, string fileHref, string fileMd5, IList<Host> hosts)
|
|||
|
|
{
|
|||
|
|
if (hosts == null || hosts.Count == 0)
|
|||
|
|
{
|
|||
|
|
throw new ApplicationException("升级失败,没有找到需要升级的主机。");
|
|||
|
|
}
|
|||
|
|
if (String.IsNullOrEmpty(fileHref))
|
|||
|
|
{
|
|||
|
|
throw new ApplicationException("升级失败,无效的升级文件。");
|
|||
|
|
}
|
|||
|
|
string updateFile = Tools.GetApplicationPath() + fileHref;
|
|||
|
|
if (!File.Exists(updateFile))
|
|||
|
|
{
|
|||
|
|
throw new ApplicationException("升级失败,【" + updateFile + "】文件不存在。");
|
|||
|
|
}
|
|||
|
|
this.updateHostList.Clear();
|
|||
|
|
foreach (var host in hosts)
|
|||
|
|
{
|
|||
|
|
SendUpdateRequest(host, fileMd5, (byte)fileType, fileHref.Substring(fileHref.IndexOf("/")));
|
|||
|
|
|
|||
|
|
this.updateHostList.Add(new UpdateHostWorker(host, hostUpdate, MessageIP, fileHref, updateFile)); ;
|
|||
|
|
HostUpdateStatus hostUpdateStatus = HostUpdateStatusRepository.Get(host, hostUpdate);
|
|||
|
|
if (hostUpdateStatus == null)
|
|||
|
|
{
|
|||
|
|
hostUpdateStatus = new HostUpdateStatus();
|
|||
|
|
hostUpdateStatus.Host = host;
|
|||
|
|
hostUpdateStatus.HostUpdate = hostUpdate;
|
|||
|
|
hostUpdateStatus.PublishTime = DateTime.Now;
|
|||
|
|
}
|
|||
|
|
hostUpdateStatus.Status = 0;
|
|||
|
|
hostUpdateStatus.UpdatedTime = DateTime.Now;
|
|||
|
|
HostUpdateStatusRepository.SaveOrUpdate(hostUpdateStatus);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override void Process(ReceiverContext context)
|
|||
|
|
{
|
|||
|
|
int startIndex = StructConverter.SizeOf(context.SystemHeader);
|
|||
|
|
UpdateHostPacketReply? reply = DecodeUpdateHostPacketReply(context.Data, startIndex);
|
|||
|
|
if (reply.HasValue)
|
|||
|
|
{
|
|||
|
|
//logger.Error(string.Format("收到ftp升级回复命令({0}:{1}):{2}", context.RemoteEndPoint.Address.ToString(), context.RemoteEndPoint.Port, Tools.ByteToString(context.Data)));
|
|||
|
|
var updateHostWorker = updateHostList.FirstOrDefault(r => r.Host.SysHotel.Code == context.SystemHeader.Value.HostNumber.ToHotelCode().ToString() && r.Host.HostNumber == context.SystemHeader.Value.HostNumber.ToString());
|
|||
|
|
if (updateHostWorker != null)
|
|||
|
|
{
|
|||
|
|
SaveSystemLog(30, "升级主机", string.Format("收到主机({0})升级回复命令,状态:{1}", updateHostWorker.Host.RoomNumber, reply.Value.Status), "收到命令", "RCU", context.RemoteEndPoint.Address.ToString(), updateHostWorker.Host.SysHotel.ID);
|
|||
|
|
HostUpdateStatus hostUpdateStatus = HostUpdateStatusRepository.Get(updateHostWorker.Host, updateHostWorker.HostUpdate);
|
|||
|
|
if (hostUpdateStatus == null)
|
|||
|
|
{
|
|||
|
|
hostUpdateStatus = new HostUpdateStatus();
|
|||
|
|
hostUpdateStatus.Host = updateHostWorker.Host;
|
|||
|
|
hostUpdateStatus.HostUpdate = updateHostWorker.HostUpdate;
|
|||
|
|
hostUpdateStatus.PublishTime = DateTime.Now;
|
|||
|
|
hostUpdateStatus.Status = 0;
|
|||
|
|
}
|
|||
|
|
switch (reply.Value.Status)
|
|||
|
|
{
|
|||
|
|
case UpdateHostPacketReply.Ready:
|
|||
|
|
hostUpdateStatus.Status = 0;
|
|||
|
|
break;
|
|||
|
|
case UpdateHostPacketReply.Completed:
|
|||
|
|
Reply(context);//升级完成回复主机
|
|||
|
|
hostUpdateStatus.Status = 1;
|
|||
|
|
updateHostList.Remove(updateHostWorker);
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
hostUpdateStatus.Status = 2;
|
|||
|
|
updateHostList.Remove(updateHostWorker);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
hostUpdateStatus.UpdatedTime = DateTime.Now;
|
|||
|
|
HostUpdateStatusRepository.SaveOrUpdate(hostUpdateStatus);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
public override CommandType CommandType
|
|||
|
|
{
|
|||
|
|
get { return CommandType.FTPUpdate; }
|
|||
|
|
}
|
|||
|
|
#region Private Methods
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 发送升级指令到RCU主机
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="host"></param>
|
|||
|
|
/// <param name="updateFileMd5">升级文件MD5值</param>
|
|||
|
|
private void SendUpdateRequest(Host host, string updateFileMd5, byte fileType, string fileName)
|
|||
|
|
{
|
|||
|
|
byte[] data = CreateUpdateRequestPacket(updateFileMd5, fileType, fileName);
|
|||
|
|
Send(data, host.HostNumber, host.MAC);// host.IP, host.Port);
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 创建主机升级请求数据包
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="updateFileMd5">升级文件MD5值</param>
|
|||
|
|
/// <param name="blockNum">块数量</param>
|
|||
|
|
/// <param name="fileType">文件类型</param>
|
|||
|
|
/// <param name="fileName">文件名(含酒店编码)</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private byte[] CreateUpdateRequestPacket(string updateFileMd5, byte fileType, string fileName)
|
|||
|
|
{
|
|||
|
|
SystemHeader systemHeader = CreateSystemHeader();
|
|||
|
|
int headerSize = StructConverter.SizeOf(systemHeader);
|
|||
|
|
|
|||
|
|
byte[] ipArr = IPAddress.Parse(this.FTPServer).GetAddressBytes();
|
|||
|
|
byte[] portArr = BitConverter.GetBytes(this.FTPPort);//ftp通讯端口
|
|||
|
|
|
|||
|
|
//string ftpName = SysSettingRepository.GetValue("FTPName").ToString();
|
|||
|
|
byte[] bFTPName = System.Text.Encoding.Default.GetBytes(this.FTPName);
|
|||
|
|
|
|||
|
|
//string ftpPassword = SysSettingRepository.GetValue("FTPPassword").ToString();
|
|||
|
|
byte[] bFTPPassword = System.Text.Encoding.Default.GetBytes(this.FTPPassword);
|
|||
|
|
|
|||
|
|
uint[] md5Arr = Tools.MD5StringToUIntArray(updateFileMd5);
|
|||
|
|
|
|||
|
|
byte[] bFileName = System.Text.Encoding.Default.GetBytes(fileName);
|
|||
|
|
|
|||
|
|
using (var stream = new MemoryStream())
|
|||
|
|
{
|
|||
|
|
stream.Seek(headerSize, SeekOrigin.Begin);
|
|||
|
|
stream.Write(ipArr, 0, ipArr.Length);
|
|||
|
|
stream.Write(portArr, 0, portArr.Length);
|
|||
|
|
stream.Write(BitConverter.GetBytes(md5Arr[0]), 0, 4);
|
|||
|
|
stream.Write(BitConverter.GetBytes(md5Arr[1]), 0, 4);
|
|||
|
|
stream.Write(BitConverter.GetBytes(md5Arr[2]), 0, 4);
|
|||
|
|
stream.Write(BitConverter.GetBytes(md5Arr[3]), 0, 4);
|
|||
|
|
stream.Write(new byte[] { fileType }, 0, 1);//文件类型:0是bin,1是cfg
|
|||
|
|
stream.Write(BitConverter.GetBytes(this.FTPName.Length), 0, 1);//用户名长度
|
|||
|
|
stream.Write(BitConverter.GetBytes(this.FTPPassword.Length), 0, 1);//密码长度
|
|||
|
|
stream.Write(BitConverter.GetBytes(Tools.GetLength(fileName)), 0, 1);//文件名长度
|
|||
|
|
stream.Write(bFTPName, 0, bFTPName.Length);//用户名
|
|||
|
|
stream.Write(bFTPPassword, 0, bFTPPassword.Length);//密码
|
|||
|
|
stream.Write(bFileName, 0, bFileName.Length);//文件名
|
|||
|
|
stream.Write(new byte[] { 0, 0 }, 0, 2);//补两个长度
|
|||
|
|
|
|||
|
|
//填充 SystemHeader
|
|||
|
|
stream.Seek(0, SeekOrigin.Begin);
|
|||
|
|
systemHeader.FrameLength = (ushort)stream.Length;
|
|||
|
|
systemHeader.FrameNo = 0xFFFF;
|
|||
|
|
byte[] headerData = StructConverter.StructToBytes(systemHeader);
|
|||
|
|
stream.Write(headerData, 0, headerData.Length);
|
|||
|
|
|
|||
|
|
return stream.ToArray();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 解码 UpdateHostPacketReply
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="data"></param>
|
|||
|
|
/// <param name="startIndex"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private UpdateHostPacketReply? DecodeUpdateHostPacketReply(byte[] data, int startIndex)
|
|||
|
|
{
|
|||
|
|
return StructConverter.BytesToStruct(data, startIndex, typeof(UpdateHostPacketReply)) as UpdateHostPacketReply?;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
}
|
|||
|
|
}
|