net: add RAII socket and use it instead of bare SOCKET #20788

pull vasild wants to merge 6 commits into bitcoin:master from vasild:sock changing 11 files +527 −147
  1. vasild commented at 4:12 pm on December 28, 2020: member

    Introduce a class to manage the lifetime of a socket - when the object that contains the socket goes out of scope, the underlying socket will be closed.

    In addition, the new Sock class has a Send(), Recv() and Wait() methods that can be overridden by unit tests to mock the socket operations.

    The Wait() method also hides the #ifdef USE_POLL poll() #else select() #endif technique from higher level code.

  2. vasild commented at 4:18 pm on December 28, 2020: member

    The following two PRs would benefit from this:

    • #19203 would only need to add the fuzzing test and the mocked/fuzzed Sock implementation (last commit from that PR).
    • #20685 would become smaller. Sock originated there and that PR contains a copy of it. So if this PR gets merged, then the size of #20685 will be reduced.
  3. in src/sock.cpp:7 in 99b8e88a15 outdated
    0@@ -0,0 +1,134 @@
    1+// Copyright (c) 2012-2020 The Bitcoin Core developers
    2+// Distributed under the MIT software license, see the accompanying
    3+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
    4+
    5+#include <compat.h>
    6+#include <netaddress.h>
    7+#include <netbase.h>
    


    MarcoFalke commented at 4:26 pm on December 28, 2020:
    0#include <netbase.h> // For CloseSocket
    

    It seems this is the only Bitcoin Core related dependency. Are the other includes needed at all? If not, it would be good to move this module to util, which is the place for general utility stuff (not bitcoin related).


    vasild commented at 6:09 pm on December 29, 2020:

    No, the other includes are not needed (and I removed them). However there is a circular dependency now:

    • netbase -> sock (netbase.cpp uses the Sock class, of course)
    • sock -> netbase (sock.cpp uses MillisToTimeval() and CloseSocket() which are defined in netbase.cpp)

    One way to resolve that is to put the Sock class in netbase.{h,cpp} and ditch sock.{h,cpp}.

    Another one would be to move MillisToTimeval() and CloseSocket() outside of netbase.cpp, somewhere in src/util/ and use them from both netbase.cpp and from sock.cpp.

    Hmm…


    vasild commented at 11:38 am on December 30, 2020:

    One way to resolve that is to put the Sock class in netbase.{h,cpp}

    Did that.


    vasild commented at 12:44 pm on January 22, 2021:

    This was finally changed to:

    move MillisToTimeval() and CloseSocket() outside of netbase.cpp, somewhere in src/util/ and use them from both netbase.cpp and from sock.cpp

    it looks much better now.

  4. MarcoFalke commented at 4:28 pm on December 28, 2020: member
    left a style comment, no other review. Feel free to ignore.
  5. DrahtBot added the label Build system on Dec 28, 2020
  6. DrahtBot added the label P2P on Dec 28, 2020
  7. jonatack commented at 4:56 pm on December 28, 2020: member

    Concept ACK, was unable to build this pull @ 99b8e88a15cb12483f28079d0f91fe8cf361da56

     0$ gcc --version
     1gcc (Debian 10.2.1-1) 10.2.1 20201207
     2
     3.../...
     4
     5  AR       qt/libbitcoinqt.a
     6/usr/bin/ld: libbitcoin_common.a(libbitcoin_common_a-netbase.o): in function `std::_MakeUniq<Sock>::__single_object std::make_unique<Sock, unsigned int&>(unsigned int&)':
     7/usr/include/c++/10/bits/unique_ptr.h:962: undefined reference to `Sock::Sock(unsigned int)'
     8  CXXLD    qt/bitcoin-qt
     9  CXXLD    bitcoin-gui
    10/usr/bin/ld: libbitcoin_common.a(libbitcoin_common_a-netbase.o): in function `std::_MakeUniq<Sock>::__single_object std::make_unique<Sock, unsigned int&>(unsigned int&)':
    11/usr/include/c++/10/bits/unique_ptr.h:962: undefined reference to `Sock::Sock(unsigned int)'
    12collect2: error: ld returned 1 exit status
    13make[2]: *** [Makefile:5503: bitcoin-node] Error 1
    14make[2]: *** Waiting for unfinished jobs....
    15collect2: error: ld returned 1 exit status
    16make[2]: *** [Makefile:5515: bitcoind] Error 1
    17/usr/bin/ld: libbitcoin_common.a(libbitcoin_common_a-netbase.o): in function `std::_MakeUniq<Sock>::__single_object std::make_unique<Sock, unsigned int&>(unsigned int&)':
    18/usr/include/c++/10/bits/unique_ptr.h:962: undefined reference to `Sock::Sock(unsigned int)'
    19/usr/bin/ld: libbitcoin_common.a(libbitcoin_common_a-netbase.o): in function `std::_MakeUniq<Sock>::__single_object std::make_unique<Sock, unsigned int&>(unsigned int&)':
    20/usr/include/c++/10/bits/unique_ptr.h:962: undefined reference to `Sock::Sock(unsigned int)'
    21collect2: error: ld returned 1 exit status
    22make[2]: *** [Makefile:5521: qt/bitcoin-qt] Error 1
    23collect2: error: ld returned 1 exit status
    24make[2]: *** [Makefile:5499: bitcoin-gui] Error 1
    25make[2]: Leaving directory '/home/jon/projects/bitcoin/bitcoin/src'
    26make[1]: *** [Makefile:14882: all-recursive] Error 1
    27make[1]: Leaving directory '/home/jon/projects/bitcoin/bitcoin/src'
    28make: *** [Makefile:806: all-recursive] Error 1
    
  8. DrahtBot commented at 5:07 pm on December 28, 2020: member

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

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #21015 (Make all of net_processing (and some of net) use std::chrono types by dhruv)
    • #20685 (Add I2P support using I2P SAM by vasild)
    • #19415 (net: Make DNS lookup mockable, add fuzzing harness by practicalswift)
    • #19203 (net: Add regression fuzz harness for CVE-2017-18350. Add FuzzedSocket. Add thin SOCKET wrapper. by practicalswift)

    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.

  9. in src/netbase.cpp:345 in 99b8e88a15 outdated
    348@@ -347,15 +349,15 @@ enum class IntrRecvError {
    349  *      Sockets can be made non-blocking with SetSocketNonBlocking(const
    350  *      SOCKET&, bool).
    351  */
    352-static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const SOCKET& hSocket)
    353+static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const Sock& sock)
    


    lontivero commented at 7:26 pm on December 28, 2020:
    Q: would it make sense to have this method as part of the Sock? (Something similar to Sock::recv but with a timeout parameter)

    vasild commented at 2:10 pm on December 29, 2020:

    Yes, indeed. That would be convenient together with a send method that retries upon temporary failures (see below).

    I did not include such methods in this PR because it is self-sufficient as it is and achieves the initial purpose to introduce a mockable socket that can be used for fuzzing in #19203.

    Possible future improvements (which I resisted adding in this PR):

    • Add robust receiving method, like InterruptibleRecv() (or change that function to a method of the Sock class)
    • Add robust sending method, like SendComplete() from #20685
    • Use Sock in more places instead of the bare SOCKET - chase all places where Sock::Release() or Sock::Get() is called and see if the consumer can be changed to use Sock instead. E.g. in CNode constructor.
  10. practicalswift commented at 8:57 pm on December 28, 2020: contributor

    Strong concept ACK

    This abstraction would be extremely useful to have when fuzzing low-level networking code.

  11. vasild force-pushed on Dec 30, 2020
  12. vasild commented at 11:37 am on December 30, 2020: member

    99b8e88a1…408a9473b: moved the Sock class inside netbase.cpp to resolve a circular dependency.

    Another option would be to keep the Sock class in its own file src/sock.cpp or src/util/sock.cpp. Since it uses MillisToTimeval() and CloseSocket() they would have to be moved out of netbase.cpp.

  13. in src/netbase.h:126 in 408a9473be outdated
    122+     */
    123+    virtual ssize_t Send(const void* data, size_t len, int flags) const;
    124+
    125+    /**
    126+     * recv(2) wrapper. Equivalent to `recv(this->Get(), buf, len, flags);`. Code that uses this
    127+     * wrapper can be unit-tested if this method is overriden by a mock Sock implementation.
    


    jonatack commented at 4:02 pm on December 30, 2020:
    nit here and L120, s/overriden/overridden/

    vasild commented at 2:14 pm on December 31, 2020:
    Fixed
  14. in src/net.cpp:479 in 408a9473be outdated
    496-    CAddress addr_bind = GetBindAddress(hSocket);
    497-    CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", conn_type);
    498+    CAddress addr_bind = GetBindAddress(sock->Get());
    499+    CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), sock->Release(), addrConnect,
    500+                             CalculateKeyedNetGroup(addrConnect), nonce, addr_bind,
    501+                             pszDest ? pszDest : "", conn_type);
    


    lontivero commented at 4:17 pm on December 30, 2020:

    nit: i would like to suggest rename Sock::Release as Sock::GetAndRelease. IMO it makes it just a tiny bit more readable. Feel free to ignore this comment.

    0    CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), sock->GetAndRelease(), addrConnect,
    1                             CalculateKeyedNetGroup(addrConnect), nonce, addr_bind,
    2                             pszDest ? pszDest : "", conn_type);
    

    vasild commented at 1:53 pm on December 31, 2020:
    I agree GetAndRelease() is more descriptive, but I am trying to mimic std::unique_ptr and its method which is called release().
  15. jonatack commented at 4:20 pm on December 30, 2020: member

    Tested approach ACK 408a9473bed6b3be82b124c171435247100b9d34 (modulo missing test coverage?)

    • moving the Sock class to its own file and the common deps to a utility seems appealing, at least in principle, not sure in practice
    • review of the diff would be easier and nicer, and there would be less unnecessary churn and risk of overlooking a regression, if unneeded formatting and line break changes were not added when only an argument in the function signature is being updated
    • do you plan to add unit tests for the Sock class?
  16. in src/netbase.cpp:599 in 408a9473be outdated
    607+ssize_t Sock::Recv(void* buf, size_t len, int flags) const
    608+{
    609+    return recv(m_socket, static_cast<char*>(buf), len, flags);
    610+}
    611+
    612+bool Sock::Wait(const std::chrono::milliseconds& timeout, Event requested, Event* returned) const
    


    lontivero commented at 4:24 pm on December 30, 2020:
    The returned parameter is never used by any caller. It seems this is something that was added for future usage maybe. Does it make sense to have it at this point in time, I mean, if tomorrow it is needed then it could be added in a future PR.

    vasild commented at 2:15 pm on December 31, 2020:
    Removed, the less code - the better.
  17. lontivero commented at 4:26 pm on December 30, 2020: contributor
    I’ve finished the review. Only two comments.
  18. jnewbery commented at 2:08 pm on December 31, 2020: member
    Concept ACK. Is there any reason not to use the Sock object in CNode?
  19. vasild force-pushed on Dec 31, 2020
  20. vasild commented at 2:14 pm on December 31, 2020: member
    408a9473b…8fc63e344: fixed a typo and removed unused parameter
  21. vasild commented at 2:35 pm on December 31, 2020: member

    @jonatack

    moving the Sock class to its own file and the common deps to a utility seems appealing

    I will try this. Opinions, anybody? That would mean:

    • Move Sock from netbase.cpp to util/sock.cpp
    • Move MillisToTimeval() from netbase.cpp to util/where?
    • Move CloseSocket() from netbase.cpp to util/where? (it uses LogPrintf())

    do you plan to add unit tests for the Sock class?

    I did not but any ideas are welcome. I think it may be required to create a TCP server and client and do some communication between them to check that send() is indeed being called by the Send() method. May be an overkill, given that the Send() method is 1 line.

    I don’t know how to reliably check if the socket was closed by the destructor, given that the same file descriptor number could be assigned to a newly created socket (or opened file) after we close it. @jnewbery

    Is there any reason not to use the Sock object in CNode?

    No, other than minimizing the size of this PR. See also #20788 (review) :-)

  22. lontivero commented at 4:23 pm on December 31, 2020: contributor

    I agree with moving it to its own file and with adding UTs for it. I am not sure a real socket is necessary for testing this abstraction, could it be enough to simply mock send, recv and select? Something it could be useful is to make sure the ownership of the SOCKET is always correct (copy ctor, Release, operator =)

    btw, utACK 8fc63e344660f52a35bd97c1f881afdb1643b52a

  23. DrahtBot added the label Needs rebase on Jan 2, 2021
  24. vasild force-pushed on Jan 8, 2021
  25. vasild force-pushed on Jan 8, 2021
  26. vasild commented at 1:24 pm on January 8, 2021: member

    8fc63e3…3fa2a11:

    • rebased due to conflicts
    • moved Sock to its dedicated src/util/sock.{cpp,h}
    • added unit tests
  27. DrahtBot removed the label Needs rebase on Jan 8, 2021
  28. fanquake removed the label Build system on Jan 10, 2021
  29. in src/test/sock_tests.cpp:5 in 3fa2a11f6e outdated
    0@@ -0,0 +1,150 @@
    1+// Copyright (c) 2021-2021 The Bitcoin Core developers
    2+// Distributed under the MIT software license, see the accompanying
    3+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
    4+
    5+#ifndef WIN32
    


    lontivero commented at 2:12 pm on January 11, 2021:
    Q: Why are these tests disabled for Windows?

    vasild commented at 4:49 pm on January 11, 2021:
    They were because Windows does not have socketpair(), but since not all tests use this function I have now enabled the tests that don’t.
  30. in src/test/sock_tests.cpp:85 in 3fa2a11f6e outdated
    80+    const SOCKET s = CreateSocket();
    81+    Sock* sock = new Sock(s);
    82+    BOOST_CHECK_EQUAL(sock->Release(), s);
    83+    delete sock;
    84+    BOOST_CHECK(!SocketIsClosed(s));
    85+    BOOST_REQUIRE_EQUAL(close(s), 0);
    


    lontivero commented at 2:15 pm on January 11, 2021:
    Q: Why not CloseSocket here?

    vasild commented at 4:51 pm on January 11, 2021:
    Right, changed to CloseSocket().
  31. in src/test/sock_tests.cpp:140 in 3fa2a11f6e outdated
    136+    CreateSocketPair(s);
    137+
    138+    Sock sock0(s[0]);
    139+    Sock sock1(s[1]);
    140+
    141+    std::thread waiter([&sock0]() { sock0.Wait(24h, Sock::RECV); });
    


    lontivero commented at 2:28 pm on January 11, 2021:
    Does 24h means 24 hours? If that’s the case it looks too much to me, even for a UT.

    vasild commented at 5:02 pm on January 11, 2021:

    Yes, 24 hours. I wanted to use 1y (1 year), but y is not supported.

    If this test detects a failure, it would result in a “test timeout in CI” which waits for 2 hours.

    I don’t know how else to check if Wait() works as expected. Notice - it does not signal to the caller whether a timeout occurred or the socket is ready for the event. It was possible before, but we simplified it because nobody of the callers used that information. I think it is not worth restoring it for the sake of this test, what’s your take?

    If that functionality is provided then the test could do: “wait 1ms; ensure it caused timeout, send some data to the socket, wait 1ms; ensure it did not timeout, but signaled that the socket is ready”.


    lontivero commented at 5:51 pm on January 11, 2021:

    I think it is not worth restoring it for the sake of this test, what’s your take?

    I agree with you. I don’t think it is a good idea to have code the sake of one test only.

  32. in src/test/sock_tests.cpp:34 in 3fa2a11f6e outdated
    29+}
    30+
    31+static SOCKET CreateSocket()
    32+{
    33+    const int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    34+    BOOST_REQUIRE(s != -1);
    


    lontivero commented at 2:35 pm on January 11, 2021:
    It could make sense to use SOCKET_ERROR here.

    vasild commented at 4:55 pm on January 11, 2021:
    Done, thanks!
  33. lontivero changes_requested
  34. lontivero commented at 2:36 pm on January 11, 2021: contributor
    Mostly questions and one suggestion.
  35. vasild force-pushed on Jan 11, 2021
  36. vasild commented at 5:03 pm on January 11, 2021: member
    3fa2a11f6…ed69709c8: hopefully fix CI and address some suggestions
  37. lontivero commented at 8:13 pm on January 11, 2021: contributor
    utACK ed69709c8c86970f21b2a987a366737a01bc1c79
  38. DrahtBot added the label Needs rebase on Jan 13, 2021
  39. vasild force-pushed on Jan 14, 2021
  40. vasild commented at 12:11 pm on January 14, 2021: member
    ed69709c8…cc109a474: rebase due to conflicts
  41. DrahtBot removed the label Needs rebase on Jan 14, 2021
  42. lontivero commented at 1:22 pm on January 14, 2021: contributor
    utACK cc109a47481263e1a7fb9b74f1aea57ea0129f8e
  43. laanwj added this to the "Blockers" column in a project

  44. in src/Makefile.am:241 in cc109a4748 outdated
    237@@ -238,6 +238,7 @@ BITCOIN_CORE_H = \
    238   util/rbf.h \
    239   util/ref.h \
    240   util/settings.h \
    241+  util/sock.h \
    


    laanwj commented at 9:58 pm on January 24, 2021:
    Please create new general utilities like this in src/compat, src/support or src/util, not in the source root.

    vasild commented at 9:56 am on January 25, 2021:
    Hmm, the newly added sock.h is in src/util, so that’s already the case, no?

    laanwj commented at 10:14 am on January 25, 2021:
    Huh. Oops. I misread this. Seems good then :+1:.
  45. laanwj commented at 10:01 pm on January 24, 2021: member
    Concept ACK
  46. in src/util/system.cpp:1402 in cc109a4748 outdated
    1397+    int ret = close(socket);
    1398+#endif
    1399+    if (ret) {
    1400+        LogPrintf("Socket close failed: %d. Error: %s\n", socket, NetworkErrorString(WSAGetLastError()));
    1401+    }
    1402+    socket = INVALID_SOCKET;
    


    jonatack commented at 4:40 pm on February 3, 2021:
    acc89632 this commit isn’t move-only because hSocket was renamed, making it more error-prone and difficult to verify that the code isn’t changed, suggest clarifying the commit message with the renaming or, better yet, making this change move-only

    vasild commented at 5:21 pm on February 4, 2021:
    Changed the commit to be move-only and left the variable name as hSocket.
  47. in src/util/time.h:71 in cc109a4748 outdated
    66+struct timeval MillisToTimeval(int64_t nTimeout);
    67+
    68+/**
    69+ * Convert milliseconds to a struct timeval for e.g. select.
    70+ */
    71+struct timeval MillisToTimeval(const std::chrono::milliseconds& ms);
    


    jonatack commented at 4:48 pm on February 3, 2021:

    1dcf817 here and in the definition and in Sock::Wait()

    0struct timeval MillisToTimeval(std::chrono::milliseconds ms);
    

    vasild commented at 5:22 pm on February 4, 2021:
    Changed.
  48. in src/util/sock.h:10 in cc109a4748 outdated
     5+#ifndef BITCOIN_UTIL_SOCK_H
     6+#define BITCOIN_UTIL_SOCK_H
     7+
     8+#include <compat.h> // SOCKET
     9+
    10+#include <chrono> // std::chrono::milliseconds
    


    jonatack commented at 4:51 pm on February 3, 2021:

    1dcf817

    0#include <chrono>
    

    vasild commented at 5:23 pm on February 4, 2021:
    Those comments are useful, if they are present, during refactoring when moving code around. Unfortunately they are not widely used, so I do not insist on their presence. Removed.
  49. in src/netbase.cpp:525 in cc109a4748 outdated
    522@@ -541,58 +523,52 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
    523     uint8_t pchRet3[256];
    524     switch (pchRet2[3])
    525     {
    526-        case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
    527-        case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
    528+        case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, sock); break;
    529+        case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, sock); break;
    


    jonatack commented at 5:00 pm on February 3, 2021:
    The diff could be smaller, faster, easier and safer to review without unneeded renamings mixed with the coding changes. For existing code it’s not required to update the variable naming to current coding style and it would be good to be able to focus on the significant changes. Maybe open a separate pull for the renamings.

    vasild commented at 5:25 pm on February 4, 2021:

    I split this commit in two: variable type change from SOCKET to Sock + variable rename from hSocket to sock.

    It is good to have the implied convention of naming SOCKET variables hSocket (old code) or socket (new code) and Sock variables sock.

  50. in src/net.cpp:479 in cc109a4748 outdated
    487-    CAddress addr_bind = GetBindAddress(hSocket);
    488-    CNode* pnode = new CNode(id, nLocalServices, hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", conn_type);
    489+    CAddress addr_bind = GetBindAddress(sock->Get());
    490+    CNode* pnode = new CNode(id, nLocalServices, sock->Release(), addrConnect,
    491+                             CalculateKeyedNetGroup(addrConnect), nonce, addr_bind,
    492+                             pszDest ? pszDest : "", conn_type);
    


    jonatack commented at 5:01 pm on February 3, 2021:
    The diff could be smaller, faster, easier and safer to review without the unnecessary formatting churn in the diff. There are a few functions doing this here. Maybe open a separate pull for the formatting changes.

    vasild commented at 5:26 pm on February 4, 2021:
    Joined this back to one long line.
  51. jonatack commented at 5:05 pm on February 3, 2021: member
    Verified debug build is clean and tests pass at each commit. I’m not very confident in reviewing here with the formatting changes and various renamings mixed into the signifcant code changes. This could be a smaller, easier and safer diff to review.
  52. vasild force-pushed on Feb 4, 2021
  53. vasild commented at 5:26 pm on February 4, 2021: member
    cc109a474…bb5231615: stylistic changes to address suggestions by @jonatack, thanks!
  54. jonatack commented at 1:45 pm on February 9, 2021: member
    Thanks @vasild. I didn’t see your latest notifications as I have been adjusting to the new ghwatch.py script, will re-review.
  55. laanwj commented at 7:42 pm on February 9, 2021: member

    It seems more logical to me to move the CloseSocket and NetworkErrorString functions to sock.h, not system.h? Also do we still need an explicit CloseSocket instead of Sock::Reset? (oh those are separate types, I see)

    Cursory code review ACK otherwise.

  56. net: move MillisToTimeval() from netbase to util/time
    Move `MillisToTimeval()` from `netbase.{h,cpp}` to
    `src/util/system.{h,cpp}`.
    
    This is necessary in order to use `MillisToTimeval()` from a newly
    introduced `src/util/sock.{h,cpp}` which cannot depend on netbase
    because netbase will depend on it.
    aa17a44551
  57. vasild force-pushed on Feb 10, 2021
  58. vasild commented at 11:18 am on February 10, 2021: member

    bb5231615…7b6e4ee30: move CloseSocket() and NetworkErrorString() to util/sock.{h,cpp} instead of to util/system.{h,cpp}. @laanwj,

    It seems more logical to me to move the CloseSocket and NetworkErrorString functions to sock.h, not system.h?

    Done.

    Also do we still need an explicit CloseSocket instead of Sock::Reset?

    Actually this question makes sense - we can remove CloseSocket() altogether once its callers have switched to using the newly introduced Sock from this PR. There are about 10 places where CloseSocket() is called - should be possible (not in this PR).

  59. net: move CloseSocket() from netbase to util/sock
    Move `CloseSocket()` (and `NetworkErrorString()` which it uses) from
    `netbase.{h,cpp}` to newly added `src/util/sock.{h,cpp}`.
    
    This is necessary in order to use `CloseSocket()` from a newly
    introduced Sock class (which will live in `src/util/sock.{h,cpp}`).
    `sock.{h,cpp}` cannot depend on netbase because netbase will depend
    on it.
    dec9b5e850
  60. net: add RAII socket and use it instead of bare SOCKET
    Introduce a class to manage the lifetime of a socket - when the object
    that contains the socket goes out of scope, the underlying socket will
    be closed.
    
    In addition, the new `Sock` class has a `Send()`, `Recv()` and `Wait()`
    methods that can be overridden by unit tests to mock the socket
    operations.
    
    The `Wait()` method also hides the
    `#ifdef USE_POLL poll() #else select() #endif` technique from higher
    level code.
    ba9d73268f
  61. net: use Sock in InterruptibleRecv() and Socks5()
    Use the `Sock` class instead of `SOCKET` for `InterruptibleRecv()` and
    `Socks5()`.
    
    This way the `Socks5()` function can be tested by giving it a mocked
    instance of a socket.
    
    Co-authored-by: practicalswift <practicalswift@users.noreply.github.com>
    04ae846904
  62. style: rename hSocket to sock
    In the arguments of `InterruptibleRecv()`, `Socks5()` and
    `ConnectThroughProxy()` the variable `hSocket` was previously of type
    `SOCKET`, but has been changed to `Sock`. Thus rename it to `sock` to
    imply its type, to distinguish from other `SOCKET` variables and to
    abide to the coding style wrt variables' names.
    7bd21ce1ef
  63. vasild force-pushed on Feb 10, 2021
  64. vasild commented at 12:37 pm on February 10, 2021: member
    7b6e4ee30…e8e372a43: fix Vindows build
  65. laanwj commented at 7:24 pm on February 10, 2021: member

    @vasild Thanks! Yes, agree with not getting rid of CloseSocket in this PR, but glad to hear there’s a path to removing the loose function.

    Code review and light testing (outbound connections over Tor still work) ACK e8e372a43122366fab7d6c7a45e05d4ad18d6da7

  66. in src/test/sock_tests.cpp:22 in e8e372a431 outdated
    17+
    18+static bool SocketIsClosed(const SOCKET& s)
    19+{
    20+    // Notice that if another thread is running and creates its own socket after `s` has been
    21+    // closed, it may get assigned the same file descriptor number. In this case our test will
    22+    // wronly pretend that the socket is not closed.
    


    jonatack commented at 8:25 pm on February 10, 2021:
    0    // wrongly pretend that the socket is not closed.
    

    or “incorrectly”


    vasild commented at 9:46 am on February 11, 2021:
    Yeah, that was wron. Fixed.
  67. in src/test/sock_tests.cpp:21 in e8e372a431 outdated
    16+BOOST_FIXTURE_TEST_SUITE(sock_tests, BasicTestingSetup)
    17+
    18+static bool SocketIsClosed(const SOCKET& s)
    19+{
    20+    // Notice that if another thread is running and creates its own socket after `s` has been
    21+    // closed, it may get assigned the same file descriptor number. In this case our test will
    


    jonatack commented at 8:26 pm on February 10, 2021:
    0    // closed, it may be assigned the same file descriptor number. In this case, our test will
    

    vasild commented at 9:46 am on February 11, 2021:
    Fixed.
  68. jonatack commented at 8:45 pm on February 10, 2021: member

    ACK e8e372a43122366fab7d6c7a45e05d4ad18d6da7 rebased to master, debug build + code review at each commit, at head ran the new sock tests and the other unit tests locally and ran bitcoind while observing peer behavior–operation appears to be nominal

    Thanks for the recent updates that I found made review much easier. Below a couple of doc nits in the unit test that can be ignored or done in the follow-up if you’re inclined.

  69. laanwj commented at 8:56 am on February 11, 2021: member
    I think this is ready for merge, but would be nice to fix @jonatack’s comment typos.
  70. test: add Sock unit tests 615ba0eb96
  71. vasild force-pushed on Feb 11, 2021
  72. vasild commented at 9:47 am on February 11, 2021: member
    e8e372a43…615ba0eb9: fix typos in a comment
  73. laanwj commented at 12:23 pm on February 11, 2021: member
    Re-ACK 615ba0eb96cf131364c1ceca9d3dedf006fa1e1c Checked that only change is the comment.
  74. jonatack approved
  75. jonatack commented at 12:58 pm on February 11, 2021: member
    re-ACK 615ba0eb96cf131364c1ceca9d3dedf006fa1e1c
  76. jonatack commented at 12:59 pm on February 11, 2021: member

    (Review and comment made from gh pr as an experiment.)

    Edit: learned to never write gh pr in a comment from github cli, as it converts it to the general help.

  77. laanwj merged this on Feb 11, 2021
  78. laanwj closed this on Feb 11, 2021

  79. vasild deleted the branch on Feb 11, 2021
  80. sidhujag referenced this in commit 11681c692e on Feb 11, 2021
  81. laanwj removed this from the "Blockers" column in a project

  82. fanquake referenced this in commit 9cc8e30125 on Feb 12, 2021
  83. practicalswift commented at 9:36 am on February 12, 2021: contributor

    @vasild Thanks for making our socket handling mockable. This will be extremely useful when fuzzing!

    Similar to what you’ve done for TCP connections it would be really useful to be able to globally mock out DNS lookup to be able to have the responses be generated by a FuzzedDataProvider driven class instead of the ordinary lookup facility provided by the OS.

    If you want to address this mocking need too you can find some inspiration in #19415 :)

  84. vasild commented at 1:11 pm on February 13, 2021: member

    Just for reference: previous incarnations of this PR had the Sock::Wait() method report to the caller whether one of the requested events happened or a timeout occurred. This was removed because none of the callers needed it.

    However this is needed in #20685, so that PR contains a tiny commit to re-introduce that functionality.

  85. fanquake referenced this in commit 7c8e605bf4 on Feb 17, 2021
  86. sidhujag referenced this in commit 7f50b7edf3 on Feb 17, 2021
  87. kittywhiskers referenced this in commit 52007c9bfc on Jul 2, 2021
  88. kittywhiskers referenced this in commit 41c798344e on Jul 4, 2021
  89. kittywhiskers referenced this in commit 307649fa6b on Jul 9, 2021
  90. kittywhiskers referenced this in commit 0c2fcdc45a on Jul 9, 2021
  91. kittywhiskers referenced this in commit 5321ddbdd8 on Jul 9, 2021
  92. kittywhiskers referenced this in commit 8a40a3a55c on Jul 13, 2021
  93. kittywhiskers referenced this in commit 545d45dbbb on Jul 13, 2021
  94. kittywhiskers referenced this in commit c7d2d54cb1 on Jul 13, 2021
  95. kittywhiskers referenced this in commit 776b2eadb9 on Jul 15, 2021
  96. kittywhiskers referenced this in commit d3c15d0ee5 on Jul 15, 2021
  97. kittywhiskers referenced this in commit d905728fe7 on Jul 16, 2021
  98. kittywhiskers referenced this in commit f195d549b4 on Aug 1, 2021
  99. hebasto referenced this in commit 2ec884dd6d on Sep 11, 2021
  100. hebasto referenced this in commit 3174425255 on Sep 11, 2021
  101. MarcoFalke referenced this in commit ec7ec69c7b on Sep 16, 2021
  102. sidhujag referenced this in commit c6525c9b58 on Sep 19, 2021
  103. Fabcien referenced this in commit 824cdcfc42 on Feb 8, 2022
  104. Fabcien referenced this in commit dbfdac4aa4 on Feb 8, 2022
  105. Fabcien referenced this in commit e445307f56 on Feb 8, 2022
  106. Fabcien referenced this in commit b602a1a798 on Feb 8, 2022
  107. DrahtBot locked this on Aug 16, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-18 18:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me