Files
openlitespeed/src/extensions/extworkerconfig.cpp
T
2026-05-07 23:52:18 -04:00

261 lines
7.4 KiB
C++

/*****************************************************************************
* Open LiteSpeed is an open source HTTP server. *
* Copyright (C) 2013 - 2022 LiteSpeed Technologies, Inc. *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see http://www.gnu.org/licenses/. *
*****************************************************************************/
#include "extworkerconfig.h"
#include <http/httpdefs.h>
#include <lsr/ls_strtool.h>
#include <main/configctx.h>
#include <socket/gsockaddr.h>
#include <util/xmlnode.h>
#include <log4cxx/logger.h>
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <unistd.h>
#define sEnvPadding "LSAPI_PADDING=leave_some_room_to_avoid_overwrite_important_env"
ExtWorkerConfig::ExtWorkerConfig(const char *pName)
: m_sURL(NULL)
, m_sName(pName)
, m_pVHost(NULL)
, m_iMaxConns(1)
, m_iTimeout(10)
, m_iRetryTimeout(3)
, m_iBuffering(0)
, m_iKeepAlive(1)
, m_iDetached(0)
, m_iMaxIdleTime(INT_MAX)
, m_iKeepAliveTimeout(INT_MAX)
, m_iSelfManaged(1)
, m_iStartByServer(EXTAPP_AUTOSTART_OFF)
, m_iRefAddr(0)
, m_iDaemonSuEXEC(0)
, m_iDropCaps(0)
, m_uid(-1)
, m_gid(-1)
, m_pServerAddr(new GSockAddr())
, m_pOrgEnv(NULL)
{
}
ExtWorkerConfig::ExtWorkerConfig()
: m_pVHost(NULL)
, m_iMaxConns(1)
, m_iTimeout(10)
, m_iRetryTimeout(3)
, m_iBuffering(0)
, m_iKeepAlive(1)
, m_iDetached(0)
, m_iMaxIdleTime(INT_MAX)
, m_iKeepAliveTimeout(INT_MAX)
, m_iSelfManaged(1)
, m_iStartByServer(EXTAPP_AUTOSTART_OFF)
, m_iRefAddr(0)
, m_iDaemonSuEXEC(0)
, m_iDropCaps(0)
, m_uid(-1)
, m_gid(-1)
, m_pServerAddr(new GSockAddr())
, m_pOrgEnv(NULL)
{}
ExtWorkerConfig::~ExtWorkerConfig()
{
if (!m_iRefAddr && m_pServerAddr)
delete m_pServerAddr;
}
ExtWorkerConfig::ExtWorkerConfig(const ExtWorkerConfig &rhs)
: m_iTimeout(rhs.m_iTimeout)
, m_iRetryTimeout(rhs.m_iRetryTimeout)
, m_iKeepAlive(rhs.m_iKeepAlive)
, m_iDetached(rhs.m_iDetached)
, m_iMaxIdleTime(rhs.m_iMaxIdleTime)
, m_iKeepAliveTimeout(rhs.m_iKeepAliveTimeout)
, m_iSelfManaged(rhs.m_iSelfManaged)
, m_iStartByServer(rhs.m_iStartByServer)
, m_pOrgEnv(rhs.m_pOrgEnv)
{
m_sURL = rhs.m_sURL;
m_sName = rhs.m_sName;
m_pVHost = rhs.m_pVHost;
m_iMaxConns = rhs.m_iMaxConns;
m_iBuffering = rhs.m_iBuffering;
m_iRefAddr = rhs.m_iRefAddr;
m_iDaemonSuEXEC = rhs.m_iDaemonSuEXEC;
m_uid = rhs.m_uid;
m_gid = rhs.m_gid;
m_iDropCaps = rhs.m_iDropCaps;
if (m_iRefAddr)
m_pServerAddr = rhs.m_pServerAddr;
else
m_pServerAddr = new GSockAddr(*rhs.m_pServerAddr);
}
int ExtWorkerConfig::setURL(const char *pURL)
{
if (pURL != NULL)
{
if ((m_sURL.c_str() == NULL) || (strcmp(m_sURL.c_str(), pURL) != 0))
{
m_sURL = pURL;
return 0;
}
}
return LS_FAIL;
}
void ExtWorkerConfig::setServerAddr(const GSockAddr *pAddr)
{
if ((m_iRefAddr == 0) && (m_pServerAddr))
delete m_pServerAddr;
m_iRefAddr = 1;
m_pServerAddr = (GSockAddr *)pAddr;
}
int ExtWorkerConfig::updateServerAddr(const char *pURL)
{
if (m_iRefAddr)
return LS_FAIL;
return m_pServerAddr->set(pURL, NO_ANY | DO_NSLOOKUP);
}
void ExtWorkerConfig::setName(const char *pName)
{
if (pName != NULL)
m_sName = pName;
}
const char *ExtWorkerConfig::getServerAddrUnixSock() const
{
if (m_pServerAddr && (m_pServerAddr->family() == AF_UNIX))
return (const char *)m_pServerAddr->getUnix();
return NULL;
}
void ExtWorkerConfig::altServerAddr()
{
if (!m_pServerAddr || m_iRefAddr)
return;
switch (m_pServerAddr->family())
{
case AF_UNIX:
{
AutoStr2 s = m_sURL.c_str();
char *p1 = (char *)m_pServerAddr->getUnix();
char *p = p1 + strlen(m_sURL.c_str()) - 5;
int seq = rand() % 1000;
ls_snprintf(p, p1 + 102 - p, ".%03d", seq);
s.append(p, 4);
m_sURL.setStr(s.c_str());
}
break;
case AF_INET:
case AF_INET6:
{
short port = m_pServerAddr->getPort();
m_pServerAddr->setPort(port + 1);
}
break;
}
}
extern int removeSimiliarFiles(const char *pPath, long tm);
void ExtWorkerConfig::removeUnusedSocket()
{
removeSimiliarFiles(m_sURL.c_str() + 5, 0);
unlink(m_sURL.c_str() + 5);
}
void ExtWorkerConfig::config(const XmlNode *pNode)
{
int iMaxConns = ConfigCtx::getCurConfigCtx()->getLongValue(pNode,
"maxConns", 1, 10000, 5);
int iRetryTimeout = ConfigCtx::getCurConfigCtx()->getLongValue(pNode,
"retryTimeout", 0, LONG_MAX, 10);
int iInitTimeout = ConfigCtx::getCurConfigCtx()->getLongValue(pNode,
"initTimeout", 1, LONG_MAX, 3);
int iBuffer = ConfigCtx::getCurConfigCtx()->getLongValue(pNode,
"respBuffer", 0, 2, 1);
int iKeepAlive = ConfigCtx::getCurConfigCtx()->getLongValue(pNode,
"persistConn", 0, 1, 1);
int iKeepAliveTimeout = ConfigCtx::getCurConfigCtx()->getLongValue(pNode,
"pcKeepAliveTimeout", -1, INT_MAX, INT_MAX);
if (iKeepAliveTimeout == -1)
iKeepAliveTimeout = INT_MAX;
if (iBuffer == 1)
iBuffer = 0;
else if (iBuffer == 0)
iBuffer = HEC_RESP_NOBUFFER;
else if (iBuffer == 2)
iBuffer = HEC_RESP_NPH;
setPersistConn(iKeepAlive);
setKeepAliveTimeout(iKeepAliveTimeout);
setMaxConns(iMaxConns);
setTimeout(iInitTimeout);
setRetryTimeout(iRetryTimeout);
setBuffering(iBuffer);
clearEnv();
const XmlNodeList *pList = NULL;
if (pNode)
pList = pNode->getChildren("env");
addEnv(sEnvPadding);
if (pList)
{
char pBuf[MAX_PATH_LEN] = {0};
XmlNodeList::const_iterator iter;
for (iter = pList->begin(); iter != pList->end(); ++iter)
{
const char *pValue;
if ((pValue = (*iter)->getValue()) != NULL)
{
if (ConfigCtx::getCurConfigCtx()->expandVariable(pValue,
pBuf, MAX_PATH_LEN, 1) < 0)
{
LS_ERROR(ConfigCtx::getCurConfigCtx(),
"expand env: %s error", pValue);
continue;
}
pValue = pBuf;
addEnv(pValue);
}
}
}
}