diff --git a/CMakeLists.txt b/CMakeLists.txt index df83e7a07ebff06ba53a6b274b1c29fffc6c3131..5eca99740ab529d0691038adee43b3f202c35de0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,6 +150,8 @@ list (APPEND opendht_SOURCES src/dhtrunner.cpp src/log.cpp src/peer_discovery.cpp + src/network_utils.h + src/network_utils.cpp ) list (APPEND opendht_HEADERS diff --git a/src/Makefile.am b/src/Makefile.am index aee033e5c09175459fd269db0e6f19d6128b18df..e5b4e39bf9517062abc76ed6c7e1bb26e95267bd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,9 @@ libopendht_la_SOURCES = \ securedht.cpp \ dhtrunner.cpp \ default_types.cpp \ - log.cpp + log.cpp \ + network_utils.h \ + network_utils.cpp if WIN32 libopendht_la_SOURCES += rng.cpp diff --git a/src/dhtrunner.cpp b/src/dhtrunner.cpp index d0a1bf853e24b392165c9a17818c6e246c00477d..7c2b34f670917fe7d7a266e0dc0338432077631e 100644 --- a/src/dhtrunner.cpp +++ b/src/dhtrunner.cpp @@ -21,26 +21,12 @@ #include "dhtrunner.h" #include "securedht.h" #include "peer_discovery.h" +#include "network_utils.h" #ifdef OPENDHT_PROXY_CLIENT #include "dht_proxy_client.h" #endif -#ifndef _WIN32 -#include <unistd.h> -#else -#include <io.h> -#endif - -#ifndef _WIN32 -#include <sys/socket.h> -#else -#include <winsock2.h> -#include <ws2tcpip.h> -#define close(x) closesocket(x) -#define write(s, b, f) send(s, b, (int)strlen(b), 0) -#endif - namespace dht { constexpr std::chrono::seconds DhtRunner::BOOTSTRAP_PERIOD; @@ -181,17 +167,6 @@ DhtRunner::run(const SockAddr& local4, const SockAddr& local6, const DhtRunner:: } } -void DhtRunner::bootstrap(const InfoHash& id, const SockAddr& address) -{ - { - std::unique_lock<std::mutex> lck(storage_mtx); - pending_ops_prio.emplace([id, address](SecureDht& dht) mutable { - dht.insertNode(id, address); - }); - } - cv.notify_all(); -} - void DhtRunner::shutdown(ShutdownCallback cb) { #ifdef OPENDHT_PROXY_CLIENT @@ -523,34 +498,6 @@ int bindSocket(const SockAddr& addr, SockAddr& bound) return sock; } -#ifdef _WIN32 -inline void udpPipe(int fds[2]) -{ - int lst = socket(AF_INET, SOCK_DGRAM, 0); - if (lst < 0) - throw DhtException(std::string("Can't open socket: ") + strerror(lst)); - sockaddr_in inaddr; - sockaddr addr; - memset(&inaddr, 0, sizeof(inaddr)); - memset(&addr, 0, sizeof(addr)); - inaddr.sin_family = AF_INET; - inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - inaddr.sin_port = 0; - int yes=1; - setsockopt(lst, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)); - int rc = bind(lst, (sockaddr*)&inaddr, sizeof(inaddr)); - if (rc < 0) { - close(lst); - throw DhtException("Can't bind socket on " + print_addr((sockaddr*)&addr, sizeof(inaddr)) + " " + strerror(rc)); - } - socklen_t len = sizeof(inaddr); - getsockname(lst, &addr, &len); - fds[0] = lst; - fds[1] = socket(AF_INET, SOCK_DGRAM, 0); - connect(fds[1], &addr, len); -} -#endif - void DhtRunner::stopNetwork() { @@ -576,7 +523,7 @@ DhtRunner::startNetwork(const SockAddr sin4, const SockAddr sin6) throw DhtException(std::string("Can't open pipe: ") + strerror(errno)); } #else - udpPipe(stopfds); + net::udpPipe(stopfds); #endif int stop_readfd = stopfds[0]; stop_writefd = stopfds[1]; @@ -988,6 +935,18 @@ DhtRunner::bootstrap(const SockAddr& addr, DoneCallbackSimple&& cb) cv.notify_all(); } +void +DhtRunner::bootstrap(const InfoHash& id, const SockAddr& address) +{ + { + std::unique_lock<std::mutex> lck(storage_mtx); + pending_ops_prio.emplace([id, address](SecureDht& dht) mutable { + dht.insertNode(id, address); + }); + } + cv.notify_all(); +} + void DhtRunner::bootstrap(const std::vector<NodeExport>& nodes) { diff --git a/src/network_engine.cpp b/src/network_engine.cpp index 6eed6584d71754e1bb360f675bb580d2d00ceb4a..27d80e9f3f5b813c0b55624cdbacbd5491a5c185 100644 --- a/src/network_engine.cpp +++ b/src/network_engine.cpp @@ -23,6 +23,7 @@ #include "default_types.h" #include "log_enable.h" #include "parsed_message.h" +#include "network_utils.h" #include <msgpack.hpp> @@ -61,32 +62,6 @@ static const uint8_t v4prefix[16] = { constexpr unsigned SEND_NODES {8}; -#ifdef _WIN32 - -static bool -set_nonblocking(int fd, int nonblocking) -{ - unsigned long mode = !!nonblocking; - int rc = ioctlsocket(fd, FIONBIO, &mode); - return rc == 0; -} - -extern const char *inet_ntop(int, const void *, char *, socklen_t); - -#else - -static bool -set_nonblocking(int fd, int nonblocking) -{ - int rc = fcntl(fd, F_GETFL, 0); - if (rc < 0) - return false; - rc = fcntl(fd, F_SETFL, nonblocking?(rc | O_NONBLOCK):(rc & ~O_NONBLOCK)); - return rc >= 0; -} - -#endif - /* Transaction-ids are 4-bytes long, with the first two bytes identifying * the kind of request, and the remaining two a sequence number in @@ -165,11 +140,11 @@ NetworkEngine::NetworkEngine(InfoHash& myid, NetId net, const int& s, const int& myid(myid), network(net), dht_socket(s), dht_socket6(s6), DHT_LOG(log), scheduler(scheduler) { if (dht_socket >= 0) { - if (!set_nonblocking(dht_socket, 1)) + if (!set_nonblocking(dht_socket)) throw DhtException("Can't set socket to non-blocking mode"); } if (dht_socket6 >= 0) { - if (!set_nonblocking(dht_socket6, 1)) + if (!set_nonblocking(dht_socket6)) throw DhtException("Can't set socket to non-blocking mode"); } } diff --git a/src/network_utils.cpp b/src/network_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f542aa0b725c88790bdcfd68657086aae1aa15a9 --- /dev/null +++ b/src/network_utils.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2019 Savoir-faire Linux Inc. + * Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "network_utils.h" + +#ifndef _WIN32 +#include <arpa/inet.h> +#include <unistd.h> +#include <sys/socket.h> +#else +#include <winsock2.h> +#include <ws2tcpip.h> +#include <io.h> +#define close(x) closesocket(x) +#define write(s, b, f) send(s, b, (int)strlen(b), 0) +#endif +#include <fcntl.h> + +namespace dht { +namespace net { + +bool +set_nonblocking(int fd, bool nonblocking) +{ +#ifdef _WIN32 + unsigned long mode = !!nonblocking; + int rc = ioctlsocket(fd, FIONBIO, &mode); + return rc == 0; +#else + int rc = fcntl(fd, F_GETFL, 0); + if (rc < 0) + return false; + rc = fcntl(fd, F_SETFL, nonblocking ? (rc | O_NONBLOCK) : (rc & ~O_NONBLOCK)); + return rc >= 0; +#endif +} + +#ifdef _WIN32 +void udpPipe(int fds[2]) +{ + int lst = socket(AF_INET, SOCK_DGRAM, 0); + if (lst < 0) + throw DhtException(std::string("Can't open socket: ") + strerror(lst)); + sockaddr_in inaddr; + sockaddr addr; + memset(&inaddr, 0, sizeof(inaddr)); + memset(&addr, 0, sizeof(addr)); + inaddr.sin_family = AF_INET; + inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + inaddr.sin_port = 0; + int yes=1; + setsockopt(lst, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)); + int rc = bind(lst, (sockaddr*)&inaddr, sizeof(inaddr)); + if (rc < 0) { + close(lst); + throw DhtException("Can't bind socket on " + print_addr((sockaddr*)&addr, sizeof(inaddr)) + " " + strerror(rc)); + } + socklen_t len = sizeof(inaddr); + getsockname(lst, &addr, &len); + fds[0] = lst; + fds[1] = socket(AF_INET, SOCK_DGRAM, 0); + connect(fds[1], &addr, len); +} +#endif + +} +} diff --git a/src/network_utils.h b/src/network_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..b9148237c9a5c1fd757b4967bfb1bdf5d3956df7 --- /dev/null +++ b/src/network_utils.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2019 Savoir-faire Linux Inc. + * Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +#pragma once + +#ifdef _WIN32 +#include <winsock2.h> +#define close(x) closesocket(x) +#define write(s, b, f) send(s, b, (int)strlen(b), 0) +#endif + +namespace dht { +namespace net { + +bool set_nonblocking(int fd, bool nonblocking = true); + +#ifdef _WIN32 +void udpPipe(int fds[2]); +// extern const char *inet_ntop(int, const void *, char *, socklen_t); +#endif + +} +} diff --git a/src/peer_discovery.cpp b/src/peer_discovery.cpp index 984b7dbbfeb33fccc53cf35363506fa07177aeae..f78868fe89034d5683ce61214c8102cb277890ae 100644 --- a/src/peer_discovery.cpp +++ b/src/peer_discovery.cpp @@ -17,6 +17,7 @@ */ #include "peer_discovery.h" +#include "network_utils.h" #ifdef _WIN32 #include <Ws2tcpip.h> // needed for ip_mreq definition for multicast @@ -31,36 +32,20 @@ namespace dht { constexpr char MULTICAST_ADDRESS_IPV4[10] = "224.0.0.1"; constexpr char MULTICAST_ADDRESS_IPV6[8] = "ff05::2"; // Site-local multicast -#ifdef _WIN32 - -static bool -set_nonblocking(int fd, int nonblocking) +PeerDiscovery::PeerDiscovery(sa_family_t domain, in_port_t port) + : domain_(domain), port_(port), sockfd_(initialize_socket(domain)) { - unsigned long mode = !!nonblocking; - int rc = ioctlsocket(fd, FIONBIO, &mode); - return rc == 0; + socketJoinMulticast(sockfd_, domain); } -extern const char *inet_ntop(int, const void *, char *, socklen_t); - -#else - -static bool -set_nonblocking(int fd, int nonblocking) +PeerDiscovery::~PeerDiscovery() { - int rc = fcntl(fd, F_GETFL, 0); - if (rc < 0) - return false; - rc = fcntl(fd, F_SETFL, nonblocking?(rc | O_NONBLOCK):(rc & ~O_NONBLOCK)); - return rc >= 0; -} + if (sockfd_ != -1) + close(sockfd_); +#ifdef _WIN32 + WSACleanup(); #endif - -PeerDiscovery::PeerDiscovery(sa_family_t domain, in_port_t port) - : domain_(domain), port_(port), sockfd_(initialize_socket(domain)) -{ - socketJoinMulticast(sockfd_, domain); } int @@ -77,7 +62,7 @@ PeerDiscovery::initialize_socket(sa_family_t domain) if (sockfd < 0) { throw std::runtime_error(std::string("Socket Creation Error: ") + strerror(errno)); } - set_nonblocking(sockfd, 1); + net::set_nonblocking(sockfd); return sockfd; } @@ -235,7 +220,7 @@ PeerDiscovery::listener_thread(PeerDiscoveredCallback callback) throw std::runtime_error(std::string("Can't open pipe: ") + strerror(errno)); } #else - udpPipe(stopfds_pipe); + net::udpPipe(stopfds_pipe); #endif int stop_readfd = stopfds_pipe[0]; stop_writefd_ = stopfds_pipe[1]; @@ -329,14 +314,4 @@ PeerDiscovery::stop() } } -PeerDiscovery::~PeerDiscovery() -{ - if (sockfd_ != -1) - close(sockfd_); - -#ifdef _WIN32 - WSACleanup(); -#endif -} - }