/* * 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 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 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 != 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 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 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 *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 *objectThis = (std::shared_ptr *)(((char *)impl) + sizeof(ITcpClientHeader)); impl->mTcpClient = std::make_shared(param, objectThis); return objectThis; }