128 lines
3.9 KiB
C++
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 ¶m, 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 ¶m)
|
|
{
|
|
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;
|
|
} |