📄 w3mfc.cpp
字号:
//Pick the SSL protocol to use
SSL_METHOD* pSSLMethod = NULL;
switch (m_pSettings->m_SSLProtocol)
{
case CHttpServerSettings::SSL_V2:
{
pSSLMethod = SSLv23_server_method();
break;
}
case CHttpServerSettings::SSL_V3:
{
pSSLMethod = SSLv3_server_method();
break;
}
case CHttpServerSettings::SSL_V2_OR_V3:
{
pSSLMethod = SSLv23_server_method();
break;
}
case CHttpServerSettings::TLS_V1:
{
pSSLMethod = TLSv1_server_method();
break;
}
default:
{
ASSERT(FALSE);
break;
}
}
//Create the SSL context object
ASSERT(pSSLMethod != NULL);
SSL_CTX* pSSLContext = SSL_CTX_new(pSSLMethod);
if (pSSLContext == NULL)
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, Failed to create SSL context object"));
OnError(sError);
LogSSLErrors();
m_ListenStartEvent.SetEvent();
return;
}
else
sslContext.Attach(pSSLContext);
//Set the certificate to use
if (SSL_CTX_use_certificate_file(sslContext, T2A((LPTSTR) (LPCTSTR) m_pSettings->m_sServerCertificateFile), SSL_FILETYPE_PEM) != 1)
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, Failed to load up server certificate"));
OnError(sError);
LogSSLErrors();
m_ListenStartEvent.SetEvent();
return;
}
//Set the private key to use
if (SSL_CTX_use_PrivateKey_file(sslContext, m_pSettings->m_sPrivateKeyFile.GetLength() ?
T2A((LPTSTR) (LPCTSTR) m_pSettings->m_sPrivateKeyFile) :
T2A((LPTSTR) (LPCTSTR) m_pSettings->m_sServerCertificateFile), SSL_FILETYPE_PEM) != 1)
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, Failed to load up private key"));
OnError(sError);
LogSSLErrors();
m_ListenStartEvent.SetEvent();
return;
}
//Check that we the private key is ok
if (SSL_CTX_check_private_key(sslContext) != 1)
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, Private key does not match the certificate public key"));
OnError(sError);
LogSSLErrors();
m_ListenStartEvent.SetEvent();
return;
}
//Set the SSL session settings
if (m_pSettings->m_bReuseSessions)
{
int nOldTimeout;
nOldTimeout = SSL_CTX_set_timeout(sslContext, m_pSettings->m_dwSSLSessionTimeout);
}
else
SSL_CTX_set_timeout(sslContext, 0);
}
#endif
//Use a Win32 event notification on the server socket
int nError = WSAEventSelect(serverSocket, m_SocketEvent, FD_ACCEPT);
if (nError == SOCKET_ERROR)
{
DWORD dwError = ::GetLastError();
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, Failed in call to WSAEventSelect, GetLastError:%d"), dwError);
OnError(sError);
m_ListenStartEvent.SetEvent();
return;
}
//We're now ready for accepting client connections, inform
//the main thread that everthing is ok
m_bListenerRunningOK = TRUE;
m_ListenStartEvent.SetEvent();
//Create the wait handles array (used for waiting for an event)
HANDLE Handles[2];
Handles[0] = m_StopEvent;
Handles[1] = m_SocketEvent;
//Wait for any incoming connections and the signal to exit the thread m_ListenStopEvent
BOOL bWantStop = FALSE;
CThreadPoolQueue* pQueue = m_ThreadPool.GetQueue();
ASSERT(pQueue);
while (!bWantStop)
{
DWORD dwWait = WaitForMultipleObjects(2, (CONST HANDLE*) &Handles, FALSE, INFINITE);
int nSignaledHandle = dwWait - WAIT_OBJECT_0;
if (nSignaledHandle == 0) //It was the stop request
bWantStop = TRUE;
else if (nSignaledHandle == 1) //It was a socket event
{
CHttpThreadPoolRequest* pRequest = new CHttpThreadPoolRequest;
try
{
#ifdef W3MFC_SSL_SUPPORT
pRequest->m_pSSLContext = &sslContext;
#endif
//Accept the client connection
serverSocket.Accept(pRequest->m_ClientSocket, pRequest->m_ClientAddress);
//Let a thread pool client class instance handle the work
CThreadPoolRequest poolRequest;
poolRequest.m_dwID = 1;
poolRequest.m_pData = pRequest;
pQueue->PostRequest(poolRequest);
}
catch(CWSocketException* pEx)
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, An error occurred accepting a client connection, GetLastError:%d"), pEx->m_nError);
OnError(sError);
pEx->Delete();
}
}
}
//Revert back to normal security settings
if (bUseAccount)
{
//Revert to the usual security settings
if (bImpersonated)
RevertToSelf();
}
//Bring down the thread pool
m_ThreadPool.Stop();
}
UINT CHttpServer::ListenSocketFunction(LPVOID pParam)
{
//Get back the "this" pointer from the pParam parameter
CHttpServer* pServer = (CHttpServer*) pParam;
ASSERT(pServer);
ASSERT(pServer->IsKindOf(RUNTIME_CLASS(CHttpServer)));
//Call the run method of the CHttpServer instance
pServer->ListenSocketFunction();
#ifdef W3MFC_SSL_SUPPORT
//cleanup SSL thread state
ERR_remove_state(0);
#endif
//Return the thread exit code
return TRUE;
}
#ifdef _DEBUG
void CHttpServer::OnError(const CString& sError) //To avoid level 4 warning in release
#else
void CHttpServer::OnError(const CString& /*sError*/)
#endif
{
#ifdef _DEBUG
//The default is to just TRACE the details
TRACE(_T("%s\n"), sError);
#endif
}
BOOL CHttpServer::LoadHTMLResource(UINT nID, char*& pszHTML, DWORD& dwSize)
{
BOOL bSuccess = FALSE;
HMODULE hModule = AfxFindResourceHandle(MAKEINTRESOURCE(nID), RT_HTML);
HRSRC hRsrc = ::FindResource(hModule, MAKEINTRESOURCE(nID), RT_HTML);
if (hRsrc)
{
//Load up the resource
dwSize = ::SizeofResource(hModule, hRsrc);
HGLOBAL hGlobal = ::LoadResource(hModule, hRsrc);
//Allocate a new char array and copy the HTML resource into it
if (hGlobal)
{
pszHTML = new char[dwSize + 1];
char* pszResource = (char*) ::LockResource(hGlobal);
if (pszResource)
{
strncpy(pszHTML, pszResource, dwSize);
pszHTML[dwSize] = _T('\0');
bSuccess = TRUE;
}
else
{
//Report the error
TRACE(_T("CHttpServer::LoadHTMLResource, Failed to load HTML resource, GetLastError:%d\n"), GetLastError());
}
}
}
return bSuccess;
}
char* CHttpServer::LoadHTML(int nStatusCode, DWORD& dwSize)
{
//What will be the return value
char* pszHTML = NULL;
dwSize = 0;
switch(nStatusCode)
{
case 302:
{
pszHTML = m_psz302HTML;
dwSize = m_dw302HTML;
break;
}
case 400:
{
pszHTML = m_psz400HTML;
dwSize = m_dw400HTML;
break;
}
case 401:
{
pszHTML = m_psz401HTML;
dwSize = m_dw401HTML;
break;
}
case 404:
{
pszHTML = m_psz404HTML;
dwSize = m_dw404HTML;
break;
}
default:
{
pszHTML = m_psz500HTML;
dwSize = m_dw500HTML;
break;
}
}
return pszHTML;
}
char* CHttpServer::GetFileDeletedHTML(DWORD& dwSize)
{
dwSize = m_dwDeletedHTML;
return m_pszDeletedHTML;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -