8000 Make all networking code mockable by vasild · Pull Request #21878 · bitcoin/bitcoin · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Make all networking code mockable #21878

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

Closed
wants to merge 9 commits into from

Conversation

vasild
Copy link
Contributor
@vasild vasild commented May 7, 2021

@DrahtBot
Copy link
Contributor
DrahtBot commented May 7, 2021

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Reviews

See the guideline for information on the review process.

Type Reviewers
Concept ACK practicalswift, jonatack, promag, jnewbery, jamesob, josibake

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #27375 (net: support unix domain sockets for -proxy and -onion by pinheadmz)
  • #26812 (test: add end-to-end tests for CConnman and PeerManager by vasild)
  • #26312 (Remove Sock::Get() and Sock::Sock() by vasild)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@practicalswift
Copy link
Contributor

Strong Concept ACK: mockable means fuzzable.

@jonatack
Copy link
Member

Concept ACK

Copy link
Contributor
@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK.

@promag
Copy link
Contributor
promag commented May 12, 2021

@vasild I think 96bcc72 and refactors around it could easily be merged on its own.

@vasild vasild force-pushed the Sock_all_over_the_place branch from 0256cfd to e68bc63 Compare May 13, 2021 11:54
@vasild
Copy link
Contributor Author
vasild commented May 13, 2021

0256cfd34...e68bc633f: address review suggestions

@vasild
Copy link
Contributor Author
vasild commented May 13, 2021

@vasild I think 96bcc72 and refactors around it could easily be merged on its own.

Right! Submitted in #21943.

@jnewbery
Copy link
Contributor

Very nice. Strong concept ACK.

@vasild vasild force-pushed the Sock_all_over_the_place branch from e68bc63 to 5772edb Compare May 14, 2021 10:38
@vasild
Copy link
Contributor Author
vasild commented May 14, 2021

e68bc633f...5772edb36: add an explicit commit that shows we intentionally don't process newly accepted nodes, as discussed in #21943 (comment)

@vasild vasild force-pushed the Sock_all_over_the_place branch from 5772edb to ec5f887 Compare May 17, 2021 14:47
@vasild
Copy link
Contributor Author
vasild commented May 17, 2021

5772edb...ec5f887: replicate changes to #21943

@vasild vasild force-pushed the Sock_all_over_the_place branch from ec5f887 to a0b0030 Compare May 19, 2021 11:49
@vasild
Copy link
Contributor Author
vasild commented May 19, 2021

ec5f887543...a0b00304a8: rebase due to conflicts

@vasild vasild force-pushed the Sock_all_over_the_place branch from a0b0030 to 6bed261 Compare May 20, 2021 13:30
@vasild
Copy link
Contributor Author
vasild commented Feb 9, 2023

77ab5e8e98...b497200c7a: rebase due to conflicts

@achow101 achow101 marked this pull request as draft April 25, 2023 16:13
vasild added 9 commits August 16, 2023 14:31
Peeking at the underlying socket file descriptor of `Sock` and checkig
if it is `INVALID_SOCKET` is bad encapsulation and stands in the way of
testing/mocking/fuzzing.

Instead use an empty unique_ptr to denote that there is no valid socket.
The socket is always valid (the underlying file descriptor is not
`INVALID_SOCKET`) when `GetBindAddress()` is called.
The socket is always valid (the underlying file descriptor is not
`INVALID_SOCKET`) when `ConnectSocketDirectly()` is called.
`Sock::Get()` was used only in `sock.{cpp,h}`. Remove it and access
`Sock::m_socket` directly.

Unit tests that used `Get()` to test for equality still verify that the
behavior is correct, indirectly, by testing whether the socket is closed
or not.
Now that all network calls done by `CConnman::OpenNetworkConnection()`
are done via `Sock` they can be redirected (mocked) to `FuzzedSocket`
for testing.
@vasild vasild force-pushed the Sock_all_over_the_place branch from b497200 to 80d9dfd Compare August 16, 2023 13:27
@vasild
Copy link
Contributor Author
vasild commented Aug 16, 2023

b497200c7a...80d9dfd0f0: rebase due to conflicts

ryanofsky added a commit that referenced this pull request Oct 3, 2023
7df4508 test: improve sock_tests/move_assignment (Vasil Dimov)
5086a99 net: remove Sock default constructor, it's not necessary (Vasil Dimov)
7829272 net: remove now unnecessary Sock::Get() (Vasil Dimov)
944b21b net: don't check if the socket is valid in ConnectSocketDirectly() (Vasil Dimov)
aeac68d net: don't check if the socket is valid in GetBindAddress() (Vasil Dimov)
5ac1a51 i2p: avoid using Sock::Get() for checking for a valid socket (Vasil Dimov)

Pull request description:

  _This is a piece of #21878, chopped off to ease review._

  Peeking at the underlying socket file descriptor of `Sock` and checkig if it is `INVALID_SOCKET` is bad encapsulation and stands in the way of testing/mocking/fuzzing.

  Instead use an empty `unique_ptr` to denote that there is no valid socket where appropriate or outright remove such checks where they are not necessary.

  The default constructor `Sock::Sock()` is unnecessary now after recent changes, thus remove it.

ACKs for top commit:
  ajtowns:
    ACK 7df4508
  jonatack:
    ACK 7df4508

Tree-SHA512: 9742aeeeabe8690530bf74caa6ba296787028c52f4a3342afd193b05dbbb1f6645935c33ba0a5230199a09af01c666bd3c7fb16b48692a0d185356ea59a8ddbf
@DrahtBot
9E88 Copy link
Contributor
DrahtBot commented Oct 3, 2023

🐙 This pull request conflicts with the target branch and needs rebase.

@vasild
Copy link
Contributor Author
vasild commented Oct 4, 2023

All the functional bits of this are now merged. Thank you all!

This enables extending the test framework to be able to call any method, without worries that it may end up doing OS syscalls (try to create sockets, open connections, etc). A PR that does some of that is in #28584 (= last 4 commits from this PR).

Closing as complete.

@vasild vasild closed this Oct 4, 2023
@vasild vasild deleted the Sock_all_over_the_place branch October 4, 2023 11:35
Frank-GER pushed a commit to syscoin/syscoin that referenced this pull request Oct 13, 2023
7df4508 test: improve sock_tests/move_assignment (Vasil Dimov)
5086a99 net: remove Sock default constructor, it's not necessary (Vasil Dimov)
7829272 net: remove now unnecessary Sock::Get() (Vasil Dimov)
944b21b net: don't check if the socket is valid in ConnectSocketDirectly() (Vasil Dimov)
aeac68d net: don't check if the socket is valid in GetBindAddress() (Vasil Dimov)
5ac1a51 i2p: avoid using Sock::Get() for checking for a valid socket (Vasil Dimov)

Pull request description:

  _This is a piece of bitcoin#21878, chopped off to ease review._

  Peeking at the underlying socket file descriptor of `Sock` and checkig if it is `INVALID_SOCKET` is bad encapsulation and stands in the way of testing/mocking/fuzzing.

  Instead use an empty `unique_ptr` to denote that there is no valid socket where appropriate or outright remove such checks where they are not necessary.

  The default constructor `Sock::Sock()` is unnecessary now after recent changes, thus remove it.

ACKs for top commit:
  ajtowns:
    ACK 7df4508
  jonatack:
    ACK 7df4508

Tree-SHA512: 9742aeeeabe8690530bf74caa6ba296787028c52f4a3342afd193b05dbbb1f6645935c33ba0a5230199a09af01c666bd3c7fb16b48692a0d185356ea59a8ddbf
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Feb 27, 2024
a724c39 net: rename Sock::Reset() to Sock::Close() and make it private (Vasil Dimov)
e8ff3f0 net: remove CloseSocket() (Vasil Dimov)
175fb26 net: remove now unused Sock::Release() (Vasil Dimov)

Pull request description:

  _This is a piece of bitcoin#21878, chopped off to ease review._

  * `Sock::Release()` is unused, thus remove it
  * `CloseSocket()` is only called from `Sock::Reset()`, so move the body of `CloseSocket()` inside `Sock::Reset()` and remove `CloseSocket()` - this helps to hide low level file descriptor sockets inside the `Sock` class.
  * Rename `Sock::Reset()` to `Sock::Close()` and make it `private` - to be used only in the destructor and in the `Sock` assignment operator. This simplifies the public API by removing one method from it.

ACKs for top commit:
  laanwj:
    Code review ACK a724c39

Tree-SHA512: 4b12586642b3d049092fadcb1877132e285ec66a80af92563a7703c6970e278e0f2064fba45c7eaa78eb65db94b3641fd5e5264f7b4f61116d1a6f3333868639
PastaPastaPasta added a commit to dashpay/dash that referenced this pull request May 14, 2024
…keup pipes logic out of `CConnman` and into `EdgeTriggeredEvents` and `WakeupPipes`

bd8b5d4 net: add more details to log information in ETE and `WakeupPipes` (Kittywhiskers Van Gogh)
ec99294 net: restrict access `EdgeTriggerEvents` members (Kittywhiskers Van Gogh)
f24520a net: log `close` failures in `EdgeTriggerEvents` and `WakeupPipe` (Kittywhiskers Van Gogh)
b8c3b48 refactor: introduce `WakeupPipe`, move wakeup select pipe logic there (Kittywhiskers Van Gogh)
ed7d976 refactor: move wakeup pipe (de)registration to ETE (Kittywhiskers Van Gogh)
f50c710 refactor: move `CConnman::`(`Un`)`registerEvents` to ETE (Kittywhiskers Van Gogh)
3a9f386 refactor: move `SOCKET` addition/removal from interest list to ETE (Kittywhiskers Van Gogh)
212df06 refactor: introduce `EdgeTriggeredEvents`, move {epoll, kqueue} fd there (Kittywhiskers Van Gogh)
3b11ef9 refactor: move `CConnman::SocketEventsMode` to `util/sock.h` (Kittywhiskers Van Gogh)

Pull request description:

  ## Motivation

  `CConnman` is an entity that contains a lot of platform-specific implementation logic, both inherited from upstream and added upon by Dash (support for edge-triggered socket events modes like `epoll` on Linux and `kqueue` on FreeBSD/Darwin).

  Bitcoin has since moved to strip down `CConnman` by moving peer-related logic to the `Peer` struct in `net_processing` (portions of which are backported in #5982 and friends, tracking efforts from bitcoin#19398) and moving socket-related logic to `Sock` (portions of which are aimed to be backported in #6004, tracking efforts from bitcoin#21878).

  Due to the direction being taken and the difference in how edge-triggered events modes operate (utilizing interest lists and events instead of iterating over each socket) in comparison to level-triggered modes (which are inherited from upstream), it would be reasonable to therefore, isolate Dash-specific code into its own entities and minimize the information `CConnman` has about its internal workings.

  One of the visible benefits of this approach is comparing `develop` (as of this writing, d44b0d5) and this pull request for interactions between wakeup pipes logic and {`epoll`, `kqueue`} logic.

  This is what construction looks like:

  https://github.com/dashpay/dash/blob/d44b0d5dcb9b54821d582b267a8b92264be2da1b/src/net.cpp#L3358-L3397

  But, if we segment wakeup pipes logic (that work on any platform with POSIX APIs and excludes Windows) and {`epoll`, `kqueue`} logic (calling them `EdgeTriggeredEvents` instead), construction looks different:

  https://github.com/dashpay/dash/blob/907a3515170abed4ce9018115ed591e6ca9f4800/src/util/wpipe.cpp#L12-L38

  Now wakeup pipes logic doesn't need to know what socket events mode is being used nor are the implementation aspects of (de)registering it its concern, that is now `EdgeTriggeredEvents` problem.

  ## Additional Information

  * This pull request will need testing on macOS (FreeBSD isn't a tier-one target) to ensure that lack of breakage in `kqueue`-specific logic.

  ## Breaking Changes

  * Dependency for #6018
  * More logging has been introduced and existing log messages have been made more exhaustive. If there is parsing that relies on a particular template, they will have to be updated.
  * If `EdgeTriggeredEvents` or `WakeupPipes` fail to initialize or are incorrectly initialized and not destroyed immediately, any further attempts at calling any of its functions will result in an `assert`-induced crash. Earlier behavior may have allowed for silent failure but segmentation of logic from `CConnman` means the newly created instances must only exist if the circumstances needed for it to initialize correctly are present.

    This is to ensure that `CConnman` doesn't have to concern itself with internal workings of either entities.

  ## Checklist:

  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas
  - [x] I have added or updated relevant unit/integration/functional/e2e tests **(note: N/A)**
  - [x] I have made corresponding changes to the documentation **(note: N/A)**
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  PastaPastaPasta:
    utACK bd8b5d4

Tree-SHA512: 8f793d4b4f2d8091e05bb9cc108013e924bbfbf19081290d9c0dfd91b0f2c80652ccf853f1596562942b4433509149c526e111396937988db605707ae1fe7366
@bitcoin bitcoin locked and limited conversation to collaborators Oct 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

0