-
Notifications
You must be signed in to change notification settings - Fork 10
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
Stratum v2 connman #50
base: sv2-transport
Are you sure you want to change the base?
Conversation
@pinheadmz wrote in the original PR:
I plan to take a look at this. |
3cf779b
to
b549fd6
Compare
bdc8542
to
199234a
Compare
b549fd6
to
22d033c
Compare
199234a
to
922fd8a
Compare
22d033c
to
6b5ee20
Compare
CMake rebase. |
6b5ee20
to
4f957ee
Compare
922fd8a
to
50b6eb8
Compare
4f957ee
to
b69544c
Compare
50b6eb8
to
6a02367
Compare
b69544c
to
1ca68d2
Compare
6a02367
to
ce4269c
Compare
1ca68d2
to
b578e0a
Compare
8220337
to
5fca2c5
Compare
b578e0a
to
489c9fb
Compare
5fca2c5
to
dfb9a6d
Compare
489c9fb
to
a55fa83
Compare
Rebased to move everything into a |
using Clients = std::unordered_map<NodeId, std::shared_ptr<Sv2Client>>; | ||
Clients m_sv2_clients GUARDED_BY(m_clients_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.
Why does this need a lock? I'm curious because in HTTP I think all client-related operations take place exclusively in the Sockman I/O thread.
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 because of DisconnectFlagged()
, GetClientById()
or ForEachClient()
- or for the test-only (Fully)ConnectedClients()
. But it could be a left-over of earlier versions.
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.
In HTTP you probably don't have a need to "proactively" talk to a specific client.
Are http connections ephemeral?
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.
HTTP connections can persist ("keep-alive") and send more requests over time. My equivalents to DisconnectFlagged and GetClientById still take place inside the single sockman IO thread though so even though I started copying your code, I think I can get away with removing the lock
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.
TSan will tell you
7fb1a19
to
2503578
Compare
Rebased on the latest bitcoin#30988. |
* `CConnman::CalculateKeyedNetGroup()` needs `CNetAddr`, not `CAddress`, thus change its argument. * Both callers of `CConnman::CreateNodeFromAcceptedSocket()` create a dummy `CAddress` from `CService`, so use `CService` instead. * `GetBindAddress()` only needs to return `CAddress`. * `CNode::addrBind` does not need to be `CAddress`.
They were coupled in `struct ListenSocket`, but the socket belongs to the lower level transport protocol, whereas the permissions are specific to the higher Bitcoin P2P protocol.
Now that `CConnman::ListenSocket` is a `struct` that contains only one member variable of type `std::shared_ptr<Sock>`, drop `ListenSocket` and use `shared_ptr` directly. Replace the vector of `ListenSocket` with a vector of `shared_ptr`.
Introduce a new low-level socket managing class `SockMan` and move the `CConnman::BindListenPort()` method to it.
It was copied verbatim from `CConnman::BindListenPort()` in the previous commit. Modernize its variables and style and log the error messages from the caller. Also categorize the informative messages to the "net" category because they are quite specific to the networking layer.
Move the `CConnman::AcceptConnection()` method to `SockMan` and split parts of it: * the flip-to-CJDNS part: to just after the `AcceptConnection()` call * the permissions part: at the start of `CreateNodeFromAcceptedSocket()`
Move `CConnman::GetNewNodeId()` to `SockMan::GetNewId()`. Avoid using the word "node" because that is too specific for `CConnman`.
CConnman-specific or in other words, Bitcoin P2P specific. Now the `ThreadI2PAcceptIncoming()` method is protocol agnostic and can be moved to `SockMan`.
Change `CConnman::m_nodes` from `std::vector<CNode*>` to `std::unordered_map<NodeId, CNode*>` because interaction between `CConnman` and `SockMan` is going to be based on `NodeId` and finding a node by its id would better be fast. Change `PeerManagerImpl::EvictExtraOutboundPeers()` to account for nodes no longer always being in order of id. The old code would have failed to update `next_youngest_peer` correctly if `CConnman::m_nodes` hadn't always had nodes in ascending order of id. During fuzzing make sure that we don't generate duplicate `CNode` ids. The easiest way to do that is to use sequential ids. As a nice side effect the existent search-by-id operations in `CConnman::AttemptToEvictConnection()`, `CConnman::DisconnectNode()` and `CConnman::ForNode()` now become `O(1)` (were `O(number of nodes)`), as well as the erase in `CConnman::DisconnectNodes()`.
Move the parts of `CConnman::GenerateWaitSockets()` that are specific to the Bitcoin-P2P protocol to dedicated methods: `ShouldTryToSend()` and `ShouldTryToRecv()`. This brings us one step closer to moving `GenerateWaitSockets()` to the protocol agnostic `SockMan` (which would call `ShouldTry...()` from `CConnman`).
…cketHandler() Move some parts of `CConnman::SocketHandlerConnected()` and `CConnman::ThreadSocketHandler()` that are specific to the Bitcoin-P2P protocol to dedicated methods: `EventIOLoopCompletedForOne(id)` and `EventIOLoopCompletedForAll()`. This brings us one step closer to moving `SocketHandlerConnected()` and `ThreadSocketHandler()` to the protocol agnostic `SockMan` (which would call `EventIOLoopCompleted...()` from `CConnman`).
Introduce 4 new methods for the interaction between `CConnman` and `SockMan`: * `EventReadyToSend()`: called when there is readiness to send and do the actual sending of data. * `EventGotData()`, `EventGotEOF()`, `EventGotPermanentReadError()`: called when the corresponing recv events occur. These methods contain logic that is specific to the Bitcoin-P2P protocol and move it away from `CConnman::SocketHandlerConnected()` which will become a protocol agnostic method of `SockMan`. Also, move the counting of sent bytes to `CConnman::SocketSendData()` - both callers of that method called `RecordBytesSent()` just after the call, so move it from the callers to inside `CConnman::SocketSendData()`.
Move the protocol agnostic parts of `CConnman::ConnectNode()` into `SockMan::ConnectAndMakeId()` and leave the Bitcoin-P2P specific stuff in `CConnman::ConnectNode()`. Move the protocol agnostic `CConnman::m_unused_i2p_sessions`, its mutex and `MAX_UNUSED_I2P_SESSIONS_SIZE` to `SockMan`. Move `GetBindAddress()` from `net.cpp` to `sockman.cpp`.
Move `MaybeFlipIPv6toCJDNS()`, which is Bitcoin P2P specific from the callers of `CConnman::EventNewConnectionAccepted()` to inside that method. Move the IsSelectable check, the `TCP_NODELAY` option set and the generation of new connection id out of `CConnman::EventNewConnectionAccepted()` because those are protocol agnostic. Move those to a new method `SockMan::NewSockAccepted()` which is called instead of `CConnman::EventNewConnectionAccepted()`.
Move `CNode::m_sock` and `CNode::m_i2p_sam_session` to `SockMan::m_connected`. Also move all the code that handles sockets to `SockMan`. `CNode::CloseSocketDisconnect()` becomes `CConnman::MarkAsDisconnectAndCloseConnection()`. `CConnman::SocketSendData()` is renamed to `CConnman::SendMessagesAsBytes()` and its sockets-touching bits are moved to `SockMan::SendBytes()`. `CConnman::GenerateWaitSockets()` goes to `SockMan::GenerateWaitSockets()`. `CConnman::ThreadSocketHandler()` and `CConnman::SocketHandler()` are combined into `SockMan::ThreadSocketHandler()`. `CConnman::SocketHandlerConnected()` goes to `SockMan::SocketHandlerConnected()`. `CConnman::SocketHandlerListening()` goes to `SockMan::SocketHandlerListening()`.
`SockMan` members `AcceptConnection()` `NewSockAccepted()` `GetNewId()` `m_i2p_sam_session` `m_listen` are now used only by `SockMan`, thus make them private.
Co-Authored-By: Christopher Coverdale <[email protected]>
Co-Authored-By: Vasil Dimov <[email protected]>
2503578
to
360aedd
Compare
Rebased after bitcoin#30205 landed. |
Based on:
Followed by #49. Parent PR #68
This PR introduces
Sv2Connman
, a subclass ofSockMan
(bitcoin#30988). It uses theSv2Transport
introduced in bitcoin#30315 to enable incoming connections from other Stratum v2 roles.It's main target user is the Template Provider role introduced in #49.
There may be other Stratum v2 roles we want to support in the future.
Earlier version(s): bitcoin#30332
Note to self, to keep this rebased until bitcoin#30205 and bitcoin#30988 land (2 merge commits and 3 normal commits):
This won't include changes in the original branches. To achieve that:
Note that this code will most likely not be upstreamed to Bitcoin Core, but instead used to create a standalone c++ application that connects to a running node via an IPC interface. See bitcoin#31098.