📄 w3mfc.cpp
字号:
OnError(sError);
return FALSE;
}
m_pListenThread->m_bAutoDelete = FALSE;
m_pListenThread->ResumeThread();
//Wait until the thread has completely started and return the success indicator
::WaitForSingleObject(m_ListenStartEvent, INFINITE);
return m_bListenerRunningOK;
}
BOOL CHttpServer::Wait()
{
CSingleLock sl(&m_csListenThread, TRUE); //synchronize access to the listening thread
//If the listener thread is running, then just wait for it to exit
if (m_pListenThread)
{
::WaitForSingleObject(m_pListenThread->m_hThread, INFINITE);
delete m_pListenThread;
m_pListenThread = NULL;
return TRUE;
}
else
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::Wait, Http server is not running, so no need to wait"));
OnError(sError);
return FALSE;
}
}
BOOL CHttpServer::Stop()
{
//Signal the listener thread to stop and wait for it to do so, Note that we do
//this before we enter the critical section because otherwise we could end
//up in a deadlock situation between this function and Wait
m_StopEvent.SetEvent();
CSingleLock sl(&m_csListenThread, TRUE); //synchronize access to the listening thread
//If the listener thread is running, then stop it
if (m_pListenThread)
{
::WaitForSingleObject(m_pListenThread->m_hThread, INFINITE);
delete m_pListenThread;
m_pListenThread = NULL;
//Release SSPI
#ifndef W3MFC_NO_SSPI_SUPPORT
ReleaseSSPI();
#endif
}
return TRUE;
}
BOOL CHttpServer::ReverseDNSLookup(in_addr sin_addr, CString& sDomainName)
{
BOOL bSuccess = FALSE;
HOSTENT* pHostEnt = gethostbyaddr((const char*) &sin_addr, sizeof(sin_addr), AF_INET);
if (pHostEnt)
{
bSuccess = TRUE;
sDomainName = pHostEnt->h_name;
}
return bSuccess;
}
#ifdef W3MFC_SSL_SUPPORT
void CHttpServer::LogSSLErrors()
{
char sError[1024];
unsigned long nError;
do
{
nError = ERR_get_error();
if (nError)
{
ERR_error_string(nError, sError);
OnError(sError);
}
}
while (nError);
}
#endif
CString CHttpServer::ErrorString()
{
DWORD err = ::GetLastError();
CString Error;
LPTSTR s;
if(::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
err,
0x0409,
(LPTSTR)&s,
0,
NULL) == 0)
{ /* failed */
// Unknown error code %08x (%d)
CString fmt;
CString t;
fmt.LoadString(IDS_UNKNOWN_ERROR);
t.Format(fmt, err, LOWORD(err));
Error = t;
} /* failed */
else
{ /* success */
LPTSTR p = _tcschr(s, _T('\r'));
if(p != NULL)
{ /* lose CRLF */
*p = _T('\0');
} /* lose CRLF */
Error = s;
::LocalFree(s);
} /* success */
return Error;
}
void CHttpServer::ListenSocketFunction()
{
USES_CONVERSION;
//Setup the thread pool
ASSERT(m_pSettings);
ASSERT(m_pSettings->m_pRuntimeClientClass);
if (!m_ThreadPool.Start(m_pSettings->m_pRuntimeClientClass, m_pSettings->m_bUseIOCPQueue ? RUNTIME_CLASS(CIOCPThreadPoolQueue) : RUNTIME_CLASS(CHttpDirectedThreadPoolQueue),
m_pSettings->m_nThreadPoolSize, m_pSettings->m_nThreadPoolSize, TRUE))
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, Failed to create thread pool, GetLastError:%d"), ::GetLastError());
OnError(sError);
m_ListenStartEvent.SetEvent();
return;
}
//Setup the pointers in the thread pool instances and resume the threads
for (int i=0; i<m_pSettings->m_nThreadPoolSize; i++)
{
CHttpClient* pClient = (CHttpClient*) m_ThreadPool.GetAtClient(i);
ASSERT(pClient);
ASSERT(pClient->IsKindOf(RUNTIME_CLASS(CHttpClient)));
pClient->m_pServer = this;
pClient->m_pWorkerThread->ResumeThread();
}
//Setup the recycling of threads
if (!m_ThreadPool.SetMaxThreadClientLifetime(m_pSettings->m_bEnableThreadLifetime, m_pSettings->m_dwThreadLifetime))
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, Failed in call to m_ThreadPool.SetMaxThreadClientLifetime, GetLastError:%d"), GetLastError());
OnError(sError);
m_ListenStartEvent.SetEvent();
return;
}
//Create the server socket
CHttpSocket serverSocket;
try
{
serverSocket.Create();
}
catch(CWSocketException* pEx)
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, Failed to create server socket, GetLastError:%d"), pEx->m_nError);
OnError(sError);
m_ListenStartEvent.SetEvent();
pEx->Delete();
return;
}
//Bind the server socket
try
{
if (m_pSettings->m_bBind)
serverSocket.Bind(m_pSettings->m_nPort, m_pSettings->m_sBindAddress);
else
serverSocket.Bind(m_pSettings->m_nPort);
}
catch(CWSocketException* pEx)
{
//Report the error
CString sError;
sError.Format(_T("Error Code:%d %s"), pEx->m_nError, ErrorString());
OnError(sError);
m_ListenStartEvent.SetEvent();
pEx->Delete();
return;
}
//Put the server socket in a listening state
try
{
serverSocket.Listen();
}
catch(CWSocketException* pEx)
{
//Report the error
CString sError;
sError.Format(_T("Error Code:%d %s"), pEx->m_nError, ErrorString());
OnError(sError);
m_ListenStartEvent.SetEvent();
pEx->Delete();
return;
}
//Run the server under a different account if configured to do so
BOOL bUseAccount = (m_pSettings->m_sUsername.GetLength() != 0);
CW32Handle hImpersonation;
BOOL bLoggedOn = FALSE;
BOOL bImpersonated = FALSE;
if (bUseAccount)
{
LPTSTR pszUser = m_pSettings->m_sUsername.GetBuffer(m_pSettings->m_sUsername.GetLength());
LPTSTR pszPassword = m_pSettings->m_sPassword.GetBuffer(m_pSettings->m_sPassword.GetLength());
HANDLE hRawImpersonation = NULL;
bLoggedOn = LogonUser(pszUser, NULL, pszPassword, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hImpersonation);
if (bLoggedOn)
{
hImpersonation.Attach(hRawImpersonation);
bImpersonated = ImpersonateLoggedOnUser(hImpersonation);
}
else
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, Failed to logon using user name: %s, GetLastError:%d"), pszUser, ::GetLastError());
OnError(sError);
}
m_pSettings->m_sUsername.ReleaseBuffer();
m_pSettings->m_sPassword.ReleaseBuffer();
//Clear the password now that we are finished with it
m_pSettings->m_sPassword.Empty();
}
m_hImpersonation = hImpersonation;
//Handle the case if the impersonation failed
if (bUseAccount && !bImpersonated)
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, Failed to impersonate using supplied user credentials"));
OnError(sError);
m_ListenStartEvent.SetEvent();
return;
}
//Initialize SSL context if required to do so
#ifdef W3MFC_SSL_SUPPORT
//Initialize the PRNG in OpenSSL
if (m_pSettings->m_sSSLRandomnessFile.IsEmpty())
{
//Get the default rand file from OpenSSL
char sSSLFile[1024];
const char* pszRandFile = RAND_file_name(sSSLFile, sizeof(sSSLFile));
if (pszRandFile)
m_pSettings->m_sSSLRandomnessFile = pszRandFile;
else
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, Failed to get the default RAND file from OpenSSL"));
OnError(sError);
LogSSLErrors();
}
}
RAND_load_file(T2A((LPTSTR)(LPCTSTR)m_pSettings->m_sSSLRandomnessFile), -1);
if (RAND_status() == 0)
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::ListenSocketFunction, Failed to initialize the PRNG in OpenSSL"));
OnError(sError);
LogSSLErrors();
//Failing to initialize the PRNG is not considered critical for W3MFC
}
CSSLContext sslContext;
if (m_pSettings->m_SSLProtocol != CHttpServerSettings::SSL_NONE)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -