// TestEcho-SSL-Console Client
// 基于HP-Socket的SSL客户端控制台程序

#include "pch.h"

// SSL证书配置（来自helper.cpp）
static const char* g_c_lpszPemCert = R"(-----BEGIN CERTIFICATE-----
MIIDszCCApugAwIBAgIBATANBgkqhkiG9w0BAQsFADB7MQswCQYDVQQGEwJDTjEL
MAkGA1UECAwCR0QxCzAJBgNVBAcMAkdaMQwwCgYDVQQKDANTU1QxDzANBgNVBAsM
Bkplc3NtYTETMBEGA1UEAwwKamVzc21hLm9yZzEeMBwGCSqGSIb3DQEJARYPbGRj
c2FhQDIxY24uY29tMCAXDTI0MDYyNjA1MjUwOFoYDzIyNDMwNzA5MDUyNTA4WjBu
MQswCQYDVQQGEwJDTjELMAkGA1UECAwCR0QxDDAKBgNVBAoMA1NTVDEPMA0GA1UE
CwwGSmVzc21hMRMwEQYDVQQDDApqZXNzbWEub3JnMR4wHAYJKoZIhvcNAQkBFg9s
ZGNzYWFAMjFjbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCD
+MyrJEKCheRoOpMRjR78S8hr9W7XN0/EZWyVKwXRT7EE0aGiQdH/W2a+qpWRMa6E
Qi47zdBnt0P8ZoFiItQhuhwUJ064afpVoaHHX25UdbF8r+sRTofadughETBBj2Cf
qh0ia6EOB0QvpJpywWmGZPoMtypjbUiTb/YGOJh2qsVr67MN/E48vt7qt0VxF9SE
pucvqhraTBljWCeRVCae2c0yBSpq/n+7NhamK7+g3xxCKWRz4pN3wrIoEsXTboTh
z940caDgthCc23VJ080DN44jZg6c87huKIuxbebJqw2HCM4DwrW+OSzTLszpFAXZ
yarllOzWnBut20zmYnl1AgMBAAGjTTBLMAkGA1UdEwQCMAAwHQYDVR0OBBYEFJ5E
RJmJ4pUzEbcU9Yge6nr0oi51MB8GA1UdIwQYMBaAFN49z48DywmoD4cNTQgC6nn2
QJoUMA0GCSqGSIb3DQEBCwUAA4IBAQBpoSFfDDDKMAy95tSROpYu5WSWQXe6B7kl
PGJAF6mWe/4b7jHQqDUVkEmFmbMWUAtpTC3P01TrV77dhIosAnC/B76fb7Pto8W4
cjGpWAT0sSegZuhnLtguTGlnR0vVSh/yRRDEtjN8loWpu3BLWVHYOKnn62QGfY0B
sRGrfZsKvwB+1w+HOvGopnWv6UYwrzEKthjPMR65rOsoManOv24ua8baJmq0gqF9
752kD8n703uWUBx79/QlNIPMZC1iUIi1mEjyrTgSag6+3sWAIKihaoF/Nf9d01nw
iL16EIT5dJ0QJWDCeIxhuTZckw+gL1pBeQU7pqzKHPnvo+8GBnTG
-----END CERTIFICATE-----
)";

static const char* g_c_lpszPemKey = R"(-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIK2UJW9QXIj4CAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCDDZQLhAdT91jd6v/5H0+GBIIE
0PH6tKl+nPi8sU0ryjxDIrHwrT/ZFah+3TAHGE/YFAOZnzRyCFHQTvUZX4p8eSmw
WOpt5NBUPJ3mT0Ctt7lGBRy4AXSyBrFSamlTruM3P1e3ijluYjMbweZFfCWPq8c/
jPjbcUkXe6mD96aPSTt/jIunexS8AKovu8c/bFLyTLDk38lATc+GnXQQJ0KiXCRu
vpjVSKcv2Br6cWqaNTZ71FvH1RmSD6K6givc0w65pKruHYTMApIRR8YC5Y0vx0gD
6nS12LV/EJEtxTfZFlrzZTRWZISPIzYGuTfS+3bPePlxpbwzhN6vmvgjKhdk+3lN
3W3ZfqODNhoOKG+mG5Fdj7vR2PU1UND6UUd3+FrzWkXikmalAAwKzRLnyTR1T2rl
RhM0Qe/HZianeEQTHpCw27gOz1OMw2EKfIEHM6W2BKGOTY5ls5dqgMfP1ZoQUrOr
59tJo4GpWYFGCuHhTEa5OS/gsgnzymGrkuEwPsdSQaBdzV7lFGTv2/ryKX+vNm9V
CmKw0nHzOVP19+WL4vPDtbRnLUk8KV9Mg7PdSbGbNcMmTEBk8ju8OvjIUIWZbRTa
n5C6fhD1DYZcczmlCILYgXyJISu7EDf3z9cKRAf5VbRAedDMB/xHWmrmlxUJ37Kt
tVgaCD0U6Q3q+3y6OOwugc8UbSo4yA/DbLlG0/U7afwQaNxTLa4HGBQljpoNStIt
Vgfy2olqHXaf2doSQtsYEl9MHa6neuGfZQMtonDkejnx4KKU+cMhe+KijEUwieYx
7aoPB71b82XODquDPAL5zOegj0eYgKn5iXyOx5W44S34zfclxtxxgfsDJ3qJ9qoL
sSenrQ3xAYHJSZRcqEgO31XhoEnkyt1V7G0Bk4/GUMD6uQudr3nsw/ulJpAlNK15
ZxTSKWrtwOWdwcTj6B14K6wcqMFVNF1Ydbv/qp0b5q5S/orYHzRIPcFmdOAIsjyO
6na7+D31BH/4pf+TASBNqRNRw5CBqNcGcfiXk11AywxUnmD5ZvC/C0pTpTD/9qC4
LucWJ0sNAtPq8suFjKqQ+wMvq3rUh050NRm2cm2nUJLxafTnr0v3+kKYbVW8pSWB
NMelZMVGF1MDYBujg8Mw/xuMhPeLozCZeKmo7eu7aDMXzQMZLfAEJAzU9Du8H4nq
GgQVUgEkS5rdbjZGkHP0FuM8m8lueKEPDYwHCJv9Be5Z/uxp9OO/Lmdlha0J7gJu
pihNkAYVxRst96b5okXKooYi/TZxAdThoPYH28VwinGR1I3/8I3M5DbUPIgHhDeB
ga3u7jt7ZNDUgavukUD0S7WioRb5ooXrXGZ1xmzKLCmMdCDC5S32fQS0wRGfVoMl
hWbaT+0uak+fOpqVRxSNyE3Ek788ua5iPHaTSXJSoe5lv7OQKDSZ/+wFeLmDPf4M
BHL2gBLD6RNkz5cWgy14sQcJKNAnyptU4EGPyURZcB8APtB/ITAS2Az/JSxvSBgq
g/L1FujnP2QEpWpVKkTNxsF867bUPN34KrlPKYjNqcKA2pD4fkFoKSeeNtOEWa++
d6q9y+mDD97SnIFAAhDFlukzXtyl4MU6uiqRldFiuEt3KzvV19n8M+NyyYIFhfdg
6TkYEbMJPQ/Y3EGNmyMqbFdJzrdl/B8pr7JQnikTfUZZ
-----END ENCRYPTED PRIVATE KEY-----
)";

static const char* g_c_lpszCAPemCert = R"(-----BEGIN CERTIFICATE-----
MIID2TCCAsGgAwIBAgIUM8TTtPU+ejzffYXCcs/zZsU7OuIwDQYJKoZIhvcNAQEL
BQAwezELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkdEMQswCQYDVQQHDAJHWjEMMAoG
A1UECgwDU1NUMQ8wDQYDVQQLDAZKZXNzbWExEzARBgNVBAMMCmplc3NtYS5vcmcx
HjAcBgkqhkiG9w0BCQEWD2xkY3NhYUAyMWNuLmNvbTAgFw0yNDA2MjYwNTA0NDNa
GA8yMjcwMTEyNDA1MDQ0M1owezELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkdEMQsw
CQYDVQQHDAJHWjEMMAoGA1UECgwDU1NUMQ8wDQYDVQQLDAZKZXNzbWExEzARBgNV
BAMMCmplc3NtYS5vcmcxHjAcBgkqhkiG9w0BCQEWD2xkY3NhYUAyMWNuLmNvbTCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAML+v79+aLQt0Za0dTIZHI5B
NDs0g5G8bhdOTlW/kNWflaziZ3GY6d6nJSkQ5e29kyFKxlOD6Gls6bOJ86U71u4R
bCmoFvRTDH4q2cJ/+PbiioLpNveDG6lnRCs9JNRQoJrkpRo6urnVnAdsIf6UFjLI
dlByNMPGYJ0V8/oKJG5Vu5gcbZV0jVA5+tswkH/zquexEXoKvp18mcwl+pNc/LwW
0WnGj0uoJjxHg4GsS78PASjhxMR/2d/1OpgPauldFaNHjVPtaLqJnuejwA6M6Sz8
iFPybAQAMpHL9W8kf08jtbnFvnm4ibUkQL5h+OJoIEQa9AVZOSoFG2/g5Zcn8X8C
AwEAAaNTMFEwHQYDVR0OBBYEFN49z48DywmoD4cNTQgC6nn2QJoUMB8GA1UdIwQY
MBaAFN49z48DywmoD4cNTQgC6nn2QJoUMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
hvcNAQELBQADggEBALJnYrYBSZLyYX14FQ04zxG3AX0CtQzNOOa7LDrr+H8Ly+nK
qS87gg2njMVZH1zM2demtMwydR/F2Ui8ggaduMvc9h5YgQKEwYl8KarJEY03oZoe
zbQGBxCXpDOtMs1vujzcl/iZbSzwEDF3g4la5U8q4MlmfGFKz9CJbvoxecqYA206
nNbW2XZsW/xMiQv6iAw5iP/LOR9HAyxcvXIsL790nfcgnTYLmyP254Dj4outc6R+
PA+f/c1FvkbUBTR5vJt2tsvHcNU218rY2hyOIhDmZeUWprqBO19sUk3scLbVPr3+
WEWEl2XaCekKuPtAnMgVQuFsocXGyiuIhkOe5Z4=
-----END CERTIFICATE-----
)";

static const int g_c_iVerifyMode = SSL_VM_PEER;
static const char* g_c_lpszKeyPassword = "123456";
static const LPCTSTR DEFAULT_ADDRESS = _T("127.0.0.1");
static const USHORT DEFAULT_PORT = 5555;

inline static bool writeFile(const std::string& path, const std::vector<unsigned char>& data) {
	std::ofstream f(path, std::ios::binary);
	if (!f) return false;
	// 写入数据
	f.write(reinterpret_cast<const char*>(data.data()), data.size());
	// 检查是否全部写入成功
	if (!f) return false;

	return true;
}
// 客户端监听器类
class CClientListener : public CTcpClientListener
{
private:
	bool m_bConnected;

public:
	CClientListener() : m_bConnected(false) {}

	bool IsConnected() const { return m_bConnected; }

	virtual EnHandleResult OnConnect(ITcpClient* pSender, CONNID dwConnID) override
	{
		TCHAR szAddress[100];
		int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
		USHORT usPort;
		pSender->GetLocalAddress(szAddress, iAddressLen, usPort);
		
		std::wcout << L"[客户端] 连接成功: 本地地址=" << szAddress << L":" << usPort << std::endl;
		m_bConnected = true;
		
		return HR_OK;
	}

	virtual EnHandleResult OnHandShake(ITcpClient* pSender, CONNID dwConnID) override
	{
		std::wcout << L"[客户端] SSL握手完成" << std::endl;
		return HR_OK;
	}

	virtual EnHandleResult OnReceive(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength) override
	{
		std::string strData((char*)pData, iLength);
		std::cout << "[客户端] 收到服务器数据，长度为：" << iLength << std::endl;
		
		return HR_OK;
	}

	virtual EnHandleResult OnSend(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength) override
	{
		return HR_OK;
	}

	virtual EnHandleResult OnClose(ITcpClient* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode) override
	{
		if (iErrorCode == SE_OK)
		{
			std::wcout << L"[客户端] 连接已关闭" << std::endl;
		}
		else
		{
			std::wcout << L"[客户端] 连接错误: 错误码=" << iErrorCode << std::endl;
		}
		
		m_bConnected = false;
		return HR_OK;
	}
};

void PrintMenu()
{
	std::wcout << L"\n----------------------------------------" << std::endl;
	std::wcout << L"命令菜单:" << std::endl;
	std::wcout << L"  1 - 发送 'hello' 到服务器" << std::endl;
	std::wcout << L"  Q - 断开连接并退出" << std::endl;
	std::wcout << L"----------------------------------------" << std::endl;
	std::wcout << L"请输入命令: ";
}

int main()
{
	// 设置控制台UTF-8编码和locale
	SetConsoleOutputCP(CP_UTF8);
	std::locale::global(std::locale(""));
	std::wcout.imbue(std::locale(""));
	
	std::wcout << L"========================================" << std::endl;
	std::wcout << L"  HP-Socket SSL Client 控制台演示程序" << std::endl;
	std::wcout << L"========================================" << std::endl;
	std::wcout << std::endl;

	// 创建监听器和客户端
	CClientListener listener;
	CSSLClientPtr client(&listener);

	// 初始化SSL上下文
	std::wcout << L"[客户端] 正在初始化SSL环境..." << std::endl;
	if (!client->SetupSSLContextByMemory(g_c_iVerifyMode, g_c_lpszPemCert, g_c_lpszPemKey, 
		g_c_lpszKeyPassword, g_c_lpszCAPemCert))
	{
		std::wcout << L"[客户端] SSL初始化失败！错误码: " << client->GetLastError() << std::endl;
		std::wcout << L"按任意键退出..." << std::endl;
		_getch();
		return 1;
	}
	std::wcout << L"[客户端] SSL环境初始化成功" << std::endl;

	// 连接服务器
	std::wcout << L"[客户端] 正在连接服务器 " << DEFAULT_ADDRESS << L":" << DEFAULT_PORT << L" ..." << std::endl;
	if (!client->Start(DEFAULT_ADDRESS, DEFAULT_PORT, FALSE))
	{
		std::wcout << L"[客户端] 连接失败！错误码: " << client->GetLastError() << std::endl;
		std::wcout << L"按任意键退出..." << std::endl;
		_getch();
		return 1;
	}

	// 等待连接完成
	int waitCount = 0;
	while (!listener.IsConnected() && waitCount < 50)
	{
		Sleep(100);
		waitCount++;
	}

	if (!listener.IsConnected())
	{
		std::wcout << L"[客户端] 连接超时！" << std::endl;
		client->Stop();
		client->CleanupSSLContext();
		std::wcout << L"按任意键退出..." << std::endl;
		_getch();
		return 1;
	}

	std::wcout << L"[客户端] 已连接到服务器，可以开始发送消息" << std::endl;

	// 主循环 - 等待用户输入命令
	PrintMenu();

	bool bRunning = true;
	while (bRunning)
	{
		if (_kbhit())
		{
			char ch = _getch();
			std::cout << ch << std::endl;

			if (ch == '1')
			{
				// 发送 "hello" 到服务器
				std::string message = "hello";
				if (client->Send((const BYTE*)message.c_str(), (int)message.length()))
				{
					std::cout << "[客户端] 发送消息: \"" << message << "\"" << std::endl;
				}
				else
				{
					std::wcout << L"[客户端] 发送失败！错误码: " << client->GetLastError() << std::endl;
				}
				PrintMenu();
			}
			else if (ch == 'q' || ch == 'Q')
			{
				bRunning = false;
			}
			else
			{
				std::wcout << L"无效命令，请重新输入。" << std::endl;
				PrintMenu();
			}
		}
		Sleep(100);
	}

	// 断开连接
	std::wcout << L"[客户端] 正在断开连接..." << std::endl;
	if (client->Stop())
	{
		std::wcout << L"[客户端] 已断开连接" << std::endl;
	}

	// 清理SSL上下文
	client->CleanupSSLContext();

	std::wcout << L"按任意键退出..." << std::endl;
	_getch();
	
	return 0;
}
