📄 w3mfc.cpp
字号:
Copyright / Usage Details:
You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise)
when your product is released in binary form. You are allowed to modify the source code in any way you want
except you cannot modify the copyright details at the top of each module. If you want to distribute source
code with your application, then you are only allowed to distribute versions released by the author. This is
to maintain a single distribution point for the source code.
*/
//////////////// Includes ////////////////////////////////////////////
#include "stdafx.h"
#include "..\resource.h"
#include "SocMFC.h"
#include "HttpClient.h"
#include "W3Mfc.h"
#include "Win32Handle.h"
#ifdef W3MFC_SSL_SUPPORT
#include "OpenSSLMfc.h"
#include <openssl\rand.h>
#endif
#ifndef __AFXPRIV_H__
#pragma message("To avoid this message please put afxpriv.h in your PCH (normally stdafx.h)")
#include <afxpriv.h>
#endif
//////////////// Macros / Defines /////////////////////////////////////
//automatically pull in Winsock 2
#pragma comment(lib, "Ws2_32.lib")
//automatically pull in SSPI (if required)
#ifndef W3MFC_NO_SSPI_SUPPORT
//#pragma comment(lib, "E:\\sdk\\Lib\\secur32.lib")
#endif
#ifndef SEC_E_OK
#define SEC_E_OK ((SECURITY_STATUS)0x0000)
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////// Implementation //////////////////////////////////////
CHttpServerSettings::CHttpServerSettings()
{
m_nPort = 80; //Default to the standard HTTP port
m_bBind = FALSE; //Default to not binding to a specific IP address
#ifdef _DEBUG
m_dwIdleClientTimeout = 90000; //Default to client idle timeout of 90 seconds (when in debug mode)
#else
m_dwIdleClientTimeout = 30000; //Default to client idle timeout of 30 seconds
#endif
//Default root directory will be where the exe is running from
TCHAR sPath[_MAX_PATH];
GetModuleFileName(NULL, sPath, _MAX_PATH);
TCHAR sDrive[_MAX_DRIVE];
TCHAR sDir[_MAX_DIR];
_tsplitpath(sPath, sDrive, sDir, NULL, NULL);
_tmakepath(sPath, sDrive, sDir, NULL, NULL);
CHttpDirectory* pDir = new CHttpDirectory;
pDir->SetDirectory(sPath);
pDir->SetAlias(_T('/'));
pDir->SetDefaultFile(_T("default.htm")); //Default filename returned for root requests will be "default.htm"
m_Directories.Add(pDir);
m_sServerName = _T("MiniCA Web Server"); //Default server name will be the name of the MFC classes i.e "W3MFC" plus the current version number
m_pRuntimeClientClass = RUNTIME_CLASS(CHttpClient); //Default class to use is CHttpClient
m_nThreadPoolSize = 10;
m_bDNSLookup = FALSE;
m_dwWritableTimeout = 10000;
m_bEnableThreadLifetime = FALSE;
m_dwThreadLifetime = 120;
m_pMimeManager = NULL;
m_bUseIOCPQueue = FALSE;
m_bKeepAlives = TRUE;
m_bAutoExpire = FALSE;
m_bAllowDeleteRequest = FALSE;
#ifndef W3MFC_NO_CGI_SUPPORT
m_dwCGIResponseBufferSize = 4096;
#endif
m_bAllowAnonymous = TRUE;
m_bAllowBasicAuthentication = TRUE;
m_bAllowNTLMAuthentication = FALSE;
m_bPerformPassthroughAuthentication = TRUE;
#ifndef W3MFC_NO_ISAPI_SUPPORT
m_bCacheISAPI = TRUE;
m_pISAPIManager = NULL;
m_pISAPI = NULL;
#endif
#ifndef W3MFC_NO_CGI_SUPPORT
m_pCGI = NULL;
#endif
#ifdef W3MFC_SSL_SUPPORT
m_SSLProtocol = SSL_NONE;
m_sServerCertificateFile = _T("W3MFC.pem");
m_bReuseSessions = TRUE;
m_dwSSLSessionTimeout = 300;
m_dwSSLNegotiationTimeout = 10000;
#endif
}
CHttpServerSettings::~CHttpServerSettings()
{
FreeDirectoryArray();
}
void CHttpServerSettings::FreeDirectoryArray()
{
for (int i=0; i<m_Directories.GetSize(); i++)
{
CHttpDirectory* pDir = m_Directories.GetAt(i);
delete pDir;
pDir = NULL;
}
m_Directories.RemoveAll();
}
IMPLEMENT_DYNCREATE(CHttpDirectedThreadPoolQueue, CDirectedThreadPoolQueue)
CHttpDirectedThreadPoolQueue::~CHttpDirectedThreadPoolQueue()
{
//Before we are destroyed, deallocate any user requests
//which may still be lying around in the requests array
for (int i=0; i<m_Requests.GetSize(); i++)
{
CThreadPoolRequest& request = m_Requests.ElementAt(i);
if (request.m_dwID == THREADPOOL_USER_DEFINED_REQUEST)
{
CHttpThreadPoolRequest* pHttpRequest = (CHttpThreadPoolRequest*) request.m_pData;
delete pHttpRequest;
pHttpRequest = NULL;
}
}
}
IMPLEMENT_DYNAMIC(CHttpServer, CObject)
CHttpServer::CHttpServer() : m_ListenStartEvent(TRUE), m_pListenThread(NULL), m_hImpersonation(NULL)
{
#ifndef W3MFC_NO_SSPI_SUPPORT
ZeroMemory(&m_hCredHandle, sizeof(m_hCredHandle));
#endif
LoadHTMLResources();
}
void CHttpServer::LoadHTMLResources()
{
m_psz302HTML = NULL;
m_dw302HTML = 0;
m_psz400HTML = NULL;
m_dw400HTML = 0;
m_psz401HTML = NULL;
m_dw401HTML = 0;
m_psz404HTML = NULL;
m_dw404HTML = 0;
m_psz500HTML = NULL;
m_dw500HTML = 0;
m_pszDeletedHTML = NULL;
m_dwDeletedHTML = 0;
LoadHTMLResource(IDH_302, m_psz302HTML, m_dw302HTML);
LoadHTMLResource(IDH_400, m_psz400HTML, m_dw400HTML);
LoadHTMLResource(IDH_401, m_psz401HTML, m_dw401HTML);
LoadHTMLResource(IDH_404, m_psz404HTML, m_dw404HTML);
LoadHTMLResource(IDH_500, m_psz500HTML, m_dw500HTML);
LoadHTMLResource(IDH_FILE_DELETED_OK, m_pszDeletedHTML, m_dwDeletedHTML);
}
CHttpServer::~CHttpServer()
{
Stop();
FreeHTMLResources();
}
void CHttpServer::FreeHTMLResources()
{
if (m_psz302HTML)
{
delete [] m_psz302HTML;
m_psz302HTML = NULL;
m_dw302HTML = 0;
}
if (m_psz400HTML)
{
delete [] m_psz400HTML;
m_psz400HTML = NULL;
m_dw400HTML = 0;
}
if (m_psz401HTML)
{
delete [] m_psz401HTML;
m_psz401HTML = NULL;
m_dw401HTML = 0;
}
if (m_psz404HTML)
{
delete [] m_psz404HTML;
m_psz404HTML = NULL;
m_dw404HTML = 0;
}
if (m_psz500HTML)
{
delete [] m_psz500HTML;
m_psz500HTML = NULL;
m_dw500HTML = 0;
}
if (m_pszDeletedHTML)
{
delete [] m_pszDeletedHTML;
m_pszDeletedHTML = NULL;
m_dwDeletedHTML = 0;
}
}
#ifndef W3MFC_NO_SSPI_SUPPORT
BOOL CHttpServer::AcquireSSPI()
{
//Get a connection to SSPI
TimeStamp tsExpires;
SECURITY_STATUS ss = AcquireCredentialsHandle(NULL, _T("NTLM"), SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &m_hCredHandle, &tsExpires);
BOOL bSuccess = (ss == SEC_E_OK);
//Report the error
if (!bSuccess)
{
CString sError;
sError.Format(_T("CHttpServer::AcquireSSPI, Failed in call to AcquireCredentialsHandle, Error:%d"), ss);
OnError(sError);
}
return bSuccess;
}
void CHttpServer::ReleaseSSPI()
{
SECURITY_STATUS ss = FreeCredentialsHandle(&m_hCredHandle);
if (ss != SEC_E_OK)
{
CString sError;
sError.Format(_T("CHttpServer::ReleaseSSPI, Failed in call to FreeCredentialsHandle, Error:%d"), ss);
OnError(sError);
}
}
#endif
BOOL CHttpServer::Start(CHttpServerSettings* pSettings)
{
CSingleLock sl(&m_csListenThread, TRUE); //synchronize access to the listening thread
ASSERT(m_pListenThread == NULL); //Trying to start an already started server
ASSERT(pSettings);
ASSERT(pSettings->m_pMimeManager); //must be assigned before you call this function
#ifndef W3MFC_NO_ISAPI_SUPPORT
ASSERT(pSettings->m_pISAPIManager); //must be assigned before you call this function
ASSERT(pSettings->m_pISAPI); //must be assigned before you call this function
pSettings->m_pISAPI->SetServer(this);
#endif
#ifndef W3MFC_NO_CGI_SUPPORT
ASSERT(pSettings->m_pCGI); //must be assigned before you call this function
#endif
//Initialize SSPI
#ifndef W3MFC_NO_SSPI_SUPPORT
if (!AcquireSSPI())
return FALSE;
#endif
//Start the listener thread
m_pSettings = pSettings;
m_bListenerRunningOK = FALSE;
m_StopEvent.ResetEvent();
m_ListenStartEvent.ResetEvent();
m_pListenThread = AfxBeginThread(ListenSocketFunction, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
if (m_pListenThread == NULL)
{
//Report the error
CString sError;
sError.Format(_T("CHttpServer::Start, Failed to call to create listener thread, please check settings"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -