#pragma once #include #include #include #include namespace brynet { namespace net { namespace wrapper { template class BaseSocketConnectBuilder { protected: using AddSocketOptionFunc = detail::AddSocketOptionFunc; using ConnectOptionFunc = detail::ConnectOptionFunc; public: virtual ~BaseSocketConnectBuilder() = default; Derived& configureConnector(AsyncConnector::Ptr connector) { mConnector = std::move(connector); return static_cast(*this); } Derived& configureConnectOptions( std::vector options) { mConnectOptions = std::move(options); return static_cast(*this); } void asyncConnect() const { asyncConnect(mConnectOptions); } TcpSocket::Ptr syncConnect() const { return syncConnect(mConnectOptions); } protected: void asyncConnect(std::vector connectOptions) const { if (mConnector == nullptr) { throw BrynetCommonException("connector is nullptr"); } if (connectOptions.empty()) { throw BrynetCommonException("options is empty"); } mConnector->asyncConnect(connectOptions); } TcpSocket::Ptr syncConnect(std::vector connectOptions) const { auto timeout = ConnectOption::ExtractTimeout(connectOptions); auto socketPromise = std::make_shared>(); connectOptions.push_back(ConnectOption::WithCompletedCallback( [socketPromise](TcpSocket::Ptr socket) { socketPromise->set_value(std::move(socket)); })); connectOptions.push_back(ConnectOption::WithFailedCallback([socketPromise]() { socketPromise->set_value(nullptr); })); asyncConnect(connectOptions); auto future = socketPromise->get_future(); if (future.wait_for(timeout) != std::future_status::ready) { return nullptr; } return future.get(); } std::vector getConnectOptions() const { return mConnectOptions; } private: AsyncConnector::Ptr mConnector; std::vector mConnectOptions; }; class SocketConnectBuilder : public BaseSocketConnectBuilder { }; template class BaseConnectionBuilder : public BaseSocketConnectBuilder { protected: using AddSocketOptionFunc = detail::AddSocketOptionFunc; using ConnectOptionFunc = detail::ConnectOptionFunc; public: Derived& configureService(TcpService::Ptr service) { mTcpService = std::move(service); return static_cast(*this); } Derived& configureConnectionOptions(std::vector options) { mConnectionOptions = std::move(options); return static_cast(*this); } void asyncConnect() const { asyncConnect(BaseSocketConnectBuilder::getConnectOptions(), mConnectionOptions); } TcpConnection::Ptr syncConnect() const { return syncConnect(BaseSocketConnectBuilder::getConnectOptions(), mConnectionOptions); } protected: void asyncConnect(std::vector connectOptions, std::vector connectionOptions) const { if (mTcpService == nullptr) { throw BrynetCommonException("tcp serviceis nullptr"); } if (connectionOptions.empty()) { throw BrynetCommonException("options is empty"); } auto service = mTcpService; auto enterCallback = [service, connectionOptions](TcpSocket::Ptr socket) mutable { service->addTcpConnection(std::move(socket), connectionOptions); }; connectOptions.push_back(ConnectOption::WithCompletedCallback(enterCallback)); BaseSocketConnectBuilder::asyncConnect(connectOptions); } TcpConnection::Ptr syncConnect(std::vector connectOptions, std::vector connectionOptions) const { auto timeout = ConnectOption::ExtractTimeout(connectOptions); auto sessionPromise = std::make_shared>(); connectOptions.push_back(ConnectOption::WithFailedCallback( [sessionPromise]() { sessionPromise->set_value(nullptr); })); connectionOptions.push_back(AddSocketOption::AddEnterCallback( [sessionPromise](const TcpConnection::Ptr& session) { sessionPromise->set_value(session); })); asyncConnect(connectOptions, connectionOptions); auto future = sessionPromise->get_future(); if (future.wait_for(timeout) != std::future_status::ready) { return nullptr; } return future.get(); } std::vector getConnectionOptions() const { return mConnectionOptions; } private: TcpService::Ptr mTcpService; std::vector mConnectionOptions; }; class ConnectionBuilder : public BaseConnectionBuilder { }; } } }