From 34553ba89b8d90482b990691f4a5c762206738aa Mon Sep 17 00:00:00 2001 From: David Maw Date: Sun, 26 Jan 2020 21:42:48 -0800 Subject: [PATCH] Allow an Ansi build of StreamServer. This still uses a Unicode build of SSLServer so to permit that SSLServer no longer uses MFC - it uses ATL instead, which leads to a few minor changes as method names or parameters are a little different. A fw Windows calls are now explicitly "W" (wide) versions. There's now a "Debug Ansi" build which builds SimpleClient, SteamClient and StreamServer using multibyte (ansi) and SSLClient and SSLServer using Unicode. --- SSLServer/Include/Listener.h | 12 ++-- SSLServer/Listener.cpp | 46 +++++++------ SSLServer/SSLServer.vcxproj | 8 +-- SSLServer/framework.h | 7 +- Samples/StreamServer/StreamServer.cpp | 8 +-- Samples/StreamServer/StreamServer.vcxproj | 80 +++++++++++++++++++++++ StreamSSL.sln | 8 +-- 7 files changed, 124 insertions(+), 45 deletions(-) diff --git a/SSLServer/Include/Listener.h b/SSLServer/Include/Listener.h index 4473b0b..f7294b8 100644 --- a/SSLServer/Include/Listener.h +++ b/SSLServer/Include/Listener.h @@ -7,7 +7,7 @@ class ISocketStream; class CListener { public: - enum ErrorType { + enum class ErrorType { NoError, UnknownError, SocketInuse, @@ -20,19 +20,19 @@ class CListener HANDLE m_hSocketEvents[FD_SETSIZE]{}; int m_iNumListenSockets{ 0 }; CCriticalSection m_WorkerCountLock; - CWinThread * m_ListenerThread{ nullptr }; - static UINT __cdecl Worker(LPVOID); - static UINT __cdecl ListenerWorker(LPVOID); + uintptr_t m_ListenerThread { 0 }; + static void __cdecl Worker(LPVOID); + static void __cdecl ListenerWorker(LPVOID); void Listen(); std::function m_actualwork; public: static void LogWarning(const WCHAR* const); static void LogWarning(const CHAR* const); int m_WorkerCount{ 0 }; - CEvent m_StopEvent{ FALSE, TRUE }; + CEvent m_StopEvent{ TRUE, FALSE }; // Initialize the listener ErrorType Initialize(int TCPSocket); - std::function SelectServerCert; + std::function SelectServerCert; std::function ClientCertAcceptable; void EndListening(); void BeginListening(std::function actualwork); diff --git a/SSLServer/Listener.cpp b/SSLServer/Listener.cpp index 6ff9de1..99aad66 100644 --- a/SSLServer/Listener.cpp +++ b/SSLServer/Listener.cpp @@ -29,24 +29,22 @@ CListener::~CListener() // This is the individual worker process, all it does is start, change its name to something useful, // then call the Lambda function passed in via the BeginListening method -UINT __cdecl CListener::Worker(void * v) +void __cdecl CListener::Worker(LPVOID v) { std::unique_ptr SSLServer(reinterpret_cast(v)); SetThreadName("Connection Worker"); // Invoke the caller provided function defining the work to do, passing an interface which // allows the user code to send and receive messages and so on. (SSLServer->GetListener()->m_actualwork)(SSLServer->GetSocketStream()); - return 0; } // Worker process for connection listening -UINT __cdecl CListener::ListenerWorker(LPVOID v) +void __cdecl CListener::ListenerWorker(LPVOID v) { auto * Listener = static_cast(v); // See _beginthread call for parameter definition SetThreadName("Listener"); Listener->Listen(); - return 0; } // Initialize the listener, set up the socket to listen on, or return an error @@ -56,7 +54,7 @@ CListener::ErrorType CListener::Initialize(int TCPSocket) WSADATA wsadata; if (WSAStartup(MAKEWORD(1, 1), &wsadata)) - return UnknownError; + return CListener::ErrorType::UnknownError; // Get list of addresses to listen on ADDRINFOT Hints, *AddrInfo, *AI; @@ -69,7 +67,7 @@ CListener::ErrorType CListener::Initialize(int TCPSocket) WCHAR MsgText[100]; StringCchPrintf(MsgText, _countof(MsgText), L"getaddressinfo error: %i", GetLastError()); LogWarning(MsgText); - return UnknownError; + return CListener::ErrorType::UnknownError; } // Create one or more passive sockets to listen on @@ -92,14 +90,14 @@ CListener::ErrorType CListener::Initialize(int TCPSocket) nullptr); // no name if (!(m_hSocketEvents[i])) - return UnknownError; + return CListener::ErrorType::UnknownError; // StringCchPrintf(MsgText, _countof(MsgText), L"::OnInit Created m_hSocketEvents[%d], handle=%d"), i, m_hSocketEvents[i]; // LogWarning(MsgText); m_iListenSockets[i] = WSASocket(AI->ai_family, SOCK_STREAM, 0, nullptr, 0, WSA_FLAG_OVERLAPPED); if (m_iListenSockets[i] == INVALID_SOCKET) - return SocketUnusable; + return CListener::ErrorType::SocketUnusable; // StringCchPrintf(MsgText, _countof(MsgText), L"::OnInit binding m_iListenSockets[%d] to sa_family=%u sa_data=%s len=%d"), i, AI->ai_addr->sa_family, AI->ai_addr->sa_data, AI->ai_addrlen; // LogWarning(MsgText); @@ -108,15 +106,15 @@ CListener::ErrorType CListener::Initialize(int TCPSocket) if (rc) { if (WSAGetLastError() == WSAEADDRINUSE) - return SocketInuse; + return CListener::ErrorType::SocketInuse; else - return SocketUnusable; + return CListener::ErrorType::SocketUnusable; } if (listen(m_iListenSockets[i], 10)) - return SocketUnusable; + return CListener::ErrorType::SocketUnusable; if (WSAEventSelect(m_iListenSockets[i], m_hSocketEvents[i], FD_ACCEPT)) - return SocketUnusable; + return CListener::ErrorType::SocketUnusable; i++; } @@ -125,32 +123,32 @@ CListener::ErrorType CListener::Initialize(int TCPSocket) // StringCchPrintf(MsgText, _countof(MsgText), L"::OnInit no errors, m_iNumListenSockets = %d"), m_iNumListenSockets; // LogWarning(MsgText); - return NoError; + return CListener::ErrorType::NoError; } // Start listening for connections, if a timeout is specified keep listening until then void CListener::BeginListening(std::function actualwork) { m_actualwork = actualwork; - m_ListenerThread = AfxBeginThread(ListenerWorker, this); + m_ListenerThread = _beginthread(ListenerWorker, 0, this); } void CListener::IncrementWorkerCount(int i) { - m_WorkerCountLock.Lock(); + m_WorkerCountLock.Enter(); m_WorkerCount += i; - m_WorkerCountLock.Unlock(); + m_WorkerCountLock.Leave(); } // Stop listening, tells the listener thread it can stop, then waits for it to terminate void CListener::EndListening() { - m_StopEvent.SetEvent(); + m_StopEvent.Set(); if (m_ListenerThread) { - WaitForSingleObject(m_ListenerThread->m_hThread, INFINITE); // Will auto delete + WaitForSingleObject((HANDLE)m_ListenerThread, INFINITE); // Will auto delete } - m_ListenerThread = nullptr; + m_ListenerThread = 0; } // Log a warning @@ -220,22 +218,22 @@ void CListener::Listen() auto SSLServer = CSSLServer::Create(iReadSocket, this); if (SSLServer && SSLServer->IsConnected) - AfxBeginThread(Worker, SSLServer); + _beginthread(Worker, 0, SSLServer); else delete SSLServer; iReadSocket = INVALID_SOCKET; } // Either we're done, or there has been a problem, wait for all the worker threads to terminate Sleep(500); - m_WorkerCountLock.Lock(); + m_WorkerCountLock.Enter(); while (m_WorkerCount) { - m_WorkerCountLock.Unlock(); + m_WorkerCountLock.Leave(); Sleep(1000); DebugMsg("Waiting for all workers to terminate: worker thread count = %i", m_WorkerCount); - m_WorkerCountLock.Lock(); + m_WorkerCountLock.Enter(); }; - m_WorkerCountLock.Unlock(); + m_WorkerCountLock.Leave(); if ((iReadSocket != NULL) && (iReadSocket != INVALID_SOCKET)) closesocket(iReadSocket); DebugMsg("End Listen method"); diff --git a/SSLServer/SSLServer.vcxproj b/SSLServer/SSLServer.vcxproj index 059e205..4b046f6 100644 --- a/SSLServer/SSLServer.vcxproj +++ b/SSLServer/SSLServer.vcxproj @@ -31,14 +31,14 @@ true v142 Unicode - Dynamic + false StaticLibrary true v142 Unicode - Dynamic + false StaticLibrary @@ -46,7 +46,7 @@ v142 true Unicode - Dynamic + false StaticLibrary @@ -54,7 +54,7 @@ v142 true Unicode - Dynamic + false diff --git a/SSLServer/framework.h b/SSLServer/framework.h index d2ec495..2c5c300 100644 --- a/SSLServer/framework.h +++ b/SSLServer/framework.h @@ -31,11 +31,12 @@ const bool debug = false; #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers #endif -#include -#include // MFC core and standard components -#include +#include +#include +#include #include +#pragma comment(lib, "Ws2_32.lib") #define SECURITY_WIN32 #include #include diff --git a/Samples/StreamServer/StreamServer.cpp b/Samples/StreamServer/StreamServer.cpp index 6f205d0..bb97c76 100644 --- a/Samples/StreamServer/StreamServer.cpp +++ b/Samples/StreamServer/StreamServer.cpp @@ -14,7 +14,7 @@ using namespace std; // This method is called when the first client tries to connect in order to allow a certificate to be selected to send to the client // It has to wait for the client connect request because the client tells the server what identity it expects it to present // This is called SNI (Server Name Indication) and it is a relatively new (it began to become available about 2005) SSL/TLS feature -SECURITY_STATUS SelectServerCert(PCCERT_CONTEXT & pCertContext, LPCTSTR pszSubjectName) +SECURITY_STATUS SelectServerCert(PCCERT_CONTEXT & pCertContext, LPCWSTR pszSubjectName) { SECURITY_STATUS status = SEC_E_INVALID_HANDLE; @@ -48,11 +48,11 @@ bool ClientCertAcceptable(PCCERT_CONTEXT pCertContext, const bool trusted) // This function simply runs arbitrary code and returns process information to the caller, it's just a handy utility function bool RunApp(std::wstring app, PROCESS_INFORMATION& pi) { // Not strictly needed but it makes testing easier - STARTUPINFO si = {}; + STARTUPINFOW si = {}; si.cb = sizeof si; ZeroMemory(&pi, sizeof(pi)); #pragma warning(suppress:6335) - if (CreateProcess(nullptr, &app[0], nullptr, FALSE, 0, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi)) + if (CreateProcessW(nullptr, &app[0], nullptr, FALSE, 0, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi)) return true; else { @@ -65,7 +65,7 @@ void RunClient(std::wstring toHost = L"", PROCESS_INFORMATION * ppi = nullptr) { cout << "Initiating a client instance for testing.\n" << endl; WCHAR acPathName[MAX_PATH + 1]; - GetModuleFileName(nullptr, acPathName, _countof(acPathName)); + GetModuleFileNameW(nullptr, acPathName, _countof(acPathName)); std::wstring appName(acPathName); const auto len = appName.find_last_of(L'\\'); appName = appName.substr(0, len + 1) + L"StreamClient.exe " + toHost; diff --git a/Samples/StreamServer/StreamServer.vcxproj b/Samples/StreamServer/StreamServer.vcxproj index 25f75c1..f056774 100644 --- a/Samples/StreamServer/StreamServer.vcxproj +++ b/Samples/StreamServer/StreamServer.vcxproj @@ -1,6 +1,14 @@ + + Debug Ansi + Win32 + + + Debug Ansi + x64 + Debug Win32 @@ -34,6 +42,13 @@ Unicode Dynamic + + Application + true + v142 + MultiByte + Dynamic + Application false @@ -49,6 +64,13 @@ Unicode Dynamic + + Application + true + v142 + MultiByte + Dynamic + Application false @@ -65,12 +87,18 @@ + + + + + + @@ -78,9 +106,15 @@ true + + true + true + + true + false @@ -109,6 +143,28 @@ ..\..\Common\Include + + + Use + Level4 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + ..\..\SSLServer\Include;..\..\Common\Include + stdcpplatest + true + true + + + Console + true + + + ..\..\Common\Include + + Use @@ -131,6 +187,28 @@ ..\..\Common\Include + + + Use + Level4 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + ..\..\SSLServer\Include;..\..\Common\Include + stdcpplatest + true + true + + + Console + true + + + ..\..\Common\Include + + Use @@ -197,7 +275,9 @@ Create + Create Create + Create Create Create diff --git a/StreamSSL.sln b/StreamSSL.sln index 3f7bf0c..30a28c8 100644 --- a/StreamSSL.sln +++ b/StreamSSL.sln @@ -66,10 +66,10 @@ Global {144CCC0E-0CE9-42D2-887B-4210DEAA2BC6}.Release|Win32.Build.0 = Release|Win32 {144CCC0E-0CE9-42D2-887B-4210DEAA2BC6}.Release|x64.ActiveCfg = Release|x64 {144CCC0E-0CE9-42D2-887B-4210DEAA2BC6}.Release|x64.Build.0 = Release|x64 - {6FC978B9-9CC8-4C8A-A5E3-D575B59ED415}.Debug Ansi|Win32.ActiveCfg = Debug|Win32 - {6FC978B9-9CC8-4C8A-A5E3-D575B59ED415}.Debug Ansi|Win32.Build.0 = Debug|Win32 - {6FC978B9-9CC8-4C8A-A5E3-D575B59ED415}.Debug Ansi|x64.ActiveCfg = Debug|x64 - {6FC978B9-9CC8-4C8A-A5E3-D575B59ED415}.Debug Ansi|x64.Build.0 = Debug|x64 + {6FC978B9-9CC8-4C8A-A5E3-D575B59ED415}.Debug Ansi|Win32.ActiveCfg = Debug Ansi|Win32 + {6FC978B9-9CC8-4C8A-A5E3-D575B59ED415}.Debug Ansi|Win32.Build.0 = Debug Ansi|Win32 + {6FC978B9-9CC8-4C8A-A5E3-D575B59ED415}.Debug Ansi|x64.ActiveCfg = Debug Ansi|x64 + {6FC978B9-9CC8-4C8A-A5E3-D575B59ED415}.Debug Ansi|x64.Build.0 = Debug Ansi|x64 {6FC978B9-9CC8-4C8A-A5E3-D575B59ED415}.Debug|Win32.ActiveCfg = Debug|Win32 {6FC978B9-9CC8-4C8A-A5E3-D575B59ED415}.Debug|Win32.Build.0 = Debug|Win32 {6FC978B9-9CC8-4C8A-A5E3-D575B59ED415}.Debug|x64.ActiveCfg = Debug|x64