1. 修正:SSH连接后,超时断开后,客户端可能会反复重连,最终导致核心服务假死;

2. 修正:后台配置超时无操作自动断开时,配置为0,即永不超时,选项不生效。
dev
Apex Liu 2021-03-04 01:25:23 +08:00
parent f6cc313f87
commit 47c2fdcff4
20 changed files with 1041 additions and 673 deletions

View File

@ -8,9 +8,10 @@
<file url="file://$PROJECT_DIR$/common/libex/src/ex_ini.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/common/libex/src/ex_log.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/common/libex/src/ex_util.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/common/pyshell/include/pys.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/common/pyshell/include/pys.h" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/pyshell/src/pys_api.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/common/pyshell/src/pys_core.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/common/pyshell/src/pys_core.h" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/teleport/teleport_const.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/server/tp_core/common/base_env.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/server/tp_core/common/base_record.cpp" charset="GBK" />
@ -46,7 +47,7 @@
<file url="file://$PROJECT_DIR$/server/tp_core/protocol/telnet/telnet_recorder.h" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/server/tp_core/protocol/telnet/telnet_session.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/server/tp_core/protocol/telnet/telnet_session.h" charset="GBK" />
<file url="file://$PROJECT_DIR$/server/tp_web/src/main.cpp" charset="GBK" />
<file url="file://$PROJECT_DIR$/server/tp_web/src/main.cpp" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/server/tp_web/src/ts_env.cpp" charset="GBK" />
</component>
</project>

View File

@ -3,9 +3,11 @@ project(teleport)
include(CMakeCfg.txt)
if (OS_LINUX)
add_subdirectory(server/tp_web/src)
endif()
#if (OS_LINUX)
# add_subdirectory(server/tp_web/src)
#endif()
add_subdirectory(server/tp_web/src)
add_subdirectory(server/tp_core/core)
add_subdirectory(server/tp_core/protocol/ssh)

View File

@ -102,7 +102,7 @@
"name": "FreeRDP",
"display": "FreeRDP",
"app": "",
"cmdline": "/u:{user_name} /v:{host_ip} /port:{host_port}",
"cmdline": "/u:{user_name} /v:{host_ip} /port:{host_port} +glyph-cache /relax-order-checks",
"desc": [
"建议使用homebrew安装freerdp安装后freerdp默认路径在/usr/local/Cellar/freerdp/x.y.z/bin/xfreerdp",
"首次安装freerdp后需要重新启动计算机"

View File

@ -19,42 +19,49 @@ typedef std::map<ex_wstr, ex_wstr> ex_ini_kvs;
class ExIniSection
{
public:
ExIniSection();
ExIniSection(const ex_wstr& strSectionName);
~ExIniSection();
ExIniSection();
void ClearUp(void);
explicit ExIniSection(const ex_wstr& strSectionName);
ex_wstr Name(void) { return m_strName; }
~ExIniSection();
void GetStr(const ex_wstr& strKey, ex_wstr& strValue, const ex_wstr& strDefault);
bool GetStr(const ex_wstr& strKey, ex_wstr& strValue);
void ClearUp();
void GetInt(const ex_wstr& strKey, int& iValue, int iDefault);
bool GetInt(const ex_wstr& strKey, int& iValue);
ex_wstr Name() { return m_strName; }
void GetBool(const ex_wstr& strKey, bool& bValue, bool bDefault);
bool GetBool(const ex_wstr& strKey, bool& bValue);
bool SetValue(const ex_wstr& strKey, const ex_wstr& strValue, bool bAddIfNotExists = false);
void GetStr(const ex_wstr& strKey, ex_wstr& strValue, const ex_wstr& strDefault);
ex_ini_kvs& GetKeyValues(void) { return m_kvs; }
bool GetStr(const ex_wstr& strKey, ex_wstr& strValue);
void GetInt(const ex_wstr& strKey, int& iValue, int iDefault);
bool GetInt(const ex_wstr& strKey, int& iValue);
void GetBool(const ex_wstr& strKey, bool& bValue, bool bDefault);
bool GetBool(const ex_wstr& strKey, bool& bValue);
bool SetValue(const ex_wstr& strKey, const ex_wstr& strValue, bool bAddIfNotExists = false);
ex_ini_kvs& GetKeyValues() { return m_kvs; }
int Count() const
{
return (int) m_kvs.size();
}
void Save(FILE* file, int codepage);
int Count(void) const
{
return (int)m_kvs.size();
}
void Save(FILE* file, int codepage);
#ifdef EX_DEBUG
void Dump(void);
void Dump(void);
#endif
protected:
bool _IsKeyExists(const ex_wstr& strKey);
bool _IsKeyExists(const ex_wstr& strKey);
private:
ex_wstr m_strName;
ex_ini_kvs m_kvs;
ex_wstr m_strName;
ex_ini_kvs m_kvs;
};
@ -64,49 +71,55 @@ typedef std::map<ex_wstr, ExIniSection*> ex_ini_sections;
class ExIniFile
{
public:
enum PARSE_RV
{
PARSE_ERROR,
PARSE_SECTION,
PARSE_KEYVALUE,
PARSE_COMMENT,
PARSE_OTHER
};
enum PARSE_RV
{
PARSE_ERROR,
PARSE_SECTION,
PARSE_KEYVALUE,
PARSE_COMMENT,
PARSE_OTHER
};
public:
ExIniFile();
~ExIniFile();
ExIniFile();
const ex_wstr& get_filename(void){return m_file_path;}
~ExIniFile();
void ClearUp(void);
const ex_wstr& get_filename() { return m_file_path; }
// Read and parse special file.
bool LoadFromFile(const ex_wstr& strFileName, bool bClearOld = true);
bool LoadFromMemory(const ex_wstr& strData, bool bClearOld = true);
void ClearUp();
ex_ini_sections& GetAllSections(void) { return m_secs; }
// Read and parse special file.
bool LoadFromFile(const ex_wstr& strFileName, bool bClearOld = true);
ExIniSection* GetSection(const ex_wstr& strName, bool bCreateIfNotExists = false);
ExIniSection* GetDumySection(void) { return &m_dumy_sec; }
bool LoadFromMemory(const ex_wstr& strData, bool bClearOld = true);
ex_ini_sections& GetAllSections() { return m_secs; }
ExIniSection* GetSection(const ex_wstr& strName, bool bCreateIfNotExists = false);
ExIniSection* GetDumySection() { return &m_dumy_sec; }
int Count() const
{
return (int) (m_secs.size());
}
void Save(int codepage = EX_CODEPAGE_UTF8);
int Count(void) const
{
return (int)(m_secs.size());
}
void Save(int codepage = EX_CODEPAGE_UTF8);
#ifdef EX_DEBUG
void Dump(void);
void Dump(void);
#endif
protected:
static PARSE_RV _ParseLine(const ex_wstr& strLine, ex_wstr& strKey, ex_wstr& strValue);
bool _ProcessLine(const ex_wstr strLine, ExIniSection** pCurSection);
static PARSE_RV parse_line_(const ex_wstr& strLine, ex_wstr& strKey, ex_wstr& strValue);
bool process_line_(const ex_wstr& strLine, ExIniSection** pCurSection);
private:
ex_ini_sections m_secs;
ExIniSection m_dumy_sec;
ex_wstr m_file_path;
ex_ini_sections m_secs;
ExIniSection m_dumy_sec;
ex_wstr m_file_path;
};
#endif // __EX_INI_H__

View File

@ -66,11 +66,11 @@ void EXLOG_FILE(const wchar_t *log_file, const wchar_t *log_path = nullptr, ex_u
void EXLOG_CONSOLE(bool output_to_console);
#define EXLOGD ex_printf_d
#define EXLOGV ex_printf_v
#define EXLOGI ex_printf_i
#define EXLOGW ex_printf_w
#define EXLOGE ex_printf_e
#define EXLOGD ex_printf_d
#define EXLOG_BIN ex_printf_bin
#ifdef EX_OS_WIN32

View File

@ -4,524 +4,493 @@
ExIniSection::ExIniSection(const ex_wstr& strSectionName)
{
m_kvs.clear();
m_strName = strSectionName;
m_kvs.clear();
m_strName = strSectionName;
}
ExIniSection::ExIniSection()
{
m_kvs.clear();
m_strName = L"N/A";
m_kvs.clear();
m_strName = L"N/A";
}
ExIniSection::~ExIniSection()
{
m_kvs.clear();
m_kvs.clear();
}
bool ExIniSection::_IsKeyExists(const ex_wstr& strKey)
{
return (m_kvs.end() != m_kvs.find(strKey));
return (m_kvs.end() != m_kvs.find(strKey));
}
void ExIniSection::GetStr(const ex_wstr& strKey, ex_wstr& strValue, const ex_wstr& strDefault)
{
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (m_kvs.end() == it)
strValue = strDefault;
else
strValue = (*it).second;
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (m_kvs.end() == it)
strValue = strDefault;
else
strValue = (*it).second;
}
bool ExIniSection::GetStr(const ex_wstr& strKey, ex_wstr& strValue)
{
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (m_kvs.end() == it)
return false;
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (m_kvs.end() == it)
return false;
strValue = (*it).second;
return true;
strValue = (*it).second;
return true;
}
void ExIniSection::GetInt(const ex_wstr& strKey, int& iValue, int iDefault)
{
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (m_kvs.end() == it)
{
iValue = iDefault;
return;
}
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (m_kvs.end() == it)
{
iValue = iDefault;
return;
}
#ifdef EX_OS_WIN32
iValue = _wtoi(it->second.c_str());
iValue = _wtoi(it->second.c_str());
#else
ex_astr tmp;
ex_wstr2astr(it->second, tmp);
iValue = atoi(tmp.c_str());
iValue = atoi(tmp.c_str());
#endif
}
bool ExIniSection::GetInt(const ex_wstr& strKey, int& iValue)
{
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (m_kvs.end() == it)
return false;
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (m_kvs.end() == it)
return false;
#ifdef EX_OS_WIN32
iValue = _wtoi(it->second.c_str());
iValue = _wtoi(it->second.c_str());
#else
ex_astr tmp;
ex_wstr2astr(it->second, tmp);
iValue = atoi(tmp.c_str());
iValue = atoi(tmp.c_str());
#endif
return true;
return true;
}
void ExIniSection::GetBool(const ex_wstr& strKey, bool& bValue, bool bDefault)
{
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (m_kvs.end() == it)
{
bValue = bDefault;
return;
}
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (m_kvs.end() == it)
{
bValue = bDefault;
return;
}
if (
it->second == L"1"
#ifdef EX_OS_WIN32
|| 0 == _wcsicmp(it->second.c_str(), L"true")
#else
|| 0 == wcscasecmp(it->second.c_str(), L"true")
if (
it->second == L"1"
#ifdef EX_OS_WIN32
|| 0 == _wcsicmp(it->second.c_str(), L"true")
#else
|| 0 == wcscasecmp(it->second.c_str(), L"true")
#endif
)
bValue = true;
else
bValue = false;
)
bValue = true;
else
bValue = false;
}
bool ExIniSection::GetBool(const ex_wstr& strKey, bool& bValue)
{
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (m_kvs.end() == it)
return false;
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (m_kvs.end() == it)
return false;
if (
it->second == L"1"
#ifdef EX_OS_WIN32
|| 0 == _wcsicmp(it->second.c_str(), _T("true"))
#else
|| 0 == wcscasecmp(it->second.c_str(), L"true")
if (
it->second == L"1"
#ifdef EX_OS_WIN32
|| 0 == _wcsicmp(it->second.c_str(), _T("true"))
#else
|| 0 == wcscasecmp(it->second.c_str(), L"true")
#endif
)
bValue = true;
else
bValue = false;
)
bValue = true;
else
bValue = false;
return true;
return true;
}
bool ExIniSection::SetValue(const ex_wstr& strKey, const ex_wstr& strValue, bool bAddIfNotExists)
{
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (it != m_kvs.end())
{
it->second = strValue;
return true;
}
ex_ini_kvs::iterator it = m_kvs.find(strKey);
if (it != m_kvs.end())
{
it->second = strValue;
return true;
}
if (bAddIfNotExists)
{
m_kvs.insert(std::make_pair(strKey, strValue));
return true;
}
if (bAddIfNotExists)
{
m_kvs.insert(std::make_pair(strKey, strValue));
return true;
}
return false;
return false;
}
void ExIniSection::ClearUp(void)
{
m_kvs.clear();
m_kvs.clear();
}
void ExIniSection::Save(FILE* file, int codepage)
void ExIniSection::Save(FILE* file, int codepage)
{
ex_ini_kvs::iterator it = m_kvs.begin();
for (; it != m_kvs.end(); ++it)
{
ex_wstr temp;
temp += it->first.c_str();
temp += L"=";
temp += it->second.c_str();
temp += L"\n";
ex_astr temp2;
ex_wstr2astr(temp, temp2, codepage);
fwrite(temp2.c_str(), temp2.size(), 1, file);
}
return;
for (auto it = m_kvs.begin(); it != m_kvs.end(); ++it)
{
ex_wstr temp;
temp += it->first;
temp += L'=';
temp += it->second;
temp += L'\n';
ex_astr temp2;
ex_wstr2astr(temp, temp2, codepage);
fwrite(temp2.c_str(), temp2.size(), 1, file);
}
}
#ifdef EX_DEBUG
void ExIniSection::Dump(void)
{
ex_ini_kvs::iterator it = m_kvs.begin();
for (; it != m_kvs.end(); ++it)
{
EXLOGD(_T(" [%s]=[%s]\n"), it->first.c_str(), it->second.c_str());
}
for (auto it = m_kvs.begin(); it != m_kvs.end(); ++it)
{
EXLOGD(_T(" [%s]=[%s]\n"), it->first.c_str(), it->second.c_str());
}
}
#endif
ExIniFile::ExIniFile()
{
}
ExIniFile::ExIniFile() = default;
ExIniFile::~ExIniFile()
{
ClearUp();
ClearUp();
}
bool ExIniFile::LoadFromFile(const ex_wstr& strFileName, bool bClearOld)
{
#ifdef EX_OS_WIN32
HANDLE hFile = ::CreateFileW(strFileName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile)
return false;
HANDLE hFile = ::CreateFileW(strFileName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile)
return false;
ULONG ulFileSize = GetFileSize(hFile, NULL);
if (INVALID_FILE_SIZE == ulFileSize)
{
CloseHandle(hFile);
return false;
}
ULONG ulFileSize = GetFileSize(hFile, NULL);
if (INVALID_FILE_SIZE == ulFileSize)
{
CloseHandle(hFile);
return false;
}
std::vector<char> vFile;
vFile.resize(ulFileSize + 1);
ZeroMemory(&vFile[0], ulFileSize + 1);
std::vector<char> vFile;
vFile.resize(ulFileSize + 1);
ZeroMemory(&vFile[0], ulFileSize + 1);
DWORD dwRead = 0;
if (!ReadFile(hFile, &vFile[0], ulFileSize, &dwRead, NULL) || ulFileSize != dwRead)
{
CloseHandle(hFile);
return false;
}
DWORD dwRead = 0;
if (!ReadFile(hFile, &vFile[0], ulFileSize, &dwRead, NULL) || ulFileSize != dwRead)
{
CloseHandle(hFile);
return false;
}
CloseHandle(hFile);
CloseHandle(hFile);
m_file_path = strFileName;
m_file_path = strFileName;
#else
FILE* f = NULL;
FILE* f = nullptr;
ex_astr _fname;
ex_wstr2astr(strFileName, _fname);
f = fopen(_fname.c_str(), "rb");
if(f == NULL)
return false;
fseek(f, 0L, SEEK_END);
unsigned long ulFileSize = (unsigned long)ftell(f);
if(-1 == ulFileSize)
{
fclose(f);
return false;
}
f = fopen(_fname.c_str(), "rb");
if (!f)
return false;
fseek(f, 0L, SEEK_END);
auto ulFileSize = static_cast<unsigned long>(ftell(f));
if (-1 == ulFileSize)
{
fclose(f);
return false;
}
std::vector<char> vFile;
vFile.resize(ulFileSize + 1);
memset(&vFile[0], 0, ulFileSize + 1);
std::vector<char> vFile;
vFile.resize(ulFileSize + 1);
memset(&vFile[0], 0, ulFileSize + 1);
fseek(f, 0L, SEEK_SET);
fread(&vFile[0], 1, ulFileSize, f);
fclose(f);
fseek(f, 0L, SEEK_SET);
fread(&vFile[0], 1, ulFileSize, f);
fclose(f);
m_file_path = strFileName;
m_file_path = strFileName;
#endif
char *pOffset = &vFile[0];
if ((ulFileSize > 3) && (0 == memcmp(pOffset, "\xEF\xBB\xBF", 3)))
{
pOffset += 3;
}
// 配置文件均使用UTF8编码
ex_wstr fileData;
if (!ex_astr2wstr(pOffset, fileData, EX_CODEPAGE_UTF8))
return false;
char* pOffset = &vFile[0];
if ((ulFileSize > 3) && (0 == memcmp(pOffset, "\xEF\xBB\xBF", 3)))
{
pOffset += 3;
}
// 配置文件均使用UTF8编码
ex_wstr fileData;
if (!ex_astr2wstr(pOffset, fileData, EX_CODEPAGE_UTF8))
return false;
return LoadFromMemory(fileData, bClearOld);
return LoadFromMemory(fileData, bClearOld);
}
bool ExIniFile::LoadFromMemory(const ex_wstr& strData, bool bClearOld)
{
if (strData.empty())
return false;
if (strData.empty())
return false;
ex_wstr strAll(strData);
bool bRet = true;
ExIniSection* pCurSection = NULL;
ex_wstr strAll(strData);
bool bRet = true;
ExIniSection* pCurSection = nullptr;
do {
// Clear old data.
if (bClearOld)
ClearUp();
do
{
// Clear old data.
if (bClearOld)
ClearUp();
ex_wstr strKey(L"");
ex_wstr strValue(L"");
ex_wstr strKey;
ex_wstr strValue;
ex_wstr strLine(L"");
ex_wstr::size_type posCR = ex_wstr::npos;
ex_wstr::size_type posLF = ex_wstr::npos;
for (;;)
{
posCR = ex_wstr::npos;
posLF = ex_wstr::npos;
posCR = strAll.find(L"\r");
posLF = strAll.find(L"\n");
ex_wstr strLine;
ex_wstr::size_type posCR = ex_wstr::npos;
ex_wstr::size_type posLF = ex_wstr::npos;
for (;;)
{
posCR = strAll.find(L'\r');
posLF = strAll.find(L'\n');
if(posCR == ex_wstr::npos && posLF == ex_wstr::npos) {
if (strAll.empty())
break;
strLine = strAll;
strAll.clear();
} else if(posCR != ex_wstr::npos && posLF != ex_wstr::npos) {
if(posLF != posCR + 1) {
if(posLF < posCR) {
strLine.assign(strAll, 0, posLF);
strAll.erase(0, posLF + 1);
} else {
strLine.assign(strAll, 0, posCR);
strAll.erase(0, posCR + 1);
}
} else {
strLine.assign(strAll, 0, posCR);
strAll.erase(0, posCR + 2);
}
} else {
if(posCR != ex_wstr::npos) {
strLine.assign(strAll, 0, posCR);
strAll.erase(0, posCR + 1);
} else {
strLine.assign(strAll, 0, posLF);
strAll.erase(0, posLF + 1);
}
}
if (posCR == ex_wstr::npos && posLF == ex_wstr::npos)
{
if (strAll.empty())
break;
strLine = strAll;
strAll.clear();
}
else if (posCR != ex_wstr::npos && posLF != ex_wstr::npos)
{
if (posLF != posCR + 1)
{
if (posLF < posCR)
{
strLine.assign(strAll, 0, posLF);
strAll.erase(0, posLF + 1);
}
else
{
strLine.assign(strAll, 0, posCR);
strAll.erase(0, posCR + 1);
}
}
else
{
strLine.assign(strAll, 0, posCR);
strAll.erase(0, posCR + 2);
}
}
else
{
if (posCR != ex_wstr::npos)
{
strLine.assign(strAll, 0, posCR);
strAll.erase(0, posCR + 1);
}
else
{
strLine.assign(strAll, 0, posLF);
strAll.erase(0, posLF + 1);
}
}
// if (ex_wstr::npos == pos)
// {
// pos = strAll.find(L'\n');
// if (ex_wstr::npos == pos)
// {
// if (strAll.empty())
// break;
//
// strLine = strAll;
// strAll.clear();
// }
// else
// {
// strLine.assign(strAll, 0, pos);
// strAll.erase(0, pos + 1);
// }
// }
// else
// {
// strLine.assign(strAll, 0, pos);
// strAll.erase(0, pos + 2);
// }
if (ex_only_white_space(strLine))
continue;
if (ex_only_white_space(strLine))
continue;
if (!process_line_(strLine, &pCurSection))
{
bRet = false;
break;
}
}
if (!_ProcessLine(strLine, &pCurSection))
{
bRet = false;
break;
}
}
} while (false);
} while (false);
return bRet;
return bRet;
}
void ExIniFile::Save(int codepage/* = EX_CODEPAGE_UTF8*/)
{
//ex_astr temp;
//ex_wstr2astr(m_file_path, temp);
//FILE* file = NULL;
//fopen(temp.c_str(), "wt");
//fopen_s(&file, temp.c_str(), "wt");
FILE* file = ex_fopen(m_file_path, L"wt");
if (!file)
return;
if (file == NULL)
{
return;
}
// 如果有不属于任何小节的值对,先保存之
if (m_dumy_sec.Count() > 0)
m_dumy_sec.Save(file, codepage);
// 如果有不属于任何小节的值对,先保存之
if (m_dumy_sec.Count() > 0)
m_dumy_sec.Save(file, codepage);
for (auto it = m_secs.begin(); it != m_secs.end(); ++it)
{
EXLOGD(L"{%s}\n", it->first.c_str());
ex_wstr temp;
temp += L"[";
temp += it->first;
temp += L"]\n";
ex_astr temp2;
ex_wstr2astr(temp, temp2, codepage);
fwrite(temp2.c_str(), temp2.size(), 1, file);
ex_ini_sections::iterator it = m_secs.begin();
for (; it != m_secs.end(); ++it)
{
EXLOGD(L"{%s}\n", it->first.c_str());
ex_wstr temp;
temp += L"[";
temp += it->first.c_str();
temp += L"]\n";
ex_astr temp2;
ex_wstr2astr(temp, temp2, codepage);
fwrite(temp2.c_str(), temp2.size(), 1, file);
it->second->Save(file, codepage);
}
fclose(file);
it->second->Save(file, codepage);
}
fclose(file);
}
#ifdef EX_DEBUG
void ExIniFile::Dump(void)
{
ex_ini_sections::iterator it = m_secs.begin();
for (; it != m_secs.end(); ++it)
{
EXLOGD(_T("{%s}\n"), it->first.c_str());
it->second->Dump();
}
for (auto it = m_secs.begin(); it != m_secs.end(); ++it)
{
EXLOGD(_T("{%s}\n"), it->first.c_str());
it->second->Dump();
}
}
#endif
void ExIniFile::ClearUp(void)
void ExIniFile::ClearUp()
{
ex_ini_sections::iterator it = m_secs.begin();
for (; it != m_secs.end(); ++it)
{
delete it->second;
}
m_secs.clear();
for (auto it = m_secs.begin(); it != m_secs.end(); ++it)
{
delete it->second;
}
m_secs.clear();
}
ExIniSection* ExIniFile::GetSection(const ex_wstr& strName, bool bCreateIfNotExists)
{
ex_ini_sections::iterator it = m_secs.find(strName);
if (it != m_secs.end())
return it->second;
auto it = m_secs.find(strName);
if (it != m_secs.end())
return it->second;
if (!bCreateIfNotExists)
return NULL;
if (!bCreateIfNotExists)
return nullptr;
ExIniSection* pSec = new ExIniSection(strName);
m_secs.insert(std::make_pair(strName, pSec));
return pSec;
auto pSec = new ExIniSection(strName);
m_secs.insert(std::make_pair(strName, pSec));
return pSec;
}
// static function.
// 解析一行,返回值为 [节名/值对/注释/什么也不是/出错了]
// 节名 => strKey = [section_name]
// 值对 => strKey = strValue
ExIniFile::PARSE_RV ExIniFile::_ParseLine(const ex_wstr& strOrigLine, ex_wstr& strKey, ex_wstr& strValue)
ExIniFile::PARSE_RV ExIniFile::parse_line_(const ex_wstr& strLine, ex_wstr& strKey, ex_wstr& strValue)
{
// 首先去掉行首的空格或者 TAB 控制
ex_wstr strLine(strOrigLine);
ex_remove_white_space(strLine, EX_RSC_BEGIN);
// 首先去掉行首的空格或者 TAB 控制
ex_wstr line(strLine);
ex_remove_white_space(line, EX_RSC_BEGIN);
// 判断是否为注释。 .ini 文件以 分号';'/'#' 作为注释行的第一个字符
if (';' == strLine[0] || '#' == strLine[0])
{
return PARSE_COMMENT;
}
// 判断是否为注释。 .ini 文件以 分号';'/'#' 作为注释行的第一个字符
if (';' == line[0] || '#' == line[0])
{
return PARSE_COMMENT;
}
if ('[' == strLine[0])
{
// 这是一个节(section)
ex_wstr::size_type startPos = strLine.find('[');
ex_wstr::size_type endPos = strLine.rfind(']');
strLine.erase(endPos);
strLine.erase(startPos, 1);
if ('[' == line[0])
{
// 这是一个节(section)
ex_wstr::size_type startPos = line.find('[');
ex_wstr::size_type endPos = line.rfind(']');
line.erase(endPos);
line.erase(startPos, 1);
strKey = strLine;
return PARSE_SECTION;
}
else
{
// 看看能否找到等号(=),这是 key=value 的判别方法
ex_wstr::size_type pos = strLine.find('=');
if (ex_wstr::npos == pos)
{
//return PARSE_OTHER; // 没有等号
ex_remove_white_space(strLine);
strKey = strLine;
strValue.clear();
return PARSE_KEYVALUE;
}
strKey = line;
return PARSE_SECTION;
}
else
{
// 看看能否找到等号(=),这是 key=value 的判别方法
// 如果没有等号,则整个视作 keyvalue为 NULL这样。
ex_wstr::size_type pos = line.find('=');
if (ex_wstr::npos == pos)
{
//return PARSE_OTHER; // 没有等号
ex_remove_white_space(line);
strKey = line;
strValue.clear();
return PARSE_KEYVALUE;
}
// 将等号前面的与等号后面的分割
strKey.assign(strLine, 0, pos);
strValue.assign(strLine, pos + 1, strLine.length() - pos);
ex_remove_white_space(strKey);
// 将等号前面的与等号后面的分割
strKey.assign(line, 0, pos);
strValue.assign(line, pos + 1, line.length() - pos);
ex_remove_white_space(line);
// 等号后面的应该原封不动,不应该移除空白字符
ex_remove_white_space(strValue, EX_RSC_BEGIN);
// 等号后面的应该原封不动,不应该移除空白字符
ex_remove_white_space(strValue, EX_RSC_BEGIN);
return PARSE_KEYVALUE;
}
return PARSE_KEYVALUE;
}
return PARSE_OTHER;
// return PARSE_OTHER;
}
bool ExIniFile::_ProcessLine(const ex_wstr strLine, ExIniSection** pCurSection)
bool ExIniFile::process_line_(const ex_wstr& strLine, ExIniSection** pCurSection)
{
if (strLine.empty())
return true;
if (strLine.empty())
return true;
ex_wstr strKey;//(_T(""));
ex_wstr strValue;//(_T(""));
ex_wstr strKey;
ex_wstr strValue;
auto parse_rv = parse_line_(strLine, strKey, strValue);
PARSE_RV parse_rv = PARSE_ERROR;
bool bError = false;
parse_rv = _ParseLine(strLine, strKey, strValue);
switch (parse_rv)
{
case PARSE_ERROR:
bError = true;
break;
case PARSE_SECTION:
{
// 创建一个节
auto pSection = GetSection(strKey, true);
if (!pSection)
{
bError = true;
break;
}
bool bError = false;
*pCurSection = pSection;
}
break;
case PARSE_KEYVALUE:
if (!pCurSection || !*pCurSection)
{
*pCurSection = &m_dumy_sec;
}
switch (parse_rv)
{
case PARSE_ERROR:
bError = true;
break;
case PARSE_SECTION:
{
// 创建一个节
ExIniSection* pSection = GetSection(strKey, true);
if (NULL == pSection)
{
bError = true;
break;
}
// 创建一个值对
if (!(*pCurSection)->SetValue(strKey, strValue, true))
{
bError = true;
break;
}
*pCurSection = pSection;
}
break;
case PARSE_KEYVALUE:
if (NULL == pCurSection || NULL == *pCurSection)
{
//bError = true;
//break;
*pCurSection = &m_dumy_sec;
}
break;
// 创建一个值对
if (!(*pCurSection)->SetValue(strKey, strValue, true))
{
bError = true;
break;
}
case PARSE_COMMENT:
case PARSE_OTHER:
default:
break;
}
break;
case PARSE_COMMENT:
case PARSE_OTHER:
default:
break;
}
return (!bError);
return (!bError);
}

View File

@ -26,6 +26,9 @@ extern "C" {
#elif defined(EX_OS_LINUX)
# define PYS_USE_PYLIB_STATIC
# include <Python.h>
#elif defined(EX_OS_MACOS)
# define PYS_USE_PYLIB_SHARED
# include <Python.h>
#else
# error This platform not supported yet.
#endif
@ -200,73 +203,73 @@ extern "C" {
typedef void* PYS_HANDLE;
// 创建一个PyShell句柄所有操作均对应此句柄进行一个进程仅有一个句柄
// 创建一个PyShell句柄所有操作均对应此句柄进行一个进程仅有一个句柄
PYS_HANDLE pys_create(void);
// 销毁一个PyShell句柄
// 销毁一个PyShell句柄
void pys_destroy(PYS_HANDLE* pysh);
// 使用指定的运行时路径进行初始化运行时路径中包含pythonXX.dll/python.zip/modules等等
// 使用指定的运行时路径进行初始化运行时路径中包含pythonXX.dll/python.zip/modules等等
PYS_BOOL pys_init_runtime(PYS_HANDLE pysh, const wchar_t* exec_file, const wchar_t* runtime_path);
// 设置python包搜索路径可多次调用进行追加可省略
// 设置python包搜索路径可多次调用进行追加可省略
PYS_BOOL pys_add_search_path(PYS_HANDLE pysh, const wchar_t* path);
// 设置python运行时的命令行参数可省略
// 设置python运行时的命令行参数可省略
void pys_set_argv(PYS_HANDLE pysh, int argc, wchar_t** argv);
// 追加python运行时的命令行参数可省略
// 追加python运行时的命令行参数可省略
void pys_add_arg(PYS_HANDLE pysh, const wchar_t* arg);
// 设置python解释器名称可省略默认为当前可执行程序文件名的绝对路径
// 设置python解释器名称可省略默认为当前可执行程序文件名的绝对路径
void pys_set_program(PYS_HANDLE pysh, const wchar_t* program_name);
// 设置入口脚本文件名,可以是一个.py文件也可以是一个.zip文件
// 设置入口脚本文件名,可以是一个.py文件也可以是一个.zip文件
void pys_set_startup_file(PYS_HANDLE pysh, const wchar_t* filename);
// 设置启动模块名和入口函数名func_name为NULL时默认执行指定模块中的main函数
// 本函数可以省略,默认情况下:
// 如果startup_file是一个.py文件则默认module_name就是.py文件的文件名本身
// 如果startup_file是一个.zip文件则默认module_name是`pysmain`。
// 设置启动模块名和入口函数名func_name为NULL时默认执行指定模块中的main函数
// 本函数可以省略,默认情况下:
// 如果startup_file是一个.py文件则默认module_name就是.py文件的文件名本身
// 如果startup_file是一个.zip文件则默认module_name是`pysmain`。
void pys_set_bootstrap_module(PYS_HANDLE pysh, const char* module_name, const char* func_name);
// 初始化模块的函数原型
// 初始化模块的函数原型
typedef PyObject* (*pys_init_module_func)(void);
typedef struct PYS_BUILTIN_FUNC
{
const char* py_func_name; // Python中调用时使用的函数名
PyCFunction c_func_addr; // 对应的C的函数
PYS_BOOL have_args; // 此函数是否需要参数
const char* py_func_desc; // 此函数的文档注释可以为NULL。
const char* py_func_name; // Python中调用时使用的函数名
PyCFunction c_func_addr; // 对应的C的函数
PYS_BOOL have_args; // 此函数是否需要参数
const char* py_func_desc; // 此函数的文档注释可以为NULL。
}PYS_BUILTIN_FUNC;
typedef enum PYS_CONST_TYPE
{
PYS_CONST_BOOL, // Python中得到 True/False 的值
PYS_CONST_LONG, // Python中得到一个整数
PYS_CONST_STRING, // Python中得到一个字符串
PYS_CONST_BYTES // Python中得到一个Bytes类型数据
PYS_CONST_BOOL, // Python中得到 True/False 的值
PYS_CONST_LONG, // Python中得到一个整数
PYS_CONST_STRING, // Python中得到一个字符串
PYS_CONST_BYTES // Python中得到一个Bytes类型数据
}PYS_CONST_TYPE;
typedef struct PYS_BUILTIN_CONST
{
char* py_const_name; // Python中调用时使用的变量名
PYS_CONST_TYPE type; // 常量类型
size_t size; // 常量数据的长度
void* buffer; // 常量数据的内容
char* py_const_name; // Python中调用时使用的变量名
PYS_CONST_TYPE type; // 常量类型
size_t size; // 常量数据的长度
void* buffer; // 常量数据的内容
}PYS_BUILTIN_CONST;
// 增加一个内建模块其中如果没有函数或常量那么对应的funcs/consts可以为NULL。
// 可多次调用本函数来创建多个内建模块。如果多次调用时使用相同的模块名,则函数和常量会追加到此模块中
// 同一个模块中,函数名和常量名不能重复(但可以通过大小写区分)
// 增加一个内建模块其中如果没有函数或常量那么对应的funcs/consts可以为NULL。
// 可多次调用本函数来创建多个内建模块。如果多次调用时使用相同的模块名,则函数和常量会追加到此模块中
// 同一个模块中,函数名和常量名不能重复(但可以通过大小写区分)
PYS_BOOL pys_add_builtin_module(PYS_HANDLE pysh, const char* module_name, pys_init_module_func init_func);
PyObject* pys_create_module(const char* module_name, PYS_BUILTIN_FUNC* funcs);
void pys_builtin_const_bool(PyObject* mod, const char* name, PYS_BOOL val);
void pys_builtin_const_long(PyObject* mod, const char* name, long val);
void pys_builtin_const_utf8(PyObject* mod, const char* name, const char* val); // val 必须是utf8编码的字符串
void pys_builtin_const_utf8(PyObject* mod, const char* name, const char* val); // val 必须是utf8编码的字符串
void pys_builtin_const_wcs(PyObject* mod, const char* name, const wchar_t* val);
void pys_builtin_const_bin(PyObject* mod, const char* name, const ex_u8* val, size_t size);
// 运行python解释器
// 运行python解释器
int pys_run(PYS_HANDLE pysh);
#ifdef __cplusplus

View File

@ -3,6 +3,9 @@
#include "pys_util.h"
#ifdef PYS_USE_PYLIB_SHARED
#if defined(EX_OS_WIN32)
//========================================================
// WIN32
//========================================================
@ -30,6 +33,39 @@ if(!pylib_ ## name) { \
return -1; \
}
#else
//========================================================
// Unix
//========================================================
#define DECLPROC(name) \
__PROC__ ## name pylib_ ## name = NULL;
#define GETPROCOPT(lib, name, sym) \
pylib_ ## name = (__PROC__ ## name)dlsym(lib, #sym)
#define GETPROC(lib, name) \
GETPROCOPT(lib, name, name); \
if(!pylib_ ## name) { \
EXLOGE("[pys] can not GetProcAddress for " #name "\n"); \
return -1;\
}
#pragma warning(disable:4054)
#define DECLVAR(name) \
__VAR__ ## name* pylib_ ## name = NULL;
#define GETVAR(lib, name) \
pylib_ ## name = (__VAR__ ## name*)dlsym(lib, #name); \
if (!pylib_ ## name) { \
EXLOGE("[pys] can not GetProcAddress for " #name "\n"); \
return -1; \
}
#endif
static int _pys_map_python_lib(DYLIB_HANDLE handle);
static DYLIB_HANDLE _pys_dlopen(const wchar_t* dylib_path);
@ -70,7 +106,7 @@ DYLIB_HANDLE _pys_dlopen(const wchar_t* dylib_path)
return NULL;
}
EXLOGD("[pys] py-lib-a: %s\n", path);
EXLOGD("[pys] py-lib-a: %s\n", path.c_str());
handle = dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL);

View File

@ -18,10 +18,10 @@ namespace pys
Core();
~Core();
// 调用各个成员函数设置必要信息之后再运行
int run(void);
// 调用各个成员函数设置必要信息之后再运行
int run();
// 初始化为默认设置
// 初始化为默认设置
bool init(const wchar_t* exec_file, const wchar_t* runtime_path);
bool add_search_path(const wchar_t* wpath);
@ -32,27 +32,27 @@ namespace pys
bool get_builtin_module_by_init_func(pys_init_module_func init_func, ex_astr& module_name);
private:
bool _load_dylib(void);
bool _load_dylib();
bool _run_init_builtin_modules(void);
bool _run_prepare(void);
void _run_set_program(void);
void _run_set_path(void);
void _run_set_argv(void);
bool _run_init_builtin_modules();
bool _run_prepare();
void _run_set_program();
void _run_set_path();
void _run_set_argv();
public:
ex_wstr m_prog_name; // 传递给Python解释器的如果没有设置此值则默认使用m_exec_file。
ex_wstr m_prog_name; // 传递给Python解释器的如果没有设置此值则默认使用m_exec_file。
ex_astr m_bootstrap_module;
ex_astr m_bootstrap_func;
pys_wstr_list m_py_args; // 传递给Python脚本的参数
pys_wstr_list m_py_args; // 传递给Python脚本的参数
private:
bool m_is_zipped_app;
ex_wstr m_exec_file; // 当前可执行程序的文件名(绝对路径)
ex_wstr m_exec_path; // 当前可执行程序所在的路径(绝对路径)
ex_wstr m_runtime_path; // python运行环境路径默认为可执行程序所在路径下的 `pysrt` 目录。
ex_wstr m_exec_file; // 当前可执行程序的文件名(绝对路径)
ex_wstr m_exec_path; // 当前可执行程序所在的路径(绝对路径)
ex_wstr m_runtime_path; // python运行环境路径默认为可执行程序所在路径下的 `pysrt` 目录。
ex_wstr m_start_file;
ex_wstr m_search_path_tmp;

Binary file not shown.

View File

@ -63,11 +63,10 @@ static bool _process_cmd_line(int argc, wchar_t** argv)
}
g_run_type = RUN_UNKNOWN;
bool is_py_arg = false;
if (0 == wcscmp(argv[1], L"--version"))
{
EXLOGV("\nTeleport Server, version %ls.\n\n", TP_SERVER_VER);
EXLOGI("\nTeleport Server, version %ls.\n\n", TP_SERVER_VER);
return false;
}
else if (0 == wcscmp(argv[1], L"-i"))

View File

@ -143,7 +143,7 @@ bool ts_http_get(const ex_astr& url, ex_astr& body)
mg_mgr_init(&_mgr, NULL);
mg_connection* nc = mg_connect_http(&_mgr, ev_handler, url.c_str(), NULL, NULL);
if (NULL == nc) {
if (nc == nullptr) {
mg_mgr_free(&_mgr);
return false;
}

View File

@ -205,6 +205,7 @@ void SshChannelPair::process_pty_data_from_server(const uint8_t* data, uint32_t
}
// 处理输入回显,合成最终的命令行字符串
// https://www.systutorials.com/docs/linux/man/4-console_codes/
int offset = 0;
bool esc_mode = false;
int esc_arg = 0;

File diff suppressed because it is too large Load Diff

View File

@ -80,7 +80,7 @@ public:
// --------------------------
// 通道管理
// --------------------------
void set_channel_tp2srv_callbacks(ssh_channel ch_tp2srv);
// void set_channel_tp2srv_callbacks(ssh_channel ch_tp2srv);
bool make_channel_pair(ssh_channel ch_tp2cli, ssh_channel ch_tp2srv);
@ -156,6 +156,8 @@ private:
bool m_first_auth;
// 远程主机认证是否通过
bool m_auth_passed;
// 如果认证过程中发生了错误,记录错误提示,后续建立通道后可以发送给客户端进行提示
std::string m_auth_err_msg;
// 发生了不可逆的错误,需要关闭整个会话(包括所有的通道)
bool m_fault;

View File

@ -55,8 +55,8 @@ static ex_rv tpp_cmd_set_runtime_config(const char* param) {
return TPE_PARAM;
ex_u32 noop_timeout = jp["noop_timeout"].asUInt();
if (noop_timeout == 0)
return TPE_PARAM;
// if (noop_timeout == 0)
// return TPE_PARAM;
g_ssh_proxy.set_cfg(noop_timeout * 60);

View File

@ -49,8 +49,8 @@ static ex_rv tpp_cmd_set_runtime_config(const char* param) {
return TPE_PARAM;
ex_u32 noop_timeout = jp["noop_timeout"].asUInt();
if (noop_timeout == 0)
return TPE_PARAM;
// if (noop_timeout == 0)
// return TPE_PARAM;
g_telnet_proxy.set_cfg(noop_timeout * 60);

View File

@ -19,11 +19,23 @@ include_directories(
../../../common/pyshell/include
)
include_directories(
${TP_EXTERNAL_RELEASE_DIR}/include
${TP_EXTERNAL_RELEASE_DIR}/include/python3.7m
)
link_directories(${TP_EXTERNAL_RELEASE_DIR}/lib)
if (OS_LINUX)
include_directories(
${TP_EXTERNAL_RELEASE_DIR}/include
${TP_EXTERNAL_RELEASE_DIR}/include/python3.7m
)
link_directories(${TP_EXTERNAL_RELEASE_DIR}/lib)
add_executable(tp_web ${DIR_SRCS})
target_link_libraries(tp_web python3.7m ssl crypto dl pthread rt util)
elseif (OS_MACOS)
include_directories(
/usr/local/Cellar/python@3.9/3.9.0_1/Frameworks/Python.framework/Versions/3.9/include/python3.9
)
link_directories(
# /usr/local/Cellar/python@3.9/3.9.0_1/Frameworks/Python.framework/Versions/3.9/lib
/usr/local/opt/python@3.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/config-3.9-darwin
)
add_executable(tp_web ${DIR_SRCS})
target_link_libraries(tp_web python3.9 intl dl)
endif ()
add_executable(tp_web ${DIR_SRCS})
target_link_libraries(tp_web python3.7m ssl crypto dl pthread rt util)

View File

@ -4,28 +4,28 @@
#include <ex.h>
#include <pys.h>
// 命令行参数说明(不带参数运行则以服务方式启动)
// 命令行参数说明(不带参数运行则以服务方式启动)
// tp_web [-i|-u|--version] [ [-d] start] [...]
// -d 启动程序并输出调试信息(不会运行为守护进程/服务模式)
// -i 安装服务然后退出仅限Win平台
// -u 卸载服务然后退出仅限Win平台
// --version 打印版本号然后退出
// start 以服务方式运行
// ... 剩余的所有参数均传递给python脚本
// -d 启动程序并输出调试信息(不会运行为守护进程/服务模式)
// -i 安装服务然后退出仅限Win平台
// -u 卸载服务然后退出仅限Win平台
// --version 打印版本号然后退出
// start 以服务方式运行
// ... 剩余的所有参数均传递给python脚本
//
//
// 执行指定的Python脚本
// 执行指定的Python脚本
// tp_web --py [-f FuncName] script_file.py ...
// --py 必须为第一个参数,表示本次执行为执行指定脚本
// -f FuncName 指定入口函数默认为main。
// script-file.py 被执行的脚本文件
// ... 剩余的所有参数均传递给Python脚本
// --py 必须为第一个参数,表示本次执行为执行指定脚本
// -f FuncName 指定入口函数默认为main。
// script-file.py 被执行的脚本文件
// ... 剩余的所有参数均传递给Python脚本
ExLogger g_ex_logger;
bool g_is_debug = false;
static ex_wstrs g_py_args;
// 如果是执行指定脚本
// 如果是执行指定脚本
static ex_wstr g_py_script_file;
static ex_wstr g_py_main_func;
@ -40,8 +40,8 @@ static ex_u8 g_run_type = RUN_UNKNOWN;
static bool _run_daemon(void);
// 导出函数给Python脚本使用主要是为了记录日志
// Windows平台上tp_web程序打开日志文件写之后Python脚本尝试写入方式打开此日志文件时会失败。
// 导出函数给Python脚本使用主要是为了记录日志
// Windows平台上tp_web程序打开日志文件写之后Python脚本尝试写入方式打开此日志文件时会失败。
PyObject* init_web_builtin_module(void);
#ifdef EX_OS_WIN32
@ -186,7 +186,7 @@ static int _main_loop(void)
return 1;
}
// 设置web的路径
// 设置web的路径
ex_wstr sf_path;
if (g_run_type == RUN_WEB)
{
@ -344,10 +344,10 @@ static DWORD WINAPI service_thread_func(LPVOID lpParam);
int main()
{
int ret = 0;
LPWSTR szCmdLine = (LPWSTR)::GetCommandLineW(); //获取命令行参数;
LPWSTR szCmdLine = (LPWSTR)::GetCommandLineW(); //获取命令行参数;
int _argc = 0;
wchar_t** _argv = ::CommandLineToArgvW(szCmdLine, &_argc); //拆分命令行参数字符串;
wchar_t** _argv = ::CommandLineToArgvW(szCmdLine, &_argc); //拆分命令行参数字符串;
ret = _app_main(_argc, _argv);
@ -379,7 +379,7 @@ static DWORD WINAPI service_thread_func(LPVOID lpParam)
{
int ret = _main_loop();
// 更新服务状态(如果服务还在运行,将其设置为停止状态)
// 更新服务状态(如果服务还在运行,将其设置为停止状态)
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwCheckPoint = 0;
@ -552,7 +552,7 @@ static bool _run_daemon(void)
//===============================================================
// 加入内建模块供脚本调用
// 加入内建模块供脚本调用
//===============================================================
PyObject* _py_log_output(PyObject* self, PyObject* args)
{
@ -629,10 +629,10 @@ PyObject* _py_log_console(PyObject* self, PyObject* args)
PYS_BUILTIN_FUNC _demo_funcs[] = {
{
"log_output", // 脚本函数名,在脚本中使用
_py_log_output, // 对应的C代码函数名
PYS_TRUE, // 函数的基本信息(是否需要参数,等等)
"write log." // 函数的说明文档,可选(可以是空字符串)
"log_output", // 脚本函数名,在脚本中使用
_py_log_output, // 对应的C代码函数名
PYS_TRUE, // 函数的基本信息(是否需要参数,等等)
"write log." // 函数的说明文档,可选(可以是空字符串)
},
{
@ -649,7 +649,7 @@ PYS_BUILTIN_FUNC _demo_funcs[] = {
"set log to console or not."
},
// 最后一组,第一个成员为空指针,表示结束
// 最后一组,第一个成员为空指针,表示结束
{ NULL, NULL, 0, NULL }
};
@ -666,7 +666,7 @@ PyObject* init_web_builtin_module(void)
pys_builtin_const_long(mod, "EX_LOG_LEVEL_ERROR", EX_LOG_LEVEL_ERROR);
// pys_builtin_const_bool(mod, "DEMO_CONST_2", PYS_TRUE);
// //pys_builtin_const_wcs(mod, "DEMO_CONST_3", L"STRING 中文测试 this is string.");
// //pys_builtin_const_wcs(mod, "DEMO_CONST_3", L"STRING 中文测试 this is string.");
// pys_builtin_const_wcs(mod, "DEMO_CONST_3", L"STRING this is string.");
// pys_builtin_const_utf8(mod, "DEMO_CONST_4", "this is string.");
//

View File

@ -132,9 +132,9 @@ class WebApp:
if not tp_stats().init():
log.e('can not initialize system status collector.\n')
return 0
if not tp_host_alive().init():
log.e('can not initialize host state inspector.\n')
return 0
# if not tp_host_alive().init():
# log.e('can not initialize host state inspector.\n')
# return 0
settings = {
#
@ -189,7 +189,7 @@ class WebApp:
except:
log.e('\n')
tp_host_alive().stop()
# tp_host_alive().stop()
tp_cron().stop()
return 0