mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2025-02-20 15:14:26 +01:00
211 lines
5.7 KiB
C++
211 lines
5.7 KiB
C++
#pragma once
|
|
|
|
#include <brynet/net/AsyncConnector.hpp>
|
|
#include <brynet/net/Exception.hpp>
|
|
#include <brynet/net/TcpService.hpp>
|
|
#include <future>
|
|
#include <utility>
|
|
|
|
namespace brynet { namespace net { namespace wrapper {
|
|
|
|
using CompletedCallback = detail::AsyncConnectAddr::CompletedCallback;
|
|
using ProcessTcpSocketCallback = detail::AsyncConnectAddr::ProcessTcpSocketCallback;
|
|
using FailedCallback = detail::AsyncConnectAddr::FailedCallback;
|
|
|
|
template<typename Derived>
|
|
class BaseSocketConnectBuilder
|
|
{
|
|
public:
|
|
virtual ~BaseSocketConnectBuilder() = default;
|
|
|
|
Derived& WithConnector(AsyncConnector::Ptr connector)
|
|
{
|
|
mConnector = std::move(connector);
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
Derived& WithAddr(std::string ip, size_t port)
|
|
{
|
|
mConnectOption.ip = std::move(ip);
|
|
mConnectOption.port = port;
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
Derived& WithTimeout(std::chrono::nanoseconds timeout)
|
|
{
|
|
mConnectOption.timeout = timeout;
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
Derived& AddSocketProcessCallback(const ProcessTcpSocketCallback& callback)
|
|
{
|
|
mConnectOption.processCallbacks.push_back(callback);
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
Derived& WithCompletedCallback(CompletedCallback callback)
|
|
{
|
|
mConnectOption.completedCallback = std::move(callback);
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
Derived& WithFailedCallback(FailedCallback callback)
|
|
{
|
|
mConnectOption.failedCallback = std::move(callback);
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
void asyncConnect() const
|
|
{
|
|
if (mConnector == nullptr)
|
|
{
|
|
throw BrynetCommonException("connector is nullptr");
|
|
}
|
|
if (mConnectOption.ip.empty())
|
|
{
|
|
throw BrynetCommonException("address is empty");
|
|
}
|
|
|
|
mConnector->asyncConnect(mConnectOption);
|
|
}
|
|
|
|
TcpSocket::Ptr syncConnect()
|
|
{
|
|
if (mConnectOption.completedCallback != nullptr || mConnectOption.failedCallback != nullptr)
|
|
{
|
|
throw std::runtime_error("already setting completed callback or failed callback");
|
|
}
|
|
|
|
auto socketPromise = std::make_shared<std::promise<TcpSocket::Ptr>>();
|
|
mConnectOption.completedCallback = [socketPromise](TcpSocket::Ptr socket) {
|
|
socketPromise->set_value(std::move(socket));
|
|
};
|
|
mConnectOption.failedCallback = [socketPromise]() {
|
|
socketPromise->set_value(nullptr);
|
|
};
|
|
|
|
asyncConnect();
|
|
|
|
auto future = socketPromise->get_future();
|
|
if (future.wait_for(mConnectOption.timeout) != std::future_status::ready)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
return future.get();
|
|
}
|
|
|
|
private:
|
|
AsyncConnector::Ptr mConnector;
|
|
ConnectOption mConnectOption;
|
|
};
|
|
|
|
class SocketConnectBuilder : public BaseSocketConnectBuilder<SocketConnectBuilder>
|
|
{
|
|
};
|
|
|
|
template<typename Derived>
|
|
class BaseConnectionBuilder
|
|
{
|
|
public:
|
|
Derived& WithService(TcpService::Ptr service)
|
|
{
|
|
mTcpService = std::move(service);
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
Derived& WithConnector(AsyncConnector::Ptr connector)
|
|
{
|
|
mConnectBuilder.WithConnector(std::move(connector));
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
Derived& WithAddr(std::string ip, size_t port)
|
|
{
|
|
mConnectBuilder.WithAddr(std::move(ip), port);
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
Derived& WithTimeout(std::chrono::nanoseconds timeout)
|
|
{
|
|
mConnectBuilder.WithTimeout(timeout);
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
Derived& AddSocketProcessCallback(const ProcessTcpSocketCallback& callback)
|
|
{
|
|
mConnectBuilder.AddSocketProcessCallback(callback);
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
Derived& WithFailedCallback(FailedCallback callback)
|
|
{
|
|
mConnectBuilder.WithFailedCallback(std::move(callback));
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
Derived& WithMaxRecvBufferSize(size_t size)
|
|
{
|
|
mOption.maxRecvBufferSize = size;
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
#ifdef BRYNET_USE_OPENSSL
|
|
Derived& WithSSL()
|
|
{
|
|
mOption.useSSL = true;
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
#endif
|
|
Derived& WithForceSameThreadLoop()
|
|
{
|
|
mOption.forceSameThreadLoop = true;
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
Derived& AddEnterCallback(const TcpConnection::EnterCallback& callback)
|
|
{
|
|
mOption.enterCallback.push_back(callback);
|
|
return static_cast<Derived&>(*this);
|
|
}
|
|
|
|
void asyncConnect()
|
|
{
|
|
auto service = mTcpService;
|
|
auto option = mOption;
|
|
mConnectBuilder.WithCompletedCallback([service, option](TcpSocket::Ptr socket) mutable {
|
|
service->addTcpConnection(std::move(socket), option);
|
|
});
|
|
|
|
mConnectBuilder.asyncConnect();
|
|
}
|
|
|
|
TcpConnection::Ptr syncConnect()
|
|
{
|
|
auto sessionPromise = std::make_shared<std::promise<TcpConnection::Ptr>>();
|
|
|
|
auto option = mOption;
|
|
option.enterCallback.push_back([sessionPromise](const TcpConnection::Ptr& session) {
|
|
sessionPromise->set_value(session);
|
|
});
|
|
|
|
auto socket = mConnectBuilder.syncConnect();
|
|
if (socket == nullptr || !mTcpService->addTcpConnection(std::move(socket), option))
|
|
{
|
|
return nullptr;
|
|
}
|
|
return sessionPromise->get_future().get();
|
|
}
|
|
|
|
private:
|
|
TcpService::Ptr mTcpService;
|
|
ConnectionOption mOption;
|
|
SocketConnectBuilder mConnectBuilder;
|
|
};
|
|
|
|
class ConnectionBuilder : public BaseConnectionBuilder<ConnectionBuilder>
|
|
{
|
|
};
|
|
|
|
}}}// namespace brynet::net::wrapper
|