mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-21 01:01:43 +00:00
This is a libuv-based parallel, repeating TCP connector for making multiple parallel DNS resolution and TCP connection attempts to a network server.
120 lines
3.7 KiB
C++
120 lines
3.7 KiB
C++
// Copyright (c) FIRST and other WPILib contributors.
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
// the WPILib BSD license file in the root directory of this project.
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "wpi/span.h"
|
|
#include "wpi/uv/Timer.h"
|
|
|
|
namespace wpi {
|
|
|
|
class Logger;
|
|
|
|
namespace uv {
|
|
class GetAddrInfoReq;
|
|
class Loop;
|
|
class Tcp;
|
|
class Timer;
|
|
} // namespace uv
|
|
|
|
/**
|
|
* Parallel TCP connector. Attempts parallel resolution and connection to
|
|
* multiple servers with automatic retry if none connect.
|
|
*
|
|
* Each successful TCP connection results in a call to the connected callback.
|
|
* For correct operation, the consuming code (either the connected callback or
|
|
* e.g. task it starts) must call Succeeded() to indicate if the connection has
|
|
* succeeded prior to the reconnect rate timeout. A successful connection
|
|
* results in the connector terminating all other connection attempts.
|
|
*
|
|
* After the reconnect rate times out, all remaining active connection attempts
|
|
* are canceled and new ones started.
|
|
*/
|
|
class ParallelTcpConnector
|
|
: public std::enable_shared_from_this<ParallelTcpConnector> {
|
|
struct private_init {};
|
|
|
|
public:
|
|
/**
|
|
* Create.
|
|
*
|
|
* @param loop loop
|
|
* @param reconnectRate how long to wait after starting connection attempts
|
|
* to cancel and attempt connecting again
|
|
* @param logger logger
|
|
* @param connected callback function when a connection succeeds; may be
|
|
* called multiple times if it does not call Succeeded()
|
|
* before returning
|
|
* @return Parallel connector
|
|
*/
|
|
static std::shared_ptr<ParallelTcpConnector> Create(
|
|
wpi::uv::Loop& loop, wpi::uv::Timer::Time reconnectRate,
|
|
wpi::Logger& logger, std::function<void(wpi::uv::Tcp& tcp)> connected) {
|
|
return std::make_shared<ParallelTcpConnector>(
|
|
loop, reconnectRate, logger, std::move(connected), private_init{});
|
|
}
|
|
|
|
ParallelTcpConnector(wpi::uv::Loop& loop, wpi::uv::Timer::Time reconnectRate,
|
|
wpi::Logger& logger,
|
|
std::function<void(wpi::uv::Tcp& tcp)> connected,
|
|
const private_init&);
|
|
~ParallelTcpConnector();
|
|
|
|
ParallelTcpConnector(const ParallelTcpConnector&) = delete;
|
|
ParallelTcpConnector& operator=(const ParallelTcpConnector&) = delete;
|
|
|
|
/**
|
|
* Closes resources, canceling all pending action attempts.
|
|
*/
|
|
void Close();
|
|
|
|
/**
|
|
* Changes the servers/ports to connect to. Starts connection attempts if not
|
|
* already connected.
|
|
*
|
|
* @param servers array of server/port pairs
|
|
*/
|
|
void SetServers(
|
|
wpi::span<const std::pair<std::string, unsigned int>> servers);
|
|
|
|
/**
|
|
* Tells the parallel connector that the current connection has terminated and
|
|
* it is necessary to start reconnection attempts.
|
|
*/
|
|
void Disconnected();
|
|
|
|
/**
|
|
* Tells the parallel connector that a particular connection has succeeded and
|
|
* it should stop trying to connect.
|
|
*
|
|
* @param tcp connection passed to connected callback
|
|
*/
|
|
void Succeeded(wpi::uv::Tcp& tcp);
|
|
|
|
private:
|
|
bool IsConnected() const { return m_isConnected || m_servers.empty(); }
|
|
void Connect();
|
|
void CancelAll(wpi::uv::Tcp* except = nullptr);
|
|
|
|
wpi::uv::Loop& m_loop;
|
|
wpi::Logger& m_logger;
|
|
wpi::uv::Timer::Time m_reconnectRate;
|
|
std::function<void(wpi::uv::Tcp& tcp)> m_connected;
|
|
std::shared_ptr<wpi::uv::Timer> m_reconnectTimer;
|
|
std::vector<std::pair<std::string, unsigned int>> m_servers;
|
|
std::vector<std::weak_ptr<wpi::uv::GetAddrInfoReq>> m_resolvers;
|
|
std::vector<std::weak_ptr<wpi::uv::Tcp>> m_attempts;
|
|
bool m_isConnected{false};
|
|
};
|
|
|
|
} // namespace wpi
|