📄 httpmain.cpp
字号:
DWORD WINAPI InitializeGlobalsThread(LPVOID lpv) {
MyWaitForAdminThreadReadyState();
DEBUGCHK(g_fState == SERVICE_STATE_STARTING_UP);
InitializeGlobals();
CloseHandle(g_hAdminThread);
g_hAdminThread = 0;
return 0;
}
DWORD WINAPI HttpConnectionThread(LPVOID lpv) {
CHttpRequest *pRequest = (CHttpRequest*) lpv;
DEBUGCHK(pRequest && pRequest->m_dwSig == CHTTPREQUEST_SIG);
SOCKET sock = pRequest->m_socket;
// this outer _try--_except is to catch crashes in the destructor
__try {
__try {
// This loops as long the the socket is being kept alive
for(;;) {
pRequest->HandleRequest();
// figure out if we must keep this connection alive,
// Either session is over through this request's actions or
// globally set to accept no more connections.
// We do the global g_pVars->m_fAcceptConnections check
// because it's possible that we may be in the process of
// shutting down the web server, in which case we want to
// exit even if we're performing a keep alive.
if(! (g_pVars->m_fAcceptConnections && pRequest->m_fKeepAlive)) {
if(g_pVars->m_fFilters)
pRequest->CallFilter(SF_NOTIFY_END_OF_NET_SESSION);
break;
}
// If we're continuing the session don't delete all data, just request specific data
if ( ! pRequest->ReInit())
break;
}
}
__finally {
// Note: To get this to compile under Visual Studio on NT, the /Gx- compile line option is set
delete pRequest;
pRequest = 0;
}
}
__except(ReportFault(GetExceptionInformation(),0), EXCEPTION_EXECUTE_HANDLER) {
RETAILMSG(1, (L"HTTP Server got an exception!!!\r\n"));
g_pVars->m_pLog->WriteEvent(IDS_HTTPD_EXCEPTION,GetExceptionCode(),GetLastError());
}
return 0;
}
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// UTILITY FUNCTIONS
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
void WaitForConnectionThreadsToEnd(void) {
DEBUGCHK (g_fState == SERVICE_STATE_SHUTTING_DOWN || g_fState == SERVICE_STATE_UNLOADING);
// NOTE. It's possible ASP pages or ISAPI extns may have an
// infinite loop in them, in which case we never decrement this value and
// never get to stop the server. There is no clean way to fix this.
DEBUGMSG(ZONE_LISTEN,(L"HTTPD: Wating for %d HTTP threads to come to a halt\r\n", g_pVars->m_nConnections));
g_pVars->m_pLog->WriteEvent(IDS_HTTPD_SHUTDOWN_START);
g_pVars->m_pThreadPool->Shutdown();
DEBUGCHK(g_pVars->m_nConnections == 0);
DEBUGMSG(ZONE_LISTEN,(L"HTTPD: All HTTPD threads have come to halt, shutting down server\r\n"));
}
// Note: This function is executed on the super services accept thread, blocking all
// other services from receiving new connections. Need to execute this code as quickly as possible.
BOOL CreateHTTPConnection(SOCKET sock, PSOCKADDR pSockAddr, DWORD cbSockAddr) {
DEBUG_CODE_INIT;
BOOL fRet = FALSE;
CHttpRequest *pRequest = NULL;
BOOL fSecure;
EnterCriticalSection(&g_CritSect);
DEBUGCHK(g_pVars->m_nConnections <= g_pVars->m_nMaxConnections);
if (g_pVars->m_nConnections + 1 > g_pVars->m_nMaxConnections) {
DEBUGMSG(ZONE_ERROR, (TEXT("HTTPD: Connection Count -- Reached maximum # of connections, won't accept current request.")));
send(sock,g_pVars->m_szMaxConnectionMsg,strlen(g_pVars->m_szMaxConnectionMsg),0);
myleave(59);
}
fSecure = g_pVars->IsSecureSocket(pSockAddr,cbSockAddr);
if (fSecure && !g_pVars->m_fSSL) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: Request fails because client requests SSL, SSL not activated\r\n"));
goto done;
}
pRequest = new CHttpRequest(sock,fSecure);
if (!pRequest)
myleave(60);
g_pVars->m_nConnections++;
if (! g_pVars->m_pThreadPool->ScheduleEvent(HttpConnectionThread,(LPVOID) pRequest))
myleave(61);
fRet = TRUE;
done:
if (!fRet) {
SetLastError(ERROR_SERVICE_CANNOT_ACCEPT_CTRL);
shutdown(sock, 1);
closesocket(sock);
if (pRequest)
delete pRequest; // pRequest destructor decrements m_nConnections
}
LeaveCriticalSection(&g_CritSect);
return fRet;
}
// When we get a connection socket from IOCTL_SERVICE_CONNECTION, need to determine if
// it's an SSL sock or not. We'll only accept SSL over TCP/IP port 443, so should
// getsockname() fail (for instance in case where service provider had a larger SOCKADDR) assume
// clear text.
BOOL CGlobalVariables::IsSecureSocket(PSOCKADDR pSockAddr, DWORD cbSockAddr) {
if ((pSockAddr->sa_family == AF_INET || pSockAddr->sa_family == AF_INET6))
{
return (GetSocketPort(pSockAddr) == htons((WORD)m_dwSSLPort));
}
return FALSE;
}
// runs through active sockets and closes them during shutdown. This will cause
// any threads waiting for recv timeouts to exit more promptly. It will not help
// in the case of an ISAPI or ASP page in an infinite loop, only TerminateThread will
// do the trick there, and we're not willing to do this given how much it'd gunk up services.exe.
void CloseAllConnections(void) {
EnterCriticalSection(&g_CritSect);
CHttpRequest *pTrav = g_pRequestList;
while (pTrav) {
pTrav->CloseSocket();
pTrav = pTrav->m_pNext;
// leave it to the ~CHttpRequest to remove itself from the list and do its own memory cleanup.
}
LeaveCriticalSection(&g_CritSect);
}
DWORD WINAPI PeriodicWakeupThread(LPVOID lpv) {
EnterCriticalSection(&g_CritSect);
if (g_pVars && g_pVars->m_pISAPICache)
g_pVars->m_pISAPICache->RemoveUnusedISAPIs(FALSE);
if (g_pFileLockManager)
g_pFileLockManager->RemoveTimedOutLocks();
g_pTimer->ScheduleEvent(PeriodicWakeupThread,0,PERIODIC_TIMER_SLEEP_TIMEOUT);
LeaveCriticalSection(&g_CritSect);
return 0;
}
PSTR MassageMultiStringToAnsi(PCWSTR wszIn, PCWSTR wszDefault) {
if(!wszIn) wszIn = wszDefault;
if(!wszIn) return NULL;
int iAlloc = MyW2A(wszIn,0,0);
if (!iAlloc)
return NULL;
iAlloc++; // +1 for dbl-null term
PSTR szBuffer = MySzAllocA(iAlloc);
if (!szBuffer)
return NULL;
MyW2A(wszIn,szBuffer,iAlloc);
PSTR szRead = szBuffer;
PSTR szWrite = szBuffer;
// now that we've converted buffer, write out in place.
for ( ; *szRead; szRead++, szWrite++) {
PREFAST_SUPPRESS(394,"Updating buffer pointer is safe here");
*szWrite = (*szRead==';' ? '\0' : *szRead);
// Ignore space between ";" and next non-space
if (';' == *szRead || 0 == *szRead) {
szRead++;
svsutil_SkipWhiteSpace(szRead);
szRead--; // otherwise we skip first char of new string.
}
}
szWrite[0] = szWrite[1] = 0; // dbl-null
DEBUGCHK((szWrite - szBuffer + 2) <= iAlloc);
return szBuffer;
}
PWSTR MassageMultiString(PCWSTR wszIn, PCWSTR wszDefault) {
if(!wszIn) wszIn = wszDefault;
if(!wszIn) return NULL;
PWSTR wszOut = MyRgAllocNZ(WCHAR, 2+wcslen(wszIn)); // +2 for dbl-null term
if (!wszOut)
return NULL;
for(PWSTR wszNext=wszOut; *wszIn; wszIn++, wszNext++) {
PREFAST_SUPPRESS(394,"Updating buffer pointer is safe here");
*wszNext = (*wszIn==L';' ? L'\0' : *wszIn);
// Ignore space between ";" and next non-space
if ( L';' == *wszIn) {
wszIn++;
svsutil_SkipWWhiteSpace(wszIn);
wszIn--; // otherwise we skip first char of new string.
}
}
wszNext[0] = wszNext[1] = 0; // dbl-null
return wszOut;
}
BOOL GetRemoteAddress(SOCKET sock, PSTR pszBuf, BOOL fTryHostName, DWORD cbBuf) {
SOCKADDR_STORAGE sockAddr;
int iLen = sizeof(sockAddr);
*pszBuf=0;
if(getpeername(sock, (PSOCKADDR)&sockAddr, &iLen)) {
DEBUGMSG(ZONE_SOCKET, (L"HTTPD: getpeername failed GLE=%d\r\n", GetLastError()));
return FALSE;
}
if (fTryHostName && (0 == getnameinfo((PSOCKADDR)&sockAddr,iLen,pszBuf,cbBuf,NULL,0,0)))
return TRUE;
// if getnameinfo fails on resolving host name, fall through to use IP ADDR.
return (0 == getnameinfo((PSOCKADDR)&sockAddr,iLen,pszBuf,cbBuf,NULL,0,NI_NUMERICHOST));
}
PSTR MySzDupA(PCSTR pszIn, int iLen) {
if(!pszIn) return NULL;
if(!iLen) iLen = strlen(pszIn);
PSTR pszOut=MySzAllocA(iLen);
if(pszOut) {
memcpy(pszOut, pszIn, iLen);
pszOut[iLen] = 0;
}
return pszOut;
}
PWSTR MySzDupW(PCWSTR wszIn, int iLen) {
if(!wszIn) return NULL;
if(!iLen) iLen = wcslen(wszIn);
PWSTR wszOut=MySzAllocW(iLen);
if(wszOut) {
memcpy(wszOut, wszIn, sizeof(WCHAR)*iLen);
wszOut[iLen] = 0;
}
return wszOut;
}
PWSTR MySzDupAtoW(PCSTR pszIn, int iInLen) {
PWSTR pwszOut = 0;
int iOutLen = MultiByteToWideChar(CP_ACP, 0, pszIn, iInLen, 0, 0);
if(!iOutLen)
goto error;
pwszOut = MySzAllocW(iOutLen);
if(!pwszOut)
goto error;
if(MultiByteToWideChar(CP_ACP, 0, pszIn, iInLen, pwszOut, iOutLen))
return pwszOut;
error:
DEBUGMSG(ZONE_ERROR, (L"HTTPD: MySzDupAtoW(%a, %d) failed. pOut=%0x08x GLE=%d\r\n", pszIn, iInLen, pwszOut, GetLastError()));
MyFree(pwszOut);
return FALSE;
}
PSTR MySzDupWtoA(PCWSTR wszIn, int iInLen) {
PSTR pszOut = 0;
int iOutLen = WideCharToMultiByte(CP_ACP, 0, wszIn, iInLen, 0, 0, 0, 0);
if(!iOutLen)
goto error;
pszOut = MySzAllocA(iOutLen);
if(!pszOut)
goto error;
if(WideCharToMultiByte(CP_ACP, 0, wszIn, iInLen, pszOut, iOutLen, 0, 0))
return pszOut;
error:
DEBUGMSG(ZONE_ERROR, (L"HTTPD: MySzDupWtoA(%s, %d) failed. pOut=%0x08x GLE=%d\r\n", wszIn, iInLen, pszOut, GetLastError()));
MyFree(pszOut);
return FALSE;
}
BOOL MyStrCatA(PSTR *ppszDest, PSTR pszSource, PSTR pszDivider) {
DEBUG_CODE_INIT;
BOOL ret = FALSE;
PSTR pszNew = *ppszDest; // protect orignal ptr should realloc fail
PSTR pszTrav;
DWORD dwSrcLen = MyStrlenA(pszSource);
DWORD dwDestLen = MyStrlenA(*ppszDest);
DWORD dwDivLen = MyStrlenA(pszDivider);
if (!pszSource) {
SetLastError(ERROR_INVALID_PARAMETER);
myleave(259);
}
if (!pszNew) { // do an alloc first time, ignore divider
if (NULL == (pszNew = MySzDupA(pszSource,dwSrcLen)))
myleave(260);
}
else {
if (NULL == (pszNew = MyRgReAlloc(char,pszNew,dwDestLen,dwSrcLen + dwDestLen + dwDivLen + 1)))
myleave(261);
pszTrav = pszNew + dwDestLen;
if (pszDivider) {
memcpy(pszTrav, pszDivider, dwDivLen);
pszTrav += dwDivLen;
}
strcpy(pszTrav, pszSource);
}
*ppszDest = pszNew;
ret = TRUE;
done:
DEBUGMSG_ERR(ZONE_ERROR,(L"HTTPD: MyStrCat err = %d\r\n",GetLastError()));
return ret;
}
/*===================================================================
strcpyEx
Copy one string to another, returning a pointer to the NUL character
in the destination
Parameters:
szDest - pointer to the destination string
szSrc - pointer to the source string
Returns:
A pointer to the NUL terminator is returned.
===================================================================*/
char *strcpyEx(char *szDest, const char *szSrc) {
while (*szDest++ = *szSrc++)
;
return szDest - 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -