Skip to content
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

SockMan #64

Closed
wants to merge 33 commits into from
Closed

SockMan #64

wants to merge 33 commits into from

Conversation

Sjors
Copy link
Owner

@Sjors Sjors commented Sep 27, 2024

No description provided.

Sjors and others added 30 commits September 20, 2024 18:08
Co-Authored-By: Christopher Coverdale <[email protected]>
This commit adds the simplest stratum v2 message. The remaining messages are introduced in later commits.

Co-Authored-By: Christopher Coverdale <[email protected]>
This avoids a circular dependency between bitcoin-sv2 and bitcoin-node.
This allows us to subclass Transport.
Implemented starting from a copy of V2Transport and the V2TransportTester,
modifying it to fit Stratum v2 and Noise Protocol requirements.

Co-Authored-By: Christopher Coverdale <[email protected]>
Co-Authored-By: Fi3
Co-Authored-By: Christopher Coverdale <[email protected]>
Move the implementation (method definitions) from `test/util/net.h` to
`test/util/net.cpp` to make the header easier to follow.
…lass

This allows reusing them in other mocked implementations.
…o it

And also allows gradually providing the data to be returned by `Recv()`
and sending and receiving net messages (`CNetMessage`).
Co-Authored-By: Vasil Dimov <[email protected]>
Similar to e9bfbb5 for Cirrus, but
not opt-in, because Github CI lacks custom variables.
* `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.
Introduce a new low-level socket managing class `SockMan`
and move the `CConnman::BindListenPort()` method to it.

Also, separate the listening socket from the permissions -
they were coupled in `struct ListenSocket`, but the socket
is protocol agnostic, whereas the permissions are specific
to the application of the Bitcoin P2P protocol.
It was copied verbatim from `CConnman::BindListenPort()` in the previous
commit. Modernize its variables and style and log the error messages
from the caller.
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()`
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.

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:
`EventIOLoopCompletedForNode()` and `EventIOLoopCompletedForAllPeers()`.

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::ConnectAndMakeNodeId()` 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 node 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()`.
vasild and others added 3 commits September 27, 2024 13:22
`SockMan` members

`AcceptConnection()`
`NewSockAccepted()`
`GetNewNodeId()`
`m_i2p_sam_session`
`m_listen private`

are now used only by `SockMan`, thus make them private.
@vasild
Copy link

vasild commented Oct 4, 2024

Yo! There are two problems here:

  1. In Sv2Connman::EventReadyToSend() it forgot to erase the sent message from the queue, so it kept sending the same message over and over again. Fixed by adding client->m_send_messages.erase(). This fixes the failure of BOOST_REQUIRE_EQUAL(tester.LocalToRemoteBytes(), SV2_HEADER_ENCRYPTED_SIZE + 6 + Poly1305::TAGLEN);
  2. After this, at the exit it didn't properly interrupt SockMan. Fixed by adding interruptNet() in Sv2Connman::Interrupt().

Here is a patch: sv2sockman.diff.txt

The changes to sv2_connman_tests.cpp are not needed for the test to pass but I made them to unconfuse myself from the send vs recv interaction - since both ends of the connection are inside one program, I was confused what does it mean to "send" bytes. So I renamed a bunch of symbols to use the notation of "local" and "remote" and "local to remote" and "remote to local". Another possibility would be to use "us" and "them", e.g. "from us to them" and "from them to us". Feel free to ignore those.

@Sjors
Copy link
Owner Author

Sjors commented Oct 4, 2024

Thanks. I'll apply your changes as well as the test clarifications.

@Sjors
Copy link
Owner Author

Sjors commented Oct 4, 2024

Folded all of it into #50! Left a few followup questions there.

Additionally I fixed a few locking warnings and implemented EventGotEOF and EventGotPermanentReadError to just disconnect.

@Sjors Sjors closed this Oct 4, 2024
@Sjors Sjors deleted the 2024/09/sv2_sockman branch October 4, 2024 13:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants