Files
Web_CRICS_Server_VS2010_Prod/RCUHost/Implement/UpdateHostFTPReceiver.cs
2025-12-11 09:17:16 +08:00

181 lines
8.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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是bin1是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
}
}