mirror of
https://github.com/ZmnSCPxj/clboss.git
synced 2026-08-15 12:50:42 +02:00
105 lines
3 KiB
C++
105 lines
3 KiB
C++
#include"Boss/Mod/InitialConnect.hpp"
|
|
#include"Boss/Mod/Rpc.hpp"
|
|
#include"Boss/Msg/Init.hpp"
|
|
#include"Boss/Msg/NeedsConnect.hpp"
|
|
#include"Boss/Msg/Timer10Minutes.hpp"
|
|
#include"Boss/concurrent.hpp"
|
|
#include"Boss/log.hpp"
|
|
#include"Ev/Io.hpp"
|
|
#include"Jsmn/Object.hpp"
|
|
#include"Json/Out.hpp"
|
|
#include"S/Bus.hpp"
|
|
#include<assert.h>
|
|
|
|
namespace Boss { namespace Mod {
|
|
|
|
void InitialConnect::start() {
|
|
bus.subscribe<Boss::Msg::Init>([this](Boss::Msg::Init const& init) {
|
|
rpc = &init.rpc;
|
|
bus.subscribe<Boss::Msg::Timer10Minutes>([this](Boss::Msg::Timer10Minutes const& _) {
|
|
return periodic_check();
|
|
});
|
|
return init_check();
|
|
});
|
|
}
|
|
|
|
Ev::Io<void> InitialConnect::init_check() {
|
|
return Ev::lift().then([this]() {
|
|
assert(rpc);
|
|
return rpc->command("listpeers", Json::Out().start_object().end_object());
|
|
}).then([this](Jsmn::Object result) {
|
|
if (result.is_object() && result.has("peers")) {
|
|
auto peers = result["peers"];
|
|
if (peers.is_array()) {
|
|
for (size_t i = 0; i < peers.size(); ++i) {
|
|
auto peer = peers[i];
|
|
if (!(peer.is_object() && peer.has("channels")))
|
|
continue;
|
|
auto channels = peer["channels"];
|
|
if (!channels.is_array())
|
|
continue;
|
|
for (size_t j = 0; j < channels.size(); ++j) {
|
|
auto channel = channels[j];
|
|
if (!(channel.is_object() && channel.has("state")))
|
|
continue;
|
|
auto state = channel["state"];
|
|
if (!state.is_string())
|
|
continue;
|
|
auto state_s = std::string(state);
|
|
if ( state_s == "CHANNELD_AWAITING_LOCKIN"
|
|
|| state_s == "CHANNELD_NORMAL"
|
|
|| state_s == "CHANNELD_SHUTTING_DOWN"
|
|
)
|
|
return Ev::lift();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If we got through all the peers and none of them
|
|
* are CHANNELD_*, then it is likely lightningd will
|
|
* not connect to anyone, so we should try adding
|
|
* more connections. */
|
|
return needs_connect("No peers with live channels.");
|
|
});
|
|
}
|
|
|
|
Ev::Io<void> InitialConnect::periodic_check() {
|
|
return Ev::lift().then([this]() {
|
|
assert(rpc);
|
|
return rpc->command("listpeers", Json::Out().start_object().end_object());
|
|
}).then([this](Jsmn::Object result) {
|
|
if (result.is_object() && result.has("peers")) {
|
|
auto peers = result["peers"];
|
|
if (peers.is_array()) {
|
|
for (size_t i = 0; i < peers.size(); ++i) {
|
|
auto peer = peers[i];
|
|
if (!(peer.is_object() && peer.has("connected")))
|
|
continue;
|
|
auto connected = peer["connected"];
|
|
if ( connected.is_boolean()
|
|
&& bool(connected)
|
|
)
|
|
/* At least one connected peer. */
|
|
return Ev::lift();
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If we got through all the peers and none of them
|
|
* are connected, we should probably try adding more
|
|
* connections. */
|
|
return needs_connect("No connected peers.");
|
|
});
|
|
}
|
|
|
|
Ev::Io<void> InitialConnect::needs_connect(std::string reason) {
|
|
return Boss::log( bus, Debug
|
|
, "InitialConnect: Needs connect: %s"
|
|
, reason.c_str()
|
|
).then([this]() {
|
|
return Boss::concurrent(bus.raise(Boss::Msg::NeedsConnect()));
|
|
});
|
|
}
|
|
|
|
}}
|