2018-12-31 20:04:05 +01:00
|
|
|
//
|
2018-01-02 14:42:31 +01:00
|
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
2018-12-31 20:04:05 +01:00
|
|
|
//
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
//
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "td/actor/actor.h"
|
|
|
|
#include "td/actor/PromiseFuture.h"
|
|
|
|
|
|
|
|
#include "td/telegram/net/NetType.h"
|
|
|
|
|
|
|
|
#include "td/utils/common.h"
|
|
|
|
|
|
|
|
namespace td {
|
|
|
|
class StateManager final : public Actor {
|
|
|
|
public:
|
|
|
|
enum class State : int32 { WaitingForNetwork, ConnectingToProxy, Connecting, Updating, Ready, Empty };
|
|
|
|
|
|
|
|
class Callback {
|
|
|
|
public:
|
|
|
|
Callback() = default;
|
|
|
|
Callback(const Callback &) = delete;
|
|
|
|
Callback &operator=(const Callback &) = delete;
|
|
|
|
virtual ~Callback() = default;
|
|
|
|
virtual bool on_state(State state) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
virtual bool on_network(NetType network_type, uint32 generation) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
virtual bool on_online(bool is_online) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void on_synchronized(bool is_synchronized);
|
|
|
|
|
|
|
|
void on_network(NetType new_network_type);
|
|
|
|
|
|
|
|
void on_online(bool is_online);
|
|
|
|
|
|
|
|
void on_proxy(bool use_proxy);
|
|
|
|
|
|
|
|
void add_callback(unique_ptr<Callback> net_callback);
|
|
|
|
|
|
|
|
void wait_first_sync(Promise<> promise);
|
|
|
|
|
|
|
|
void close();
|
|
|
|
|
|
|
|
class ConnectionToken {
|
|
|
|
public:
|
|
|
|
ConnectionToken() = default;
|
|
|
|
explicit ConnectionToken(ActorShared<StateManager> state_manager) : state_manager_(std::move(state_manager)) {
|
|
|
|
}
|
|
|
|
ConnectionToken(const ConnectionToken &) = delete;
|
|
|
|
ConnectionToken &operator=(const ConnectionToken &) = delete;
|
|
|
|
ConnectionToken(ConnectionToken &&) = default;
|
|
|
|
ConnectionToken &operator=(ConnectionToken &&other) {
|
|
|
|
reset();
|
|
|
|
state_manager_ = std::move(other.state_manager_);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
~ConnectionToken() {
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset() {
|
|
|
|
if (!state_manager_.empty()) {
|
|
|
|
send_closure(state_manager_, &StateManager::dec_connect);
|
|
|
|
state_manager_.reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool empty() const {
|
|
|
|
return state_manager_.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
ActorShared<StateManager> state_manager_;
|
|
|
|
};
|
|
|
|
|
|
|
|
static ConnectionToken connection(ActorId<StateManager> state_manager) {
|
|
|
|
return connection_impl(state_manager, 1);
|
|
|
|
}
|
|
|
|
static ConnectionToken connection_proxy(ActorId<StateManager> state_manager) {
|
|
|
|
return connection_impl(state_manager, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint32 connect_cnt_ = 0;
|
|
|
|
uint32 connect_proxy_cnt_ = 0;
|
|
|
|
bool sync_flag_ = true;
|
|
|
|
bool network_flag_ = true;
|
|
|
|
NetType network_type_ = NetType::Unknown;
|
|
|
|
uint32 network_generation_ = 1;
|
|
|
|
bool online_flag_ = false;
|
|
|
|
bool use_proxy_ = false;
|
|
|
|
|
|
|
|
static constexpr double UP_DELAY = 0.05;
|
|
|
|
static constexpr double DOWN_DELAY = 0.3;
|
|
|
|
|
|
|
|
State pending_state_ = State::Empty;
|
|
|
|
bool has_timestamp_ = false;
|
|
|
|
double pending_timestamp_ = 0;
|
|
|
|
State flush_state_ = State::Empty;
|
|
|
|
|
|
|
|
vector<unique_ptr<Callback>> callbacks_;
|
|
|
|
|
|
|
|
bool was_sync_ = false;
|
|
|
|
std::vector<Promise<>> wait_first_sync_;
|
|
|
|
|
|
|
|
void inc_connect();
|
|
|
|
void dec_connect();
|
|
|
|
|
2018-04-19 15:08:30 +02:00
|
|
|
enum class Flag : int32 { Online, State, Network };
|
|
|
|
void notify_flag(Flag flag);
|
2018-12-31 20:04:05 +01:00
|
|
|
|
|
|
|
void start_up() override;
|
|
|
|
void loop() override;
|
|
|
|
|
|
|
|
void on_network_soft();
|
|
|
|
void do_on_network(NetType new_network_type, bool inc_generation);
|
|
|
|
|
|
|
|
State get_real_state() const;
|
|
|
|
|
|
|
|
static ConnectionToken connection_impl(ActorId<StateManager> state_manager, int mode) {
|
|
|
|
auto actor = ActorShared<StateManager>(state_manager, mode);
|
|
|
|
send_closure(actor, &StateManager::inc_connect);
|
|
|
|
return ConnectionToken(std::move(actor));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace td
|