/** .============.* // M A K E / \* // C++ DEV / \* // E A S Y / \/ \* ++ ----------. \/\ .* \\ \ \ /\ /* \\ \ \ /* \\ \ \ /* -============'** Copyright (c) 2018 Hevake and contributors, all rights reserved.** This file is part of cpp-tbox (https://github.com/cpp-main/cpp-tbox)* Use of this source code is governed by MIT license that can be found* in the LICENSE file in the root of the source tree. All contributing* project authors may be found in the CONTRIBUTORS.md file in the root* of the source tree.*/#include "tcp_client.h"#include <tbox/base/log.h>#include <tbox/base/assert.h>#include <tbox/base/defines.h>#include <tbox/base/wrapped_recorder.h>#include "tcp_connector.h"#include "tcp_connection.h"#include "tcp_factory.h"#include "tcp_raw_factory.h"#include "tls_factory_entry.h"#undef MODULE_ID#define MODULE_ID "tbox.tcp"namespace tbox {namespace network {struct TcpClient::Data {event::Loop *wp_loop;State state = State::kNone;ConnectedCallback connected_cb;DisconnectedCallback disconnected_cb;ReceiveCallback received_cb;size_t received_threshold = 0;SendCompleteCallback send_complete_cb;ByteStream *wp_receiver = nullptr;bool reconnect_enabled = true;TcpFactory *sp_factory = nullptr;TcpConnector *sp_connector = nullptr;TcpConnection *sp_connection = nullptr;int cb_level = 0;};TcpClient::TcpClient(event::Loop *wp_loop): d_(new Data){TBOX_ASSERT(d_ != nullptr);d_->wp_loop = wp_loop;d_->sp_factory = new TcpRawFactory;d_->sp_connector = d_->sp_factory->createConnector(wp_loop);}TcpClient::~TcpClient(){TBOX_ASSERT(d_->cb_level == 0);cleanup();CHECK_DELETE_RESET_OBJ(d_->sp_connection);CHECK_DELETE_RESET_OBJ(d_->sp_connector);CHECK_DELETE_RESET_OBJ(d_->sp_factory);delete d_;}bool TcpClient::setTlsConfig(const TlsConfig &config){if (d_->state != State::kNone) {LogWarn("cannot set TLS config after initialization");return false;}if (!config.isValid()) {LogWarn("invalid TLS config");return false;}//! 替换 factory 和 connectorTcpFactory *tls_factory = CreateTlsFactory(TlsRole::kClient, config);if (tls_factory == nullptr) {LogWarn("failed to create TLS factory, TLS module may not be linked");return false;}if (!tls_factory->initialize()) {LogWarn("failed init TLS factory, config may invalid");delete tls_factory;return false;}CHECK_DELETE_RESET_OBJ(d_->sp_connector);CHECK_DELETE_RESET_OBJ(d_->sp_factory);d_->sp_factory = tls_factory;d_->sp_connector = d_->sp_factory->createConnector(d_->wp_loop);return true;}bool TcpClient::initialize(const SockAddr &server_addr){if (d_->state != State::kNone) {LogWarn("not in none state, cleanup first.");return false;}using namespace std::placeholders;d_->sp_connector->initialize(server_addr);d_->sp_connector->setConnectedCallback(std::bind(&TcpClient::onTcpConnected, this, _1));d_->state = State::kInited;return true;}void TcpClient::setConnectedCallback(const ConnectedCallback &cb){d_->connected_cb = cb;}void TcpClient::setDisconnectedCallback(const DisconnectedCallback &cb){d_->disconnected_cb = cb;}void TcpClient::setAutoReconnect(bool enable){d_->reconnect_enabled = enable;}void TcpClient::setReconnectDelayCalcFunc(const ReconnectDelayCalc &func){d_->sp_connector->setReconnectDelayCalcFunc(func);}bool TcpClient::start(){if (d_->state != State::kInited) {LogWarn("not in idle state, initialize or stop first");return false;}d_->state = State::kConnecting;return d_->sp_connector->start();}void TcpClient::stop(){if (d_->state == State::kConnecting) {d_->state = State::kInited;d_->sp_connector->stop();} else if (d_->state == State::kConnected) {TcpConnection *tobe_delete = nullptr;std::swap(tobe_delete, d_->sp_connection);tobe_delete->disconnect();d_->wp_loop->runNext([tobe_delete] { delete tobe_delete; },"TcpClient::stop, delete");d_->state = State::kInited;}}bool TcpClient::shutdown(int howto){if (d_->state == State::kConnected)return d_->sp_connection->shutdown(howto);return false;}void TcpClient::cleanup(){if (d_->state <= State::kNone)return;stop();d_->sp_connector->cleanup();d_->connected_cb = nullptr;d_->disconnected_cb = nullptr;d_->received_cb = nullptr;d_->received_threshold = 0;d_->send_complete_cb = nullptr;d_->wp_receiver = nullptr;d_->reconnect_enabled = true;d_->state = State::kNone;}TcpClient::State TcpClient::state() const{return d_->state;}void TcpClient::setReceiveCallback(const ReceiveCallback &cb, size_t threshold){if (d_->sp_connection != nullptr)d_->sp_connection->setReceiveCallback(cb, threshold);d_->received_cb = cb;d_->received_threshold = threshold;}void TcpClient::setSendCompleteCallback(const SendCompleteCallback &cb){if (d_->sp_connection != nullptr)d_->sp_connection->setSendCompleteCallback(cb);d_->send_complete_cb = cb;}bool TcpClient::send(const void *data_ptr, size_t data_size){if (d_->sp_connection != nullptr)return d_->sp_connection->send(data_ptr, data_size);return false;}void TcpClient::bind(ByteStream *receiver){if (d_->sp_connection != nullptr)d_->sp_connection->bind(receiver);d_->wp_receiver = receiver;}void TcpClient::unbind(){if (d_->sp_connection != nullptr)d_->sp_connection->unbind();d_->wp_receiver = nullptr;}Buffer* TcpClient::getReceiveBuffer(){if (d_->sp_connection != nullptr)return d_->sp_connection->getReceiveBuffer();return nullptr;}void TcpClient::onTcpConnected(TcpConnection *new_conn){RECORD_SCOPE();new_conn->setDisconnectedCallback(std::bind(&TcpClient::onTcpDisconnected, this));new_conn->setReceiveCallback(d_->received_cb, d_->received_threshold);new_conn->setSendCompleteCallback(d_->send_complete_cb);if (d_->wp_receiver != nullptr)new_conn->bind(d_->wp_receiver);//! 可以直接释放,因为本函数一定是 d_->sp_connector 对象调用的CHECK_DELETE_RESET_OBJ(d_->sp_connection);d_->sp_connection = new_conn;d_->state = State::kConnected;if (d_->connected_cb) {RECORD_SCOPE();++d_->cb_level;d_->connected_cb();--d_->cb_level;}}void TcpClient::onTcpDisconnected(){RECORD_SCOPE();TcpConnection *tobe_delete = nullptr;std::swap(tobe_delete, d_->sp_connection);//! 这里要使用延后释放,因为本函数一定是 d_->sp_connection 对象自己调用的d_->wp_loop->runNext([tobe_delete] { delete tobe_delete; },"TcpClient::onTcpDisconnected, delete");d_->state = State::kInited;if (d_->reconnect_enabled)start();if (d_->disconnected_cb) {RECORD_SCOPE();++d_->cb_level;d_->disconnected_cb();--d_->cb_level;}}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型