diff --git a/middleware/IpcConfig/include/IIpcConfig.h b/middleware/IpcConfig/include/IIpcConfig.h index 732f1b3..5a84893 100644 --- a/middleware/IpcConfig/include/IIpcConfig.h +++ b/middleware/IpcConfig/include/IIpcConfig.h @@ -12,8 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef IIPCCONFIG_H -#define IIPCCONFIG_H +#ifndef I_IPC_CONFIG_H +#define I_IPC_CONFIG_H #include "StatusCode.h" #include #include diff --git a/test/GtestUsing.h b/test/GtestUsing.h index 7378611..e829a58 100644 --- a/test/GtestUsing.h +++ b/test/GtestUsing.h @@ -12,8 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef GTESTUSING_H -#define GTESTUSING_H +#ifndef GTEST_USING_H +#define GTEST_USING_H #include #include using ::testing::_; @@ -41,11 +41,11 @@ using ::testing::ReturnRefOfCopy; using ::testing::ReturnRoundRobin; using ::testing::SaveArg; using ::testing::SetArgPointee; +using ::testing::SetArgReferee; using ::testing::SetArgumentPointee; using ::testing::Unused; using ::testing::WithArgs; using ::testing::internal::BuiltInDefaultValue; -using ::testing::SetArgReferee; // using ::testing::Mock::VerifyAndClearExpectations; using ::testing::Mock; #endif \ No newline at end of file diff --git a/test/all/CMakeLists.txt b/test/all/CMakeLists.txt index ea317d8..d75f030 100644 --- a/test/all/CMakeLists.txt +++ b/test/all/CMakeLists.txt @@ -18,10 +18,6 @@ link_directories( ${EXTERNAL_LIBS_OUTPUT_PATH} ) - - - - aux_source_directory(. SRC_FILES) aux_source_directory(${TEST_SOURCE_PATH}/middleware/IpcConfig/src SRC_FILES) set(TARGET_NAME AllTest) diff --git a/test/utils/TcpModule/CMakeLists.txt b/test/utils/TcpModule/CMakeLists.txt index 72dce6d..f51ec8c 100644 --- a/test/utils/TcpModule/CMakeLists.txt +++ b/test/utils/TcpModule/CMakeLists.txt @@ -32,7 +32,7 @@ endif() if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) target_link_libraries(${TARGET_NAME} LinuxApiMock) endif() -# if ("${COMPILE_IMPROVE_SUPPORT}" MATCHES "true") +if ("${COMPILE_IMPROVE_SUPPORT}" MATCHES "true") add_custom_target( TcpModuleTest_code_check COMMAND ${CLANG_TIDY_EXE} @@ -61,7 +61,7 @@ add_custom_command( COMMAND make TcpModuleTest_code_format WORKING_DIRECTORY ${PLATFORM_PATH}/cmake-shell/ ) -# endif() +endif() define_file_name(${TARGET_NAME}) diff --git a/test/utils/TcpModule/src/TcpModule_Test.cpp b/test/utils/TcpModule/src/TcpModule_Test.cpp index a493ca4..39a4ea3 100644 --- a/test/utils/TcpModule/src/TcpModule_Test.cpp +++ b/test/utils/TcpModule/src/TcpModule_Test.cpp @@ -16,6 +16,7 @@ #include "TcpModule.h" #include #include +#include namespace TcpModuleTest { // ../output_files/test/bin/TcpModuleTest --gtest_filter=TcpModuleTest.UNIT_TcpModule_AUTO_IllegalObject @@ -24,8 +25,33 @@ namespace TcpModuleTest */ TEST(TcpModuleTest, UNIT_TcpModule_AUTO_IllegalObject) { + static void *tcpClientAccept = nullptr; + TcpParam param = { + .mIp = "127.0.0.1", + .mPort = 9876, + .mReadFunc = [](const void *p, const size_t len, void *context) -> void { + return; + }, + .mAcceptClientFunc = [](void *object, const char *ip) -> void { + LogInfo("accept client, peer ip: %s", ip); + tcpClientAccept = object; + return; + }, + }; CreateLogModule(); ILogInit(LOG_INSTANCE_TYPE_END); + void *tcpServer = CreateTcpServer(param); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + void *tcpClient = CreateTcpClient(param); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + TcpClientWrite(tcpClient, "123456789", strlen("123456789")); + std::this_thread::sleep_for(std::chrono::milliseconds(3000)); + if (nullptr != tcpClient) { + FreeTcpClient(tcpClient); + } + if (nullptr != tcpServer) { + FreeTcpServer(tcpServer); + } ILogUnInit(); } } // namespace TcpModuleTest \ No newline at end of file diff --git a/utils/ConfigBase/src/ConfigBase.cpp b/utils/ConfigBase/src/ConfigBase.cpp index 4a4bfbb..b15ec75 100644 --- a/utils/ConfigBase/src/ConfigBase.cpp +++ b/utils/ConfigBase/src/ConfigBase.cpp @@ -21,7 +21,7 @@ static bool ObjectCheck(void *object) LogError("nullptr object!\n"); return false; } - if (*((const char **)(((char *)object) - sizeof(IConfigBase))) != GetConfigBaseModuleName()) { + if (*((const char **)(((char *)object) - sizeof(IConfigBaseHeader))) != GetConfigBaseModuleName()) { LogError("Illegal object!\n"); return false; } @@ -47,7 +47,7 @@ void CloseConfigFile(void *object) if (ObjectCheck(object) == true) { (*(std::shared_ptr *)object)->CloseConfigFile(); (*(std::shared_ptr *)object).reset(); - free(((char *)object) - sizeof(IConfigBase)); // TODO: bug? + free(((char *)object) - sizeof(IConfigBaseHeader)); // TODO: bug? } } StatusCode ConfigGetInt(void *object, const char *name, int *value) diff --git a/utils/TcpModule/CMakeLists.txt b/utils/TcpModule/CMakeLists.txt index 732bd8f..a3d94d2 100644 --- a/utils/TcpModule/CMakeLists.txt +++ b/utils/TcpModule/CMakeLists.txt @@ -8,6 +8,7 @@ include_directories( ${UTILS_SOURCE_PATH}/LinuxApi/include ${UTILS_SOURCE_PATH}/StatusCode/include ${UTILS_SOURCE_PATH}/Log/include + ${EXTERNAL_SOURCE_PATH}/libhv/libhv-1.3.2/include/hv ) # link_directories( # ${EXTERNAL_SOURCE_PATH}/libconfig/libconfig-1.7.3/lib/.libs @@ -17,9 +18,9 @@ aux_source_directory(./src SRC_FILES) set(TARGET_NAME TcpModule) add_library(${TARGET_NAME} STATIC ${SRC_FILES}) -target_link_libraries(${TARGET_NAME} LinuxApi StatusCode Log) +target_link_libraries(${TARGET_NAME} LinuxApi hv_static StatusCode Log) -# if ("${COMPILE_IMPROVE_SUPPORT}" MATCHES "true") +if ("${COMPILE_IMPROVE_SUPPORT}" MATCHES "true") add_custom_target( TcpModule_code_check COMMAND ${CLANG_TIDY_EXE} @@ -46,7 +47,7 @@ add_custom_command( COMMAND make TcpModule_code_format WORKING_DIRECTORY ${PLATFORM_PATH}/cmake-shell/ ) -# endif() +endif() define_file_name(${TARGET_NAME}) diff --git a/utils/TcpModule/include/TcpModule.h b/utils/TcpModule/include/TcpModule.h index e3d9d09..2044b24 100644 --- a/utils/TcpModule/include/TcpModule.h +++ b/utils/TcpModule/include/TcpModule.h @@ -14,22 +14,27 @@ */ #ifndef TCP_MODULE_H #define TCP_MODULE_H +#include +#include #ifdef __cplusplus extern "C" { #endif -typedef void (*TcpReadFunction)(void *, const int, void *); +typedef void (*TcpReadFunction)(const void *, const size_t, void *); +typedef void (*TcpAcceptClientFunction)(void *, const char *); typedef struct tcp_parm { const char *mIp; const int mPort; - const TcpReadFunction mReadFunc; -} TcpPram; -void *CreateTcpServer(const TcpPram param); -void FreeTcpServer(void *pointer); -int TcpServerWrite(void *object, void *buf, const int bufLenght); -void *CreateTcpClient(const TcpPram param); -void FreeTcpClient(void *pointer); -int TcpClientWrite(void *object, void *buf, const int bufLenght); + TcpReadFunction mReadFunc; // TODO: delete this memeber + TcpAcceptClientFunction mAcceptClientFunc; +} TcpParam; +void *CreateTcpServer(const TcpParam param); +void FreeTcpServer(void *object); +int AcceptClientSetReadFunc(void *object, TcpReadFunction readFunc); +int AcceptClientWrite(void *object, void *buf, const size_t bufLenght); +void *CreateTcpClient(const TcpParam param); +void FreeTcpClient(void *object); +ssize_t TcpClientWrite(void *object, const void *buf, const size_t bufLenght); #ifdef __cplusplus } #endif diff --git a/utils/TcpModule/src/TcpClient.cpp b/utils/TcpModule/src/ITcpClient.cpp similarity index 62% rename from utils/TcpModule/src/TcpClient.cpp rename to utils/TcpModule/src/ITcpClient.cpp index f297c00..0e0ca32 100644 --- a/utils/TcpModule/src/TcpClient.cpp +++ b/utils/TcpModule/src/ITcpClient.cpp @@ -11,4 +11,22 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ \ No newline at end of file + */ +#include "ITcpClient.h" +#include "ILog.h" +#include +void ITcpClient::Init(void) +{ +} +void ITcpClient::UnInit(void) +{ +} +ssize_t ITcpClient::Write(const void *buf, const size_t bufLenght) +{ + return WRITE_ERROR; +} +static const char *TCP_CLIENT_NAME = "tcp_client"; +const char *GetTcpClientModuleName(void) +{ + return TCP_CLIENT_NAME; +} \ No newline at end of file diff --git a/utils/TcpModule/src/ITcpClient.h b/utils/TcpModule/src/ITcpClient.h new file mode 100644 index 0000000..992174b --- /dev/null +++ b/utils/TcpModule/src/ITcpClient.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef I_TCP_CLIENT_H +#define I_TCP_CLIENT_H +#include "StatusCode.h" +#include +constexpr int WRITE_ERROR = -1; +class ITcpClient +{ +public: + ITcpClient() = default; + virtual ~ITcpClient() = default; + virtual void Init(void); + virtual void UnInit(void); + virtual ssize_t Write(const void *buf, const size_t bufLenght); +}; +typedef struct i_tcp_client_header +{ + const char *mCheckName; +} ITcpClientHeader; +typedef struct tcp_client +{ + ITcpClientHeader mHeader; + std::shared_ptr mTcpClient; +} TcpClient; +const char *GetTcpClientModuleName(void); +#endif \ No newline at end of file diff --git a/utils/TcpModule/src/TcpClient.h b/utils/TcpModule/src/ITcpServer.cpp similarity index 55% rename from utils/TcpModule/src/TcpClient.h rename to utils/TcpModule/src/ITcpServer.cpp index f297c00..4c8c0e2 100644 --- a/utils/TcpModule/src/TcpClient.h +++ b/utils/TcpModule/src/ITcpServer.cpp @@ -11,4 +11,26 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ \ No newline at end of file + */ +#include "ITcpServer.h" +#include "ILog.h" +#include +void ITcpClientAccept::Readed(const void *data, size_t length) +{ +} +void ITcpServer::Init(void) +{ +} +void ITcpServer::UnInit(void) +{ +} +static const char *TCP_SERVER_NAME = "tcp_server"; +static const char *TCP_CLIENT_ACCEPT_NAME = "tcp_client_accept"; +const char *GetTcpServerModuleName(void) +{ + return TCP_SERVER_NAME; +} +const char *GetTcpClientAcceptName(void) +{ + return TCP_CLIENT_ACCEPT_NAME; +} \ No newline at end of file diff --git a/utils/TcpModule/src/ITcpServer.h b/utils/TcpModule/src/ITcpServer.h new file mode 100644 index 0000000..34a4cc7 --- /dev/null +++ b/utils/TcpModule/src/ITcpServer.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef I_TCP_SERVER_H +#define I_TCP_SERVER_H +#include "StatusCode.h" +#include +class ITcpClientAccept +{ +public: + ITcpClientAccept() = default; + virtual ~ITcpClientAccept() = default; + virtual void Readed(const void *data, size_t length); +}; +class ITcpServer +{ +public: + ITcpServer() = default; + virtual ~ITcpServer() = default; + virtual void Init(void); + virtual void UnInit(void); +}; +typedef struct i_tcp_server_header +{ + const char *mCheckName; +} ITcpServerHeader; +typedef struct tcp_server +{ + ITcpServerHeader mHeader; + std::shared_ptr mTcpServer; +} TcpServer; +typedef struct tcp_client_accept +{ + ITcpServerHeader mHeader; + std::shared_ptr mTcpClientAccept; +} TcpClientAccept; +const char *GetTcpServerModuleName(void); +const char *GetTcpClientAcceptName(void); +#endif \ No newline at end of file diff --git a/utils/TcpModule/src/TcpClientImpl.cpp b/utils/TcpModule/src/TcpClientImpl.cpp new file mode 100644 index 0000000..532ad74 --- /dev/null +++ b/utils/TcpModule/src/TcpClientImpl.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "TcpClientImpl.h" +#include "ILog.h" +#include +TcpClientImpl::TcpClientImpl(const TcpParam param) : mParam(param) +{ +} +static void on_message(hio_t *io, void *buf, int len) +{ + LogInfo("onmessage: %.*s\n", len, (char *)buf); + TcpClientImpl *cli = (TcpClientImpl *)hevent_userdata(io); + // ... +} +static void on_connect(hio_t *io) +{ + LogInfo("onconnect: connfd=%d\n", hio_fd(io)); + TcpClientImpl *cli = (TcpClientImpl *)hevent_userdata(io); + // cli->connected = 1; + + // hio_write(io, "hello\r\n", 7); + + hio_setcb_read(io, on_message); + hio_read(io); +} +static void on_close(hio_t *io) +{ + LogInfo("onclose: connfd=%d error=%d\n", hio_fd(io), hio_error(io)); + TcpClientImpl *cli = (TcpClientImpl *)hevent_userdata(io); + // cli->connected = 0; + // reconnect + // if (cli->reconn_setting && reconn_setting_can_retry(cli->reconn_setting)) { + // uint32_t delay = reconn_setting_calc_delay(cli->reconn_setting); + // LogInfo("reconnect cnt=%d, delay=%d ...\n", cli->reconn_setting->cur_retry_cnt, + // cli->reconn_setting->cur_delay); cli->reconn_timer = htimer_add(cli->mLoop, reconnect_timer_cb, delay, 1); + // hevent_set_userdata(cli->reconn_timer, cli); + // } +} +void TcpClientImpl::Init(void) +{ + constexpr int NO_FALGS = 0; + mLoop = hloop_new(NO_FALGS); + if (nullptr == mLoop) { + LogError("TcpClientImpl::Init hloop_new failed.\n"); + return; + } + hio_t *io = hio_create_socket(mLoop, mParam.mIp, mParam.mPort, HIO_TYPE_TCP, HIO_CLIENT_SIDE); + if (nullptr == io) { + LogError("TcpClientImpl::Init hio_create_socket failed.\n"); + return; + } + hevent_set_userdata(io, this); + hio_setcb_connect(io, on_connect); + hio_setcb_close(io, on_close); + hio_connect(io); + mIo = io; + std::shared_ptr impl = std::dynamic_pointer_cast(shared_from_this()); + auto recvThread = [](std::shared_ptr tcpClient) { + tcpClient->Loop(); + }; + mTcpClientThread = std::thread(recvThread, impl); +} +void TcpClientImpl::UnInit(void) +{ + if (nullptr != mLoop) { + LogInfo("Stop loop.\n"); + hloop_stop(mLoop); + } + if (mTcpClientThread.joinable()) { + mTcpClientThread.join(); + } + hloop_free(&mLoop); + mLoop = nullptr; + mIo = nullptr; +} +ssize_t TcpClientImpl::Write(const void *buf, const size_t bufLenght) +{ + if (nullptr == mIo) { + LogError("mIo is nullptr.\n"); + return WRITE_ERROR; + } + return hio_write(mIo, buf, bufLenght); +} +void TcpClientImpl::Loop(void) +{ + if (nullptr == mLoop) { + LogError("mLoop is null\n"); + return; + } + hloop_run(mLoop); +} +std::shared_ptr *NewTcpClient(const TcpParam param) +{ + LogInfo("Create tcp server object.\n"); + TcpClient *impl = (TcpClient *)malloc(sizeof(TcpClient)); + if (nullptr == impl) { + LogError("NewTcpServer::malloc failed.\n"); + return nullptr; + } + TcpClient tmp; + memcpy((void *)impl, (void *)&tmp, sizeof(TcpClient)); + impl->mHeader.mCheckName = GetTcpClientModuleName(); + impl->mTcpClient = std::make_shared(param); + return (std::shared_ptr *)(((char *)impl) + sizeof(ITcpClientHeader)); +} \ No newline at end of file diff --git a/utils/TcpModule/src/TcpClientImpl.h b/utils/TcpModule/src/TcpClientImpl.h new file mode 100644 index 0000000..9404a89 --- /dev/null +++ b/utils/TcpModule/src/TcpClientImpl.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef TCP_CLIENT_IMPL_H +#define TCP_CLIENT_IMPL_H +#include "ITcpClient.h" +#include "TcpModule.h" +#include "hloop.h" +#include "hsocket.h" +#include "hssl.h" +#include +#include +class TcpClientImpl : public ITcpClient, public std::enable_shared_from_this +{ +public: + TcpClientImpl(const TcpParam param); + virtual ~TcpClientImpl() = default; + void Init(void) override; + void UnInit(void) override; + ssize_t Write(const void *buf, const size_t bufLenght) override; + void Loop(void); + +private: + hloop_t* mLoop; + hio_t *mIo; + const TcpParam mParam; + std::thread mTcpClientThread; +}; +std::shared_ptr *NewTcpClient(const TcpParam param); +#endif \ No newline at end of file diff --git a/utils/TcpModule/src/TcpModule.cpp b/utils/TcpModule/src/TcpModule.cpp index 544800d..939c2a4 100644 --- a/utils/TcpModule/src/TcpModule.cpp +++ b/utils/TcpModule/src/TcpModule.cpp @@ -13,9 +13,71 @@ * limitations under the License. */ #include "TcpModule.h" +#include "ILog.h" +#include "ITcpServer.h" +#include "TcpClientImpl.h" #include "TcpModuleImpl.h" -void *CreateTcpServer(const TcpPram param) +#include "TcpModuleMakePtr.h" +static bool TcpServerObjectCheck(void *object) { - // - return NewTcpServer(param); + if (nullptr == object) { + LogError("nullptr object!\n"); + return false; + } + if (*((const char **)(((char *)object) - sizeof(ITcpServerHeader))) != GetTcpServerModuleName()) { + LogError("Illegal object!\n"); + return false; + } + return true; +} +static bool TcpClientObjectCheck(void *object) +{ + if (nullptr == object) { + LogError("nullptr object!\n"); + return false; + } + if (*((const char **)(((char *)object) - sizeof(ITcpClientHeader))) != GetTcpClientModuleName()) { + LogError("Illegal object!\n"); + return false; + } + return true; +} +void *CreateTcpServer(const TcpParam param) +{ + std::shared_ptr *server = TcpModuleMakePtr::GetInstance()->CreateTcpServer(param); + if (nullptr != *server) { + (*server)->Init(); + } + return server; +} +void FreeTcpServer(void *object) +{ + if (TcpServerObjectCheck(object) == true) { + (*(std::shared_ptr *)object)->UnInit(); + (*(std::shared_ptr *)object).reset(); + free(((char *)object) - sizeof(ITcpServerHeader)); // TODO: bug? + } +} +void *CreateTcpClient(const TcpParam param) +{ + std::shared_ptr *client = TcpModuleMakePtr::GetInstance()->CreateTcpClient(param); + if (nullptr != *client) { + (*client)->Init(); + } + return client; +} +void FreeTcpClient(void *object) +{ + if (TcpClientObjectCheck(object) == true) { + (*(std::shared_ptr *)object)->UnInit(); + (*(std::shared_ptr *)object).reset(); + free(((char *)object) - sizeof(ITcpClientHeader)); // TODO: bug? + } +} +ssize_t TcpClientWrite(void *object, const void *buf, const size_t bufLenght) +{ + if (TcpClientObjectCheck(object) == true) { + return (*(std::shared_ptr *)object)->Write(buf, bufLenght); + } + return -1; } \ No newline at end of file diff --git a/utils/TcpModule/src/TcpModuleImpl.cpp b/utils/TcpModule/src/TcpModuleImpl.cpp index 8d96ffe..85e5619 100644 --- a/utils/TcpModule/src/TcpModuleImpl.cpp +++ b/utils/TcpModule/src/TcpModuleImpl.cpp @@ -15,26 +15,26 @@ #include "TcpModuleImpl.h" #include "ILog.h" #include -static const char *TCP_MODULE_NAME = "tcp_module"; -const char *GetTcpModuleName(void) -{ - return TCP_MODULE_NAME; -} -void *NewTcpModuleImpl(const TcpPram &tcpParam) -{ - if (nullptr == tcpParam.mIp) { - LogError("Parament error, nullptr == tcpParam.mIp\n"); - return nullptr; - } - LogInfo("Create the tcp module object.\n"); - TcpServer *impl = (TcpServer *)malloc(sizeof(TcpServer)); - TcpServer tmp; - memcpy((void *)impl, (void *)&tmp, sizeof(TcpServer)); - impl->mHeader.mCheckName = TCP_MODULE_NAME; - impl->mTcpImpl = std::make_shared(tcpParam); - return (void *)(((char *)impl) + sizeof(TcpModuleHeader)); -} -void *NewTcpServer(const TcpPram &tcpParam) -{ - return nullptr; -} \ No newline at end of file +// static const char *TCP_MODULE_NAME = "tcp_module"; +// const char *GetTcpModuleName(void) +// { +// return TCP_MODULE_NAME; +// } +// void *NewTcpModuleImpl(const TcpParam &tcpParam) +// { +// if (nullptr == tcpParam.mIp) { +// LogError("Parament error, nullptr == tcpParam.mIp\n"); +// return nullptr; +// } +// LogInfo("Create the tcp module object.\n"); +// TcpServer *impl = (TcpServer *)malloc(sizeof(TcpServer)); +// TcpServer tmp; +// memcpy((void *)impl, (void *)&tmp, sizeof(TcpServer)); +// impl->mHeader.mCheckName = TCP_MODULE_NAME; +// impl->mTcpImpl = std::make_shared(tcpParam); +// return (void *)(((char *)impl) + sizeof(TcpModuleHeader)); +// } +// void *NewTcpServer(const TcpParam &tcpParam) +// { +// return nullptr; +// } \ No newline at end of file diff --git a/utils/TcpModule/src/TcpModuleImpl.h b/utils/TcpModule/src/TcpModuleImpl.h index 138441a..6b58fa6 100644 --- a/utils/TcpModule/src/TcpModuleImpl.h +++ b/utils/TcpModule/src/TcpModuleImpl.h @@ -17,36 +17,36 @@ #include "StatusCode.h" #include "TcpModule.h" #include -#define TCP_MODULE_INIT_NAME "UART" -typedef struct tcp_module_header -{ - const char *mCheckName; -} TcpModuleHeader; -class TcpModuleImpl -{ -public: - TcpModuleImpl(const TcpPram &uatrInfo); - virtual ~TcpModuleImpl() = default; +// #define TCP_MODULE_INIT_NAME "UART" +// typedef struct tcp_module_header +// { +// const char *mCheckName; +// } TcpModuleHeader; +// class TcpModuleImpl +// { +// public: +// TcpModuleImpl(const TcpParam &uatrInfo); +// virtual ~TcpModuleImpl() = default; -private: - const StatusCode SetConfig(void); +// private: +// const StatusCode SetConfig(void); -private: - const TcpPram mUatrInfo; - int mFd; -}; +// private: +// const TcpParam mUatrInfo; +// int mFd; +// }; // TODO: There may be a CPU byte alignment bug. -typedef struct tcp_server TcpServer; -typedef struct tcp_server -{ - TcpModuleHeader mHeader; - std::shared_ptr mTcpImpl; -} TcpServer; -void *NewTcpModuleImpl(const TcpPram &tcpParam); -void *NewTcpServer(const TcpPram &tcpParam); -static inline TcpServer *TcpModuleImplConvert(void *object) -{ - return ((TcpServer *)(((char *)object) - sizeof(TcpModuleHeader))); -} -const char *GetTcpModuleName(void); +// typedef struct tcp_server TcpServer; +// typedef struct tcp_server +// { +// TcpModuleHeader mHeader; +// std::shared_ptr mTcpImpl; +// } TcpServer; +// void *NewTcpModuleImpl(const TcpParam &tcpParam); +// void *NewTcpServer(const TcpParam &tcpParam); +// static inline TcpServer *TcpModuleImplConvert(void *object) +// { +// return ((TcpServer *)(((char *)object) - sizeof(TcpModuleHeader))); +// } +// const char *GetTcpModuleName(void); #endif \ No newline at end of file diff --git a/utils/TcpModule/src/TcpServer.h b/utils/TcpModule/src/TcpModuleMakePtr.cpp similarity index 50% rename from utils/TcpModule/src/TcpServer.h rename to utils/TcpModule/src/TcpModuleMakePtr.cpp index f297c00..0c0d2f5 100644 --- a/utils/TcpModule/src/TcpServer.h +++ b/utils/TcpModule/src/TcpModuleMakePtr.cpp @@ -11,4 +11,24 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ \ No newline at end of file + */ +#include "TcpModuleMakePtr.h" +#include "ILog.h" +#include "TcpServerImpl.h" +#include "TcpClientImpl.h" +std::shared_ptr &TcpModuleMakePtr::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) { + instance = *impl; + } + return instance; +} +std::shared_ptr *TcpModuleMakePtr::CreateTcpServer(const TcpParam param) +{ + return NewTcpServer(param); +} +std::shared_ptr *TcpModuleMakePtr::CreateTcpClient(const TcpParam param) +{ + return NewTcpClient(param); +} \ No newline at end of file diff --git a/utils/TcpModule/src/TcpModuleMakePtr.h b/utils/TcpModule/src/TcpModuleMakePtr.h new file mode 100644 index 0000000..78f31bf --- /dev/null +++ b/utils/TcpModule/src/TcpModuleMakePtr.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef TCP_MODULE_MAKE_PTR_H +#define TCP_MODULE_MAKE_PTR_H +#include "StatusCode.h" +#include "TcpModule.h" +#include "ITcpServer.h" +#include "ITcpClient.h" +#include +class TcpModuleMakePtr +{ +public: + TcpModuleMakePtr() = default; + virtual ~TcpModuleMakePtr() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + virtual std::shared_ptr *CreateTcpServer(const TcpParam param); + virtual std::shared_ptr *CreateTcpClient(const TcpParam param); +}; +#endif // !TCP_MODULE_MAKE_PTR_H \ No newline at end of file diff --git a/utils/TcpModule/src/TcpServerHandle.cpp b/utils/TcpModule/src/TcpServerHandle.cpp new file mode 100644 index 0000000..3006dc0 --- /dev/null +++ b/utils/TcpModule/src/TcpServerHandle.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "TcpServerHandle.h" +#include "ILog.h" +std::shared_ptr &TcpServerHandle::GetInstance(std::shared_ptr *impl) +{ + static auto instance = std::make_shared(); + if (impl) { + if (instance.use_count() == 1) { + LogInfo("Instance changed succeed.\n"); + instance = *impl; + } + else { + LogError("Can't changing the instance becase of using by some one.\n"); + } + } + return instance; +} +void TcpServerHandle::AddServer(const int &fd, const std::shared_ptr &server) +{ + LogInfo("AddServer fd = %d\n", fd); + mFd[fd] = server; +} +bool TcpServerHandle::GetServer(const int &fd, std::shared_ptr &server) +{ + auto it = mFd.find(fd); + if (it != mFd.end()) { + server = it->second; + return true; + } + LogError("There no ITcpServer fd = %d\n", fd); + return false; +} \ No newline at end of file diff --git a/utils/TcpModule/src/TcpServer.cpp b/utils/TcpModule/src/TcpServerHandle.h similarity index 52% rename from utils/TcpModule/src/TcpServer.cpp rename to utils/TcpModule/src/TcpServerHandle.h index f297c00..8413bec 100644 --- a/utils/TcpModule/src/TcpServer.cpp +++ b/utils/TcpModule/src/TcpServerHandle.h @@ -11,4 +11,22 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ \ No newline at end of file + */ +#ifndef TCP_SERVER_HANDLE_H +#define TCP_SERVER_HANDLE_H +#include "ITcpServer.h" +#include +#include +class TcpServerHandle +{ +public: + TcpServerHandle() = default; + ~TcpServerHandle() = default; + static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); + void AddServer(const int &fd, const std::shared_ptr &server); + bool GetServer(const int &fd, std::shared_ptr &server); + +private: + std::map> mFd; +}; +#endif \ No newline at end of file diff --git a/utils/TcpModule/src/TcpServerImpl.cpp b/utils/TcpModule/src/TcpServerImpl.cpp new file mode 100644 index 0000000..5a24d54 --- /dev/null +++ b/utils/TcpModule/src/TcpServerImpl.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "TcpServerImpl.h" +#include "ILog.h" +#include "TcpServerHandle.h" +static bool TcpClientAcceptObjectCheck(void *object) +{ + if (nullptr == object) { + LogError("nullptr object!\n"); + return false; + } + if (*((const char **)(((char *)object) - sizeof(ITcpServerHeader))) != GetTcpClientAcceptName()) { + LogError("Illegal object!\n"); + return false; + } + return true; +} +static void on_close(hio_t *io) +{ + LogInfo("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io)); + // std::shared_ptr server; + // if (TcpServerHandle::GetInstance()->GetServer(hio_fd(io), server) == true) { + // std::shared_ptr impl = std::dynamic_pointer_cast(server); + // if (impl != nullptr) { + // impl->ClosedEvent(); + // } + // } +} +static void on_recv(hio_t *io, void *buf, int readbytes) +{ + LogInfo("on_recv fd=%d readbytes=%d\n", hio_fd(io), readbytes); + char localaddrstr[SOCKADDR_STRLEN] = {0}; + char peeraddrstr[SOCKADDR_STRLEN] = {0}; + LogInfo( + "[%s] <=> [%s]\n", SOCKADDR_STR(hio_localaddr(io), localaddrstr), SOCKADDR_STR(hio_peeraddr(io), peeraddrstr)); + LogInfo("< %.*s", readbytes, (char *)buf); + ITcpClientAccept *client = (ITcpClientAccept *)hevent_userdata(io); + client->Readed((const char *)buf, readbytes); + // server->RemoveClient(hio_fd(io)); + // std::shared_ptr server; + // if (TcpServerHandle::GetInstance()->GetServer(hio_fd(io), server) == true) { + // std::shared_ptr impl = std::dynamic_pointer_cast(server); + // if (impl != nullptr) { + // impl->TcpServerReaded(buf, readbytes); + // } + // } + // echo + // LogInfo("> %.*s", readbytes, (char *)buf); + // hio_write(io, buf, readbytes); +} +static void on_accept(hio_t *io) +{ + LogInfo("on_accept connfd=%d\n", hio_fd(io)); + char localaddrstr[SOCKADDR_STRLEN] = {0}; + char peeraddrstr[SOCKADDR_STRLEN] = {0}; + LogInfo("accept connfd=%d [%s] <= [%s]\n", + hio_fd(io), + SOCKADDR_STR(hio_localaddr(io), localaddrstr), + SOCKADDR_STR(hio_peeraddr(io), peeraddrstr)); + + hio_setcb_close(io, on_close); + hio_setcb_read(io, on_recv); + std::shared_ptr *client = NewTcpClientAccept(io); + TcpServerImpl *server = (TcpServerImpl *)hevent_userdata(io); + // std::shared_ptr server; + // if (TcpServerHandle::GetInstance()->GetServer(hio_fd(io), server) == true) { + // std::shared_ptr impl = std::dynamic_pointer_cast(server); + // if (impl != nullptr) { + // impl->SetIo(io); + // } + // } + server->AddClient(io, client); + hevent_set_userdata(io, (*client).get()); + hio_read_start(io); +} +TcpClientAcceptImpl::TcpClientAcceptImpl(const hio_t *io) : mIo(io) +{ +} +void TcpClientAcceptImpl::Readed(const void *data, size_t length) +{ + LogInfo("TcpClientAcceptImpl::Readed\n"); +} +TcpServerImpl::TcpServerImpl(const TcpParam param) : mParam(param) +{ + mLoop = nullptr; + mIo = nullptr; +} +void TcpServerImpl::Init(void) +{ + constexpr int NO_FALGS = 0; + mLoop = hloop_new(NO_FALGS); + if (nullptr == mLoop) { + LogError("hloop_new failed\n"); + return; + } + hio_t *listenio = hloop_create_tcp_server(mLoop, mParam.mIp, mParam.mPort, on_accept); + if (nullptr == listenio) { + LogError("hloop_create_tcp_server failed\n"); + return; + } + LogInfo("listenfd=%d\n", hio_fd(listenio)); + hevent_set_userdata(listenio, this); + mIo = listenio; + std::shared_ptr server = shared_from_this(); + // TcpServerHandle::GetInstance()->AddServer(hio_fd(listenio), server); + std::shared_ptr impl = std::dynamic_pointer_cast(server); + auto recvThread = [](std::shared_ptr tcpServer) { + tcpServer->Loop(); + }; + mTcpServerThread = std::thread(recvThread, impl); +} +void TcpServerImpl::UnInit(void) +{ + LogInfo("UnInit TcpServerImpl\n"); + FreeClients(); + if (nullptr != mLoop) { + LogInfo("Stop loop.\n"); + hloop_stop(mLoop); + } + if (mTcpServerThread.joinable()) { + mTcpServerThread.join(); + } + hloop_free(&mLoop); + mLoop = nullptr; + mIo = nullptr; +} +void TcpServerImpl::TcpServerReaded(const void *buf, size_t length) +{ +} +void TcpServerImpl::TcpServerWrite(const void *buf, size_t length) +{ + if (mIo) { + hio_write(mIo, buf, length); + return; + } + LogError("mIo is null\n"); +} +void TcpServerImpl::ClosedEvent(void) +{ + mLoop = nullptr; + mIo = nullptr; +} +void TcpServerImpl::Loop(void) +{ + if (nullptr == mLoop) { + LogError("mLoop is null\n"); + return; + } + hloop_run(mLoop); +} +void TcpServerImpl::AddClient(hio_t *io, std::shared_ptr *client) +{ + char localaddrstr[SOCKADDR_STRLEN] = {0}; + char peeraddrstr[SOCKADDR_STRLEN] = {0}; + LogInfo("accept connfd=%d [%s] <= [%s]\n", + hio_fd(io), + SOCKADDR_STR(hio_localaddr(io), localaddrstr), + SOCKADDR_STR(hio_peeraddr(io), peeraddrstr)); + mClients[hio_fd(io)] = client; + if (mParam.mAcceptClientFunc) { + mParam.mAcceptClientFunc(client, peeraddrstr); + } +} +void TcpServerImpl::FreeClients(void) +{ + for (auto &client : mClients) { + if (nullptr != client.second) { + // delete client.second; + // client.second = nullptr; + void *object = (void *)client.second; + if (TcpClientAcceptObjectCheck(object) == true) { + // (*(std::shared_ptr *)object)->UnInit(); + (*(std::shared_ptr *)object).reset(); + free(((char *)object) - sizeof(ITcpServerHeader)); // TODO: bug? + } + } + } + // for (auto it = mClients.begin(); it != mClients.end();) { + // // 检查指针是否为空 + // if (it->second != nullptr) { + // // 释放 shared_ptr,这将减少引用计数 + // it->second->reset(); + // // 删除指针 + // delete it->second; + // // 从 map 中删除条目 + // it = mClients.erase(it); + // } + // else { + // // 指针为空,继续迭代 + // ++it; + // } + // } +} +std::shared_ptr *NewTcpServer(const TcpParam param) +{ + LogInfo("Create tcp server object.\n"); + TcpServer *impl = (TcpServer *)malloc(sizeof(TcpServer)); + if (nullptr == impl) { + LogError("NewTcpServer::malloc failed.\n"); + return nullptr; + } + TcpServer tmp; + memcpy((void *)impl, (void *)&tmp, sizeof(TcpServer)); + impl->mHeader.mCheckName = GetTcpServerModuleName(); + impl->mTcpServer = std::make_shared(param); + return (std::shared_ptr *)(((char *)impl) + sizeof(ITcpServerHeader)); +} +std::shared_ptr *NewTcpClientAccept(const hio_t *io) +{ + LogInfo("Create tcp server object.\n"); + TcpClientAccept *impl = (TcpClientAccept *)malloc(sizeof(TcpClientAccept)); + if (nullptr == impl) { + LogError("NewTcpServer::malloc failed.\n"); + return nullptr; + } + TcpClientAccept tmp; + memcpy((void *)impl, (void *)&tmp, sizeof(TcpClientAccept)); + impl->mHeader.mCheckName = GetTcpClientAcceptName(); + impl->mTcpClientAccept = std::make_shared(io); + return (std::shared_ptr *)(((char *)impl) + sizeof(ITcpServerHeader)); +} \ No newline at end of file diff --git a/utils/TcpModule/src/TcpServerImpl.h b/utils/TcpModule/src/TcpServerImpl.h new file mode 100644 index 0000000..3db698c --- /dev/null +++ b/utils/TcpModule/src/TcpServerImpl.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef TCP_SERVER_IMPL_H +#define TCP_SERVER_IMPL_H +#include "ITcpServer.h" +#include "TcpModule.h" +#include "hloop.h" +#include "hsocket.h" +#include "hssl.h" +#include +#include +class TcpClientAcceptImpl : public ITcpClientAccept +{ +public: + TcpClientAcceptImpl(const hio_t *io); + virtual ~TcpClientAcceptImpl() = default; + void Readed(const void *data, size_t length) override; + +private: + const hio_t *mIo; +}; +class TcpServerImpl : public ITcpServer, public std::enable_shared_from_this +{ +public: + TcpServerImpl(const TcpParam param); + virtual ~TcpServerImpl() = default; + void Init(void) override; + void UnInit(void) override; + void TcpServerReaded(const void *buf, size_t length); + void TcpServerWrite(const void *buf, size_t length); + void ClosedEvent(void); + void Loop(void); + void AddClient(hio_t *io, std::shared_ptr *client); + void FreeClients(void); + +private: + hloop_t *mLoop; + hio_t *mIo; + const TcpParam mParam; + std::thread mTcpServerThread; + std::map *> mClients; +}; +std::shared_ptr *NewTcpServer(const TcpParam param); +std::shared_ptr *NewTcpClientAccept(const hio_t *io); +#endif \ No newline at end of file