hunting/utils/TcpModule/src/TcpClientImpl.cpp
2024-04-12 20:10:13 +08:00

128 lines
3.9 KiB
C++

/*
* 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 <cstring>
static void on_message(hio_t *io, void *buf, int len)
{
LogInfo("onmessage: %.*s\n", len, (char *)buf);
TcpClientImpl *tcpClient = (TcpClientImpl *)hevent_userdata(io);
tcpClient->Readed(buf, len);
}
static void on_connect(hio_t *io)
{
LogInfo("onconnect: connfd=%d\n", hio_fd(io));
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 *tcpClient = (TcpClientImpl *)hevent_userdata(io);
tcpClient->Closed();
}
TcpClientImpl::TcpClientImpl(const TcpClientParam &param, const void *object) : mParam(param), mObjectThis(object)
{
}
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<TcpClientImpl> impl = std::dynamic_pointer_cast<TcpClientImpl>(shared_from_this());
auto recvThread = [](std::shared_ptr<TcpClientImpl> tcpClient) {
tcpClient->Loop();
};
mTcpClientThread = std::thread(recvThread, impl);
}
void TcpClientImpl::UnInit(void)
{
if (nullptr != mIo) {
LogInfo("Close io.\n");
hio_close(mIo);
mIo = nullptr;
}
if (mTcpClientThread.joinable()) {
mTcpClientThread.join();
}
}
void TcpClientImpl::Readed(const void *data, size_t length)
{
if (nullptr != mParam.mReadFunc) {
mParam.mReadFunc(data, length, nullptr);
return;
}
LogError("mParam.mReadFunc is nullptr.\n");
}
ssize_t TcpClientImpl::Write(const void *buf, const size_t bufLenght)
{
std::lock_guard<std::mutex> locker(mMutex);
if (nullptr == mIo) {
LogError("mIo is nullptr.\n");
return TCP_MODULE_WRITE_ERROR;
}
return hio_write(mIo, buf, bufLenght);
}
void TcpClientImpl::Closed(void)
{
std::lock_guard<std::mutex> locker(mMutex);
mIo = nullptr;
if (nullptr != mParam.mClosedFunc) {
mParam.mClosedFunc(mObjectThis);
}
if (nullptr != mLoop) {
LogInfo("Stop loop.\n");
hloop_stop(mLoop);
}
}
void TcpClientImpl::Loop(void)
{
if (nullptr == mLoop) {
LogError("mLoop is null\n");
return;
}
hloop_run(mLoop);
hloop_free(&mLoop);
mLoop = nullptr;
}
std::shared_ptr<ITcpClient> *NewTcpClient(const TcpClientParam &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();
std::shared_ptr<ITcpClient> *objectThis =
(std::shared_ptr<ITcpClient> *)(((char *)impl) + sizeof(ITcpClientHeader));
impl->mTcpClient = std::make_shared<TcpClientImpl>(param, objectThis);
return objectThis;
}