New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor router code #728
Refactor router code #728
Conversation
llarp/link/link_manager.cpp
Outdated
{ | ||
{ | ||
util::Lock l(&_mutex); | ||
if (stopping) return nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't need to lock to check an atomic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed.
llarp/link/link_manager.cpp
Outdated
LinkManager::SendTo(const RouterID& remote, const llarp_buffer_t& buf) | ||
{ | ||
{ | ||
util::Lock l(&_mutex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lock again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed.
llarp/link/link_manager.cpp
Outdated
if (!stopping) | ||
{ | ||
LogInfo("stopping links"); | ||
stopping.store(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stopping = true;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed.
{ | ||
DoCallback(msg.second, SendStatus::Success); | ||
} | ||
DoCallback(msg.second, SendStatus::Congestion); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this what you mean? we always call the congestion func rn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you mean by this, but I don't see any congestion function anywhere in the old SendToOrQueue
codepath.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I reviewed the function looked like https://github.com/loki-project/loki-network/blob/1d6f010ea9056ff4deee38cd97de3d47727095bb/llarp/router/outbound_message_handler.cpp#L162-L169
struct Logic; | ||
enum class SessionResult; | ||
|
||
struct OutboundMessageHandler : public IOutboundMessageHandler |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
final
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed.
|
||
LogInfo("session with ", router, " established"); | ||
|
||
if (not _rcLookup->RemoteIsAllowed(router)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually prefer the not
token over !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does MSVC support it yet (without #include <ciso646>
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually good question. I'm not sure. you just need iso646.h
(since c99) but msvc is weird and is a c++ exclusive compiler 🤷♀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update on this? Also, perhaps make format
can change to the preferred style? Not sure, haven't really used it, but I imagine it'd be cool if it could.
} | ||
|
||
void | ||
Init(LinkManager *linkManager, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hate init methods. why not a constructor which does this?
llarp/router/rc_lookup_handler.cpp
Outdated
[&](const RouterContact &rc) { | ||
if(HavePendingLookup(rc.pubkey)) | ||
return; | ||
GetRC(rc.pubkey, nullptr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GetRC calls stuff that acquires a lock that is held while visiting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's...gonna be fun to resolve.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed.
llarp/router/rc_lookup_handler.cpp
Outdated
} | ||
|
||
void | ||
RCLookupHandler::Init(llarp_dht_context *dht, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be the constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above, not changed.
} | ||
|
||
void | ||
LinkManager::Init(IOutboundSessionMaker *sessionMaker) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should ALSO be the constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So for objects which need to point to one another you would end up mixing and matching this style and in-constructor init of pointers. Ideally that situation wouldn't occur, but it's non-trivial to avoid. In order to have consistency among these new classes I opted for this style.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i am segfaulting in my local testing because a timer is called with a member being nullptr and i assumed it's happpening before calling init
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Init
s are run during Router::FromConfig
. If that's not early enough then the lack of segfault before was just masking something using Router
before it was fully configured/initialized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After further discussion, leaving it as-is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Init functions like this are evils in API design :( but okay
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can definitely agree with arguments against doing it this way. It's definitely something to revisit in the future.
} | ||
|
||
void | ||
OutboundSessionMaker::Init(ILinkManager *linkManager, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also this should be a constructor. :>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above, not changed.
} | ||
|
||
void | ||
OutboundMessageHandler::Init(ILinkManager* linkManager, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also a constructor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above, not changed.
llarp/link/link_manager.cpp
Outdated
false | ||
); | ||
|
||
auto sz = connectedRouters.size(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be const
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed.
std::unordered_map< RouterID, llarp_time_t, RouterID::Hash > | ||
m_PersistingSessions GUARDED_BY(_mutex); | ||
|
||
IOutboundSessionMaker *_sessionMaker; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be a const *
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only if I change it to be set in the constructor as @michael-loki suggested, but in case / because some of these things need to point to one another I opted to set all of their pointers in an Init function. Naturally the pointers are private to at least mostly mitigate the risk of accidentally changing them rather than using them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose I could make these pointers const
and cast the const
away in the Init
function, but that also feels messy. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not casting const away, no change.
case SessionResult::NoLink: | ||
OnNoLink(router); | ||
break; | ||
default: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should probably error on default case "just in case"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess, but that would be a very interesting case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added LogError
and abort.
std::unordered_map< RouterID, MessageQueue, RouterID::Hash > | ||
outboundMessageQueue GUARDED_BY(_mutex); | ||
|
||
ILinkManager* _linkManager; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this also be a const *
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above, not changed.
} | ||
else | ||
{ | ||
//TODO: shouldn't happen, how to handle? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe abort()
? probably log error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added LogError
but not abort.
ILinkManager *_linkManager; | ||
I_RCLookupHandler *_rcLookup; | ||
std::shared_ptr< Logic > _logic; | ||
llarp_nodedb *_nodedb; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const *
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above, not changed.
RouterID::Hash > | ||
pendingCallbacks GUARDED_BY(_mutex); | ||
|
||
ILinkManager *_linkManager; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* const
(i kept on saying const *
>.>)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which the compiler corrected several times as a result...
// update nodedb if required | ||
if (rc.IsPublicRouter()) | ||
{ | ||
_nodedb->UpdateAsyncIfNewer(rc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't update the inserted timestamp so it either should be InsertAsync
or make UpdateAsyncIfNewer
change insertion timestamps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think changing UpdateAsyncIfNewer is cleaner, which do you prefer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changing UpdateAsyncIfNewer
works fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
llarp/router/rc_lookup_handler.cpp
Outdated
|
||
while (not callbackQueue.empty()) | ||
{ | ||
callbackQueue.front()(router, rc, result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happens if the callback eventually wants to acquire the RCLookupHandler lock again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair point. I don't particularly like the idea of collecting the callbacks in a local container first (and then unlocking) but that's probably for the best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed.
llarp/router/rc_lookup_handler.hpp
Outdated
|
||
mutable util::Mutex _mutex; // protects pendingCallbacks, whitelistRouters | ||
|
||
llarp_dht_context *_dht = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* const
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above, not changed.
} | ||
|
||
void | ||
LinkManager::Init(IOutboundSessionMaker *sessionMaker) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Init functions like this are evils in API design :( but okay
}; | ||
|
||
using RouterCallback = | ||
std::function< void(const RouterID, const SessionResult) >; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const RouterID&
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, will change now.
void | ||
OutboundMessageHandler::OnConnectFailure(const RouterID &router) | ||
{ | ||
FinalizeRequest(router, SendStatus::Timeout); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is a connect failure always a timeout?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when this func is called, yes. Changing func name.
{ | ||
DoCallback(msg.second, SendStatus::Success); | ||
} | ||
DoCallback(msg.second, SendStatus::Congestion); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I reviewed the function looked like https://github.com/loki-project/loki-network/blob/1d6f010ea9056ff4deee38cd97de3d47727095bb/llarp/router/outbound_message_handler.cpp#L162-L169
|
||
LinkLayer_ptr link = _linkManager->GetCompatibleLink(rc); | ||
|
||
if(link == nullptr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if(!link)
?
llarp/router/rc_lookup_handler.cpp
Outdated
{ | ||
collectedCallbacks.push_back(callbackQueue.front()); | ||
callbackQueue.pop(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could be simplified to be:
std::vector< RCRequestCallback > collectedCallbacks;
{
util::Lock l(&_mutex);
auto itr = pendingCallbacks.find(router);
if(itr != pendingCallbacks.end())
{
auto &callbackQueue = itr->second;
if(callbackQueue.size())
{
collectedCallbacks.reserve(callbackQueue.size());
}
collectedCallbacks.assign(callbackQueue.begin(), callbackQueue.end());
pendingCallbacks.erase(itr);
}
} // lock
for(const auto &callback : collectedCallbacks)
{
callback(router, rc, result);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, probably. neat.
@@ -25,8 +25,6 @@ namespace llarp | |||
return false; | |||
} | |||
|
|||
buf.sz = buf.cur - buf.base; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ebin af
{ | ||
// TODO: do we want to keep it | ||
|
||
const auto &router = RouterID(session->GetPubKey()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const RouterID router{session->GetPubKey()};
|
||
CreatePendingSession(router); | ||
|
||
LogWarn("Creating session establish attempt to ", router, " ."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a stray LogWarn
{ | ||
// TODO: retry/num attempts | ||
|
||
LogWarn("Session establish attempt to ", RouterID(session->GetPubKey()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nvm this is fine
llarp/router/rc_lookup_handler.hpp
Outdated
llarp_dht_context *_dht = nullptr; | ||
llarp_nodedb *_nodedb = nullptr; | ||
std::shared_ptr< llarp::thread::ThreadPool > _threadpool; | ||
service::Context *_hiddenServiceContext; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should set to nullptr
like the other bare pointers
llarp/router/rc_lookup_handler.hpp
Outdated
llarp_nodedb *_nodedb = nullptr; | ||
std::shared_ptr< llarp::thread::ThreadPool > _threadpool; | ||
service::Context *_hiddenServiceContext; | ||
ILinkManager *_linkManager; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also this too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
squash it
83034e4
to
fbd5746
Compare
fbd5746
to
3f69228
Compare
100 comments and a 3 way merge conflict ain't one :> |
This commit refactors functionality from the Router class into separate, dedicated classes. There are a few behavior changes that came as a result of discussion on what the correct behavior should be. In addition, many things Router was previously doing can now be provided callback functions to alert the calling point when the asynchronous action completes, successfully or otherwise.
3f69228
to
baf8019
Compare
YOLO! |
This PR refactors a lot of the functionality that is "kitchen sink"ed into router.cpp into separate classes.
This PR will be squashed before merge.
There are also some minor behavior changes along with this refactor as I came across behavior that was either incorrect or sub-optimal.