Init: Migrate SimpleRemoter (Since v1.3.1) to Gitea

This commit is contained in:
yuanyuanxiang
2026-04-19 19:55:01 +02:00
commit 5a325a202b
744 changed files with 235562 additions and 0 deletions

View File

@@ -0,0 +1,251 @@
// CDlgFileSend.cpp: 实现文件
//
#include "stdafx.h"
#include "CDlgFileSend.h"
#include "2015RemoteDlg.h" // For g_2015RemoteDlg->FindHost()
// CDlgFileSend 对话框
IMPLEMENT_DYNAMIC(CDlgFileSend, CDialog)
CDlgFileSend::CDlgFileSend(CMy2015RemoteDlg* pParent, Server* IOCPServer, CONTEXT_OBJECT* ContextObject, BOOL sendFile)
: DialogBase(CDlgFileSend::IDD, pParent, IOCPServer, ContextObject, IDI_File), m_bIsSending(sendFile)
{
m_pParent = (CMy2015RemoteDlg*)pParent;
}
CDlgFileSend::~CDlgFileSend()
{
}
void CDlgFileSend::DoDataExchange(CDataExchange* pDX)
{
__super::DoDataExchange(pDX);
DDX_Control(pDX, IDC_PROGRESS_FILESEND, m_Progress);
}
BEGIN_MESSAGE_MAP(CDlgFileSend, CDialog)
ON_WM_CLOSE()
ON_WM_TIMER()
ON_MESSAGE(WM_UPDATEFILEPROGRESS, &CDlgFileSend::OnUpdateFileProgress)
ON_MESSAGE(WM_FINISHFILESEND, &CDlgFileSend::OnFinishFileSend)
END_MESSAGE_MAP()
// CDlgFileSend 消息处理程序
std::string GetPwdHash();
std::string GetHMAC(int offset);
void RecvData(void* ptr)
{
FileChunkPacket* pkt = (FileChunkPacket*)ptr;
}
void CDlgFileSend::OnReceiveComplete(void)
{
LPBYTE szBuffer = m_ContextObject->InDeCompressedBuffer.GetBuffer();
unsigned len = m_ContextObject->InDeCompressedBuffer.GetBufferLen();
if (len == 0) return;
BYTE cmd = szBuffer[0];
std::string hash = GetPwdHash(), hmac = GetHMAC(100);
// V2 文件完成校验包
if (cmd == COMMAND_FILE_COMPLETE_V2) {
if (len < sizeof(FileCompletePacketV2)) {
Mprintf("[FileSend] FILE_COMPLETE_V2 包太短: %u < %zu\n", len, sizeof(FileCompletePacketV2));
return;
}
FileCompletePacketV2* completePkt = (FileCompletePacketV2*)szBuffer;
// C2C 包:转发到目标客户端
if (completePkt->dstClientID != 0) {
context* dstCtx = m_pParent->FindHost(completePkt->dstClientID);
if (dstCtx) {
dstCtx->Send2Client(szBuffer, len);
Mprintf("[C2C] 转发校验包 -> 客户端 %llu\n", completePkt->dstClientID);
} else {
Mprintf("[C2C] 转发校验包失败: 目标客户端 %llu 不存在\n", completePkt->dstClientID);
}
return;
}
// 目标是服务端,本地校验
bool verifyOk = HandleFileCompleteV2((const char*)szBuffer, len, 0);
Mprintf("[FileSend] 文件校验%s\n", verifyOk ? "通过" : "失败");
return;
}
if (cmd == COMMAND_SEND_FILE_V2) {
// V2 协议
FileChunkPacketV2* chunk = (FileChunkPacketV2*)szBuffer;
// C2C 包:转发到目标客户端,同时更新进度
if (chunk->dstClientID != 0) {
// 如果已标记目标离线,直接忽略后续数据
if (m_bTargetOffline) {
return;
}
// 转发到目标客户端
context* dstCtx = m_pParent->FindHost(chunk->dstClientID);
if (dstCtx) {
dstCtx->Send2Client(szBuffer, len);
double percent = chunk->fileSize ? 100.0 * (chunk->offset + chunk->dataLength) / chunk->fileSize : 100.0;
Mprintf("[C2C] 转发 %d/%d: %.1f%% (%llu/%llu)\n",
1 + chunk->fileIndex, chunk->totalFiles, percent,
chunk->offset + chunk->dataLength, chunk->fileSize);
} else {
Mprintf("[C2C] CDlgFileSend 转发失败: 目标客户端 %llu 不存在,发送取消包\n", chunk->dstClientID);
m_bTargetOffline = TRUE;
// 发送取消包给发送方
FileResumePacketV2 cancelPkt = {};
cancelPkt.cmd = COMMAND_FILE_RESUME;
cancelPkt.transferID = chunk->transferID;
cancelPkt.srcClientID = 0; // 来自服务端
cancelPkt.dstClientID = chunk->srcClientID; // 回复给发送方
cancelPkt.fileIndex = chunk->fileIndex;
cancelPkt.fileSize = chunk->fileSize;
cancelPkt.receivedBytes = chunk->offset;
cancelPkt.flags = FFV2_CANCEL;
cancelPkt.rangeCount = 0;
m_ContextObject->Send2Client((LPBYTE)&cancelPkt, sizeof(cancelPkt));
// 关闭此连接
FinishFileSend(FALSE);
return;
}
BYTE* name = szBuffer + sizeof(FileChunkPacketV2);
UpdateProgress(CString((char*)name, (int)chunk->nameLength), FileProgressInfo(chunk));
return;
}
// 目标是服务端,本地接收
int n = RecvFileChunkV2((char*)szBuffer, len, nullptr, nullptr, hash, hmac, 0);
if (n) {
Mprintf("RecvFileChunkV2 failed: %d\n", n);
}
BYTE* name = szBuffer + sizeof(FileChunkPacketV2);
UpdateProgress(CString((char*)name, (int)chunk->nameLength), FileProgressInfo(chunk));
} else {
// V1 协议
CONNECT_ADDRESS addr = { 0 };
memcpy(addr.pwdHash, hash.c_str(), min(hash.length(), sizeof(addr.pwdHash)));
int n = RecvFileChunk((char*)szBuffer, len, &addr, RecvData, hash, hmac);
if (n) {
Mprintf("RecvFileChunk failed: %d. hash: %s, hmac: %s\n", n, hash.c_str(), hmac.c_str());
}
FileChunkPacket* chunk = (FileChunkPacket*)szBuffer;
BYTE* name = szBuffer + sizeof(FileChunkPacket);
UpdateProgress(CString((char*)name, chunk->nameLength), FileProgressInfo(chunk));
}
}
void CDlgFileSend::UpdateProgress(CString file, const FileProgressInfo& info)
{
if (!GetSafeHwnd()) return;
PostMessageA(WM_UPDATEFILEPROGRESS, (WPARAM)new CString(file), (LPARAM)new FileProgressInfo(info));
}
void CDlgFileSend::FinishFileSend(BOOL succeed)
{
if (!GetSafeHwnd()) return;
PostMessageA(WM_FINISHFILESEND, NULL, (LPARAM)succeed);
}
LRESULT CDlgFileSend::OnUpdateFileProgress(WPARAM wParam, LPARAM lParam)
{
CString* pFile = (CString*)wParam;
FileProgressInfo* pInfo = (FileProgressInfo*)lParam;
CString status;
double percent = pInfo->fileSize ? (pInfo->offset + pInfo->dataLength) * 100. / pInfo->fileSize : 100.;
m_bIsSending ?
status.FormatL("发送文件(%d/%d): %.2f%%", 1 + pInfo->fileIndex, pInfo->totalFiles, percent):
status.FormatL("接收文件(%d/%d): %.2f%%", 1 + pInfo->fileIndex, pInfo->totalFiles, percent);
SetDlgItemText(IDC_STATIC_CURRENTINDEX, status);
SetDlgItemText(IDC_STATIC_CURRENT_FILE, *pFile);
m_Progress.SetPos((int)percent);
// 只在第一次显示时置顶,后续更新不抢焦点
if (!IsWindowVisible()) {
ShowWindow(SW_SHOW);
SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
// 只有最后一个文件完成时才设置自动关闭定时器
// 避免多文件传输时第一个文件完成后就关闭对话框
bool isLastFile = (pInfo->fileIndex + 1 >= pInfo->totalFiles);
if (percent >= 100. && isLastFile) {
SetTimer(1, 3000, NULL);
} else {
// 传输新文件时取消之前的定时器
KillTimer(1);
}
delete pInfo;
delete pFile;
return 0;
}
LRESULT CDlgFileSend::OnFinishFileSend(WPARAM wParam, LPARAM lParam)
{
BOOL success = (BOOL)lParam;
m_bIsSending ?
SetDlgItemText(IDC_STATIC_CURRENTINDEX, success ? _TR("文件发送完成") : _TR("文件发送失败")):
SetDlgItemText(IDC_STATIC_CURRENTINDEX, success ? _TR("文件接收完成") : _TR("文件接收失败"));
if (success)
m_Progress.SetPos(100);
// 完成后取消置顶,恢复普通窗口
SetWindowPos(&wndNoTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
ShowWindow(SW_SHOW);
SetTimer(1, 3000, NULL); // 3秒后自动关闭
return 0;
}
BOOL CDlgFileSend::OnInitDialog()
{
DialogBase::OnInitDialog();
// 多语言翻译 - Static控件
SetDlgItemText(IDC_STATIC_CURRENTINDEX, _TR("发送文件(999/999):"));
SetIcon(m_hIcon, FALSE);
SetWindowText(m_bIsSending ? _TR("发送文件") : _TR("接收文件"));
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != nullptr) {
pSysMenu->EnableMenuItem(SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
}
return TRUE;
}
void CDlgFileSend::OnClose()
{
// V2传输使用主连接关闭对话框时不应断开连接
if (!m_bKeepConnection) {
CancelIO();
}
// 等待数据处理完毕
if (IsProcessing()) {
ShowWindow(SW_HIDE);
return;
}
DialogBase::OnClose();
}
void CDlgFileSend::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == 1) {
KillTimer(1);
PostMessageA(WM_CLOSE, 0, 0);
}
}