|
9 | 9 | #include <netbase.h> |
10 | 10 | #include <util/sock.h> |
11 | 11 |
|
12 | | -bool SockMan::BindListenPort(const CService& addrBind, bilingual_str& strError) |
| 12 | +bool SockMan::BindAndStartListening(const CService& to, bilingual_str& err_msg) |
13 | 13 | { |
14 | | - int nOne = 1; |
15 | | - |
16 | 14 | // Create socket for listening for incoming connections |
17 | | - struct sockaddr_storage sockaddr; |
18 | | - socklen_t len = sizeof(sockaddr); |
19 | | - if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len)) |
20 | | - { |
21 | | - strError = Untranslated(strprintf("Bind address family for %s not supported", addrBind.ToStringAddrPort())); |
22 | | - LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original); |
| 15 | + sockaddr_storage storage; |
| 16 | + socklen_t len{sizeof(storage)}; |
| 17 | + if (!to.GetSockAddr(reinterpret_cast<sockaddr*>(&storage), &len)) { |
| 18 | + err_msg = Untranslated(strprintf("Bind address family for %s not supported", to.ToStringAddrPort())); |
23 | 19 | return false; |
24 | 20 | } |
25 | 21 |
|
26 | | - std::unique_ptr<Sock> sock = CreateSock(addrBind.GetSAFamily(), SOCK_STREAM, IPPROTO_TCP); |
| 22 | + std::unique_ptr<Sock> sock{CreateSock(to.GetSAFamily(), SOCK_STREAM, IPPROTO_TCP)}; |
27 | 23 | if (!sock) { |
28 | | - strError = Untranslated(strprintf("Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError()))); |
29 | | - LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original); |
| 24 | + err_msg = Untranslated(strprintf("Cannot create %s listen socket: %s", |
| 25 | + to.ToStringAddrPort(), |
| 26 | + NetworkErrorString(WSAGetLastError()))); |
30 | 27 | return false; |
31 | 28 | } |
32 | 29 |
|
| 30 | + int one{1}; |
| 31 | + |
33 | 32 | // Allow binding if the port is still in TIME_WAIT state after |
34 | 33 | // the program was closed and restarted. |
35 | | - if (sock->SetSockOpt(SOL_SOCKET, SO_REUSEADDR, &nOne, sizeof(int)) == SOCKET_ERROR) { |
36 | | - strError = Untranslated(strprintf("Error setting SO_REUSEADDR on socket: %s, continuing anyway", NetworkErrorString(WSAGetLastError()))); |
37 | | - LogPrintf("%s\n", strError.original); |
| 34 | + if (sock->SetSockOpt(SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == SOCKET_ERROR) { |
| 35 | + LogPrintLevel(BCLog::NET, |
| 36 | + BCLog::Level::Info, |
| 37 | + "Cannot set SO_REUSEADDR on %s listen socket: %s, continuing anyway\n", |
| 38 | + to.ToStringAddrPort(), |
| 39 | + NetworkErrorString(WSAGetLastError())); |
38 | 40 | } |
39 | 41 |
|
40 | 42 | // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option |
41 | 43 | // and enable it by default or not. Try to enable it, if possible. |
42 | | - if (addrBind.IsIPv6()) { |
| 44 | + if (to.IsIPv6()) { |
43 | 45 | #ifdef IPV6_V6ONLY |
44 | | - if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_V6ONLY, &nOne, sizeof(int)) == SOCKET_ERROR) { |
45 | | - strError = Untranslated(strprintf("Error setting IPV6_V6ONLY on socket: %s, continuing anyway", NetworkErrorString(WSAGetLastError()))); |
46 | | - LogPrintf("%s\n", strError.original); |
| 46 | + if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)) == SOCKET_ERROR) { |
| 47 | + LogPrintLevel(BCLog::NET, |
| 48 | + BCLog::Level::Info, |
| 49 | + "Cannot set IPV6_V6ONLY on %s listen socket: %s, continuing anyway\n", |
| 50 | + to.ToStringAddrPort(), |
| 51 | + NetworkErrorString(WSAGetLastError())); |
47 | 52 | } |
48 | 53 | #endif |
49 | 54 | #ifdef WIN32 |
50 | | - int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED; |
51 | | - if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, &nProtLevel, sizeof(int)) == SOCKET_ERROR) { |
52 | | - strError = Untranslated(strprintf("Error setting IPV6_PROTECTION_LEVEL on socket: %s, continuing anyway", NetworkErrorString(WSAGetLastError()))); |
53 | | - LogPrintf("%s\n", strError.original); |
| 55 | + int prot_level{PROTECTION_LEVEL_UNRESTRICTED}; |
| 56 | + if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, &prot_level, sizeof(prot_level)) == SOCKET_ERROR) { |
| 57 | + LogPrintLevel(BCLog::NET, |
| 58 | + BCLog::Level::Info, |
| 59 | + "Cannot set IPV6_PROTECTION_LEVEL on %s listen socket: %s, continuing anyway\n", |
| 60 | + to.ToStringAddrPort(), |
| 61 | + NetworkErrorString(WSAGetLastError())); |
54 | 62 | } |
55 | 63 | #endif |
56 | 64 | } |
57 | 65 |
|
58 | | - if (sock->Bind(reinterpret_cast<struct sockaddr*>(&sockaddr), len) == SOCKET_ERROR) { |
59 | | - int nErr = WSAGetLastError(); |
60 | | - if (nErr == WSAEADDRINUSE) |
61 | | - strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToStringAddrPort(), CLIENT_NAME); |
62 | | - else |
63 | | - strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToStringAddrPort(), NetworkErrorString(nErr)); |
64 | | - LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original); |
| 66 | + if (sock->Bind(reinterpret_cast<sockaddr*>(&storage), len) == SOCKET_ERROR) { |
| 67 | + const int err{WSAGetLastError()}; |
| 68 | + if (err == WSAEADDRINUSE) { |
| 69 | + err_msg = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), |
| 70 | + to.ToStringAddrPort(), |
| 71 | + CLIENT_NAME); |
| 72 | + } else { |
| 73 | + err_msg = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), |
| 74 | + to.ToStringAddrPort(), |
| 75 | + NetworkErrorString(err)); |
| 76 | + } |
65 | 77 | return false; |
66 | 78 | } |
67 | | - LogPrintf("Bound to %s\n", addrBind.ToStringAddrPort()); |
68 | 79 |
|
69 | 80 | // Listen for incoming connections |
70 | | - if (sock->Listen(SOMAXCONN) == SOCKET_ERROR) |
71 | | - { |
72 | | - strError = strprintf(_("Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError())); |
73 | | - LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original); |
| 81 | + if (sock->Listen(SOMAXCONN) == SOCKET_ERROR) { |
| 82 | + err_msg = strprintf(_("Cannot listen on %s: %s"), to.ToStringAddrPort(), NetworkErrorString(WSAGetLastError())); |
74 | 83 | return false; |
75 | 84 | } |
76 | 85 |
|
|
0 commit comments